目錄
一、 初始化容器 InitContainer
1. InitContainer 的基本概念
2.?延遲指定時間后啟動
3.?使用初始化容器修改內核參數
4.?等待依賴的服務啟動后再啟動應用
5.?pause 容器
二、?臨時容器 Ephemeral Containers
1.?臨時容器的概念
2.?臨時容器的使用示例
三、?自動擴縮容 HPA
1.?什么是 HPA
2.?HPA 實踐步驟(以 Nginx 為例)
一、 初始化容器 InitContainer
首先來看初始化容器,顧名思義,初始化容器是用來進行初始化操作的。很多情況下,程序的啟動需要依賴各類配置、資源。但是又不能繼承在原有的啟動命令或者鏡像當中,因為程序的鏡像可能并沒有加載配置命令,此時 InitContainer 就起了很大的作用。
1. InitContainer 的基本概念
InitContainer 是 Kubernetes 的初始化容器(也可稱之為 Init 容器),它是一種特殊的容器,在 Pod 內的應用容器啟動之前運行,可以包括一些應用鏡像中不存在的使用工具和安裝腳本,用以在程序啟動時進行初始化,比如創建文件、修改內核參數、等待依賴程序啟動等。
每個 Pod 中可以包含多個容器,同時 Pod 也可以有一個或多個先于應用程序啟動的 Init 容器:
- 在 Pod 定義中,
initContainers
?與?containers
?同級,按順序逐個執行;- 當所有的 Init 容器運行完成時,Kubernetes 才會啟動 Pod 內的普通容器。
Init 容器與普通容器的核心差異:
- 總是運行到完成:Init 容器必須執行完畢,才會啟動后續容器。
- 串行執行:上一個 Init 容器運行完成后,才會啟動下一個。
- 重啟策略關聯:若 Init 容器失敗,Kubernetes 會不斷重啟 Pod(除非 Pod 的?
restartPolicy
?為?Never
)。
為 Pod 設置 Init 容器時,需在?spec
?中添加?initContainers
?字段(與?containers
?同級),配置方式與普通容器類似,但?Init 容器不支持?lifecycle
、livenessProbe
、readinessProbe
、startupProbe
(因需在 Pod 就緒前運行完成)。
2.?延遲指定時間后啟動
需求:讓應用容器啟動前,Init 容器休眠 15 秒。
YAML 定義(init01.yml
):
apiVersion: v1 kind: Pod metadata:creationTimestamp: nulllabels:run: initc01name: initc01 spec:terminationGracePeriodSeconds: 0containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: n1resources: {}initContainers:- name: initc01image: nginx:1.7.9imagePullPolicy: IfNotPresentcommand: ["sh", "-c", "sleep 15"] # 休眠15秒dnsPolicy: ClusterFirstrestartPolicy: Never status: {}
部署與觀察:
# 創建 Pod kubectl create -f init01.yml # 持續查看 Pod 狀態(Init 階段會持續 15 秒) kubectl get pod # 初始狀態:STATUS 為 Init:0/1 # 15秒后,STATUS 變為 PodInitializing → Running
3.?使用初始化容器修改內核參數
需求:在 Init 容器中修改物理機內核參數(vm.swappiness=0
,減少 swap 使用)。
關鍵說明:
容器默認無法修改內核參數,需通過?securityContext.privileged: true
?賦予特權。
YAML 定義(init02.yml
):
apiVersion: v1 kind: Pod metadata:creationTimestamp: nulllabels:run: initc02name: initc02 spec:terminationGracePeriodSeconds: 0containers:- image: nginx:1.7.9imagePullPolicy: IfNotPresentname: n1resources: {}initContainers:- name: initc02image: alpine # 選擇輕量鏡像imagePullPolicy: IfNotPresentcommand: ["sh", "-c", "/sbin/sysctl -w vm.swappiness=0"] # 修改內核參數securityContext:privileged: true # 賦予特權dnsPolicy: ClusterFirstrestartPolicy: Never status: {}
驗證:
# 部署 kubectl apply -f init02.yml # 查看 Pod 狀態 kubectl get pod # 驗證內核參數是否修改成功 kubectl exec -it initc02 -- cat /proc/sys/vm/swappiness # 輸出應為 0
4.?等待依賴的服務啟動后再啟動應用
需求:Web 服務(Nginx)依賴 Redis 和 MySQL 服務,需等兩者就緒后再啟動。
(1) 創建帶 Init 容器的 Pod(myapp.yml
):
Init 容器通過?nslookup
?檢查依賴服務的 DNS 解析(即服務是否就緒),未就緒則循環等待。
apiVersion: v1 kind: Pod metadata:name: nginxlabels:app: nginx spec:containers:- name: nginximage: nginx:1.7.9ports:- containerPort: 80initContainers:- name: init-redisimage: busybox:1.28command: ['sh', '-c', 'until nslookup redis-server; do echo waiting for redis; sleep 2; done;']- name: init-mysqlimage: busybox:1.28command: ['sh', '-c', 'until nslookup mysql-server; do echo waiting for mysql; sleep 2; done;']
部署后觀察初始狀態:
kubectl create -f myapp.yml kubectl get pod # 狀態為 Init:0/2(兩個 Init 容器均未完成)
(2)?創建第一個依賴服務
apiVersion: apps/v1 kind: Deployment metadata:labels:app: redisname: redis spec:replicas: 1selector:matchLabels:app: redistemplate:metadata:labels:app: redisspec:containers:- image: redis:5.0imagePullPolicy: IfNotPresentname: redis --- apiVersion: v1 kind: Service metadata:labels:app: redisname: redis-service spec:ports:- port: 6379protocol: TCPtargetPort: 6379selector:app: redistype: NodePort
部署與驗證:
kubectl create -f redis-deployment.yml kubectl get svc # 查看 redis-service 的 NodePort kubectl get pod # Redis Pod 啟動后,Init 容器狀態變為 Init:1/2
(3)?創建第二個依賴服務
apiVersion: apps/v1 kind: Deployment metadata:labels:app: mysqlname: mysql spec:replicas: 1selector:matchLabels:app: mysqltemplate:metadata:labels:app: mysqlspec:containers:- env:- name: MYSQL_ROOT_PASSWORDvalue: 'moonfdd'image: 'mysql:8.0'imagePullPolicy: IfNotPresentname: mysql --- apiVersion: v1 kind: Service metadata:labels:app: mysqlname: mysql-service spec:ports:- port: 3306protocol: TCPtargetPort: 3306selector:app: mysqltype: NodePort
部署后最終狀態:
kubectl create -f mysql-deployment.yml kubectl get pod # Nginx Pod 狀態變為 Running(兩個 Init 容器均完成,依賴服務就緒)
(4)?完成 MySQL 服務定義
name: mysqlvolumeMounts:- mountPath: /var/lib/mysqlname: volvvolumes:- hostPath:path: /root/k8s/moonfdd/mysql/var/lib/mysql # 主機路徑,需提前創建type: DirectoryOrCreatename: volv --- apiVersion: v1 kind: Service metadata:labels:app: mysqlname: mysql-service spec:ports:- port: 3306protocol: TCPtargetPort: 3306selector:app: mysqltype: NodePort
部署與驗證:
kubectl create -f mysql-deployment.yml # 輸出:deployment.apps/mysql created、service/mysql-service created kubectl get svc # 查看 mysql-service 的 NodePort(如 3306:31452/TCP) kubectl get pod # 等待 MySQL Pod 啟動后,Nginx Pod 的 Init 容器完成,狀態變為 Running
5.?pause 容器
在 Kubernetes 中,pause 容器是每個 Pod 的 “基礎容器”,并非暫停執行,而是負責:
- 共享網絡命名空間:Pod 內所有容器共享同一個 IP、端口空間,可通過?
localhost
?通信。- 維持網絡接口:為 Pod 配置網絡出口,使容器能訪問外部網絡。
- 保證穩定性:即使業務容器停止,pause 容器運行時,Pod 網絡命名空間仍保留。
- 生命周期綁定:pause 容器是 Pod 第一個啟動的容器,生命周期與 Pod 綁定(鏡像極小,約 700KB,運行?
/pause
?無限循環)。
Pause 容器的實現邏輯
Pod 內多個容器共享網絡的核心是?Infra 容器(即 pause 容器):
- Infra 容器先啟動,創建 Pod 的 Network Namespace。
- 業務容器通過?
Join Namespace
?加入 Infra 的網絡命名空間。- 所有容器看到的網絡設備、IP、MAC 完全一致,共享 Pod 級網絡資源。
驗證 pause 容器存在:
# 查看 Nginx Pod 所在節點 kubectl get pod -o wide # 在節點上查看容器(過濾 Nginx Pod 相關容器) docker ps | grep <pod-name> # 輸出中會包含: # registry.aliyuncs.com/google_containers/pause:3.6 # pause 容器 # nginx 容器...
二、?臨時容器 Ephemeral Containers
生產環境中,業務鏡像通常不預裝調試工具(如?curl
、wget
、net-tools
),導致排查問題時無法直接執行命令。Kubernetes 1.16+ 引入?臨時容器,支持動態注入調試工具,無需修改業務鏡像。
1.?臨時容器的概念
- 用途:臨時附加到 Pod,用于在線調試(如診斷網絡、查看進程),不參與業務運行。
- 特性:
- 無自動重啟,狀態不影響業務容器。
- 不支持?
ports
、livenessProbe
、readinessProbe
、resources
?等字段(僅調試用)。- 通過特殊 API 創建(非?
pod.spec
),無法用?kubectl edit
?修改,Pod 重啟后自動銷毀。- 場景:業務容器無 Shell、調試工具缺失時,快速注入?
busybox
?等鏡像進行診斷。
2.?臨時容器的使用示例
(1)?創建待調試的 Tomcat Pod
apiVersion: v1 kind: Pod metadata:name: tomcat-testnamespace: defaultlabels:app: tomcat spec:containers:- name: tomcat-javaports:- containerPort: 8080image: kubeguide/tomcat-app:v1imagePullPolicy: IfNotPresent
(2)?部署并查看 Pod
kubectl apply -f pod-tomcat.yml kubectl get pod # 狀態:Running(1/1)
(3)?注入臨時容器
kubectl debug -it tomcat-test \--image=busybox:1.28 \--target=tomcat-java
tomcat-test
:目標 Pod 名稱。--target=tomcat-java
:指定注入到哪個業務容器的命名空間(共享網絡、PID 等)。--image=busybox:1.28
:臨時容器使用的鏡像(含常用調試工具)。
(4)?驗證臨時容器
# 檢查 Tomcat 端口 netstat -tunlp | grep 8080 # 測試網絡連通性 wget http://localhost:8080
三、?自動擴縮容 HPA
1.?什么是 HPA
- 作用:根據資源利用率或自定義指標,動態擴縮 Pod 數量(僅支持可擴縮的資源,如 Deployment,不支持 DaemonSet)。
- 原理:HPA 控制器定期(默認 15 秒)查詢 Metrics Server,對比實際指標與目標值,調整副本數。
2.?HPA 實踐步驟(以 Nginx 為例)
(1)?部署帶資源請求的 Nginx Deployment
apiVersion: apps/v1 kind: Deployment metadata:name: nginx-serverlabels:name: nginx-server spec:replicas: 2 # 初始副本數selector:matchLabels:app: nginxtemplate:metadata:labels:app: nginxspec:containers:- name: nginxresources:requests: # 必須配置 requests,否則 Metrics Server 無法采集cpu: 10m # 10 毫核(0.01 CPU)image: nginx:1.7.9ports:- name: nginxcontainerPort: 80
(2)?部署 Deployment
kubectl apply -f nginx-deployment.yml kubectl get deployment # 確認初始副本數為 2
(3)?安裝 Metrics Server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
驗證 Metrics Server 運行
kubectl get pods -n kube-system -l k8s-app=metrics-server
(4)?創建 HPA 規則
kubectl autoscale deployment nginx-server \--cpu-percent=50 \ # 目標 CPU 利用率 50%--min=2 \ # 最小副本數--max=10 # 最大副本數
(5)?模擬負載,觸發擴縮容
# 進入 Nginx Pod,或在節點上運行: stress --cpu 2 --timeout 600 # 模擬 2 個 CPU 核心滿載,持續 10 分鐘 # 觀察 HPA 狀態: kubectl get hpa # CPU 利用率超過 50% 后,副本數會逐步增加到 max(10)。 # 停止壓測后,副本數會回落到 min(2)。