目錄貼:Kubernetes學習系列
下面我們將主要介紹運行在Kubernetes集群中的容器所能夠感知到的上下文環境,以及容器是如何獲知這些信息的。
首先,Kubernetes提供了一個能夠讓容器感知到集群中正在發生的事情的方法:環境變量。作為容器環境組成的一部分,這些集群信息對于容器構建“集群環境感知”起著非常重要的作用。其次,Kubernetes容器環境還包括一系列與容器生命周期相關的容器鉤子,其對應的回調函數hook handler可以作為單個容器可選定義項的一部分。這個容器鉤子與操作系統傳統進程模型的通知回調機制有些類似。其實,還有一個與容器環境相關的重要部分是容器可用的文件系統。通過前面的討論可知,在Kubernetes中,容器的文件系統由一個容器鏡像和若干個Volume組成。
下面我們將著重討論暴露給容器的集群信息和用于向容器發布對其生命周期管理信息的容器鉤子這兩種同容器上下文環境協作的方法。
1、集群環境感知
運行在Kubernetes集群中的一個容器在容器內部能夠感知兩種類型的環境變量信息,一種是與容器自身相關的信息,另一種是集群的信息。
1.1容器自身信息
容器能夠感知到的與容器自身相關的信息包括運行該容器的pod的名字、pod所在的namespace、在pod資源配置文件中env字段定義的鍵/值對,等等。其中,pod的名字被設置成容器的的主機名,而且可以在容器內通過所有訪問主機名的方式獲得,例如,hostname命令或JAVA中InetAddress.getLocalHost()函數調用。pod的名字和namespace還可以通過downwardAPI進行訪問。對容器而言,用戶在pod資源配置文件中自定義的環境變量的可訪問性與在Docker鏡像中指定的環境變量是一樣的。downwardAPI示例如下:
[root@k8s-master downwardapi]# cat test-downwardapi.yaml apiVersion: v1 kind: Pod metadata:name: test-downwardaoi-volumelabels:name: test-downwardaoi-volumezone: us-eastcluster: test-cluster1annotations:build: twobuilder: zhenyuyaodidiao spec:containers:- name: test-hostpathimage: registry:5000/back_demon:1.0volumeMounts:- name: podinfomountPath: /home/laizy/podinforeadOnly: falsecommand:- /run.shvolumes:- name: podinfodownwardAPI:items:- path: "pod_name"fieldRef:fieldPath: metadata.name- path: "pod_namespace"fieldRef:fieldPath: metadata.namespace- path: "pod_labels"fieldRef:fieldPath: metadata.labels- path: "pod_annotations"fieldRef:fieldPath: metadata.annotations[root@k8s-master downwardapi]# kubectl create -f test-downwardapi.yaml pod "test-downwardaoi-volume" created[root@k8s-master downwardapi]# kubectl exec -ti test-downwardaoi-volume /bin/bash [root@test-downwardaoi-volume /]# cd /home/laizy/podinfo/ [root@test-downwardaoi-volume podinfo]# ls pod_annotations pod_labels pod_name pod_namespace [root@test-downwardaoi-volume podinfo]# cat pod_annotations build="two" builder="zhenyuyaodidiao" kubernetes.io/config.seen="2017-03-22T09:42:11.832955302+08:00" kubernetes.io/config.source="api" [root@test-downwardaoi-volume podinfo]# cat pod_labels cluster="test-cluster1" name="test-downwardaoi-volume" zone="us-east" [root@test-downwardaoi-volume podinfo]# cat pod_name test-downwardaoi-volume [root@test-downwardaoi-volume podinfo]# cat pod_name test-downwardaoi-volume [root@test-downwardaoi-volume podinfo]# cat pod_namespace default [root@test-downwardaoi-volume podinfo]# exit exit
?
1.2集群信息
我們在前面已經討論過Kubernetes服務發現的兩種機制:DNS和環境變量。service環境變量屬于集群信息,在容器創建時由Kubemetes集群API注人,在容器內以環境變量或域名的方式被訪問。
2.容器鉤子
容器鉤子是Kubemetes針對容器生命周期管理引入的事件處理機制,它負責監聽Kubemetes對容器生命周期的管理信息,并將這些信息以廣播的形式通知給容器。然后執行相應的回調函數。
2.1容器鉤子類型
Kubemetes支持兩種類型的容器鉤子,分別為PostStart和PreStop。
PostStart。該鉤子在容器被創建后立刻觸發,通知容器它已經被創建。該鉤子不需要向其所對應的hook handler傳人任何參數。如果該鉤子對應的hook handler執行失敗,則該容器會被殺死,并根據該容器的重啟策略決定是否要重啟該容器。
PreStop。該鉤子在容器被刪除前觸發,其所對應的hook handler必須在刪除該容器的請求發送給Docker daemon之前完成。在該鉤子對應的hook handler完成后不論執行的結果如何,Docker daemon會發送一個SGTERN信號量給Docker daemon來刪除該容器。同樣地。該鉤子也不需要傳人任何參數
2.2hook handler執行
當一個容器管理hook發生時,管理系統將會在容器中調用注冊的hook handler。其中hook handler通過在包含該容器的pod資源配置文件的Lifecycle字段中定義來完成注冊。注意,當hook handler在執行時,其他對該容器所在pod的管理動作將被阻塞除非該容器異常退出。而如果你自定義的hook handler阻塞時,其他對pod的管理操作包括容器健康檢查將不會發生,直到hook handler繼續執行完畢。因此,一般建議用戶自定義的hook handler代碼盡可能地輕量化,盡管確實有一些場景的hook handler需要長時間運行(例如在容器時退出保存運行狀態等)。
2.3hook handler的執行方式
hook handler是hook在容器內執行的回調函數,也即hook暴露給容器的方式。Kubemetes支持兩種不同的hook handler類型,分別是Exec和HTTPGet。
Exec。在容器的cgroup和namespace內啟動一個新進程來執行指定的命令,由該命令消耗的資源全部要計人容器的消耗。正如在之前容器健康檢查中提到的,如果Exec執行的命令最后在標準輸出stdout的結果為0k,就代表handler執行成功,否則就被認為執行異常,并且Kuberlet將強制重新啟動該容器。
HTTPGet。向容器的指定接口發起一個HTTP請求作為handler的具體執行內容,并通過返回的HTTP狀態碼來判斷該請求執行是否成功。
綜上,hook機制為用戶提供了一種能夠根據容器生命周期及其上下文的變化來觸發不同操作的協作方法。這對于很多需要精細控制容器的場景是非常有用的,比如在容器結束前執行一些清理工作來保證其“優雅”退出。以下給出hook執行exec的示例:
[root@k8s-master hook]# cat test-lifecycle-hostpath.yaml apiVersion: v1 kind: Pod metadata:labels:name: test-lifecycle-hostpathrole: mastername: test-lifecycle-hostpath spec:containers:- name: test-lifecycle-hostpathimage: registry:5000/back_demon:1.0lifecycle:postStart:exec:command:- "touch"- "/home/laizy/test/hostpath/post-start"preStop:exec:command:- "touch"- "/home/laizy/test/hostpath/pre-stop"volumeMounts:- name: testhostmountPath: /home/laizy/test/hostpathreadOnly: falsecommand:- /run.shvolumes:- name: testhosthostPath:path: /home/testhost [root@k8s-master hook]# date 2017年 03月 22日 星期三 10:21:58 CST [root@k8s-master hook]# kubectl create -f test-lifecycle-hostpath.yaml pod "test-lifecycle-hostpath" created [root@k8s-master hook]# kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE test-lifecycle-hostpath 1/1 Running 0 13s 10.0.9.3 k8s-node-3 [root@k8s-master hook]# date 2017年 03月 22日 星期三 10:22:52 CST [root@k8s-master hook]# kubectl delete pod test-lifecycle-hostpath pod "test-lifecycle-hostpath" deleted
在node3上查看外掛出來的路徑上,生成了兩個文件,post-start文件是在pod創建之后生成的;pre-stop文件是在pod刪除之前生成的。
[root@k8s-node-3 ~]# ll /home/testhost/ 總用量 0 -rw-r--r--. 1 root root 0 3月 22 10:22 post-start -rw-r--r--. 1 root root 0 3月 22 10:23 pre-stop [root@k8s-node-3 ~]#
?
對應的httpGet示例簡單示意如下:
containers:- name: lifecycleimage: busyboxlifecycle:postStart:exec:command:- "touch"- "/var/log/lifecycle/post-start"preStop:httpGet:path: "/abort"port: 8080
?