kubernetes之pod超詳細解讀--第一篇(三)

   小編在這裏向各位博友道個歉,上篇文章確實寫的有些應付,但怎麼說,部署確實因人而異,並且不多有剛剛進公司就讓你搭建一個集羣,通常公司都有本身的集羣,因此小編以爲,側重點不該該在安裝,應該在維護!雖然有些牽強,但小編保證,這一篇絕對有質量!但願看了小編的博客,你們對pod有更深刻的認識。
   這篇文章,小編打算介紹關於pod的11個重要的知識點,你們要有耐心的看下去哦!雖然內容比較多,有興趣的朋友能夠細細閱讀,小編會盡量的用比較容易理解的話和圖,去介紹比較重要而且難以理解的地方。php

1. pod的基本定義和用法

  首先咱們經過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對外提供服務:
kubernetes之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

kubernetes之pod超詳細解讀--第一篇(三)
  這裏有一個container,死了,多是鏡像出了問題,固然重點不在這裏,主要是演示如何運行2個容器在一個pod中有興趣的能夠解決一下這個問題:
kubernetes之pod超詳細解讀--第一篇(三)redis

2. 靜態pod

  所謂的靜態的pod就是經過kubelet管理而且僅存在於特定的node上的pod,它們不能經過API server 進行管理,也沒法與RC、deployment、daemonSet進行關聯,而且kubelet也不能對其進行健康檢查。他們老是由kubelet建立,而且總在kubelet所在node上運行。其中建立靜態的pod有兩種方式:配置文件方式HTTP方式
① 配置文件方式
這裏個人kubelet的配置文件在/etc/kubernetes/kubelet
kubernetes之pod超詳細解讀--第一篇(三)
而後在配置文件中加入:--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

kubernetes之pod超詳細解讀--第一篇(三)
kubernetes之pod超詳細解讀--第一篇(三)
  此時這個靜態的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

3.pod容器共享volume

  這裏的配置管理,就是將程序和配置分離,使程序更加靈活,通常的咱們在打包應用程序爲鏡像,能夠經過環境變量或者外掛volume的方式在建立容器的時候進行配置注入,可是若是機器規模比較大的時候,對多容器進行不一樣的配置注入將十分複雜,因此這裏咱們介紹一種便捷方式configMap。
configMap典型使用場景:
 生成容器內部的環境變量
 設置容器的啓動命令的參數
 以volume的形式掛載爲容器內部的文件或者目錄
在同一個pod中的多個容器之間可以共享pod級別的存儲卷volume,volume能夠被定義爲各類類型,多個容器之間進行各自掛載,將一個volume掛載爲容器內部的目錄:
kubernetes之pod超詳細解讀--第一篇(三)
上圖就是一個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

kubernetes之pod超詳細解讀--第一篇(三)

4. pod的配置管理

  這裏的配置管理,就是將程序和配置分離,使程序更加靈活,通常的咱們在打包應用程序爲鏡像,能夠經過環境變量或者外掛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

kubernetes之pod超詳細解讀--第一篇(三)

[root@zy yaml_file]# kubectl describe configmap cm-aoovars  #查看configmap定義的內容

kubernetes之pod超詳細解讀--第一篇(三)

#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  #查看詳細內容

kubernetes之pod超詳細解讀--第一篇(三)
② 基於命令

[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建立的文件會總體的將掛載數據卷的容器的目錄下的文件所有覆蓋

5.在容器中獲取pod的信息

  在咱們建立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  #查看

kubernetes之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

kubernetes之pod超詳細解讀--第一篇(三)

② 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

kubernetes之pod超詳細解讀--第一篇(三)
Downward API的做用:在某些集羣中,集羣中的節點須要將自身標識以及進程綁定的IP地址等信息預習寫入配置文件,進程啓動時讀取這些信息,而後發佈到相似於服務註冊中心中,作集羣的節點的自動發現功能。那麼Downward API就大有用處,它能夠先編寫一個預啓動腳本或者init container,經過環境變量或者文件的方式獲取pod自身的名稱、IP地址等信息,而後寫入主程序配置中。

6.pod的聲明週期和重啓策略

  pod在整個聲明週期中有不少狀態,瞭解其各類狀態對於集羣排錯大有幫助:
kubernetes之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不會被健康檢查)

7 .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介紹分爲兩篇博文向你們介紹,

後續部分URL:http://www.javashuo.com/article/p-vbawsosa-dd.html

文章參考至《kubernetes權威指南》

相關文章
相關標籤/搜索