k8s pod 詳述


 

Kubernetes |Pod 深入理解與實踐

這篇文章參考自《Kubernete權威指南》,對其中的相關章節做了一些總結,從下面十個點對pod進行深入講解,也會有些配置的實例,希望對大家學習kubernetes帶來些許幫助。

1pod定義詳解
2pod到底是什么
3靜態pod
4pod容器共享volume
5pod的配置管理
6pod的生命周期和重啟策略
7pod健康檢查
8玩轉pod調度
9pod的擴容和縮容
10pod的滾動升級

1pod定義詳解

下面是一個完整的yaml格式定義的文件,注意格式,子集包含關系,不要有tab,要用空格。不是所有的元素都要寫,按照實際應用場景配置即可。

apiVersion: v1            //版本 kind: pod //類型,pod metadata: //元數據 name: String //元數據,pod的名字 namespace: String //元數據,pod的命名空間 labels: //元數據,標簽列表 - name: String //元數據,標簽的名字 annotations: //元數據,自定義注解列表 - name: String //元數據,自定義注解名字 spec: //pod中容器的詳細定義 containers: //pod中的容器列表,可以有多個容器 - name: String image: String //容器中的鏡像 imagesPullPolicy: [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: Srting memory: String requeste: cpu: String memory: String livenessProbe: //pod內容器健康檢查的設置 exec: command: [String] httpGet: //通過httpget檢查健康 path: String port: number host: String scheme: Srtring httpHeaders: - name: Stirng value: String tcpSocket: //通過tcpSocket檢查健康 port: number initialDelaySeconds: 0//首次檢查時間 timeoutSeconds: 0 //檢查超時時間 periodSeconds: 0 //檢查間隔時間 successThreshold: 0 failureThreshold: 0 securityContext: //安全配置 privileged: falae restartPolicy: [Always|Never|OnFailure]//重啟策略 nodeSelector: object //節點選擇 imagePullSecrets: - name: String hostNetwork: false //是否使用主機網絡模式,默認否 volumes: //在該pod上定義共享存儲卷 - name: String meptyDir: {} hostPath: path: string secret: //類型為secret的存儲卷 secretName: String item: - key: String path: String configMap: //類型為configMap的存儲卷 name: String items: - key: String path: String 

2pod到底是什么

kubernetes中的一切都可以理解為是一種資源對象,pod,rc,service,都可以理解是 一種資源對象。podd的組成示意圖如下:

 
QQ截圖20170405161659.png

由一個叫”pause“的根容器,加上一個或多個用戶自定義的容器構造。pause的狀態帶便了這一組容器的狀態,pod里多個業務容器共享pod的Ip和數據卷。

我是這樣理解的,在kubernetes環境下,pod是容器的載體,所有的容器都是在pod中被管理,一個或多個容器放在pod里作為一個單元方便管理。還有就是docker和kubernetes也不是一家公司的,如果做一個編排部署的工具,你也不可能直接去管理別人公司開發的東西吧,然后就把docker容器放在了pod里,在kubernetes的集群環境下,我直接管理我的pod,然后對於docker容器的操作,我把它封裝在pod里,不直接操作。

3靜態pod

靜態Pod是由kubelet進行管理的僅存在於特定Node上的pod.它們不能通過API Server進行管理,無法與ReplicationController,Ddeployment或者DaemonSet進行關聯,也無法進行健康檢查。

所以我覺得這個靜態pod沒啥用武之地啊,就不詳細的寫下去了,偷個懶,嘻嘻。

4pod容器共享volume

在pod中定義容器的時候可以為單個容器配置volume,然后也可以為一個pod中的多個容器定義一個共享的pod 級別的volume。 那為啥要這樣做呢,比如你在一個pod里定義了一個web容器,然后把生成的日志文件放在了一個文件夾,你還定義了一個分析日志的容器,那這個時候你就可以把這放日志的文件配置為共享的,這樣一個容器生產,一個容器度就好了。

下面是一個使用共享volume的配置示例

apiVersion: v1
kind: Pod
metadata:
 name: volume-pod
spec:
  containers:
  - name: tomcat
    image: tomcat
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: app-logs
      mountPath: /usr/local/tomcat/logs - name: loganalysis image: loganalysis volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs volumes: - name: app-logs emptyDir: {} 

這個配置文件除了“emptyDir: {}”這個地方有點詭異以為,其他地方我估計大家一看就能明白,在最下面定義了一個叫“app-logs”的volume,然后上面的兩個容器來使用它就好了。

然后現在來說說“emptyDir: {}”,其實這個地方有三種選擇

  volumes:
  - name: app-logs
  emptyDir: {}
  
  
  volumes:
  - name: app-logs
  hostPth: 
    path: "/data" volumes: - name: app-logs gcePersistenDisk: pdName: my-data-disk //my-data-disk需要先創建好 fsType: ext4 

emptyDir是Pod分配到Node后創建的,他的初始內容為空,pod在Node上移除以后也就被銷毀了。

hostPath是掛載到宿主機上的目錄,比較適用於需要永久保存的數據

gcePersistenDisk 表示使用谷歌公有雲提供的磁盤
創建my-data-disk: gcloud compute disks create --size=500GB --zone=us-centrall-a my-data-disk

5pod的配置管理

應用部署的一個最佳實踐,就是將應用所需的配置信息與程序進行分離

kubernetes 提供了一種的集群配置管理方案,即ConfigMap,就是將一些環境變量或者配置文件定義為configmap,放在kubernetes中,可以讓其他pod 調用
configmap 有以下典型的用法

1 生成為容器內的環境變量

2 設置容器啟動命令的啟動參數(需設置為環境變量)

3 以volume的形式掛載為容器內部的文件或目錄

局限:

1ConfigMap 必須在pod之前創建

2ConfigMap也可以定於屬於某個NameSpace,只有處於相同NameSpace的pod可以應用它

3ConfigMap中的配額管理還未實現

4如果是volume的形式掛載到容器內部,只能掛載到某個目錄下,該目錄下原有的文件會被覆蓋掉

5靜態不能用configmap(靜態pod 不受API server 管理)

下面是使用ConfigMap的示例

1定義一個ConfigMap 配置文件 cm-appvars.yaml

apiVersion: v1
kind: ConfigMap
metadata:
 name: cm-appvars
data:
  apploglevel: info
  appdatadir: /var/date 

2創建ConfigMap: kubectl create -f cm-appvars.yaml

3使用ConfigMap(環境變量的形式)

apiVersion: v1
kind: Pod
metadata:
 name: cm-test-pod
spec:
  containers:
  - name: cm-test
    image: busybux
    env:
    - name: APPLOGLEVEL
      vlaueFrom:
        configMapKeyRef:
          name: cm-appvars   //要和之前創建的ConfigMap的name對應 key: apploglevel - name: APPDATADIR vlaueFrom: configMapKeyRef: name: cm-appvars //要和之前創建的ConfigMap的name對應 key: appdatadir 

除了可以定義簡單的k-v鍵值對,還可以將整個配置文件定義成ConfigMap
比如server.xml logging.properties(使用volumeMount的形式,掛載到容器內部)

1定義一個ConfigMap 配置文件 cm-jdbcproperties.yaml

apiVersion: v1
kind: ConfigMap
metadata:
 name: cm-jdbcproperties
data:
  key-jdbcproperties: |
    JDBC_DRIVER_CLASS_NAME=com.mysql.jdbc.Driver
    JDBC_URL=jdbc:mysql://localhost:3306/bz_argon?useUnicode=true&characterEncoding=utf8 JDBC_USER_NAME=root JDBC_PASSWORD=maojiancai JDBC_INITIALSIZE=10 JDBC_MAXACTIVE=20 JDBC_MAXIDLE=20 JDBC_MINIDLE=10 JDBC_MAXWAIT=60000 JDBC_VALIDATIONQUERY=SELECT 1 FROM DUAL JDBC_TESTONBORROW=false JDBC_TESTONRETURN=false JDBC_TESTWHILEIDLE=true JDBC_TIMEBETWEENEVICTIONRUNSMILLIS=6000 JDBC_MINEVICTABLEIDLETIMEMILLIS=25200000 JDBC_REMOVEABANDONED=true JDBC_REMOVEABANDONEDTIMEOUT=1800 JDBC_LOGABANDONED=true 

2創建ConfigMap: kubectl create -f cm-jdbcproperties.yaml

3使用ConfigMap(使用volumeMount的形式)

apiVersion: v1
kind: Pod
metadata:
 name: cm-test-app
spec:
  containers:
  - name: cm-test-app
    image: cm-test-app
    ports:
    - containerPort: 8080 volumeMounts: - name: jdbcproperties //應用下面定義的volumes名 mountPath: /configfiles volumes: - name: jdbcproperties //volumes名 configMap: name: cm-jdbcproperties//這個名字是第二步創建的configMap items: - key: key-jdbcproperties path: jdbc.properties 

再提醒一下;

如果是volume的形式掛載到容器內部,只能掛載到某個目錄下,該目錄下原有的文件會被覆蓋掉

6pod的生命周期和重啟策略

pod一共有四種狀態

狀態值 描述
Pending APIserver已經創建該server,但pod內有一個或多個容器的鏡像還未創建,可能在下載中。
Running Pod內所有的容器已創建,且至少有一個容器處於運行狀態,正在啟動或重啟狀態
Failed Pod內所有容器都已退出,其中至少有一個容器退出失敗
Unknown 由於某種原因無法獲取Pod的狀態比如網絡不通。
重啟策略 描述
Always 容器失效時,即重啟
OnFailure 容器終止運行,且退出碼不為0 時重啟
Never P不重啟

Pod的重啟策略應用於Pod內的所有容器,由Pod所在Node節點上的Kubelet進行判斷和重啟操作。重啟策略有以下三種:

重啟策略 描述
Always 容器失效時,即重啟
OnFailure 容器終止運行,且退出碼不為0 時重啟
Never P不重啟

7pod健康檢查

Kubernetes內部通過2種探針,實現了對Pod健康的檢查

LivenessProbe探針:判斷容器是否存活(running)
ReadinessProbe探針: 用於判斷容器是否啟動完成(ready)

LivenessProbe探針通過三種方式來檢查容器是否健康

(1)ExecAction:在容器內部執行一個命令,如果返回碼為0,則表示健康

示例:

apiVersion: v1
kind: Pod
metadata:
 name: liveness
spec:
  containers:
  - name: liveness
    image: liveness
    args: 
    - /bin/sh
    - -c
    - echo ok > /tmp/healthy: sleep 10; rm - rf /tmp/healthy; sleep 600 livenessProbe: exec: command: - cat - /tmp/health initialDelaySeconds: 15 timeoutSeconds: 1 

(2)TcpAction:通過IP 和port ,如果能夠和容器建立連接則表示容器健康

示例:

apiVersion: v1
kind: Pod
metadata:
 name: pod-with-healthcheck spec: containers: - name: nginx image: nginx ports: - containerPort: 80 livenessProbe: tcpSocket: port: 80 initialDelaySeconds: 15 timeoutSeconds: 1 

(3)HttpGetAction:發送一個http Get請求(ip+port+請求路徑)如果返回狀態嗎在200-400之間則表示健康

示例:

apiVersion: v1
kind: Pod
metadata:
 name: pod-with-healthcheck spec: containers: - name: nginx image: nginx ports: - containerPort: 80 livenessProbe: httpGet: path: /_status/healthz //請求路徑 port: 80 initialDelaySeconds: 15 timeoutSeconds: 1 

8玩轉pod調度

在kubernetes系統中,pod在大部分場景下都只是容器的載體而已,通常需要通過Deployment,DaemonSet,Job等對象來完成Pod的調度與自動控制功能。

(1)RC,Deployment: 全自動調度

RC的主要功能之一就是自動部署一個容器應用的多份副本,以及持續監控,保持集群內有一定數量的副本數量(配置文件指定了副本數量)

NodeSelector: 定向調度

kubernetes中的Schduler 負責實現pode的調度,他會根據一些復雜的算法,把pod調度到某一個Node上,如果你想指定某個Pod需要指定在某個Node上則可以通過NodeSelector定向調度

示例:

1首先通過kubectl給node打上標簽:

格式: kubectl label nodes <node-name> <label-key>=<label-value>

kubectl label nodes node1 zone=north

2在pod定義里選擇某個node

apiVersion: v1
kind: Pod
metadata:
name: pod-with-healthcheck spec: containers: - name: nginx image: nginx ports: - containerPort: 80 nodeSelector: zone: north 

除了有定向的,還有親和性的調度 NodeAffinity,符合某種條件的,比如,某個值大於1的(可以理解為模糊匹配),NodeAffinity有In NotIn Exists DoesNotExists Gt Lt 等操作規則來選擇Node.

(2)DaemonSet: 特點場景調度

DaemonSet,用於管理在集群中每個Node上只運行一份Pod的副本實例,比如在每節點上都運行有且只有一個fluentd

示例:配置使得在每個節點上都有一個fluentd 容器

apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
 name: fluentd-cloud-logging
 namespace: kube-system labels: k8s-app: fluentd-cloud-logging spec: template: metadata: namespace: kube-system labels: k8s-app: fluentd-cloud-logging spec: containers: - name: fluentd-cloud-logging images: gcr.io/google_containers/fluentd-elasticsearch:1.17 resources: limits: cpu: 100m memory: 200Mi env: - name: FLUENTD_ARGS value: -q volumeMounts: - name: varlog mountPath: /var/log readOnly: false - name: containers mountPath: /var/lib/docker/containers volumes: - name: containers hostPath: path: /var/lib/docker/containers - name: varlog hostPath: path: /var/log 

(3)Job: 批處理調度
我們可以通過Kubernetes job資源對象來定義並啟動一個批處理任務。批處理任務通常並行(或者串行)啟動多個計算機進程去處理一批工作項。·

9pod的擴容和縮容

1通過scale來完成擴容或縮容

假設 redis-slave 這個pod原來定義了5個副本(reolics:5)

擴容到10個,執行命令: kubectl scale rc redis-slave --replicas=10

縮容到2個,執行命令:kubectl scale rc redis-slave --replicas=2

2動態擴容縮容(HPA)

通過對cpu使用率的監控,HPA(Horizontal Pod Autoscaler),來動態的擴容或縮容。pod cpu使用率是考heapster組件來獲取的,所以要預先安裝好。

創建HPA:

在創建HPA前需要已經存在一個RC或Deployment對象,並且該RC或Deployment中的Pod必須定義 resource.request.cpu的請求值,否則無法獲取cpu使用情導致HPA 無法工作

假設現在有一個php-apache RC

1通過kubectl autoscale 命令創建

kubectl autoscale rc php-apache --min=1 --max=10 --cpu-percent=50

含義:在1-10之間調整副本數量,使CPU使用率維持在50%左右

2通過配置文件的方式創建HPA

apiVersion: autoscaling/v1
kind: HorizaontalPodAutoscaler
metadata:
 name: php-apache
spec:
 scaleTargetRef:
   apiVersion: v1
   kind: ReplicationController
   name: php-apache
 minReplicas: 1
 maxrReplicas: 10
 targetCPUUtilizationPercentage: 50

10pod的滾動升級

滾動升級通過kubectl rolling-update 命令一鍵完成。

示例:假設現在運行的redis-master的pod是1.0版本,現在需要升級到2.0版本。

創建redis-master-controller-v2.yaml

apiVersion: v1
kind: ReplicationController
metadata:
 name: redis-master-v2
 labels:
  name: redis-master
  version: v2
spec:
  replicas: 1 selector: name: redis-master version: v2 template: metadata: labels: name: redis-master version: v2 spec: containers: - name: master images: kubeguide/redis-master:2.0 ports: - containerPort: 6379 

更新:kubectl rolling-update redis-master -f redis-master-controller-v2.yaml

需要注意到是:

rc的名字(name)不能與舊的rc的名字相同

在selector中至少有一個Label與舊的Label不同。以標識其為新的RC


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM