天天看點

k8s資源管理1. 基礎2. 依賴3. Pod4. 控制器5. Service

1. 基礎

# 可以檢視資源配置設定情況
kubectl describe node
# 全局資源情況檢視
kubectl api-resources
           
k8s資源管理1. 基礎2. 依賴3. Pod4. 控制器5. Service

1.1 apply

apply 指令可以使用配置檔案建立資源

  • -f 使用yaml或json建立資源, 也是比較常用的方式
kubectl apply -f ./my1.yaml                   # 建立資源
kubectl apply -f ./my1.yaml -f ./my2.yaml     # 使用多個檔案建立
kubectl apply -f ./dir                        # 基于目錄下的所有清單檔案建立資源
kubectl apply -f https://git.io/vPieo         # 從 URL 中建立資源
           

從标準輸出流建立

# 從标準輸入建立多個Pod
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000000"
---
apiVersion: v1
kind: Pod
metadata:
  name: busybox-sleep-less
spec:
  containers:
  - name: busybox
    image: busybox
    args:
    - sleep
    - "1000"
EOF

# 建立有多個 key 的 Secret
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: $(echo -n "s33msi4" | base64 -w0)
  username: $(echo -n "jane" | base64 -w0)
EOF
           

1.2 get

參數 預設值 說明
-A, --all-namespace false 傳回所有命名空間的資源
–allow-missing-template-keys true
–chunk-size 500
–field-selector ‘’
-f, --filename []
–ignore-not-found false
-k, --kustomize ‘’
-L, --label-columns []
–no-headers false
-o, --output ‘’

json,yaml,name,go-template,go-template-file,template,templatefile,jsonpath,jsonpath-as-json,jsonpath-file,custom-columns-file,custom-columns,wide

yaml: 以yaml格式輸出詳細配置

wide: 以清單輸出較詳細的資訊

–output-watch-events false
–raw ‘’
-R, --recursive false
-l, --selector ‘’
–server-print true
–show-kind false
–show-labels false 檢視對應資源設定的标簽
–show-managed-fields false
–sort-by ‘’
–template ‘’
-w, --watch false
–watch-only false
-n, --namespace 命名空間

2. 依賴

2.1 命名空間 namespace

  • namespace的寫法: namespaces, namespace, ns

将資源歸類, 相關的服務放在同一個命名空間下友善管理

# 建立命名空間 
kubectl create namespace
# 查詢命名空間
kubectl get ns
# 删除命名空間
kubectl delete namespace NAME
           
# yaml 配置
apiVersion: v1
kind: Namespace
metadata:
   name: repo-nexus
   labels:
     name: repo-nexus
           

k8s叢集預設擁有如下幾個namespace

NAME              STATUS   AGE
default           Active   2d3h
kube-node-lease   Active   2d3h
kube-public       Active   2d3h
kube-system       Active   2d3h
           
  • 所有NAMESPACED的資源,在建立的時候都需要指定namespace,若不指定,預設會在default命名空間下
  • 相同namespace下的同類資源不可以重名,不同類型的資源可以重名
  • 不同namespace下的同類資源可以重名
  • 通常在項目使用的時候,我們會建立帶有業務含義的namespace來做邏輯上的整合

2.2 apiVersion

apiVersion 含義
alpha 進入K8s功能的早期候選版本,可能包含Bug,最終不一定進入K8s
beta 已經過測試的版本,最終會進入K8s,但功能、對象定義可能會發生變更。
stable 可安全使用的穩定版本
v1 stable 版本之後的首個版本,包含了更多的核心對象
apps/v1 使用最廣泛的版本,像Deployment、ReplicaSets都已進入該版本

資源類型與apiVersion對照表

Kind apiVersion
ClusterRoleBinding rbac.authorization.k8s.io/v1
ClusterRole rbac.authorization.k8s.io/v1
ConfigMap v1
CronJob batch/v1beta1
DaemonSet extensions/v1beta1
Node v1
Namespace v1
Secret v1
PersistentVolume v1
PersistentVolumeClaim v1
Pod v1
Deployment v1、apps/v1、apps/v1beta1、apps/v1beta2
Service v1
Ingress extensions/v1beta1
ReplicaSet apps/v1、apps/v1beta2
Job batch/v1
StatefulSet apps/v1、apps/v1beta1、apps/v1beta2

快速獲得資源和版本

kubectl explain pod
kubectl explain Pod.apiVersion
           

2.3 叢集node label

# 查詢node上已有的标簽資訊
kubectl get nodes --show-labels
# 為節點打标簽
kubectl label node k8s-n-1 component=mysql
           

2.4 configmap

通常用來管理應用的配置檔案或者環境變量, 放一些不是特别敏感的資訊

apiVersion: v1
kind: ConfigMap
metadata:
  name: xxxx
  namespace: default
data:
  # 配置 key: value
  MYSQL_HOST: "172.168.23.11"
  MYSQL_PORT: "3306"
           
kubectl create -f configmap.yaml
           

使用文本檔案建立

MYSQL_HOST=172.168.23.11
MYSQL_PORT=3306
           
kubectl create configmap xxx --form-env-file=xxx.txt -n default
           

2.5 secret

管理敏感類資訊, 預設會base64編碼存儲, 有三種類型

  • Service Account: 用來通路Kubernetes API, 有Kubernetes自動建立, 并且會自動挂載到Pod的/run/secrets/kubernetes.io/serviceaccount目錄中; 建立ServiceAccount後, pod中指定serviceAccount後, 自動建立該ServiceAccount對應的secret
  • Opaque: base64編碼格式的Secret, 用來存儲密碼, 密鑰等;
  • kubernetes.io/dockerconfigjson: 用來存儲私有docker registry的認證資訊
apiVersion: v1
kind: Secret
metadata:
  name: xxxx
  namespace: default
type: Opaque
data:
  # 配置 key: base64(value)
  MYSQL_USER: cm9vdA==
  MYSQL_PASSWD: MTIzNDU2
           
kubectl create -f configmap.yaml
           

使用文本檔案建立, 不需要進行base64編碼

MYSQL_USER=root
MYSQL_PASSWD=123456
           
kubectl create secret generic xxx --form-env-file=xxx.txt -n default
           

3. Pod

  • pod支援的寫法: pods, pod, po

docker排程的是容器,在k8s叢集中,最小的排程單元是Pod

  • 與容器引擎解耦 Docker、Rkt。平台設計與引擎的具體的實作解耦
  • 多容器共享網絡|存儲|程序 空間, 支援的業務場景更加靈活
# yaml
apiVersion: v1
kind: Pod  # 資源類型
metadata:  # 基本配置
  name: POD_NAME
  namespace: MY_NS
  labels:  # 給pod打标簽, 友善管理, 後面用到會有介紹
    component: POD_NAME
spec:
  containers:  # 容器配置
  - name: NAME1  # 容器名
    image: IMAGE  # 鏡像倉庫位址
    env:  # 環境變量
    - name: MYSQL_HOST   #  指定root使用者的使用者名
      value: "127.0.0.1"
    - name: MYSQL_PASSWD
      value: "123456"
    ports:  # 容器暴漏的端口
    - containerPort: 8002
  - name: mysql  # 一個pod可以擁有多個容器
    image: mysql
    ports:
    - containerPort: 3306
    env:
    - name: MYSQL_ROOT_PASSWORD
      value: "123456"
    - name: MYSQL_DATABASE
      value: "myblog"
           
# 建立pod
kubectl create -f pod.yaml
kubectl apply -f pod.yaml
kubectl run --image=IMAGE POD_NAME # 更多kubectl run 用法參考kubeclt run -h
# 可以通過試運作擷取基礎yaml檔案
kubectl run --image=nginx --dry-run -o yaml nginx
# 更新服務版本
kubectl apply -f pod.yaml
# 檢視pod, -n 指定命名空間, -o wide 顯示更多資訊(可以看到排程節點)
kubectl get pods -o wide -n xxx
# 檢視pod的明細資訊及事件
kubectl describe pods -n xxx POD_NAME
# 檢視pod完整的yaml
kubectl get pods -o yaml -n xxx POD_NAME
# 檢視Pod内容器日志,顯示标準或者錯誤輸出日志
kubectl logs -n xxx -f POD_NAME -c CONTAINER_NAME
# --tail限定行數, 類似于docker指令 docker logs --tail=10 -f xxxxx
kubectl -n default logs -f --tail=10 nginx -c nginx
# 删除容器
kubectl delete -f pod.yaml
kubectl delete pod -n xxx POD_NAME
# 進入容器, -c 指定進入哪個容器
kubectl -n xxx exec -it POD_NAME -c NAME1 bash
# 使用 -o wide 我們可以看到pod在哪台機器, 那麼對應的容器也就是在那台機器
# 我們可以在相應機器上執行 docker ps 檢視容器資訊
docker ps -a | grep NAME1
# pod 中的容器命名格式為: k8s_<container_name>_<pod_name>_<pod_uuid>
           

3.1 節點選擇器

  • nodeSelector 節點選擇器, 可将pod排程到有某個label的node上, 如果node不存在, pod将不會正常建立, 直到node被打上相應label将會自動部署, 而不用重新建立
spec:
  nodeSelector:   # 使用節點選擇器将Pod排程到指定label的節點
    component: mysql   # 指定選擇有mysql标簽的node
           

3.2 資料持久化

類似于docker的資料挂載, 但我們之前挂載都是在單機上進行, 現在我們在叢集中使用volumes挂載其也僅會挂載在pod所在的機器上, 當我們重新上線時pod被排程到其它機器就依然會存在找不到資料的問題, 在這裡我們使用nodeSelector解決, 當然生産上一般不會用這種方法

...
spec:
  volumes: 
  - name: mysql-data
    hostPath:
      path: /opt/mysql/data
  nodeSelector:
    component: mysql
  containers:
  - name: mysql
    image: mysql
    ...
    volumeMounts:
    - name: mysql-data
      mountPath: /var/lib/mysql
           

使用PV+PVC連接配接分布式存儲解決方案

  • ceph
  • glusterfs
  • nfs

3.3 服務健康檢查

兩種探針

  • LivenessProbe探針: 存活性探測, 用于判斷容器是否存活, 即Pod是否為running狀态, 如果LivenessProbe探針探測到容器不健康, 則kubelet将kill掉容器, 并根據容器的重新開機政策是否重新開機, 如果一個不包含LivenessProbe探針, 則Kubelet認為容器的LivenessProbe探針傳回值永遠成功
  • ReadinessProbe探針: 可用性探測, 用于探測容器是否正常提供服務, 即容器的Ready是否為True, 是否可以接收請求, 如果ReadinessProbe探測失敗, 則容器的Ready将為False, Endpoint Controller控制器将此Pod的Endpoint從對應的serviceEndpoint清單中移除, 不再将任何請求排程此Pod上, 直到下次探測成功. (剔除此Pod不參與接收請求不會将流量轉發給此Pod)

三種類型

  • exec: 執行一個指令, 傳回狀态值為0則表示容器健康
  • httpGet: 發送一個http請求, 傳回200-399表示容器健康
  • tcpSocket: 通過容器的IP和Port執行TCP檢查, 如果能建立連接配接, 則表示容器健康

參數及含義

  • initialDelaySeconds: 啟動後第一次執行探測需要等待多少秒
  • perioSeconds: 執行探測的頻率. 預設10秒, 最小1秒
  • timeoutSeconds: 探測逾時時間. 預設1秒, 最小1秒
  • successThreshold: 探測失敗後, 最少連續探測成功多少次才被認定為成功. 預設1
  • failureThreshold: 探測成功後, 最少連續探測失敗多少次才被認定為失敗. 預設3, 最小1
spec:
  containers:
  - image: xxx
    name: xxx
    livenessProbe:  # 指定探針, 此處也可指定 readinessProbe
      # 使用http請求, 請求容器80端口來判斷容器是否存活
      httpGet:
        path: /blog/index
        port: 80
        scheme: HTTP
      initialDelaySeconds: 10  # 容器啟動後第一次執行探測需要等待多少秒
      perioSeconds: 10  # 執行探測的頻率
      timeoutSeconds: 2  # 探測逾時時間
           

3.4 重新開機政策

Pod的重新開機政策(RestartPolicy)應用于Pod内所有容器, 并僅在Pod所處的Node上由kubelet進行判斷和重新開機操作. 當某個容器異常退出或健康檢查失敗時, kubelet将根據RestartPolicy的設定來進行相應的操作. Pod的重新開機政策包括:Always、OnFailure和Never,預設值為Always

  • Always:當容器失效時(無論是否正常退出),由kubelet自動重新開機該容器。
  • OnFailure:當容器終止運作且退出碼不為0時,由kubelet自動重新開機該容器。
  • Never:不論容器運作狀态如何,kubelet都不會重新開機該容器。
spec:
  restartPolicy: Always
  containers:
  - name: xxx
    image: xxx
    args:   # 模拟異常退出, 容器參數
    - /bin/sh
    - -c
    - sleep 10 && exit 1
           

3.5 鏡像拉取政策

spec:
  containers:
  - name: xxx
    image: xxx
    imagePullPolicy: IfNotPresent
           

鏡像拉取政策: 預設IfNotPresent

  • Always: 總是拉取鏡像, 即使本地有也從倉庫拉取
  • IfNotPresent: 優先使用本地, 本地沒有則去倉庫拉取
  • Never: 僅使用本地鏡像, 本地沒有則報錯

3.6 Pod資源限制

注意:若記憶體使用超出限制,會引發系統的OOM機制,因CPU是可壓縮資源,不會引發Pod退出或重建

spec:
  containers:
  - name: xxx
    image: xxx
    resources:
      requests:
        memory: 100Mi
        cpu: 50m
      limits:
        memory: 100Mi
        cpu: 50m
           

requests:

  • 容器使用的最小資源需求, 作用與schedule階段, 作為容器排程時資源配置設定的判斷依賴
  • 隻有當節點上可配置設定的資源量>=request時才允許将容器排程到該節點
  • request參數不限制容器的最大可使用資源
  • requests.cpu被轉成docker的–cpu-shares參數, 與cgroup cpu.shares功能相同(無論主控端有多少個cpu或核心, --cpu-shares選項都會按照比例配置設定cpu資源)
  • requests.memory沒有對應的docker參數, 僅作為k8s排程依據

limits:

  • 容器能使用的資源最大量
  • 設定為0表示對使用的資源不限制, 可無限使用
  • 當pod記憶體超過limit時, 會被oom
  • 當cpu超過limit時, 不會被kill, 但是會限制不超過limit值
  • limits.cpu會被轉為docker的-cpu-qiota參數. 與cgroup cpu.cfs_quota_us功能相同
  • limits.memory會被轉成docker的-memory參數. 用來限制容器最大記憶體

3.7 網絡

如果在POD中使用"hostNetwork: true"配置網絡,pod中運作的應用程式可以直接看到宿主主機的網絡接口,主控端所在的區域網路上所有網絡接口都可以通路到該應用程式及端口。聲明pod的網絡模式為host模式,效果同docker run --net=host

spec:
  hostNetwork: true
           

3.8 引用配置

3.8.1 引用configmap

spec:
  containers:
  - name: xxx
    image: xxx
    env:
    - name: MYSQL_HOST
      valueFrom:
        configMapKeyRef:
          name: xxx
          key: MYSQL_HOST
    - name: MYSQL_PORT
      valueFrom:
        configMapKeyRef:
          name: xxx
          key: MYSQL_PORT
    - name: MYSQL_DATABASE
      value: "xxx"
           

3.8.2 引用secret

spec:
  containers:
  - name: xxx
    image: xxx
    env:
    - name: MYSQL_USER
      valueFrom:
        secretKeyRef:
          name: xxx
          key: MYSQL_USER
    - name: MYSQL_ROOT_PASSWORD
      valueFrom:
        secretKeyRef:
          name: xxx
          key: MYSQL_PASSWD
    - name: MYSQL_DATABASE
      value: "xxx"
           

3.9 pod 生命周期

Pod狀态值描述

  • Pending: API Server已經建立該Pod,等待排程器排程。
  • ContainerCreating: 拉取鏡像啟動容器中
  • Runnung: Pod内所有容器均已建立,且至少有一個容器處于運作狀态、正在啟動狀态或正在重新開機狀态。
  • Succeeded| Completed: Pod内所有容器均成功執行後退出,且不會再重新開機。
  • Failed | Error: Pod内所有容器均已退出,但至少有一個容器退出為失敗狀态。
  • CrashLoopBackOff: Pod内有容器啟動失敗,比如配置檔案丢失導緻主程序啟動失敗
  • Unknown: 由于某種原因無法擷取該Pod的狀态,可能由于網絡通信不暢導緻。
    k8s資源管理1. 基礎2. 依賴3. Pod4. 控制器5. Service

初始化容器(init)

  • 驗證業務應用依賴的元件是否均已啟動
  • 修改目錄的權限
  • 調整系統參數

驗證Pod生命周期

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: default
  labels:
    component: nginx
spec:
  # 在業務pod啟動前啟動, 可用于處理一些業務pod啟動前的一些工作
  initContainers:
  - name: nginx1
    image: nginx
    # 容器啟動後寫入檔案時間和标記
    command: ['sh', '-c', 'echo $(date +%s): INIT >> /loap/timing']
    volumeMounts:
    - mountPath: /loap
      name: timing
  containers:
  - name: nginx2
    image: nginx
    command: ['sh', '-c', 'echo $(date +%s): START >> /loap/timing; sleep 10; echo $(date +%s): END >> /loap/timing;']
    volumeMounts:
    - mountPath: /loap
      name: timing
    livenessProbe:  # 存活性探測探針
      exec:
        command: ['sh', '-c', 'echo $(date +%s): LIVENESS >> /loap/timing']
    readinessProbe:  # 可用性探測探針
      exec:
        command: ['sh', '-c', 'echo $(date +%s): READINESS >> /loap/timing']
    lifecycle:  # 生命周期
      postStart:  # 容器啟動的時候觸發
        exec:
          command: ['sh', '-c', 'echo $(date +%s): POST-START >> /loap/timing']
      # 須主動殺掉 Pod 才會觸發 pre-stop hook,如果是 Pod 自己 Down 掉,則不會執行 pre-stop hook
      preStop:
        exec:
          command: ['sh', '-c', 'echo $(date +%s): PRE-STOP >> /loap/timing']
  volumes:
  - name: timing
    hostPath:
      path: /tmp/loap
           
kubectl apply -f nginx.yaml
# 檢視pod所在機器
kubectl get pod -o wide
# 在pod所在機器檢視檔案
cat /tmp/loap/timing 
           
1630456396: INIT
1630456398: START
1630456398: POST-START
1630456398: READINESS
1630456406: LIVENESS
1630456406: READINESS
1630456408: END
           
# 删除測試pod, 否則由于沒有常駐程序, pod會一直重新開機
kubectl delete -f nginx.yaml
           

4. 控制器

控制器又稱工作負載是用于實作管理pod的中間層,確定pod資源符合預期的狀态,pod的資源出現故障時,會嘗試 進行重新開機,當根據重新開機政策無效,則會重新建立pod的資源。

  • ReplicaSet: 代使用者建立指定數量的pod副本數量,確定pod副本數量符合預期狀态,并且支援滾動式自動擴容和縮容功能
  • Deployment:工作在ReplicaSet之上,用于管理無狀态應用,目前來說最好的控制器。支援滾動更新和復原功能,提供聲明式配置
  • DaemonSet:用于確定叢集中的每一個節點隻運作特定的pod副本,通常用于實作系統級背景任務。比如EFK服務
  • Job:隻要完成就立即退出,不需要重新開機或重建
  • Cronjob:周期性任務控制,不需要持續背景運作
  • StatefulSet:管理有狀态應用

4.1 Deployment

Deployment支援的寫法: deployment, deploy

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
spec:
  replicas: 1  # 指定Pod副本數
  selector:  # 指定Pod的選擇器
    matchLabels:
      app: nginx
  template: # temlate中内容與建立pod基本一緻
    metadata:
      labels:  # 給Pod打label
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
      dnsPolicy: ClusterFirst
      restartPolicy: Always
           
# 建立Deployment
kubectl create -f nginx.yaml 
kubectl create deploy --image=nginx nginx
# 通過試運作擷取基礎yaml
kubectl create deploy --image=nginx nginx --dry-run -o yaml
# 檢視Deployment, -n 可加命名空間
kubectl get deploy
# 會自動建立replicaSet, 可以檢視
kubectl get replicaset(rs) 
# 使用建立檔案删除Deployment
kubectl delete -f nginx.yaml 
# 更新--修改配置檔案後執行apply
kubectl apply -f nginx.yaml
# 線上更新, 類似于vim編輯器, 儲存後自動更新
kubectl edit deploy nginx
# 直接使用指令更新
kubectl set image deploy nginx nginx=nginx:1.21.1 --record
           

4.2 副本數

controller(控制器)實時檢測pod狀态,并保障副本數一直處于期望的值

spec:
  replicas: 1  # 指定Pod副本數
           
# 修改副本數
kubectl scale deploy nginx --replicas=2
# 最好是通過修改配置檔案中replicas參數重新apply來修改副本數(保持配置檔案與實際運作狀況一緻)

# 我們删除一個pod, 控制器會重新建立一個
kubectl delete pod nginx-6799fc88d8-7rppv
           
[[email protected] ~]# kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-7rppv   1/1     Running   0          9m5s
nginx-6799fc88d8-fnwqr   1/1     Running   0          56s
[[email protected] ~]# kubectl delete pod nginx-6799fc88d8-7rppv
pod "nginx-6799fc88d8-7rppv" deleted
[[email protected] ~]# kubectl get pod
NAME                     READY   STATUS              RESTARTS   AGE
nginx-6799fc88d8-fnwqr   1/1     Running             0          97s
nginx-6799fc88d8-grxfs   0/1     ContainerCreating   0          2s
           

4.3 Pod驅逐政策

K8S 有個特色功能叫 pod eviction,它在某些場景下如節點 NotReady,或者資源不足時,把 pod 驅逐至其它節點,這也是出于業務保護的角度去考慮的

4.4 更新政策

spec:
  replicas: 2  # 指定Pod副本數
  selector:  # 指定Pod的選擇器
    matchLabels:
      app: myblog
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate # 指定更新方式為滾動更新,預設政策,通過kubectl get deploy -o yaml檢視
           

政策控制:

  • maxSurge:最大激增數, 指更新過程中, 最多可以比replicas預先設定值多出的pod數量, 可以為固定值或百分比,預設為desired Pods數的25%。計算時向上取整(比如3.4,取4),更新過程中最多會有replicas + maxSurge個pod
  • maxUnavailable: 指更新過程中, 最多有幾個pod處于無法服務狀态 , 可以為固定值或百分比,預設為desired Pods數的25%。計算時向下取整(比如3.6,取3)
# 我們修改一下nginx鏡像版本
kubectl set image deploy nginx nginx=nginx:1.21.1 --record
# 檢視滾動更新事件
kubectl describe deploy nginx
           
Events:
  Type    Reason             Age                  From                   Message
  ----    ------             ----                 ----                   -------
  Normal  ScalingReplicaSet  35s                  deployment-controller  Scaled up replica set nginx-54f48578cf to 1
  Normal  ScalingReplicaSet  32s (x2 over 5m5s)   deployment-controller  Scaled down replica set nginx-6799fc88d8 to 2
  Normal  ScalingReplicaSet  32s                  deployment-controller  Scaled up replica set nginx-54f48578cf to 2
  Normal  ScalingReplicaSet  29s                  deployment-controller  Scaled down replica set nginx-6799fc88d8 to 1
  Normal  ScalingReplicaSet  29s                  deployment-controller  Scaled up replica set nginx-54f48578cf to 3
  Normal  ScalingReplicaSet  27s                  deployment-controller  Scaled down replica set nginx-6799fc88d8 to 0
           
  • 我們有三個節點, 是以最多可以增加1個pod, 最多可以有0個pod處于無法服務狀态(即至少要保持三個pod在運作中)
  • 3 old pod, 增加的政策觸發成功增加一個pod, 減少的政策觸發失敗
  • 3 old pod + 1 new pod, 增加的政策觸發失敗, 減少的政策觸發成功, 減少一個舊pod
  • 2 old pod + 1 new pod, 增加1減少0
  • 2 old pod + 2 new pod, 增加0減少1
  • 1 old pod + 2 new pod, 增加1減少0
  • 1 old pod + 3 new pod, 新的pod數滿足需求, 舊的pod減少1
  • 3 new pod 完成更新

4.5 服務復原

通過滾動更新的政策可以平滑的更新Deployment,若更新出現問題,需要最快且最好的方式回退到上一次能夠提供正常工作的版本。為此K8S提供了復原機制

revision:更新應用時,K8S都會記錄目前的版本号,即為revision,當更新出現問題時,可通過復原到某個特定的revision,預設配置下,K8S隻會保留最近的幾個revision,可以通過Deployment配置檔案中的spec.revisionHistoryLimit屬性增加revision數量,預設是10。

# 檢視目前版本及版本曆史, 如果是<none>是因為建立和更新的時候沒有加--record 
kubectl rollout history deploy nginx
# 我們删除服務重建一下
kubectl delete -f nginx.yaml
kubectl apply -f nginx.yaml --record
# 然後修改一下
kubectl set image deploy nginx nginx=nginx:1.21.1 --record
# 重新檢視曆史版本
kubectl rollout history deploy nginx
           
[[email protected] ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
1         kubectl apply --filename=nginx.yaml --record=true
2         kubectl set image deploy nginx nginx=nginx:1.21.1 --record=true
           
# 復原到具體的版本
kubectl rollout undo deploy nginx --to-revision=1
           
[[email protected] ~]# kubectl rollout undo deploy nginx --to-revision=1
deployment.apps/nginx rolled back
[[email protected] ~]# kubectl rollout history deploy nginx
deployment.apps/nginx 
REVISION  CHANGE-CAUSE
2         kubectl set image deploy nginx nginx=nginx:1.21.1 --record=true
3         kubectl apply --filename=nginx.yaml --record=true
           

我們看到本該再增加一條記錄的曆史記錄卻隻有兩條記錄, 是因為1和3是同一個版本, 則隻保留一條

5. Service

service别名: services, service, svc

通過上面,能夠通過Deployment來建立一組Pod來提供具有高可用性的服務。雖然每個Pod都會配置設定一個單獨的Pod IP,然而卻存在如下兩個問題:

  • Pod IP僅僅是叢集内可見的虛拟IP,外部無法通路
  • Pod IP會随着Pod的銷毀而消失,當ReplicaSet對Pod進行動态伸縮時,Pod IP可能随時随地都會變化,這樣對于通路這個服務帶來了難度

5.1 Service負載均衡之Cluster IP

service是一組pod的服務抽象,相當于一組pod的LB,負責将請求分發給對應的pod。service會為這個LB提供一個IP,一般稱為cluster IP 。使用Service對象,通過selector進行标簽選擇,找到對應的Pod

apiVersion: v1
kind: Service
metadata:
  name: nginx
  namespace: default
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: nginx
  type: ClusterIP
           
# 建立
kubectl apply -f svc-nginx.yaml
kubectl create svc 
kubectl expose deployment nginx --port=80 --type=NodePort
# 檢視svc
kubectl get svc
# 檢視svc詳情
kubectl describe svc nginx
           
[[email protected] ~]# kubectl describe svc nginx
Name:                     nginx
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx          # 根據此label篩選其可操控的pod
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.1.144.1
IPs:                      10.1.144.1
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30537/TCP
Endpoints:                10.2.1.12:80,10.2.2.7:80   # 其所控制的pod的ip, 會随着pod的更新而更新
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
           

我們現在就可以用 10.1.144.1:30537 來通路服務了

5.1.1 Endpoint

service對象建立的同時,會建立同名的endpoints對象,若服務設定了readinessProbe, 當readinessProbe檢測失敗時,endpoints清單中會剔除掉對應的pod_ip,這樣流量就不會分發到健康檢測失敗的Pod中

# 檢視endpoint, 與service中的Endpoints内容一緻
kubectl get endpoints nginx
           

5.1.2 存在的問題

目前使用hostNetwork部署, 需通過主控端ip+port通路, 就會有以下問題

  • 服務使用hostNetwork,使得主控端的端口大量暴漏,存在安全隐患
  • 容易引發端口沖突

服務均屬于k8s叢集,盡可能使用k8s的網絡通路,是以可以對目前myblog通路mysql的方式做改造:

  • 為mysql建立一個固定clusterIp的Service,把clusterIp配置在myblog的環境變量中
  • 利用叢集服務發現的能力,元件之間通過service name來通路

5.2 服務發現

未完待續…

.1.144.1

Port: 80/TCP

TargetPort: 80/TCP

NodePort: 30537/TCP

Endpoints: 10.2.1.12:80,10.2.2.7:80 # 其所控制的pod的ip, 會随着pod的更新而更新

Session Affinity: None

External Traffic Policy: Cluster

Events:

我們現在就可以用 10.1.144.1:30537 來通路服務了

## 5.1.1 Endpoint

service對象建立的同時,會建立同名的endpoints對象,若服務設定了readinessProbe, 當readinessProbe檢測失敗時,endpoints清單中會剔除掉對應的pod_ip,這樣流量就不會分發到健康檢測失敗的Pod中

```shell
# 檢視endpoint, 與service中的Endpoints内容一緻
kubectl get endpoints nginx
           

5.1.2 存在的問題

目前使用hostNetwork部署, 需通過主控端ip+port通路, 就會有以下問題

  • 服務使用hostNetwork,使得主控端的端口大量暴漏,存在安全隐患
  • 容易引發端口沖突

服務均屬于k8s叢集,盡可能使用k8s的網絡通路,是以可以對目前myblog通路mysql的方式做改造:

  • 為mysql建立一個固定clusterIp的Service,把clusterIp配置在myblog的環境變量中
  • 利用叢集服務發現的能力,元件之間通過service name來通路

5.2 服務發現

未完待續…

繼續閱讀