当前位置: 代码网 > 服务器>服务器>Linux > Linux环境下部署Kubernetes集群的全过程

Linux环境下部署Kubernetes集群的全过程

2026年04月22日 Linux 我要评论
在当今云原生时代,kubernetes 已成为容器编排的事实标准。无论你是 devops 工程师、后端开发者,还是系统架构师,掌握 kubernetes 的部署与运维能力都已成为必备技能。本文将带你从

在当今云原生时代,kubernetes 已成为容器编排的事实标准。无论你是 devops 工程师、后端开发者,还是系统架构师,掌握 kubernetes 的部署与运维能力都已成为必备技能。本文将带你从零开始,在 linux 环境中完整部署一个高可用的 kubernetes 集群,并通过 java 应用演示其部署、伸缩与服务发现能力。

提示:本文内容基于 ubuntu 22.04 lts 操作系统,但大部分命令适用于主流 linux 发行版如 centos、debian、rhel 等。

为什么选择 kubernetes?

在深入部署之前,我们先理解一下为什么 kubernetes 如此重要:

  • 自动化部署与回滚:一键部署应用,失败自动回滚。
  • 弹性伸缩:根据 cpu、内存或自定义指标自动扩缩容。
  • 服务发现与负载均衡:内置 service 机制实现内部通信与外部暴露。
  • 自我修复:节点宕机自动迁移 pod,保证服务高可用。
  • 配置与密钥管理:安全地注入环境变量和敏感数据。
  • 存储编排:支持本地、云盘、nfs、ceph 等多种存储方案。

基础环境准备

系统要求

我们将部署一个包含 1 个 master 节点 + 2 个 worker 节点的小型集群。建议每台机器满足以下最低配置:

角色cpu 核心数内存存储空间
master24gb20gb
worker24gb20gb

操作系统推荐使用 ubuntu 22.04 ltscentos stream 9

关闭防火墙与 selinux(可选)

# ubuntu / debian
sudo ufw disable
# centos / rhel
sudo systemctl stop firewalld
sudo systemctl disable firewalld
# 关闭 selinux(仅限 centos/rhel)
sudo setenforce 0
sudo sed -i 's/^selinux=enforcing$/selinux=permissive/' /etc/selinux/config

同步时间(重要!)

kubernetes 对时间同步非常敏感,推荐使用 chronyntp

sudo apt update && sudo apt install chrony -y
sudo systemctl enable chronyd && sudo systemctl start chronyd
chronyc sources -v

安装 docker 或 containerd

kubernetes 1.24+ 不再默认支持 docker,推荐使用 containerd 作为 cri 运行时。

安装 containerd:

# 更新包索引
sudo apt update

# 安装依赖
sudo apt install -y ca-certificates curl gnupg lsb-release

# 添加 docker gpg 密钥(用于 containerd)
curl -fssl https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装 containerd
sudo apt update && sudo apt install -y containerd.io

# 配置 containerd 使用 systemd cgroup
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo sed -i 's/systemdcgroup = false/systemdcgroup = true/g' /etc/containerd/config.toml

# 重启并启用
sudo systemctl restart containerd
sudo systemctl enable containerd

安装 kubeadm、kubelet 和 kubectl

这是部署 kubernetes 集群的核心工具链:

  • kubeadm:用于初始化集群。
  • kubelet:运行在所有节点上,负责 pod 生命周期。
  • kubectl:命令行控制工具。
# 添加 kubernetes apt 源
sudo curl -fsslo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 安装指定版本(推荐 v1.28.x)
sudo apt update
sudo apt install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00

# 锁定版本防止自动升级
sudo apt-mark hold kubelet kubeadm kubectl

小贴士:生产环境中建议锁定版本,避免因自动升级导致兼容性问题。

配置网络与主机名

确保各节点之间可以通过主机名互相解析:

# 设置主机名(分别在 master、worker1、worker2 上执行)
sudo hostnamectl set-hostname k8s-master
sudo hostnamectl set-hostname k8s-worker1
sudo hostnamectl set-hostname k8s-worker2

# 编辑 /etc/hosts,添加如下内容(ip 替换为实际值)
192.168.1.100 k8s-master
192.168.1.101 k8s-worker1
192.168.1.102 k8s-worker2

初始化 master 节点

现在我们正式初始化 kubernetes 控制平面:

sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --apiserver-advertise-address=192.168.1.100 \
  --control-plane-endpoint=k8s-master:6443 \
  --upload-certs

参数说明:

  • --pod-network-cidr:pod 网络 cidr,flannel 默认使用 10.244.0.0/16
  • --apiserver-advertise-address:api server 绑定的 ip 地址
  • --control-plane-endpoint:控制平面访问端点(便于未来扩展 ha)
  • --upload-certs:上传证书,便于后续加入其他控制节点

配置 kubectl

初始化成功后,按提示配置当前用户使用 kubectl:

mkdir -p $home/.kube
sudo cp -i /etc/kubernetes/admin.conf $home/.kube/config
sudo chown $(id -u):$(id -g) $home/.kube/config

验证是否成功:

kubectl get nodes
# 此时应看到 master 节点状态为 notready(因为还未安装网络插件)

安装 pod 网络插件 —— flannel

kubernetes 需要 cni 插件来实现 pod 间通信。我们选择轻量级的 flannel

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/documentation/kube-flannel.yml

等待几分钟,再次检查节点状态:

kubectl get nodes
# status 应变为 ready

加入 worker 节点

回到 master 初始化输出的最后一段,复制 kubeadm join 命令,在每个 worker 节点上执行:

sudo kubeadm join k8s-master:6443 \
  --token <your-token> \
  --discovery-token-ca-cert-hash sha256:<your-hash>

如果你丢失了 join 命令,可以在 master 上重新生成:

kubeadm token create --print-join-command

等待几分钟,再次在 master 上执行:

kubectl get nodes
# 应看到所有节点状态为 ready

集群拓扑结构图

下面是一个典型的三节点 kubernetes 集群架构图:

该图展示了客户端请求如何通过负载均衡器进入 api server,再由调度器分发到各个工作节点上的 pod 中。每个 pod 可以运行不同的服务,例如 java 应用、数据库、缓存等。

验证集群功能

创建测试命名空间

kubectl create namespace test-app
kubectl config set-context --current --namespace=test-app

部署第一个 pod —— nginx

kubectl create deployment nginx --image=nginx:latest
kubectl expose deployment nginx --port=80 --type=nodeport
kubectl get svc nginx

访问任一节点 ip + nodeport 即可看到欢迎页。

编写 java spring boot 应用

下面我们编写一个简单的 java 应用,用于部署到 kubernetes 集群中。

maven 项目结构

src/
├── main/
│   ├── java/
│   │   └── com/example/demo/
│   │       ├── demoapplication.java
│   │       └── hellocontroller.java
│   └── resources/
│       └── application.properties
pom.xml
dockerfile

pom.xml

<?xml version="1.0" encoding="utf-8"?>
<project xmlns="http://maven.apache.org/pom/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"
         xsi:schemalocation="http://maven.apache.org/pom/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelversion>4.0.0</modelversion>
    <groupid>com.example</groupid>
    <artifactid>k8s-demo-app</artifactid>
    <version>0.0.1-snapshot</version>
    <packaging>jar</packaging>
    <parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>3.1.0</version>
        <relativepath/>
    </parent>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-web</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-actuator</artifactid>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupid>org.springframework.boot</groupid>
                <artifactid>spring-boot-maven-plugin</artifactid>
            </plugin>
        </plugins>
    </build>
</project>

demoapplication.java

package com.example.demo;
import org.springframework.boot.springapplication;
import org.springframework.boot.autoconfigure.springbootapplication;
@springbootapplication
public class demoapplication {
    public static void main(string[] args) {
        springapplication.run(demoapplication.class, args);
    }
}

hellocontroller.java

package com.example.demo;
import org.springframework.web.bind.annotation.getmapping;
import org.springframework.web.bind.annotation.restcontroller;
import java.net.inetaddress;
import java.net.unknownhostexception;
@restcontroller
public class hellocontroller {
    @getmapping("/hello")
    public string hello() throws unknownhostexception {
        string hostname = inetaddress.getlocalhost().gethostname();
        return "hello from java spring boot! host: " + hostname + " 🎉";
    }
    @getmapping("/health")
    public string health() {
        return "up";
    }
}

application.properties

server.port=8080
management.endpoints.web.exposure.include=*
management.endpoint.health.show-details=always

dockerfile

from eclipse-temurin:17-jre-alpine
workdir /app
copy target/k8s-demo-app-0.0.1-snapshot.jar app.jar
expose 8080
entrypoint ["java", "-jar", "app.jar"]

构建并推送镜像

在项目根目录执行:

mvn clean package
docker build -t your-dockerhub-username/k8s-java-app:v1 .
docker login
docker push your-dockerhub-username/k8s-java-app:v1

替换 your-dockerhub-username 为你自己的 docker hub 用户名。

部署 java 应用到 kubernetes

创建 deployment

# java-app-deployment.yaml
apiversion: apps/v1
kind: deployment
metadata:
  name: java-app
  namespace: test-app
spec:
  replicas: 3
  selector:
    matchlabels:
      app: java-app
  template:
    metadata:
      labels:
        app: java-app
    spec:
      containers:
      - name: java-app
        image: your-dockerhub-username/k8s-java-app:v1
        ports:
        - containerport: 8080
        livenessprobe:
          httpget:
            path: /health
            port: 8080
          initialdelayseconds: 30
          periodseconds: 10
        readinessprobe:
          httpget:
            path: /health
            port: 8080
          initialdelayseconds: 5
          periodseconds: 5
        resources:
          requests:
            memory: "256mi"
            cpu: "250m"
          limits:
            memory: "512mi"
            cpu: "500m"

部署:

kubectl apply -f java-app-deployment.yaml

创建 service

# java-app-service.yaml
apiversion: v1
kind: service
metadata:
  name: java-app-service
  namespace: test-app
spec:
  selector:
    app: java-app
  ports:
    - protocol: tcp
      port: 80
      targetport: 8080
  type: nodeport

部署:

kubectl apply -f java-app-service.yaml
kubectl get svc java-app-service -n test-app

访问 http://<node_ip>:<node_port>/hello,你会看到类似:

hello from java spring boot! host: java-app-5d7c8f9b4d-xyz12 🎉

刷新页面,你会发现 host 名称变化,说明请求被负载均衡到了不同 pod!

自动扩缩容演示

kubernetes 支持根据 cpu 使用率自动扩缩容:

# 创建 hpa(horizontal pod autoscaler)
kubectl autoscale deployment java-app --cpu-percent=50 --min=2 --max=10 -n test-app

# 查看 hpa 状态
kubectl get hpa -n test-app

# 模拟压力测试(新开终端)
kubectl run load-test --image=busybox --rm -it --restart=never -- sh -c "while true; do wget -q -o- http://java-app-service/hello; echo; sleep 0.5; done"

观察 hpa 是否触发扩容:

watch kubectl get pods -n test-app

当 cpu 超过阈值,副本数会自动增加;压力解除后,又会自动缩减。

服务发现与 configmap

kubernetes 内部服务可通过 dns 自动发现。例如,我们的 java 应用想连接 redis,只需知道 service 名称即可:

// 在 java 代码中
string redishost = system.getenv().getordefault("redis_host", "redis-service.test-app.svc.cluster.local");
int redisport = integer.parseint(system.getenv().getordefault("redis_port", "6379"));

同时,我们可以使用 configmap 注入配置:

# app-config.yaml
apiversion: v1
kind: configmap
metadata:
  name: app-config
  namespace: test-app
data:
  app_name: "myk8sapp"
  log_level: "info"
  redis_host: "redis-service"
  redis_port: "6379"

在 deployment 中引用:

envfrom:
- configmapref:
    name: app-config

这样,无需修改代码或重建镜像,即可动态调整配置!

使用 secret 管理敏感信息

比如数据库密码:

kubectl create secret generic db-secret \
  --from-literal=username=admin \
  --from-literal=password=supersecret123! \
  -n test-app

在 deployment 中挂载:

env:
- name: db_username
  valuefrom:
    secretkeyref:
      name: db-secret
      key: username
- name: db_password
  valuefrom:
    secretkeyref:
      name: db-secret
      key: password

secret 数据在 etcd 中是 base64 编码存储,建议生产环境启用加密或使用外部密钥管理服务(如 hashicorp vault)。

监控与日志收集

虽然不是本文重点,但生产环境不可或缺:

  • prometheus + grafana:监控集群资源与应用指标。
  • efk stack(elasticsearch + fluentd + kibana):集中式日志收集与分析。
  • loki + promtail + grafana:轻量级日志方案。

高可用架构进阶(简述)

上述部署为单 master,生产环境建议:

  1. 多 master + 负载均衡器:使用 haproxy 或云厂商 lb。
  2. 外部 etcd 集群:独立部署 etcd,提高稳定性。
  3. 存储持久化:使用 csi 插件对接云存储或 ceph。
  4. ingress controller:如 nginx ingress、traefik,统一管理外部访问。

故障模拟与恢复

手动删除一个 pod

kubectl delete pod <pod-name> -n test-app

观察 deployment 是否自动重建新 pod:

kubectl get pods -w -n test-app

kubernetes 会确保副本数始终符合期望值。

模拟节点宕机

关闭一台 worker 节点:

sudo shutdown now

在 master 上查看:

kubectl get nodes
# 该节点状态变为 notready
kubectl get pods -o wide
# 原本运行在该节点上的 pod 会被标记为 unknown 或 nodelost

等待约 5 分钟(默认驱逐超时),pod 会自动迁移到健康节点!

常用调试命令汇总

# 查看所有资源
kubectl get all -a

# 查看 pod 日志
kubectl logs <pod-name> -n test-app

# 进入 pod 内部
kubectl exec -it <pod-name> -n test-app -- sh

# 查看事件(排错神器)
kubectl get events -n test-app --sort-by='.lasttimestamp'

# 查看节点资源使用
kubectl top nodes
kubectl top pods -n test-app

# 描述资源详情
kubectl describe pod <pod-name> -n test-app

常见问题与解决方案

pod 一直处于 pending 状态

可能原因:

  • 资源不足(cpu/memory)
  • 节点选择器不匹配
  • pvc 未绑定

解决方法:

kubectl describe pod <pod-name>
# 查看 events 部分

imagepullbackoff

镜像拉取失败:

  • 检查镜像名称是否正确
  • 私有仓库需配置 imagepullsecrets
  • 网络策略限制
kubectl get events --field-selector reason=failed

crashloopbackoff

容器反复崩溃:

  • 检查启动命令是否正确
  • 查看日志:kubectl logs <pod> --previous
  • 检查探针配置是否过于严格

java 开发者专属技巧

在 java 应用中读取 pod 信息

kubernetes 会将 pod 信息通过 downward api 注入环境变量或文件:

env:
- name: my_pod_name
  valuefrom:
    fieldref:
      fieldpath: metadata.name
- name: my_pod_namespace
  valuefrom:
    fieldref:
      fieldpath: metadata.namespace
- name: my_node_name
  valuefrom:
    fieldref:
      fieldpath: spec.nodename

java 代码中读取:

string podname = system.getenv("my_pod_name");
string namespace = system.getenv("my_pod_namespace");
system.out.println("running in pod: " + podname + ", namespace: " + namespace);

使用 actuator 暴露健康检查端点

前面我们已集成 spring-boot-starter-actuator,它提供:

  • /actuator/health:健康状态
  • /actuator/metrics:性能指标
  • /actuator/env:环境变量

配合 prometheus 可采集 jvm 指标:

<dependency>
    <groupid>io.micrometer</groupid>
    <artifactid>micrometer-registry-prometheus</artifactid>
</dependency>

访问 http://<service>/actuator/prometheus 即可获取指标数据。

使用 helm 简化部署(进阶)

helm 是 kubernetes 的包管理器,类似 linux 的 apt/yum。

安装 helm:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

添加仓库 & 部署 java 应用 chart:

helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-java-app bitnami/tomcat --set service.type=nodeport

集成 ci/cd 流水线

推荐使用 gitlab ci 或 github actions 自动构建镜像并部署:

# .gitlab-ci.yml 示例
stages:
  - build
  - deploy
build_image:
  stage: build
  script:
    - mvn package
    - docker build -t $ci_registry_image:$ci_commit_short_sha .
    - docker push $ci_registry_image:$ci_commit_short_sha
deploy_to_k8s:
  stage: deploy
  script:
    - kubectl set image deployment/java-app java-app=$ci_registry_image:$ci_commit_short_sha -n test-app
  only:
    - main

总结

至此,你已经完成了一个完整的 kubernetes 集群部署,并成功运行了 java 应用。回顾整个过程:

✅ 准备 linux 环境
✅ 安装 containerd + kubeadm 工具链
✅ 初始化 master 并加入 worker 节点
✅ 部署 cni 网络插件
✅ 编写、构建、推送 java 镜像
✅ 通过 deployment + service 部署应用
✅ 配置自动扩缩容、健康检查、服务发现
✅ 学习常用调试与排错技巧

kubernetes 的世界远不止于此,但你已经打下了坚实的基础。下一步可以探索:

  • statefulset 管理有状态应用(如 mysql、zookeeper)
  • ingress 实现域名路由
  • networkpolicy 实现网络安全隔离
  • operator 模式自动化复杂应用管理

记住:kubernetes 的学习曲线陡峭,但回报巨大。坚持实践,你将成为云原生时代的架构大师!

最后的话

希望这篇长文能帮助你在 linux 上成功部署 kubernetes,并愉快地运行 java 应用。技术世界日新月异,但基础永远是王道。动手实践、不断试错、持续学习 —— 这才是工程师的成长之道。

以上就是linux环境下部署kubernetes集群的全过程的详细内容,更多关于linux部署kubernetes集群的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com