kubernetes 最佳實踐:優雅熱更新

當kubernetes對服務滾動更新的期間,默認配置的狀況下可能會讓部分鏈接異常(好比鏈接被拒絕),咱們來分析下緣由並給出最佳實踐nginx

滾動更新場景

使用 deployment 部署服務並關聯 service後端

  • 修改 deployment 的 replica 調整副本數量來滾動更新
  • 升級程序版本(修改鏡像tag)觸發 deployment 新建 replicaset 啓動新版本的 pod
  • 使用 HPA (HorizontalPodAutoscaler) 來對 deployment 自動擴縮容更新過程鏈接異常的緣由滾動更新時,service 對應的 pod 會被建立或銷燬,也就是 service 對應的 endpoint 列表會新增或移除endpoint,更新期間可能讓部分鏈接異常,主要緣由是:
  • pod 被建立,還沒徹底啓動就被 endpoint controller 加入到 service 的 endpoint 列表,而後 kube-proxy 配置對應的路由規則(iptables/ipvs),若是請求被路由到還沒徹底啓動完成的 pod,這時 pod 還不能正常處理請求,就會致使鏈接異常
  • pod 被銷燬,可是從 endpoint controller watch 到變化並更新 service 的 endpoint 列表到 kube-proxy 更新路由規則這期間有個時間差,pod可能已經徹底被銷燬了,可是路由規則還沒來得及更新,形成請求依舊還能被轉發到已經銷燬的 pod ip,致使鏈接異常最佳實踐
  • 針對第一種狀況,能夠給 pod 裏的 container 加 readinessProbe (就緒檢查),這樣可讓容器徹底啓動了才被endpoint controller加進 service 的 endpoint 列表,而後 kube-proxy 再更新路由規則,這時請求被轉發到的全部後端 pod 都是正常運行,避免了鏈接異常
  • 針對第二種狀況,能夠給 pod 裏的 container 加 preStop hook,讓 pod 真正銷燬前先 sleep 等待一段時間,留點時間給 endpoint controller 和 kube-proxy 清理 endpoint 和路由規則,這段時間 pod 處於 Terminating 狀態,在路由規則更新徹底以前若是有請求轉發到這個被銷燬的 pod,請求依然能夠被正常處理,由於它尚未被真正銷燬

最佳實踐 yaml 示例:api

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      component: nginx
  template:
    metadata:
      labels:
        component: nginx
    spec:
      containers:
      - name: nginx
        image: "nginx"
        ports:
        - name: http
          hostPort: 80
          containerPort: 80
          protocol: TCP
        readinessProbe:
          httpGet:
            path: /healthz
            port: 80
            httpHeaders:
            - name: X-Custom-Header
              value: Awesome
          initialDelaySeconds: 15
          timeoutSeconds: 1
        lifecycle:
          preStop:
            exec:
              command: ["/bin/bash", "-c", "sleep 30"]

參考資料

相關文章
相關標籤/搜索