小編在這裏向各位博友道個歉,上篇文章確實寫的有些應付,但怎麼說,部署確實因人而異,並且不多有剛剛進公司就讓你搭建一個集羣,通常公司都有本身的集羣,因此小編以爲,側重點不該該在安裝,應該在維護!雖然有些牽強,但小編保證,這一篇絕對有質量!但願看了小編的博客,你們對pod有更深刻的認識。
這篇文章,小編打算介紹關於pod的11個重要的知識點,你們要有耐心的看下去哦!雖然內容比較多,有興趣的朋友能夠細細閱讀,小編會盡量的用比較容易理解的話和圖,去介紹比較重要而且難以理解的地方。php
首先咱們經過yaml定義的方式看看pod中能夠定義哪些內容:node
apiVersion: v1 #版本號 kind: Pod #資源對象類型 metadata: #元數據 name: string #pod的名稱 namespace: string #pod所屬的命名空間 labels: #自定義標籤列表 - name: string annotations: #自定義註解列表 - name: string spec: #pod的容器的詳細定義 containers: - name: string #容器的名稱 image: string #容器的鏡像 imagePullPolicy: [Always|Never|IfNotPresent] #鏡像獲取策略 command: [string] #容器的啓動命令列表 args: [string] #啓動命令參數 workingDir: string #容器的工做目錄 volumeMounts: #掛載到容器內部的存儲卷配置 - name: string mountPath: string #掛載的目錄 readOnly: boolean #是否只讀掛載 ports: #容器暴露的端口列表 - name: string #端口名稱 containerPort: int #容器監聽的端口 hostPort: int #容器所在主機須要監聽的端口 protocol: string #端口協議 env: #容器中的環境變量 - name: string value: string resources: #資源限制設置 limits: #最大使用資源 cpu: string memory: string requests: #請求時資源設置 cpu: string memory: string livenessProbe: #對容器的健康檢查 exec: #經過命令的返回值 command: [string] httpGet: #經過訪問容器的端口的返回的狀態碼 path: string port: number host: string scheme: string httpHeaders: - name: string value: string tcpSocket: #經過tcpSocket port: number initialDelaySeconds: 0 #首次健康檢查時間 timeoutSeconds: 0 #健康檢查的超時時間 periodSeconds: 0 #每次健康檢查的時間間隔 successThreshold: 0 failureThreshold: 0 securityContext: privileged: false restartPolicy: [Always|Never|OnFailure] #pod的重啓策略 nodeSelector: object #指定的運行pod的node標籤 imagePullSecrets: - name: string hostNetwork: false #是否使用主機網絡模式 volumes: #該pod上定義的共享存儲卷列表 - name: string emptyDir: {} #臨時掛載 hostPath: #掛載宿主機目錄 path: string secret: #類型爲secret存儲卷 secretName: string items: - key: string path: string configMap: #類型爲configMap的存儲卷 name: string items: - key: string path: string
是否是一會兒看了這麼多配置,感受有點濛濛的,不要着急,先苦後甜,小編接下來會一一介紹如何使用這些配置,以及這些配置有什麼做用。
Pod的基本用法:
固然這裏小編要強調的是,若是本身定義的image,而且image運行的程序的腳本是後臺調度運行的例:nohup ./start.sh,相似這樣的,若是是在docker中可使用docker run的方式建立並啓動這個容器,當時在kubernetes中,相似這樣後臺的程序,kubelet建立這個容器的pod以後,運行完該命令,就認爲pod執行結束,將馬上銷燬這個pod,若是給這個pod綁定了RC,那麼系統將會根據RC中的pod的副本數從新啓動這個pod,這樣下去會進入無限的死循環中,固然問題出現了確定會有解決辦法,這裏小編向你們介紹一個服務supervisor,說實話,小編也不是很懂它,有時間再把它玩一玩,這裏小編先介紹一下它是如何讓這些後臺啓動的容器持續運行,並知足kubernetes對容器啓動的要求:supervisor提供了一種能夠同時啓動多個後臺進程,並保持supervisor自身在前臺執行的機制。(好吧我知道是廢話,可是很通俗易懂,能就這樣,強行安慰本身,感受很nice)。
接下來建立幾個pod,看看效果,這裏pod能夠由一個或者多個container組成,先建立一個只有一個container的:nginx
#frontend-pod.yaml apiVersion: v1 kind: Pod metadata: name: frontend labels: name: frontend spec: containers: - name: frontend image: docker.io/kubeguide/guestbook-php-frontend env: - name: GET_HOSTS_FROM value: env ports: - containerPort: 80 hostNetwork: true
[root@zy yaml_file]# kubectl create -f frontend-pod.yaml #建立這個pod
建立一個兩個container組合成一個總體的pod對外提供服務:web
apiVersion: v1 kind: Pod metadata: name: redis-php labels: name: redis-php spec: containers: - name: frontend image: docker.io/kubeguide/guestbook-php-frontend:localredis ports: - containerPort: 80 - name: redis image: docker.io/kubeguide/redis-master ports: - containerPort: 6379
這裏有一個container,死了,多是鏡像出了問題,固然重點不在這裏,主要是演示如何運行2個容器在一個pod中有興趣的能夠解決一下這個問題:redis
所謂的靜態的pod就是經過kubelet管理而且僅存在於特定的node上的pod,它們不能經過API server 進行管理,也沒法與RC、deployment、daemonSet進行關聯,而且kubelet也不能對其進行健康檢查。他們老是由kubelet建立,而且總在kubelet所在node上運行。其中建立靜態的pod有兩種方式:配置文件方式和HTTP方式。
① 配置文件方式
這裏個人kubelet的配置文件在/etc/kubernetes/kubelet
而後在配置文件中加入:--config=/k8s/yaml_file/static-web.yamldocker
#static-web.yaml apiVersion: v1 kind: Pod metadata: name: static-web labels: name: static-web spec: containers: - name: static-web image: nginx ports: - name: web containerPort: 80
[root@zy yaml_file]# systemctl restart kubelet #重啓kubelet服務 [root@zy yaml_file]# docker ps #查看本機的容器:docker ps
此時這個靜態的pod就正在建立,而且使用kubectl delete pod pod_name刪除不了這個pod的,只能讓這個pod處於pending狀態,固然只要將該node上的定義這個pod的文件刪除,就能將這個pod從這個node上刪除了。
② HTTP方式:由於簡單這裏就不在演示,只要在kubelet的配置文件中加入:--manifest-url=xxx,kubelet就會按期的從指定的URL中下載pod的定義文件(yaml|json),而後根據定義在本身的node上建立pod。json
這裏的配置管理,就是將程序和配置分離,使程序更加靈活,通常的咱們在打包應用程序爲鏡像,能夠經過環境變量或者外掛volume的方式在建立容器的時候進行配置注入,可是若是機器規模比較大的時候,對多容器進行不一樣的配置注入將十分複雜,因此這裏咱們介紹一種便捷方式configMap。
configMap典型使用場景:
生成容器內部的環境變量
設置容器的啓動命令的參數
以volume的形式掛載爲容器內部的文件或者目錄
在同一個pod中的多個容器之間可以共享pod級別的存儲卷volume,volume能夠被定義爲各類類型,多個容器之間進行各自掛載,將一個volume掛載爲容器內部的目錄:
上圖就是一個pod中有兩個容器同時掛載一個volume共享,其中實現的功能爲:tomcat用於向其中寫日誌,busybox用於向其中讀取日誌:api
#pod-volume-applogs.yaml apiVersion: v1 kind: Pod metadata: name: volume-pod spec: containers: - name: tomcat imagePullPolicy: IfNotPresent image: docker.io/tomcat ports: - containerPort: 8080 volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs - name: logreader image: docker.io/busybox imagePullPolicy: IfNotPresent command: ["sh","-c","tail -f /logs/catalina*.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: - name: app-logs emptyDir: {}
注意 :這裏名稱爲volume-pod的pod中的兩個容器,同時掛載了類型爲emptyDir這種臨時目錄,而且在容器logreader中打印Tomcat容器生成的日誌,咱們經過命令查看:數組
[root@zy yaml_file]# kubectl logs volume-pod -c logreader
這裏的配置管理,就是將程序和配置分離,使程序更加靈活,通常的咱們在打包應用程序爲鏡像,能夠經過環境變量或者外掛volume的方式在建立容器的時候進行配置注入,可是若是機器規模比較大的時候,對多容器進行不一樣的配置注入將十分複雜,因此這裏咱們介紹一種便捷方式configMap。
configMap典型使用場景:
生成容器內部的環境變量
設置容器的啓動命令的參數
以volume的形式掛載爲容器內部的文件或者目錄
configMap用法:configMap以key-value的形式定義,這裏的value能夠是string也能夠是一個文件內容,經過kubectl create configmap 的方式建立configMap。
這裏小編經過這個幾個方面去介紹configMap的用法:
configMap的兩種建立方式:基於yaml文件或者基於命令。
configMap的兩種使用方式:環境變量和volume掛載。
configMap的建立:
① 基於yaml文件tomcat
#cm-appvars.yaml apiVersion: v1 kind: ConfigMap metadata: name: cm-aoovars data: apploglevel: info appdatadir: /var/data
[root@zy yaml_file]# kubectl create -f cm-appvars.yaml #建立configmap [root@zy yaml_file]# kubectl get configmap #查看建立的configmap
[root@zy yaml_file]# kubectl describe configmap cm-aoovars #查看configmap定義的內容
#cm-appconfigfiles.yaml(value爲文件內容) apiVersion: v1 kind: ConfigMap metadata: name: cm-appconfigfiles data: key-serverxml: | xml文件內容 key-loggingproperties: "配置文件內容"
[root@zy yaml_file]# kubectl get configmap cm-appconfigfiles -o yaml #查看詳細內容
② 基於命令
[root@zy yaml_file]# kubectl create configmap cm-figmap --from-file=server.xml
注意:這裏會將文件的名稱爲key,內容爲value,若是目錄下有多個文件,則同時建立,而且文件的名稱爲key,內容爲value。
[root@zy yaml_file]# kubectl create configmap cm-figmap --from-literal=loglevel=info --fromliteral=appdatadir=/var/data
注意:這種方式是指定具體的key-value建立configmap
configMap的使用:
① 經過環境變量的方式使用configmap
apiVersion: v1 kind: Pod metadata: name: cm-test-pod spec: containers: - name: busybox image: docker.io/busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","env|grep APP"] env: - name: APPLOGLEVEL #定義環境變量 valueFrom: configMapKeyRef: name: configMapNAME key: configMap_KEY - name: APPLOGLEVEL #定義環境變量 valueFrom: configMapKeyRef: name: configMapNAME key: configMap_KEY
在kubernetes1.6以後,有一種簡單的定義env的方式:
envFrom: - configMapRef: name: configMapNAME
② 經過volumeMount使用configmap
上面咱們定義了一個基於文件的configmap,接下來看如何使用基於文件的configmap,掛載到具體的pod的容器的目錄下:
#cm-test-pod.yaml apiVersion: v1 kind: Pod metadata: name: cm-test-pod spec: containers: - name: busybox image: kubeguide/tomcat-app:v1 imagePullPolicy: IfNotPresent ports: - containerPort: 8080 volumeMounts: - name: serverxml #引用volumes名稱 mountPath: /configfiles #將confimap中的文件掛載到容器的目錄中 volumes: - name: serverxml configMap: name: configMapName #定義的configmap的名稱 items: #須要掛載的文件的列表 - key: key-serverxml #configmap中定義的key path: server.xml #掛載後的文件名 - key: key-loggingproperties path: logging.properties
注意:若是在定義volume中的configmap時不指定items,那麼volumeMount會在容器的指定目錄下爲每個items生產一個文件名爲key,內容爲value的文件。
ConfigMap的使用限制說明:
Configmap必須在pod建立之間建立
ConfigMap受到namespace的限制,只有同一個命名空間下才能引用
靜態的pod沒法使用ConfigMap
在使用volumeMount掛載的時候,configMap基於items建立的文件會總體的將掛載數據卷的容器的目錄下的文件所有覆蓋
在咱們建立pod後,系統就會給其分配惟一的名字、IP、而且處於某個namspace下面,那麼這些信息咱們如何獲取呢?經過Downward API的方式。
Downward API能夠經過如下獲得兩種方式將pod的信息導入到container中:
環境變量,用於單個變量,能夠將pod信息和container信息注入到容器中
Volume掛載:將數組類信息生成文件掛載到容器內部。
實例:
① 環境變量的方式
#將pod信息注入爲環境變量 apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c","env"] env: - name: MY_POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: MY_POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: MY_POD_IP valueFrom: fieldRef: fieldPath: status.podIP
[root@zy yaml_file]# kubectl log dapi-test-pod #查看
#daip-test-pod-container-vars.yaml將容器資源信息注入爲環境變量 apiVersion: v1 kind: Pod metadata: name: daip-test-pod-container-vars spec: containers: - name: test-container image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c"] args: - while true; do echo -en "\n"; printenv MY_CPU_REQUEST MY_CPU_LIMIT; printenv MY_MEM_REQUEST MY_MEM_LIMIT; sleep 60; done; resources: requests: memory: "32Mi" cpu: "125m" limits: memory: "40Mi" cpu: "130m" env: - name: MY_CPU_REQUEST valueFrom: resourceFieldRef: containerName: test-container resource: requests.cpu - name: MY_CPU_LIMIT valueFrom: resourceFieldRef: containerName: test-container resource: requests.cpu - name: MY_CPU_REQUEST valueFrom: resourceFieldRef: containerName: test-container resource: limits.cpu - name: MY_MEM_REQUEST valueFrom: resourceFieldRef: containerName: test-container resource: requests.memory - name: MY_MEM_LIMIT valueFrom: resourceFieldRef: containerName: test-container resource: limits.memory
[root@zy yaml_file]# kubectl logs daip-test-pod-container-vars
② Volume掛載方式
![](https://s1.51cto.com/images/blog/201905/18/33b1db246d451ae70c8bc2738341fea9.png?x-oss-process=image/watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=)#dapi-test-pod-volume.yaml apiVersion: v1 kind: Pod metadata: name: dapi-test-pod-volume labels: zone: us-est-coast cluster: test-cluster rack: rack-22 annotations: build: two builder: john-doe spec: containers: - name: test-container image: busybox imagePullPolicy: IfNotPresent command: ["/bin/sh","-c"] args: - while true;do if [[ -e /etc/labels ]];then echo -en "\n\n";cat /etc/labels; fi; if [[ -e /etc/annotations ]];then echo -en "\n\n";cat /etc/annotations; fi; sleep 60; done; volumeMounts: - name: podinfo mountPath: /etc readOnly: false volumes: - name: podinfo downwardAPI: items: - path: "labels" fieldRef: fieldPath: metadata.labels - path: "annotations" fieldRef: fieldPath: metadata.annotations
注意:經過設置items,將會以path的名稱生成文件。
[root@zy yaml_file]# kubectl logs dapi-test-pod-volume
Downward API的做用:在某些集羣中,集羣中的節點須要將自身標識以及進程綁定的IP地址等信息預習寫入配置文件,進程啓動時讀取這些信息,而後發佈到相似於服務註冊中心中,作集羣的節點的自動發現功能。那麼Downward API就大有用處,它能夠先編寫一個預啓動腳本或者init container,經過環境變量或者文件的方式獲取pod自身的名稱、IP地址等信息,而後寫入主程序配置中。
pod在整個聲明週期中有不少狀態,瞭解其各類狀態對於集羣排錯大有幫助:
當某個pod異常退出或者健康檢查失敗的時候,kubelet會根據pod定義中的spec.RestartPolicy的設置來進行相應的操做。
Pod的重啓策略包括:
Always:當容器失效時,由kubelet自動重啓
OnFailure:當容器終止運行且退出碼不爲0時,由kubelet自動重啓
Nerver:永遠不重啓
Pod的重啓策略,與管理其的資源對象息息相關,RC、job、Daemonset以及經過kubelet直接管理的靜態的pod,每一種控制器對pod的重啓策略都有要求:
RC和Daemonset:必須設置爲Always。
Job:OnFailure或者Nerver,確保容器執行完成不在重啓
靜態pod:在pod失效時自動重啓。(注意靜態pod不會被健康檢查)
就像HDFS中的DataNode會定時發送心跳給namenode同樣,k8s集羣中經過探針的方式給Pod定時作健康檢查,一旦符合定義的狀況,就執行相應的重啓策略。
健康檢查分爲如下兩種探針:
LivenessProbe探針: 判斷容器是否存活(runnning狀態),若是探測到容器不健康,則kubelet殺死該容器,而且根據重啓策略作相應處理,若是容器中沒有LivenessProbe探針,那麼kubelet認爲該容器的LivenessProbe探針一直返回「Success」
ReadinessProbe探針: 用於判斷容器是否啓動完成(ready狀態),能夠接受請求。若是ReadinessProbe探針探測到失敗,則pod的狀態被修改。而且EndPoint Controller將從service的EndPoint中刪除包含該容器所在pod的EndPoint。
接下來咱們重點介紹一下LivenessProbe探針如何判斷pod是否健康,這裏有三種實現方式:
ExecAction:在容器中執行一個命令,若是該命令返回的狀態碼爲0,表示該容器正常
TCPSocketAction:經過容器的IP地址和端口執行TCP檢查,可以創建TCP鏈接,表示該容器正常
HTTPGetAction:經過容器的IP和端口以及路徑調用HTTP get方法,若是相應的狀態碼大於等於200而且小於400,則認爲該容器正常
實例演示:
① ExecAction
apiVersion: v1 kind: Pod metadata: labels: test:liveness name: liveness-exec spec: containers: - name: liveness images: gcr.io/google_containers/busybox args: - /bin/sh - -c - echo ok > /tmp/health; sleep 10 ;rm -rf /tmp/health;sleep 10 ; livenessProbe: exec: command: - cat - /tmp/health initialDelaySeconds: 15 #初次健康檢查時間 timeoutSeconds: 1 #超時時間
這裏注意:咱們設置了livenessProbe探針初次檢查時間爲15秒,可是程序中將10以後刪除檢查的文件,這裏cat /tmp/health 這個命令執行失敗,狀態碼返回不爲0,致使kubelet殺掉該進程,並根據相應的重啓策略進行操做。
② TCPSocketAction
apiVersion: v1 kind: Pod metadata: labels: test:liveness name: liveness-exec spec: containers: - name: nginx images: nginx ports: - containerPort: 80 livenessProbe: tcpSocket: port: 80 initialDelaySeconds: 15 #初次健康檢查時間 timeoutSeconds: 1 #超時時間
③ HTTPGetAction
apiVersion: v1 kind: Pod metadata: labels: test:liveness name: liveness-exec spec: containers: - name: nginx images: nginx ports: - containerPort: 80 livenessProbe: httpGet: path: /_status/helthz port: 80 initialDelaySeconds: 30 #初次健康檢查時間 timeoutSeconds: 1 #超時時間
這裏小編強調一下:
initialDelaySeconds:啓動容器後首次健康檢查的時間
timeoutSeconds:健康檢查發送請求後等待相應的時間
看到這裏你們必定腦子都炸了,這裏小編想說一下,後面還有不少,這裏小編把pod介紹分爲兩篇博文向你們介紹,
文章參考至《kubernetes權威指南》