天天看點

容器服務 kubernetes(ACK)中應用優雅上下線1. 概述2.優雅啟動3. 優雅下線:

1. 概述

 kubernetes滾動更新的過程:

   1. 叢集Deployment 或者 Statefulset 發生變化,觸發部署滾動更新;

   2. 根據 Deolyement 等配置,K8S叢集首先啟動新的POD來替代老 POD;

   3. Deployemnt 根據配置排程 POD,拉取鏡像,此時 POD 進入 Pending 狀态;

   4. POD 綁定到Node上,啟動容器,在就緒檢查readinessProbe 探針通過後,新的POD進入Ready狀态;

   5. K8S叢集建立Endpoint,将新的POD納入Service 的負載均衡;

   6. K8S叢集移除與老POD相關的Endpoint,并且将老POD狀态設定為Terminating,此時将不會有新的請求到達老POD,同時調用PreStop Hook執行配置的腳本;

   7. K8S叢集會給老POD發送SIGTERM信号,并且等待 terminationGracePeriodSeconds 這麼長的時間。(預設為30秒,可以根據優雅下線服務需要消耗時間調整)

   8. 超過terminationGracePeriodSeconds等待時間後, K8S叢集會強制結束老POD,在這個時間段内要将老 POD 資源釋放掉,否則可能殘留無用資源被占用。

  從以上過程可以看到,如果在terminationGracePeriodSeconds 沒有及時釋放服務注冊等資源資訊,Service 負載均衡的健康檢查又沒有檢查到老 POD服務已經挂掉,導緻請求分發到這些 POD 上,進而觸發一系列的請求錯誤,因而需要配置優雅下線腳本,在terminationGracePeriodSeconds 時間段内執行完畢。

2.優雅啟動

  kubernetes 叢集提供了探針,類似健康檢查,隻有該請求通過,新的 POD 才能進入 Ready 狀态,kubernetes叢集才會将新的 POD 納入 Service 的負載均衡。

  因而如果該應用(POD)僅僅提供 service 配置的服務,不需要配置探針,就可以優雅啟動,但是實際 POD 往往還有 HSF,LWP,Dubbo等注冊于配置服務其實作負載均衡的服務,是以需要確定這些服務都已經啟動,是以需要配置相應的探針。

同時,任何一個服務可能在運作中因為某種原因不穩定,導緻服務中斷,這個時候還需要配置livenessProbe探針,確定服務出故障時及時止損。

  我們的應用主要有HSF,LWP 和 Https 服務,對于三種服務都有的應用,要求應用提供健康檢查的接口,能即時檢查三種服務都正常與否,然後做以下配置:

livenessProbe:
  failureThreshold: 3
  initialDelaySeconds: 30
  periodSeconds: 30
  successThreshold: 1
  tcpSocket:
    port: 5084
  timeoutSeconds: 1
readinessProbe:
  failureThreshold: 3
  initialDelaySeconds: 30
  periodSeconds: 30
  successThreshold: 1
  tcpSocket:
    port: 5084
  timeoutSeconds: 1
restartPolicy: Always           

  readinessProbe配置表示隻有5804端口請求正常傳回,pod 才會進入 ready 狀态,確定各種服務 ok 。

livenessProbe 表示每10s 探一下5804端口,如果傳回失敗,達到門檻值後,pod 會重新開機,對于服務出問題的 POD 及時止損。

   注意:readinessProbe探針的 探測頻率和延時時間,不健康門檻值等資料要合理,部分應用啟動時間本身較長,如果設定的時間過短,會導緻 POD 反複無效重新開機。

3. 優雅下線:

 我們的應用雲上主要有 HSF,LWP 和 Https 服務,在 pod prestop裡設定執行摘除服務注冊資訊腳本,來完成優雅下線。

 https 服務基于 kubernetes 服務 Service 來實作服務暴露,在老 POD 狀态設定為Terminating後,就不會有請求達到,因而已經優雅下線;

 lwp 服務,通過注冊 vipserver 來提供負載均衡,需要在下線前先摘除該服務注冊,防止 老POD 下線後還有請求達到老 POD;

 HSF 服務通過注冊 configserver 來提供負載均衡,需要在下線前先摘除該服務注冊,防止 老POD 下線後還有請求達到老 POD。

yaml:

lifecycle:
  preStop:
    exec:
      command:
        - sudo
        - '-u'
        - admin
        - /home/admin/shutdown.sh
        - {app_name}           

 preStop在 pod 終止之前,執行腳本 appctl.sh {app_name} stop。

 終止 HSF 與 LWP 腳本:

#!/bin/bash

APP_NAME=$1

## HEALTH_URL="http://localhost:7002/health"

offline() {
    echo "INFO: ${APP_NAME} try to offline..."
    offline_lwp
    offline_hsf
    echo "INFO: ${APP_NAME} offline success"
    return $?
}

offline_lwp() {
    echo "offline lwp"
        times=3
        for e in $(seq 3); do
            curl -s --connect-timeout 3 --max-time 5 ${offline_lwp_url}${APP_NAME} -o /dev/null
            sleep 1
        done
}

offline_hsf() {
   check_hsf=`(/usr/sbin/ss -ln4 sport = :12200; /usr/sbin/ss -ln6 sport = :12200) | grep -c ":12200"`
    check_pandora=`(/usr/sbin/ss -ln4 sport = :12201; /usr/sbin/ss -ln6 sport = :12201) | grep -c ":12201"`
    echo "try to offline hsf..."
    if [ $check_hsf -ne 0 -a $check_pandora -ne 0 ]; then
        echo "start to offline hsf...."
        ret_str=`curl --max-time ${HSF_ONLINE_TIMEOUT} -s "http://localhost:12201/hsf/offline?k=hsf" 2>&1`
        if echo "$ret_str" | grep "server is unregistered on cs(dr)" &>/dev/null; then
            echo "hsf offline success."
            return 0
        else
            echo "hsf offline failed."
            exit 9 # hsf offline failed
        fi
    else
        if [ $check_hsf -eq 0 ]; then
            echo "WARN: port 12200 cannot be detected."
        fi
        if [ $check_pandora -eq 0 ]; then
            echo "WARN: port 12201 cannot be detected."
        fi
        echo "WARN: hsf offline failed."
        # DO NOT exit here
    fi
}


echo "[stop 1] before call offline hsf,lwp ..."
            

繼續閱讀