1 Pod
很少在 Kubernetes 中直接創(chuàng)建一個(gè)Pod,甚至是單實(shí)例(Singleton)的 Pod。 這是因?yàn)?Pod 被設(shè)計(jì)成了相對臨時(shí)性的、用后即拋的一次性實(shí)體,不支持高可用。一般使用工作負(fù)載資源來創(chuàng)建和管理多個(gè) Pod。 資源的控制器能夠處理副本的管理、上線,并在 Pod 失效時(shí)提供自愈能力。
能夠管理一個(gè)或者多個(gè) Pod 的工作負(fù)載資源有:
- Deployment
- ReplicaSet
- DaemonSet
- ReplicationController
1.1 Pod中的內(nèi)容
Pod 類似于共享namesapce、cgroup、文件系統(tǒng)卷的一組 Docker 容器。創(chuàng)建Pod時(shí),除了會(huì)創(chuàng)建1個(gè)或多個(gè)工作容器外,還會(huì)額外在Pod中創(chuàng)建Pod容器,Pod容器用于實(shí)現(xiàn)k8s的各種功能。
1.2 Pod模板
apiVersion: batch/v1
kind: Job
metadata:
name: hello
spec:
template:
# 這里是 Pod 模版
spec:
containers:
- name: hello
image: busybox
command: ['sh', '-c', 'echo "Hello, Kubernetes!" && sleep 3600']
restartPolicy: OnFailure
1.3 Pod基本操作
1.3.1 創(chuàng)建
kubectl create 或 apply -f XXX.yaml
1.3.2 查詢
查詢基礎(chǔ)信息
kubectl get pods|pod名字
kubectl get pods -o wide
查詢詳細(xì)信息
kubectl describe pod pod名字
查詢Pod的標(biāo)簽
kubectl describe pod pod名字 --show-labels
1.3.3 刪除
kubectl delete pod pod名字
kubectl delete pod --all
1.3.4 更新
kubectl apply -f XXX.yaml
2 ReplicationController
ReplicationController 確保在任何時(shí)候都有特定數(shù)量的 Pod 副本處于運(yùn)行狀態(tài)。 換句話說,ReplicationController 確保一個(gè) Pod 或一組同類的 Pod 總是可用的。
RC會(huì)根據(jù)spec.selector將當(dāng)前已經(jīng)運(yùn)行的Pod加入RC,當(dāng) Pod 數(shù)量過多時(shí),ReplicationController 會(huì)終止多余的 Pod。當(dāng) Pod 數(shù)量太少時(shí),ReplicationController 將會(huì)啟動(dòng)新的 Pod。
ReplicationController在新版本中被ReplicaSet所取代,通常使用Deployment來部署ReplicaSet,而不是直接使用ReplicaSet。
2.1 RC模板
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx
spec:
replicas: 3
selector:
app: nginx
template:
metadata:
name: nginx
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
#參數(shù)解釋
spec.replicas: 副本數(shù)
spec.selector: 選擇器,根據(jù)選擇的條件篩選Pod的labels,將符合的Pod加入RC
spec.template: Pod的模板
spec.template.metadata: Pod的元數(shù)據(jù)
spec.template.spec: Pod的具體屬性信息
2.2 RC基本操作
2.2.1 創(chuàng)建
kubectl create 或 apply -f XXX.yaml
2.2.2 查詢
查詢基礎(chǔ)信息
kubectl get rc
kubectl get rc -o wide
查詢詳細(xì)信息
kubectl describe rc rc名字
2.2.3 刪除
kubectl delete rc rc名字
kubectl delete rc --all
2.2.4 調(diào)整副本數(shù)
kubectl scale rc rc名字 --replicas=num
3 Service
3.1 Service概述
問題:
Pod創(chuàng)建完成后,如何訪問Pod呢?直接訪問Pod會(huì)有如下幾個(gè)問題:
- Pod會(huì)隨時(shí)被Deployment這樣的控制器刪除重建,那訪問Pod的結(jié)果就會(huì)變得不可預(yù)知。
- Pod的IP地址是在Pod啟動(dòng)后才被分配,在啟動(dòng)前并不知道Pod的IP地址。
- 應(yīng)用往往都是由多個(gè)運(yùn)行相同鏡像的一組Pod組成,逐個(gè)訪問Pod也變得不現(xiàn)實(shí)
解決方法:
Kubernetes中的Service對象就是用來解決上述Pod訪問問題的。Service有一個(gè)固定IP地址Cluster IP,Service將訪問它的流量轉(zhuǎn)發(fā)給Pod,具體轉(zhuǎn)發(fā)給哪些Pod通過Label來選擇,而且Service可以給這些Pod做負(fù)載均衡。
3.2 K8s中的3種IP地址
3.2.1 Node IP
Node物理節(jié)點(diǎn)的IP地址
3.2.2 Cluster IP
Service的IP地址,此為虛擬IP地址。外部網(wǎng)絡(luò)無法ping通,只有kubernetes集群內(nèi)部訪問使用。
- Cluster IP僅僅作用于Kubernetes Service這個(gè)對象,并由Kubernetes管理和分配P地址
- Cluster IP無法被ping,他沒有一個(gè)“實(shí)體網(wǎng)絡(luò)對象”來響應(yīng)
- Cluster IP只能結(jié)合Service Port組成一個(gè)具體的通信端口,單獨(dú)的Cluster IP不具備通信的基礎(chǔ),并且他們屬于Kubernetes集群這樣一個(gè)封閉的空間。
- 在不同Service下的pod節(jié)點(diǎn)在集群間相互訪問可以通過Cluster IP
3.2.3 Pod IP
每個(gè)Pod的IP地址
- 同Service下的pod可以直接根據(jù)PodIP相互通信
- 不同Service下的pod在集群間pod通信要借助于 cluster ip
- pod和集群外通信,要借助于node ip
3.2.4 3種IP的訪問關(guān)系
Cluster地址和pod地址在不同網(wǎng)段,Cluster地址為虛擬地址,不配在pod上或主機(jī)上,外部訪問時(shí),先到Node節(jié)點(diǎn)網(wǎng)絡(luò)(所有Node開放同一個(gè)端口號(hào)),再轉(zhuǎn)到service網(wǎng)絡(luò),最后代理給pod網(wǎng)絡(luò)。

3.3 Service的類型
Service的類型決定了如何向外暴露Service
3.3.1 ClusterIP

通過集群的內(nèi)部 IP 暴露服務(wù),選擇該值時(shí)服務(wù)只能夠在集群內(nèi)部訪問。 這也是默認(rèn)的 ServiceType。
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx
name: nginx-clusterip
spec:
ports:
- name: service0
port: 8080 # 訪問Service的端口
protocol: TCP # 訪問Service的協(xié)議,支持TCP和UDP
targetPort: 80 # Service訪問目標(biāo)容器的端口,此端口與容器中運(yùn)行的應(yīng)用強(qiáng)相關(guān),如本例中nginx鏡像默認(rèn)使用80端口
selector: # 標(biāo)簽選擇器,Service通過標(biāo)簽選擇Pod,將訪問Service的流量轉(zhuǎn)發(fā)給Pod,此處選擇帶有 app:nginx 標(biāo)簽的Pod
app: nginx
type: ClusterIP # Service的類型,ClusterIP表示在集群內(nèi)訪問
clusterIP: IP Address # 指定Service使用的ClusterIP,默認(rèn)為隨機(jī)分配
3.3.2 NodePort

通過每個(gè)節(jié)點(diǎn)上的 IP 和靜態(tài)端口(NodePort)暴露服務(wù)。 NodePort 服務(wù)會(huì)路由到自動(dòng)創(chuàng)建的 ClusterIP 服務(wù)。 通過請求 <Node節(jié)點(diǎn) IP>:<節(jié)點(diǎn)端口>,你可以從集群的外部訪問一個(gè) NodePort 服務(wù)。
NodePort的端口范圍默認(rèn)是30000-32767,可以修改
/etc/kubernetes/manifests/kube-apiserver.yaml文件從而修改端口范圍。
NodePort類型的Service例子:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
ports:
- port: 80
targetPort: 80
nodePort: 30007
參數(shù)解釋:
spec.ports[*].port: Cluster IP的端口
spec.ports[*].targetPort: Pod IP的端口
spec.ports[*].nodePort: Node IP的端口
spec.selector: 選擇器,根據(jù)Pod的labels,將Pod加入到Service
3.3.3 LoadBalancer
3.3.4 ExternalName
3.4 負(fù)載均衡模式
Service默認(rèn)的負(fù)載均衡模式是RR輪詢模式,可以通過修改spec.sessionAffinity為ClientIP來實(shí)現(xiàn)源地址會(huì)話保持??梢栽O(shè)置會(huì)話保持的超時(shí)時(shí)間(默認(rèn)時(shí)間是10800s),設(shè)置spec.sessionAffinityConfig.clientIP.timeoutSeconds 的值。
apiVersion: v1
kind: Service
metadata:
...
spec:
...
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10
type: NodePort
4 Deployments
4.1 Deployments概述
Deployment 管理 ReplicaSet,并向 Pod 提供聲明式的更新以及許多其他有用的功能,
- 創(chuàng)建 Deployment 以將 ReplicaSet 上線。 ReplicaSet 在后臺(tái)創(chuàng)建 Pods。 檢查 ReplicaSet 的上線狀態(tài),查看其是否成功。
- 通過更新 Deployment 的 PodTemplateSpec,聲明 Pod 的新狀態(tài)。 新的 ReplicaSet 會(huì)被創(chuàng)建,Deployment 以受控速率將 Pod 從舊 ReplicaSet 遷移到新 ReplicaSet。 每個(gè)新的 ReplicaSet 都會(huì)更新 Deployment 的修訂版本。
- 如果 Deployment 的當(dāng)前狀態(tài)不穩(wěn)定,回滾到較早的 Deployment 版本。 每次回滾都會(huì)更新 Deployment 的修訂版本。
- 擴(kuò)大 Deployment 規(guī)模以承擔(dān)更多負(fù)載。
- 暫停 Deployment以應(yīng)用對 PodTemplateSpec 所作的多項(xiàng)修改, 然后恢復(fù)其執(zhí)行以啟動(dòng)新的上線版本。
- 使用 Deployment 狀態(tài)來判定上線過程是否出現(xiàn)停滯。
- 清理較舊的不再需要的 ReplicaSet。
4.2 Deployments模板
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
#參數(shù)解釋
spec.replicas: 副本數(shù)
spec.selector: 選擇器,根據(jù)選擇的條件篩選Pod的labels,將符合的Pod加入deployment
spec.template: Pod的模板
spec.template.metadata: Pod的元數(shù)據(jù)
spec.template.spec: Pod的具體屬性信息
4.3 Deployments創(chuàng)建流程

首先根據(jù)文件創(chuàng)建deployment,加入--record參數(shù)來記錄歷史,方便在回滾時(shí)查看針對每個(gè) Deployment 修訂版本所執(zhí)行過的命令。
kubectl apply -f nginx/nginx-deployment.yaml --record
Deployment會(huì)創(chuàng)建ReplicaSet,ReplicaSet負(fù)責(zé)啟動(dòng)Pods。ReplicaSet 的名稱始終被格式化為[Deployment名稱]-[隨機(jī)字符串]。 其中的隨機(jī)字符串是使用 pod-template-hash 作為種子隨機(jī)生成的。
Pod-template-hash 標(biāo)簽
Deployment 控制器將pod-template-hash標(biāo)簽添加到 Deployment 所創(chuàng)建或收留的每個(gè)ReplicaSet 。
此標(biāo)簽可確保 Deployment 的子 ReplicaSets 不重疊。 標(biāo)簽是通過對 ReplicaSet 的PodTemplate進(jìn)行哈希處理。 所生成的哈希值被添加到ReplicaSet 選擇算符、Pod 模板標(biāo)簽,并存在于在 ReplicaSet 可能擁有的任何現(xiàn)有 Pod 中。
4.4 Deployments升級流程
僅當(dāng) Deployment Pod 模板(即
.spec.template)發(fā)生改變時(shí),例如模板的標(biāo)簽或容器鏡像被更新, 才會(huì)觸發(fā) Deployment 上線。 其他更新(如對 Deployment 執(zhí)行擴(kuò)縮容的操作)不會(huì)觸發(fā)上線動(dòng)作。
Deployment 控制器每次注意到新的 Deployment 時(shí),都會(huì)創(chuàng)建一個(gè) ReplicaSet 以啟動(dòng)所需的 Pods。 如果更新了 Deployment,則控制標(biāo)簽匹配 .spec.selector 但模板不匹配 .spec.template 的 Pods 的現(xiàn)有 ReplicaSet 被縮容。最終,新的 ReplicaSet 縮放為 .spec.replicas 個(gè)副本, 所有舊 ReplicaSets 縮放為 0 個(gè)副本。
當(dāng) Deployment 正在上線時(shí)被更新,Deployment 會(huì)針對更新創(chuàng)建一個(gè)新的 ReplicaSet 并開始對其擴(kuò)容,之前正在被擴(kuò)容的 ReplicaSet 會(huì)被翻轉(zhuǎn),添加到舊 ReplicaSets 列表 并開始縮容。
例如,假定你在創(chuàng)建一個(gè) Deployment 以生成 nginx:1.14.2 的 5 個(gè)副本,但接下來 更新 Deployment 以創(chuàng)建 5 個(gè) nginx:1.16.1 的副本,而此時(shí)只有 3 個(gè)nginx:1.14.2 副本已創(chuàng)建。在這種情況下,Deployment 會(huì)立即開始?xì)⑺?3 個(gè) nginx:1.14.2 Pods, 并開始創(chuàng)建 nginx:1.16.1 Pods。它不會(huì)等待 nginx:1.14.2 的 5 個(gè)副本都創(chuàng)建完成 后才開始執(zhí)行變更動(dòng)作。
升級操作,兩種方式:
- 直接使用命令行更新鏡像版本
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
- 使用edit在線編輯
kubectl edit deployment.v1.apps/nginx-deployment
Deployment可以通過
maxSurge和maxUnavailable兩個(gè)參數(shù)控制升級過程中同時(shí)重新創(chuàng)建Pod的比例,這在很多時(shí)候是非常有用,配置如下所示。
spec:
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
- maxSurge:與Deployment中spec.replicas相比,可以有多少個(gè)Pod存在,默認(rèn)值是25%,比如spec.replicas為 4,那升級過程中就不能超過5個(gè)Pod存在,即按1個(gè)的步伐升級,實(shí)際升級過程中會(huì)換算成數(shù)字,且換算會(huì)向上取整。這個(gè)值也可以直接設(shè)置成數(shù)字。
- maxUnavailable:與Deployment中spec.replicas相比,可以有多少個(gè)Pod失效,也就是刪除的比例,默認(rèn)值是25%,比如spec.replicas為4,那升級過程中就至少有3個(gè)Pod存在,即刪除Pod的步伐是1。同樣這個(gè)值也可以設(shè)置成數(shù)字。
4.5 Deployments回滾流程
Deployment之所以能如此容易的做到回滾,是因?yàn)镈eployment是通過ReplicaSet控制Pod的,升級后之前ReplicaSet都一直存在,Deployment回滾做的就是使用之前的ReplicaSet再次把Pod創(chuàng)建出來。Deployment中保存ReplicaSet的數(shù)量可以使用revisionHistoryLimit參數(shù)限制,默認(rèn)值為10。
查看Deployment 修訂歷史
kubectl rollout history deployment nginx-deployment
輸出
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
1 kubectl apply --filename=nginx/nginx-deployment.yaml --record=true
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
查看第n次的修訂歷史
kubectl rollout history deployment nginx-deployment --revision=n
輸出
deployment.apps/nginx-deployment with revision #2
Pod Template:
Labels: app=nginx
pod-template-hash=559d658b74
Annotations: kubernetes.io/change-cause: kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
Containers:
nginx:
Image: nginx:1.16.1
Port: 80/TCP
Host Port: 0/TCP
Environment: <none>
Mounts: <none>
Volumes: <none>
回滾到之前的修訂版本
kubectl rollout undo deployment nginx-deployment --to-revision=1
回滾后,Deployment 修訂歷史發(fā)生變化,revision 1變?yōu)閞evision 3
[root@centos7-wht ~]$ kubectl rollout history deployment nginx-deployment
deployment.apps/nginx-deployment
REVISION CHANGE-CAUSE
2 kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record=true
3 kubectl apply --filename=nginx/nginx-deployment.yaml --record=true
4.6 Deployments縮放
kubectl scale deployment deployment名字 --replicas=個(gè)數(shù)
4.7 暫停、恢復(fù) Deployment
可以在觸發(fā)一個(gè)或多個(gè)更新之前暫停 Deployment,然后再恢復(fù)其執(zhí)行。 這樣做使得你能夠在暫停和恢復(fù)執(zhí)行之間應(yīng)用多個(gè)修補(bǔ)程序,而不會(huì)觸發(fā)不必要的上線操作。
暫停
kubectl rollout pause deployment nginx-deployment
恢復(fù)
kubectl rollout resume deployment nginx-deployment
處于暫停狀態(tài)的 Deployment不能回滾,除非先恢復(fù)其執(zhí)行狀態(tài)。
4.8 Deployments進(jìn)度監(jiān)視
kubectl rollout status deployment deploy名字
5 Liveness Probe
通過檢測容器響應(yīng)是否正常來決定是否重啟Pod,Kubernetes支持如下三種探測機(jī)制:
- HTTP GET:向容器發(fā)送HTTP GET請求,如果Probe收到2xx或3xx,說明容器是健康的。
- TCP Socket:嘗試與容器指定端口建立TCP連接,如果連接成功建立,說明容器是健康的。
- Exec:Probe執(zhí)行容器中的命令并檢查命令退出的狀態(tài)碼,如果狀態(tài)碼為
0則說明容器是健康的。
Liveness Probe在containers字段中定義
5.1 HTTP GET
為Deployment中的Pod配置Liveness Probe,Probe往容器的80端口發(fā)送HTTP GET請求,如果請求不成功,Kubernetes會(huì)重啟容器。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe部分
httpGet: # HTTP GET定義
path: /
port: 80
ports:
- containerPort: 80
5.2 TCP Socket
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe部分
tcpSocket:
port: 80
ports:
- containerPort: 80
5.3 Exec
在容器中執(zhí)行cat /tmp/healthy命令,如果成功執(zhí)行并返回0,則說明容器是健康的。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
livenessProbe: # liveness probe
exec: # Exec定義
command:
- cat
- /tmp/healthy
ports:
- containerPort: 80
