8. K8s 資源部署

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.sessionAffinityClientIP來實(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)作。

升級操作,兩種方式:

  1. 直接使用命令行更新鏡像版本
kubectl set image deployment/nginx-deployment nginx=nginx:1.16.1 --record
  1. 使用edit在線編輯
kubectl edit deployment.v1.apps/nginx-deployment

Deployment可以通過maxSurgemaxUnavailable兩個(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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容