1. 概念
Pod 是 Kubernetes 項目里定義的最小可調(diào)度單元,是 Kubernetes 對應(yīng)用程序的抽象。
Pod 組成可以是一個或者多個容器,屬于同一個 Pod 的容器會共享:
- 網(wǎng)絡(luò)資源
- 相同的 IP
- 存儲
- 應(yīng)用到 Pod 的自定義配置
2. Pod 的模型
根據(jù)組成 Pod 的容器數(shù)量可以將 Pod 分為兩種類型:
單容器模型:Pod是Kubernetes可識別的最小對象,Kubernetes管理調(diào)度Pod而不是直接管理容器,所以即使只有一個容器也需要封裝到Pod里
多容器模型:在這個模型中,Pod可以容納多個緊密關(guān)聯(lián)的容器以共享Pod里的資源。這些容器作為單一的,凝聚在一起的服務(wù)單元工作。比如:在Pod中有一個應(yīng)用程序容器和一個日志記錄容器。日志記錄容器的唯一工作是從應(yīng)用程序容器中提取日志。將兩個容器放置同一個Pod里可消除額外的通信時間,因為它們位于同一個"主機",因此所有內(nèi)容都是本地的并且它們共享所有資源,就跟在同一臺物理服務(wù)器上執(zhí)行這些操作一樣。
Pod 本身不具備調(diào)節(jié)功能,如果 Pod 所在的節(jié)點發(fā)生故障,Pod 是不能自動調(diào)度到其他節(jié)點,需要使用控制器來完成 pod 的調(diào)度問題。Deployment就是最基礎(chǔ)的控制器。通常我們都是在定義的控制器的配置里通過PodTemplate定義要控制的Pod,讓控制器和所管控的Pod一起被創(chuàng)建出來。
3. Pod 的生命周期
Pod的生命周期有5個階段:
- Pending:pending 表示當(dāng) pod 中至少存在一個容器未創(chuàng)建的情況。
- Running:容器已經(jīng)創(chuàng)建完成,并且Pod已經(jīng)被調(diào)度到了一個Node上。此時Pod內(nèi)的容器正在運行,或者正在啟動或重新啟動。
- Succeeded:Pod中的所有容器均已成功終止,并且不會重新啟動。
- Faild:所有容器均已終止,至少有一個容器發(fā)生了故障。失敗的容器以非零狀態(tài)退出。
- Unknown:無法獲得Pod的狀態(tài)。
4. Pod 的 yaml 文件解析
Kubernetes 里所有的 API 對象都由四部分組成:
- apiVersion: 當(dāng)前使用的 Kubernetes 的 API 版本
- kind:想創(chuàng)建的對象的種類
- metadata:元數(shù)據(jù),用來唯一表示當(dāng)前的對象,比如 name,namespace 等
- spec:Pod 的指定配置,例如鏡像名稱、容器名稱、數(shù)據(jù)卷等
apiVersion,kind 和 metadata 是必填字段,適用于所有 Kubernetes 對象,而不僅僅是 pod。spec 里指定的內(nèi)容(spec 也是必需字段)會因?qū)ο蠖悺?/p>
Pod 文件示例:
apiVersion: "api version"
kind: "Object to create"
metadata:
name: "Pod name"
labels:
app: "label value"
spec:
containers:
- name: "container name"
image: "image to use for container"
5. 示例:
5.1 單容器 Pod
apiVersion: v1 # kubernetes 的 API 版本
kind: Pod # 創(chuàng)建的對象為 Pod
metadata: # 元數(shù)據(jù)
name: first-pod # pod 的名稱
labels:
app: myapp
spec: # 指定的配置信息
containers:
- name: my-first-pod #容器名
image: nginx # 指定的鏡像
將 Pod 的清單文件部署到本地的 Kubernetes 集群中:
kubectl create -f pod-1.yaml
查看 Pod 的運行情況:
kubectl get pods
執(zhí)行命令查看容器情況:
kubectl exec first-pod -- service nginx status
在Pod里執(zhí)行service nginx status指令,類似docker exec命令。
刪除創(chuàng)建的 Pod
kubectl delete pod first-pod
5.2 多容器的 Pod
一個擁有兩個容器的Pod,這些容器相互協(xié)作作為一個實體工作。其中一個容器每10秒將當(dāng)前日期寫入一個文件,而另一個Nginx容器則為我們展示這些日志。
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
volumes:
- name: shared-data-logs # 為 Pod 中創(chuàng)建一個共享的數(shù)據(jù)卷
emptyDir: {}
containers:
- name: container-writing-datas # 第一個容器的名稱
image: alpine
command: ["/bin/sh"]
args: ["-c", "while true; do date >> /var/log/output.txt; sleep 10; done"] # 每10秒寫入當(dāng)前時間
volumeMounts:
- name: shared-data-logs
mountPath: /var/log
- name: container-serving-dates # 第二個容器的名字
image: nginx:1.7.9 # 鏡像
ports:
- containerPort: 80 # 定義容器提供服務(wù)的端口
volumeMounts:
- name: shared-data-logs
mountPath: /usr/share/nginx/html
通過運行如下命令連接到Nginx容器里:
kubectl exec -it multi-container-pod -c container-serving-dates -- bash
在容器內(nèi)運行curl'http://localhost:80/output.txt',它應(yīng)該返回時間日志文件的內(nèi)容給我們。
5.3 SideCar模式
可以在一個 Pod 中按照順序啟動一個或多個輔助容器,來完成一些獨立于主進程(主容器)之外的工作,完成工作后這些輔助容器會依次退出,之后主容器才會啟動,這種容器設(shè)計模式叫做 sidecar。
比如對于前端Web應(yīng)用,如果把構(gòu)建后的Js項目放到Nginx鏡像的/usr/share/nginx/html目錄下,Nginx和Js應(yīng)用做成一個鏡像運行容器,每次應(yīng)用有更新或者Nginx要做升級、更新配置操作都需要重新做一個鏡像,非常麻煩。
有了Pod之后,這樣的問題就很容易解決了。我們可以把前端Web應(yīng)用和Nginx分別做成鏡像,然后把它們作為一個Pod里的兩個容器"組合"在一起。這個Pod的配置文件如下所示:
apiVersion: v1
kind: Pod
metadata:
name: web-2
spec:
initContainers:
- image: kevinyan/front-app:v2
name: front
command: ["cp", "/www/application/*", "/app"]
volumeMounts:
- mountPath: /app
name: app-volume
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80 # 定義容器提供服務(wù)的端口
volumeMounts:
- mountPath: /usr/share/nginx/html
name: app-volume
volumes:
- name: app-volume
emptyDir: {}
所有spec.initContainers定義的容器,都會比spec.containers定義的用戶容器先啟動。并且,Init容器會按順序逐一啟動,直到它們都啟動并且退出了,用戶容器才會啟動。所以,這個Init類型的容器啟動后,執(zhí)行了一句"cp /www/application/* /app",把應(yīng)用包拷貝到"/app"目錄下,然后退出。這個"/app"目錄,掛載了一個名叫app-volume 的Volume。接下來Nginx容器,同樣聲明了掛載app-volume到自己的"/usr/share/nginx/html"目錄下。由于這個Volume 是被Pod里的容器共享的所以等Nginx容器啟動時,它的目錄下就一定會存在前端項目的文件。這個文件正是上面的Init容器啟動時拷貝到Volume里面的。