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