about 1 year ago

測試一些 Kubernetes 部署 Service 的策略

先從簡單的開始,做滾動升級前先把 pod 設定成 2 份才有辦法滾動啊

cat << EOF > test-rest.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-rest-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: test-rest
    spec:
      containers:
      - name: test-rest
        image: spike234/test-rest:0.1.7
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 100m
EOF
kubectl apply -f test-rest.yaml --record

把 replicas 改成 2

然後建立 Service

cat << EOF > test-rest-svc.yaml
apiVersion: v1
kind: Service
metadata:
  name: test-rest
  labels:
    app: test-rest
spec:
  type: NodePort
  selector:
    app: test-rest
  ports:
  - port: 8080
    targetPort: 8080
    nodePort: 30080
EOF

kubectl apply -f test-rest-svc.yaml --record

更新 Deployment 跟 確認新的 pod 已經開好並提供服務了

[root@master1 ~]# kubectl apply -f test-rest.yaml --record
2017-09-15 17:19:50.556414 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 17:19:50.556763 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 17:19:50.556777 I | proto: duplicate proto type registered: google.protobuf.Timestamp
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
deployment "test-rest-deployment" configured
[root@master1 ~]# kubectl get pods
2017-09-15 17:20:05.430832 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 17:20:05.430920 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 17:20:05.430938 I | proto: duplicate proto type registered: google.protobuf.Timestamp
NAME                                    READY     STATUS              RESTARTS   AGE
test-rest-deployment-2942619840-m029v   1/1       Running             0          3h
test-rest-deployment-2942619840-ptxv4   0/1       ContainerCreating   0          15s

等開好了 READY 會是 1/1

檢視一下現在的 replica set 資訊

[root@master1 ~]# kubectl get rs
2017-09-15 17:26:53.120979 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 17:26:53.121042 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 17:26:53.121061 I | proto: duplicate proto type registered: google.protobuf.Timestamp
NAME                              DESIRED   CURRENT   READY     AGE
test-rest-deployment-2942619840   2         2         2         3h

滾動升級 ROLLING UPDATE

在這之前把程式改一下才看的出來滾動升級,把回覆內容增加一個 version 版本資訊

升級前程式回傳值如下,還沒有 version 的資訊

[root@master1 ~]# curl -s "http://192.168.31.147:30080/api/v1/test"
{"rc":"1"}

等 circleci 幫我們把程式編譯好並打包成 Docker Image 後可以取得新的 Image 跟 Tag 是 spike234/test-rest:0.1.8

再來需要修改我們 spec 中的升級策略

minReadySeconds: 5

strategy:

  # indicate which strategy we want for rolling update

  type: RollingUpdate

  rollingUpdate:

    maxSurge: 1

    maxUnavailable: 1

我從這邊 Ta-Ching 大大 抄過來紀錄的

minReadySeconds:
容器內應用程式的啟動時間,Kubernetes 會等待設定的時間後才繼續進行升級流程
如果沒有此欄位的話,Kubernetes 會假設該容器一開完後即可進行服務
若未設定此欄位,在某些極端情況下可能會造成服務無法正常運作(新誕生的 pod 尚未進入可服務階段)

maxSurge:
升級過程中最多可以比原先設定所多出的 pod 數量
此欄位可以為固定值或是比例(%)
ex. maxSurge: 1、replicas: 5,代表 Kubernetes 會先開好 1 個新 pod 後才刪掉一個舊的 pod,整個升級過程中最多會有 5+1 個 pod

maxUnavailable:
最多可以有幾個 pod 處在無法服務的狀態
當 maxSurge 不為零時,此欄位亦不可為零
ex. maxUnavailable: 1,代表 Kubernetes 整個升級過程中最多會有 1 個 pod 處在無法服務的狀態

改好的 yml 如下

cat << EOF > test-rest.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-rest-deployment
spec:
  replicas: 2
  template:
    metadata:
      labels:
        app: test-rest
    spec:
      containers:
      - name: test-rest
        image: spike234/test-rest:0.1.7
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 100m
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 1
  minReadySeconds: 30
EOF

先變更 Deployment 的資訊

[root@master1 ~]# kubectl apply -f test-rest.yaml --record
2017-09-15 18:03:06.581425 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 18:03:06.581473 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 18:03:06.581484 I | proto: duplicate proto type registered: google.protobuf.Timestamp
deployment "test-rest-deployment" configured

有三種方式可以來進行滾動升級

set image

# format

$ kubectl set image deployment <deployment> <container>=<image> --record
# example

$ kubectl set image deployment nginx nginx=nginx:1.11.5 --record

replace

spec:
  containers:
  - name: test-rest
    # newer image version

    image: spike234/test-rest:0.1.8
    ports:
    - containerPort: 8080

利用 replace 來進行升級而非 apply

# format

$ kubectl replace -f <yaml> --record
# example

$ kubectl replace -f test-rest.yaml --record

edit

# format

$ kubectl edit deployment <deployment> --record
# example

$ kubectl edit deployment nginx --record

會直接打開編輯器的視窗

我這邊用 replace 來做一個試驗

[root@master1 ~]# kubectl replace -f test-rest.yaml --record
2017-09-15 18:26:01.998419 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 18:26:01.998471 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 18:26:01.998483 I | proto: duplicate proto type registered: google.protobuf.Timestamp
deployment "test-rest-deployment" replaced

指令執行後馬上來看 pod

[root@master1 ~]# kubectl get pods
2017-09-15 18:33:51.385198 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 18:33:51.385249 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 18:33:51.385261 I | proto: duplicate proto type registered: google.protobuf.Timestamp
NAME                                    READY     STATUS              RESTARTS   AGE
test-rest-deployment-1587270817-7d2vl   0/1       ContainerCreating   0          7s
test-rest-deployment-1587270817-lg104   0/1       ContainerCreating   0          7s
test-rest-deployment-2942619840-m029v   1/1       Running             0          4h
test-rest-deployment-2942619840-ptxv4   1/1       Terminating         0          1h

並一邊查詢 API 結果

for sitenu in $(seq 1 360)
do
    currentTime=$(date +"%T")
    Response=$(curl -s "http://192.168.31.147:30080/api/v1/test")
    echo -e "Time: $currentTime Response: $Response"
    sleep 1
done

可以看到新的服務正在被啟動,中間會新舊服務一起提供服務,沒多久就都會替換成新版本的服務

另一邊用 rollout status 看更換的訊息

[root@master1 ~]# kubectl rollout status deployment test-rest-deployment
2017-09-15 18:34:04.611112 I | proto: duplicate proto type registered: google.protobuf.Any
2017-09-15 18:34:04.611306 I | proto: duplicate proto type registered: google.protobuf.Duration
2017-09-15 18:34:04.611334 I | proto: duplicate proto type registered: google.protobuf.Timestamp
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 old replicas are pending termination...
Waiting for rollout to finish: 1 of 2 updated replicas are available...
deployment "test-rest-deployment" successfully rolled out

查詢升級狀況

kubectl rollout status deployment test-rest-deployment

暫停滾動升級

kubectl rollout pause deployment <deployment>

繼續滾動升級

kubectl rollout resume deployment <deployment>

回滾 rollback (還沒測試)

如果發現升版錯誤的時候,可以進行回滾

# to previous revision

$ kubectl rollout undo deployment <deployment>
# to specific revision

$ kubectl rollout undo deployment <deployment> --to-revision=<revision>
# exmaple

$ kubectl rollout undo deployment nginx --to-revision=1

指令後面的 --record 是為了讓 Kubernete 紀錄執行動作,在查詢時就可以知道 revision 間有什麼差異

$ kubectl apply -f nginx.yaml --record
deployment "nginx" configured

$ kubectl set image deployment nginx nginx=nginx:1.11.5 --record
deployment "nginx" image updated

$ kubectl rollout history deployment ngin
deployments "nginx":
REVISION  CHANGE-CAUSE
1   kubectl apply -f nginx.yaml --record
2   kubectl set image deployment nginx nginx=nginx:1.11.5 --record

COSS 103 kubernetes 介紹 教學 指令操作
https://www.brosinski.com/post/deploying-spring-boot-app-kubernetes/
Extensions API Definitions - Kubernetes
Kubernetes Deployment 實現滾動升級
Deployment · Kubernetes指南
Linux Shell脚本编程--curl命令详解 - 上善若水,水善利万物而不争。 - CSDN博客

← CircleCI 2.0 SpringBoot config.yml Blue/Green Deployments on Kubernetes →
 
comments powered by Disqus