k8s使用Init Container確保依賴服務已啟動

在K8S使用過程中,我們在啟動服務過程中,可能會存在服務依賴啟動的問題。比如:我們希望先啟動MySQL服務,再啟動Nginx服務。此時可以使用initContainers來實現我們需要的功能,控制服務啟動順序。

Init Container簡介

Pod中能夠包含多個容器,也可能包含一個或多個先於應用容器啟動的init容器。init容器和普通容器非常像,除了以下四點:

  • 它們只運行到完成
  • 每個init容器都必須在下一個啟動之前成功完成
  • init容器不支持Readiness Probe,因為它們必須在pod啟動之前完成
  • 如果一個pod指定了多個init容器,則init容器會按順序啟動,每個init容器運行成功,下一個才能運行,當所有init容器完成後,應用容器才能正常初始化 如果pod中的init容器失敗,kubernetes會不斷的重啟該pod,直到init容器成功為止,如果pod對應的restartPolicyNever,則pod不會重啟。

Init Container作用

init容器具有和應用容器分離的獨立鏡像,能夠完成以下功能:

  • init容器可以包含運行的實用工具,處於安全考慮,不建議在應用容器中包含這些工具
  • 為應用鏡像分離出創建和部署的角色
  • Init容器提供了一種簡單的方式來阻塞或延遲應用容器的啟動,直到滿足了一組先決條件

使用Init Container確保依賴服務已啟動

Init Container 使用示例

apiVersion: apps/v1beta1  kind: Deployment  metadata:    name: init-test  spec:    replicas: 1    template:      metadata:        labels:          app: init      spec:        containers:        - name: nginx-init          image: nginx:1.7.9          ports:          - containerPort: 80        initContainers:        - name: init-mydb          image: busybox          command: ['sh', '-c', 'until nslookup mysql; do echo waiting for mysql; sleep 2; done;']        restartPolicy: Always

上面的示例是打算啟動一個Nginx服務,在啟動服務之前來判斷MySQL的服務是否啟動。通過nslookup檢測mysql服務是否成功啟動。如果mysql服務啟動了之後,nslookup 檢測域名也會成功,後續會啟動Nginx 容器;

否則,將會等待兩秒之後,再次檢測。

但是,這種方式我在使用過程中,並沒有成功。我的環境是為mysql配置了Deploy和Service,在關閉pod的情況下通過nslookup來檢測域名還是可以成功。後面我直接使用curl來判斷端口服務是否可用。

示例代碼

apiVersion: apps/v1beta1  kind: Deployment  metadata:    name: init-test  spec:    replicas: 1    template:      metadata:        labels:          app: init      spec:        containers:        - name: nginx-init          image: nginx:1.7.9          ports:          - containerPort: 80        initContainers:        - name: init-mydb          image: curlimages/curl:7.68.0          command: ['sh', '-c', 'until curl 192.168.10.254:6379;; do echo waiting for mysql; sleep 2; done;']        restartPolicy: Always

Init container容器中使用curl鏡像,命令通過curl + 服務地址,服務地址就是你的MySQL服務地址,直接來判斷服務是否可用正常使用。

當MySQL服務沒有正常啟動時,錯誤信息:curl: (7) Failed to connect to 192.168.10.254 port 6379: Connection refused,init container會一直循環檢測。

到服務正常啟動之後,It looks like you are trying to access mysql over HTTP on the native driver port.之後服務就可以正常啟動了。