Linux環(huán)境下部署Kubernetes集群的全過程
在當今云原生時代,Kubernetes 已成為容器編排的事實標準。無論你是 DevOps 工程師、后端開發(fā)者,還是系統(tǒng)架構師,掌握 Kubernetes 的部署與運維能力都已成為必備技能。本文將帶你從零開始,在 Linux 環(huán)境中完整部署一個高可用的 Kubernetes 集群,并通過 Java 應用演示其部署、伸縮與服務發(fā)現(xiàn)能力。
提示:本文內容基于 Ubuntu 22.04 LTS 操作系統(tǒng),但大部分命令適用于主流 Linux 發(fā)行版如 CentOS、Debian、RHEL 等。
為什么選擇 Kubernetes?
在深入部署之前,我們先理解一下為什么 Kubernetes 如此重要:
- 自動化部署與回滾:一鍵部署應用,失敗自動回滾。
- 彈性伸縮:根據(jù) CPU、內存或自定義指標自動擴縮容。
- 服務發(fā)現(xiàn)與負載均衡:內置 Service 機制實現(xiàn)內部通信與外部暴露。
- 自我修復:節(jié)點宕機自動遷移 Pod,保證服務高可用。
- 配置與密鑰管理:安全地注入環(huán)境變量和敏感數(shù)據(jù)。
- 存儲編排:支持本地、云盤、NFS、Ceph 等多種存儲方案。
基礎環(huán)境準備
系統(tǒng)要求
我們將部署一個包含 1 個 Master 節(jié)點 + 2 個 Worker 節(jié)點的小型集群。建議每臺機器滿足以下最低配置:
| 角色 | CPU 核心數(shù) | 內存 | 存儲空間 |
|---|---|---|---|
| Master | 2 | 4GB | 20GB |
| Worker | 2 | 4GB | 20GB |
操作系統(tǒng)推薦使用 Ubuntu 22.04 LTS 或 CentOS 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
同步時間(重要?。?/h3>
Kubernetes 對時間同步非常敏感,推薦使用 chrony 或 ntp:
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:運行在所有節(jié)點上,負責 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
小貼士:生產環(huán)境中建議鎖定版本,避免因自動升級導致兼容性問題。
配置網絡與主機名
確保各節(jié)點之間可以通過主機名互相解析:
# 設置主機名(分別在 master、worker1、worker2 上執(zhí)行) 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 節(jié)點
現(xiàn)在我們正式初始化 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
參數(shù)說明:
--pod-network-cidr:Pod 網絡 CIDR,F(xiàn)lannel 默認使用10.244.0.0/16--apiserver-advertise-address:API Server 綁定的 IP 地址--control-plane-endpoint:控制平面訪問端點(便于未來擴展 HA)--upload-certs:上傳證書,便于后續(xù)加入其他控制節(jié)點
配置 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 節(jié)點狀態(tài)為 NotReady(因為還未安裝網絡插件)
安裝 Pod 網絡插件 —— Flannel
Kubernetes 需要 CNI 插件來實現(xiàn) Pod 間通信。我們選擇輕量級的 Flannel:
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
等待幾分鐘,再次檢查節(jié)點狀態(tài):
kubectl get nodes # STATUS 應變?yōu)?Ready
加入 Worker 節(jié)點
回到 Master 初始化輸出的最后一段,復制 kubeadm join 命令,在每個 Worker 節(jié)點上執(zhí)行:
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 上執(zhí)行:
kubectl get nodes # 應看到所有節(jié)點狀態(tài)為 Ready
集群拓撲結構圖
下面是一個典型的三節(jié)點 Kubernetes 集群架構圖:

該圖展示了客戶端請求如何通過負載均衡器進入 API Server,再由調度器分發(fā)到各個工作節(jié)點上的 Pod 中。每個 Pod 可以運行不同的服務,例如 Java 應用、數(shù)據(jù)庫、緩存等。
驗證集群功能
創(chuàng)建測試命名空間
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
訪問任一節(jié)點 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"]
構建并推送鏡像
在項目根目錄執(zhí)行:
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
創(chuàng)建 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
創(chuàng)建 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 ??
刷新頁面,你會發(fā)現(xiàn) Host 名稱變化,說明請求被負載均衡到了不同 Pod!
自動擴縮容演示
Kubernetes 支持根據(jù) CPU 使用率自動擴縮容:
# 創(chuàng)建 HPA(Horizontal Pod Autoscaler) kubectl autoscale deployment java-app --cpu-percent=50 --min=2 --max=10 -n test-app # 查看 HPA 狀態(tài) 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 是否觸發(fā)擴容:
watch kubectl get pods -n test-app
當 CPU 超過閾值,副本數(shù)會自動增加;壓力解除后,又會自動縮減。
服務發(fā)現(xiàn)與 ConfigMap
Kubernetes 內部服務可通過 DNS 自動發(fā)現(xiàn)。例如,我們的 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這樣,無需修改代碼或重建鏡像,即可動態(tài)調整配置!
使用 Secret 管理敏感信息
比如數(shù)據(jù)庫密碼:
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: passwordSecret 數(shù)據(jù)在 etcd 中是 Base64 編碼存儲,建議生產環(huán)境啟用加密或使用外部密鑰管理服務(如 HashiCorp Vault)。
監(jiān)控與日志收集
雖然不是本文重點,但生產環(huán)境不可或缺:
- Prometheus + Grafana:監(jiān)控集群資源與應用指標。
- EFK Stack(Elasticsearch + Fluentd + Kibana):集中式日志收集與分析。
- Loki + Promtail + Grafana:輕量級日志方案。
高可用架構進階(簡述)
上述部署為單 Master,生產環(huán)境建議:
- 多 Master + 負載均衡器:使用 HAProxy 或云廠商 LB。
- 外部 etcd 集群:獨立部署 etcd,提高穩(wěn)定性。
- 存儲持久化:使用 CSI 插件對接云存儲或 Ceph。
- Ingress Controller:如 Nginx Ingress、Traefik,統(tǒng)一管理外部訪問。

故障模擬與恢復
手動刪除一個 Pod
kubectl delete pod <pod-name> -n test-app
觀察 Deployment 是否自動重建新 Pod:
kubectl get pods -w -n test-app
Kubernetes 會確保副本數(shù)始終符合期望值。
模擬節(jié)點宕機
關閉一臺 Worker 節(jié)點:
sudo shutdown now
在 Master 上查看:
kubectl get nodes # 該節(jié)點狀態(tài)變?yōu)?NotReady kubectl get pods -o wide # 原本運行在該節(jié)點上的 Pod 會被標記為 Unknown 或 NodeLost
等待約 5 分鐘(默認驅逐超時),Pod 會自動遷移到健康節(jié)點!
常用調試命令匯總
# 查看所有資源 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' # 查看節(jié)點資源使用 kubectl top nodes kubectl top pods -n test-app # 描述資源詳情 kubectl describe pod <pod-name> -n test-app
常見問題與解決方案
Pod 一直處于 Pending 狀態(tài)
可能原因:
- 資源不足(CPU/Memory)
- 節(jié)點選擇器不匹配
- PVC 未綁定
解決方法:
kubectl describe pod <pod-name> # 查看 Events 部分
ImagePullBackOff
鏡像拉取失敗:
- 檢查鏡像名稱是否正確
- 私有倉庫需配置
imagePullSecrets - 網絡策略限制
kubectl get events --field-selector reason=Failed
CrashLoopBackOff
容器反復崩潰:
- 檢查啟動命令是否正確
- 查看日志:
kubectl logs <pod> --previous - 檢查探針配置是否過于嚴格
Java 開發(fā)者專屬技巧
在 Java 應用中讀取 Pod 信息
Kubernetes 會將 Pod 信息通過 Downward API 注入環(huán)境變量或文件:
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.nodeNameJava 代碼中讀?。?/p>
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:健康狀態(tài)/actuator/metrics:性能指標/actuator/env:環(huán)境變量
配合 Prometheus 可采集 JVM 指標:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>訪問 http://<service>/actuator/prometheus 即可獲取指標數(shù)據(jù)。
使用 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 環(huán)境
? 安裝 containerd + kubeadm 工具鏈
? 初始化 Master 并加入 Worker 節(jié)點
? 部署 CNI 網絡插件
? 編寫、構建、推送 Java 鏡像
? 通過 Deployment + Service 部署應用
? 配置自動擴縮容、健康檢查、服務發(fā)現(xiàn)
? 學習常用調試與排錯技巧
Kubernetes 的世界遠不止于此,但你已經打下了堅實的基礎。下一步可以探索:
- StatefulSet 管理有狀態(tài)應用(如 MySQL、ZooKeeper)
- Ingress 實現(xiàn)域名路由
- NetworkPolicy 實現(xiàn)網絡安全隔離
- Operator 模式自動化復雜應用管理
記?。篕ubernetes 的學習曲線陡峭,但回報巨大。堅持實踐,你將成為云原生時代的架構大師!
最后的話
希望這篇長文能幫助你在 Linux 上成功部署 Kubernetes,并愉快地運行 Java 應用。技術世界日新月異,但基礎永遠是王道。動手實踐、不斷試錯、持續(xù)學習 —— 這才是工程師的成長之道。
以上就是Linux環(huán)境下部署Kubernetes集群的全過程的詳細內容,更多關于Linux部署Kubernetes集群的資料請關注腳本之家其它相關文章!
相關文章
Apache JMeter 5.5 下載安裝及設置中文圖文教程
這篇文章主要介紹了Apache JMeter 5.5 下載安裝以及設置中文教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-02-02
CentOS 7下部署php7.1和開啟MySQL擴展的方法教程
這篇文章主要給大家介紹了關于CentOS 7下部署php7.1和開啟MySQL擴展的方法教程,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學習價值,需要的朋友們下面來一起看看吧。2017-07-07
詳解阿里云CentOS Linux服務器上用postfix搭建郵件服務器
本篇文章主要介紹了詳解阿里云CentOS Linux服務器上用postfix搭建郵件服務器,具有一定的參考價值,感興趣的小伙伴們可以參考一下。2016-12-12

