1. Pod的定義檔案
apiVersion: v1kind: Podmetadata: name: string namaspace: string labels: - name: string annotations: - name: stringspec: containers: - name: string images: string imagePullPolice: [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: int host: string scheme: string httpHeaders: - name: string value: string tcpSocket: port: int initialDelaySeconds: number timeoutSeconds: number periodSeconds: number successThreshold: 0 failureThreshold: 0 securityContext: privileged: false restartPolicy: [Always | Never | OnFailure] nodeSelector: object imagePullSecrets: - name: string hostNetwork: false volumes: - name: string emptyDir: {} hostPath: path: string secret: secretName: string items: - key: string path: string configMap: name: string items: - key: string path: string
2. Pod的基本用法
2.1. 說明 Pod實際上是容器的集合,在k8s中對運行容器的要求為:容器的主程式需要一直在前台運行,而不是後台運行。應用可以改造成前台啟動並執行方式,例如Go語言的程式,直接運行二進位檔案;java語言則運行主類;tomcat程式可以寫個運行指令碼。或者通過supervisor的進程管理工具,即supervisor在前台運行,應用程式由supervisor管理在後台運行。具體可參考supervisord。 當多個應用之間是緊耦合的關係時,可以將多個應用一起放在一個Pod中,同個Pod中的多個容器之間互相訪問可以通過localhost來通訊(可以把Pod理解成一個虛擬機器,共用網路和儲存卷)。
2.2. Pod相關命令
| 操作 |
命令 |
說明 |
| 建立 |
kubectl create -f frontend-localredis-pod.yaml |
|
| 查詢Pod運行狀態 |
kubectl get pods –namespace=<NAMESPACE> |
|
| 查詢Pod詳情 |
kebectl describe pod <POD_NAME> –namespace=<NAMESPACE> |
該命令常用來排查問題,查看Event事件 |
| 刪除 |
kubectl delete pod <POD_NAME> ;kubectl delete pod –all |
|
| 更新 |
kubectl replace pod.yaml |
|
3. 靜態pod
靜態Pod是由kubelet進行管理,僅存在於特定Node上的Pod。它們不能通過API Server進行管理,無法與ReplicationController、Deployment或DaemonSet進行關聯,並且kubelet也無法對其健全狀態檢查。
靜態Pod總是由kubelet建立,並且總在kubelet所在的Node上運行。
建立靜態Pod的方式: 3.1. 通過設定檔方式
需要設定kubelet的啟動參數“–config”,指定kubelet需要監控的設定檔所在目錄,kubelet會定期掃描該目錄,並根據該目錄的.yaml或.json檔案進行建立操作。靜態Pod無法通過API Server刪除(若刪除會變成pending狀態),如需刪除該Pod則將yaml或json檔案從這個目錄中刪除。
例如:
配置目錄為/etc/kubelet.d/,配置啟動參數:–config=/etc/kubelet.d/,該目錄下放入static-web.yaml。
apiVersion: v1kind: Podmetadata: name: static-web labels: name: static-webspec: containers: - name: static-web image: nginx ports: - name: web containerPort: 80
4. Pod容器共用Volume
同一個Pod中的多個容器可以共用Pod層級的儲存卷Volume,Volume可以定義為各種類型,多個容器各自進行掛載,將Pod的Volume掛載為容器內部需要的目錄。
例如:Pod層級的Volume:”app-logs”,用於tomcat向其中寫記錄檔,busybox讀記錄檔。
pod-volumes-applogs.yaml
apiVersion: v1kind: Podmetadata: name: volume-podspec: containers: - name: tomcat image: tomcat ports: - containerPort: 8080 volumeMounts: - name: app-logs mountPath: /usr/local/tomcat/logs - name: busybox image: busybox command: ["sh","-c","tailf /logs/catalina*.log"] volumeMounts: - name: app-logs mountPath: /logs volumes: - name: app-logs emptuDir: {}
查看日誌 kubectl logs <pod_name> -c <container_name> kubectl exec -it <pod_name> -c <container_name> – tail /usr/local/tomcat/logs/catalina.xx.log 5. Pod的組態管理
Kubernetes v1.2的版本提供統一的叢集組態管理方案–ConfigMap。 5.1. ConfigMap:容器應用的組態管理
使用情境: 產生為容器內的環境變數。 設定容器啟動命令的啟動參數(需設定為環境變數)。 以Volume的形式掛載為容器內部的檔案或目錄。
ConfigMap以一個或多個key:value的形式儲存在kubernetes系統中供應用使用,既可以表示一個變數的值(例如:apploglevel=info),也可以表示完整設定檔的內容(例如:server.xml= 5.2. 建立ConfigMap 5.2.1. 通過yaml檔案方式
cm-appvars.yaml
apiVersion: v1kind: ConfigMapmetadata: name: cm-appvarsdata: apploglevel: info appdatadir: /var/data
常用命令
kubectl create -f cm-appvars.yaml
kubectl get configmap
kubectl describe configmap cm-appvars
kubectl get configmap cm-appvars -o yaml 5.2.2. 通過kubectl命令列方式
通過kubectl create configmap建立,使用參數–from-file或–from-literal指定內容,可以在一行中指定多個參數。
1)通過–from-file參數從檔案中進行建立,可以指定key的名稱,也可以在一個命令列中建立包含多個key的ConfigMap。
kubectl create configmap NAME –from-file=[key=]source –from-file=[key=]source
2)通過–from-file參數從目錄中進行建立,該目錄下的每個設定檔名被設定為key,檔案內容被設定為value。
kubectl create configmap NAME –from-file=config-files-dir
3)通過–from-literal從文本中進行建立,直接將指定的key=value建立為ConfigMap的內容。
kubectl create configmap NAME –from-literal=key1=value1 –from-literal=key2=value2
容器應用對ConfigMap的使用有兩種方法: 通過環境變數擷取ConfigMap中的內容。 通過Volume掛載的方式將ConfigMap中的內容掛載為容器內部的檔案或目錄。 5.2.3. 通過環境變數的方式
ConfigMap的yaml檔案:cm-appvars.yaml
apiVersion: v1kind: ConfigMapmetadata: name: cm-appvarsdata: apploglevel: info appdatadir: /var/data
Pod的yaml檔案:cm-test-pod.yaml
apiVersion: v1kind: Podmetadata: name: cm-test-podspec: containers: - name: cm-test image: busybox command: ["/bin/sh","-c","env|grep APP"] env: - name: APPLOGLEVEL valueFrom: configMapKeyRef: name: cm-appvars key: apploglevel - name: APPDATADIR valueFrom: configMapKeyRef: name: cm-appvars key: appdatadir
建立命令:
kubectl create -f cm-test-pod.yaml
kubectl get pods –show-all
kubectl logs cm-test-pod 5.3. 使用ConfigMap的限制條件 ConfigMap必須在Pod之前建立 ConfigMap也可以定義為屬於某個Namespace。只有處於相同Namespace中的Pod可以引用它。 kubelet只支援可以被API Server管理的Pod使用ConfigMap。靜態Pod無法引用。 在Pod對ConfigMap進行掛載操作時,容器內只能掛載為“目錄”,無法掛載為檔案。 6. Pod的生命週期 6.1. Pod的狀態
| 狀態值 |
說明 |
| Pending |
API Server已經建立了該Pod,但Pod中的一個或多個容器的鏡像還沒有建立,包括鏡像下載過程 |
| Running |
Pod內所有容器已建立,且至少一個容器處於運行狀態、正在啟動狀態或正在重啟狀態 |
| Succeeded |
Pod內所有容器均成功執行退出,且不會再重啟 |
| Failed |
Pod內所有容器均已退出,但至少一個容器退出失敗 |
| Unknown |
由於某種原因無法擷取Pod狀態,例如網路通訊不暢 |
6.2. Pod的重啟策略
| 重啟策略 |
說明 |
| Always |
當容器失效時,由kubelet自動重啟該容器 |
| OnFailure |
當容器終止運行且退出碼不為0時,由kubelet自動重啟該容器 |
| Never |
不論容器運行狀態如何,kubelet都不會重啟該容器 |
說明:
可以管理Pod的控制器有Replication Controller,Job,DaemonSet,及kubelet(靜態Pod)。 RC和DaemonSet:必須設定為Always,需要保證該容器持續運行。 Job:OnFailure或Never,確保容器執行完後不再重啟。 kubelet:在Pod失效的時候重啟它,不論RestartPolicy設定為什麼值,並且不會對Pod進行健全狀態檢查。 6.3. 常見的狀態轉換情境
| Pod的容器數 |
Pod目前狀態 |
發生的事件 |
Pod結果狀態 |
|
|
|
|
|
RestartPolicy=Always |
RestartPolicy=OnFailure |
RestartPolicy=Never |
| 包含一個容器 |
Running |
容器成功退出 |
Running |
Succeeded |
Succeeded |
| 包含一個容器 |
Running |
容器失敗退出 |
Running |
Running |
Failure |
| 包含兩個容器 |
Running |
1個容器失敗退出 |
Running |
Running |
Running |
| 包含兩個容器 |
Running |
容器被OOM殺掉 |
Running |
Running |
Failure |
7. Pod健全狀態檢查
Pod的健康狀態由兩類探針來檢查:LivenessProbe和ReadinessProbe。
LivenessProbe 用於判斷容器是否存活(running狀態)。 如果LivenessProbe探針探測到容器非健康,則kubelet將殺掉該容器,並根據容器的重啟策略做相應處理。 如果容器不包含LivenessProbe探針,則kubelet認為該探針的傳回值永遠為“success”。
ReadinessProbe 用於判斷容器是否啟動完成(read狀態),可以接受請求。 如果ReadnessProbe探針檢測失敗,則Pod的狀態將被修改。Endpoint Controller將從Service的Endpoint中刪除包含該容器所在Pod的Endpoint。
kubelet定期執行LivenessProbe探針來判斷容器的健康狀態。
LivenessProbe參數: initialDelaySeconds:啟動容器後首次進行健全狀態檢查的等待時間,單位為秒。 timeoutSeconds:健全狀態檢查發送請求後等待響應的時間,如果逾時響應kubelet則認為容器非健康,重啟該容器,單位為秒。
LivenessProbe三種實現方式:
1)ExecAction:在一個容器內部執行一個命令,如果該命令狀態傳回值為0,則表明容器健康。
apiVersion: v1kind: Podmetadata: name: liveness-execspec: containers: - name: liveness image: tomcagcr.io/google_containers/busybox args: - /bin/sh - -c - echo ok > /tmp/health;sleep 10;rm -fr /tmp/health;sleep 600 livenessProbe: exec: command: - cat - /tmp/health initialDelaySeconds: 15 timeoutSeconds: 1
2)TCPSocketAction:通過容器IP地址和連接埠號碼執行TCP檢查,如果能夠建立TCP串連,則表明容器健康。
apiVersion: v1kind: Podmetadata: name: pod-with-healthcheckspec: containers: - name: nginx image: nginx ports: - containnerPort: 80 livenessProbe: tcpSocket: port: 80 initialDelaySeconds: 15 timeoutSeconds: 1
3)HTTPGetAction:通過容器的IP地址、連接埠號碼及路徑調用HTTP Get方法,如果響應的狀態代碼大於等於200且小於等於400,則認為容器健康。
apiVersion: v1kind: Podmetadata: name: pod-with-healthcheckspec: containers: - name: nginx image: nginx ports: - containnerPort: 80 livenessProbe: httpGet: path: /_status/healthz port: 80 initialDelaySeconds: 15 timeoutSeconds: 1
8. Pod調度
在kubernetes叢集中,Pod(container)是應用的載體,一般通過RC、Deployment、DaemonSet、Job等對象來完成Pod的調度與自愈功能。 8.1. RC、Deployment:全自動調度
RC的功能即保持叢集中始終運行著指定個數的Pod。
在調度策略上主要有: 系統內建調度演算法[最優Node] NodeSelector[定向調度] NodeAffinity[親和性調度] 8.1.1. NodeSelector[定向調度]
k8s中kube-scheduler負責實現Pod的調度,內部系統通過一系列演算法最終計算出最佳的目標節點。如果需要將Pod調度到指定Node上,則可以通過Node的標籤(Label)和Pod的nodeSelector屬性相匹配來達到目的。
1、kubectl label nodes {node-name} {label-key}={label-value}
2、nodeSelector:
{label-key}:{label-value}
如果給多個Node打了相同的標籤,則scheduler會根據調度演算法從這組Node中選擇一個可用的Node來調度。
如果Pod的nodeSelector的標籤在Node中沒有對應的標籤,則該Pod無法被調度成功。
Node標籤的使用情境:
對叢集中不同類型的Node打上不同的標籤,可控制應用運行Node的範圍。例如role=frontend;role=backend;role=database。 8.1.2. NodeAffinity[親和性調度]
NodeAffinity意為Node親和性調度策略,NodeSelector為精確匹配,NodeAffinity為條件範圍匹配,通過In(屬於)、NotIn(不屬於)、Exists(存在一個條件)、DoesNotExist(不存在)、Gt(大於)、Lt(小於)等操作符來選擇Node,使調度更加靈活。 RequiredDuringSchedulingRequiredDuringExecution:類似於NodeSelector,但在Node不滿足條件時,系統將從該Node上移除之前調度上的Pod。 RequiredDuringSchedulingIgnoredDuringExecution:與上一個類似,區別是在Node不滿足條件時,系統不一定從該Node上移除之前調度上的Pod。 PreferredDuringSchedulingIgnoredDuringExecution:指定在滿足調度條件的Node中,哪些Node應更優先地進行調度。同時在Node不滿足條件時,系統不一定從該Node上移除之前調度上的Pod。
如果同時設定了NodeSelector和NodeAffinity,則系統將需要同時滿足兩者的設定才能進行調度。 8.1.3. DaemonSet:特定情境調度
DaemonSet是kubernetes1.2版本新增的一種資來源物件,用於管理在叢集中每個Node上僅運行一份Pod的副本執行個體。
該用法適用的應用情境: 在每個Node上運行一個GlusterFS儲存或者Ceph儲存的daemon進程。 在每個Node上運行一個日誌採集程式:fluentd或logstach。 在每個Node上運行一個健康程式,採集該Node的運行效能資料,例如:Prometheus Node Exportor、collectd、New Relic agent或Ganglia gmond等。
DaemonSet的Pod調度策略與RC類似,除了使用系統內建演算法在每台Node上進行調度,也可以通過NodeSelector或NodeAffinity來指定滿足條件的Node範圍進行調度。 8.1.4. Job:批處理調度
kubernetes從1.2版本開始支援批處理類型的應用,可以通過kubernetes Job資來源物件來定義並啟動一個批處理任務。批處理任務通常並行(或串列)啟動多個計算進程去處理一批工作項目(work item),處理完後,整個批處理任務結束。 8.1.4.1. 批處理的三種模式
批處理按任務實現方式不同分為以下幾種模式:
Job Template Expansion模式
一個Job對象對應一個待處理的Work item,有幾個Work item就產生幾個獨立的Job,通過適用於Work item數量少,每個Work item要處理的資料量比較大的情境。例如有10個檔案(Work item),每個檔案(Work item)為100G。
Queue with Pod Per Work Item
採用一個任務隊列存放Work item,一個Job對象作為消費者去完成這些Work item,其中Job會啟動N個Pod,每個Pod對應一個Work item。
Queue with Variable Pod Count
採用一個任務隊列存放Work item,一個Job對象作為消費者去完成這些Work item,其中Job會啟動N個Pod,每個Pod對應一個Work item。但Pod的數量是可變的。 8.1.4.2. Job的三種類型
1)Non-parallel Jobs
通常一個Job只啟動一個Pod,除非Pod異常才會重啟該Pod,一旦此Pod正常結束,Job將結束。
2)Parallel Jobs with a fixed completion count
並行Job會啟動多個Pod,此時需要設定Job的.spec.completions參數為一個正數,當正常結束的Pod數量達到該值則Job結束。
3)Parallel Jobs with a work queue
任務隊列方式的並行Job需要一個獨立的Queue,Work item都在一個Queue中存放,不能設定Job的.spec.completions參數。
此時Job的特性: 每個Pod能獨立判斷和決定是否還有任務項需要處理 如果某個Pod正常結束,則Job不會再啟動新的Pod 如果一個Pod成功結束,則此時應該不存在其他Pod還在幹活的情況,它們應該都處於即將結束、退出的狀態 如果所有的Pod都結束了,且至少一個Pod成功結束,則整個Job算是成功結束 9. Pod伸縮
k8s中RC的用來保持叢集中始終運行指定數目的執行個體,通過RC的scale機制可以完成Pod的擴容和縮容(伸縮)。 9.1. 手動伸縮(scale)
kubectl scale rc redis-slave --replicas=3
9.2. 自動調整(HPA)
Horizontal Pod Autoscaler(HPA)控制器用於實現基於CPU使用率進行自動Pod伸縮的功能。HPA控制器基於Master的kube-controller-manager服務啟動參數–horizontal-pod-autoscaler-sync-period定義是時間長度(預設30秒),周期性監控目標Pod的CPU使用率,並在滿足條件時對ReplicationController或Deployment中的Pod副本數進行調整,以符合使用者定義的平均Pod CPU使用率。Pod CPU使用率來源於heapster組件,因此需安裝該組件。
可以通過kubectl autoscale命令進行快速建立或者使用yaml設定檔進行建立。建立之前需已存在一個RC或Deployment對象,並且該RC或Deployment中的Pod必須定義resources.requests.cpu的資源請求值,以便heapster採集到該Pod的CPU。 9.2.1. 通過kubectl autoscale建立
例如:
php-apache-rc.yaml
apiVersion: v1kind: ReplicationControllermetadata: name: php-apachespec: replicas: 1 template: metadata: name: php-apache labels: app: php-apache spec: containers: - name: php-apache image: gcr.io/google_containers/hpa-example resources: requests: cpu: 200m ports: - containerPort: 80
建立php-apache的RC
kubectl create -f php-apache-rc.yaml
php-apache-svc.yaml
apiVersion: v1kind: Servicemetadata: name: php-apachespec: ports: - port: 80 selector: app: php-apache
建立php-apache的Service
kubectl create -f php-apache-svc.yaml
建立HPA控制器
kubectl autoscale rc php-apache --min=1 --max=10 --cpu-percent=50
9.2.2. 通過yaml設定檔建立
hpa-php-apache.yaml
apiVersion: v1kind: HorizontalPodAutoscalermetadata: name: php-apachespec: scaleTargetRef: apiVersion: v1 kind: ReplicationController name: php-apache minReplicas: 1 maxReplicas: 10 targetCPUUtilizationPercentage: 50
建立hpa
kubectl create -f hpa-php-apache.yaml
查看hpa
kubectl get hpa
10. Pod滾動升級
k8s中的滾動升級通過執行kubectl rolling-update命令完成,該命令建立一個新的RC(與舊的RC在同一個命名空間中),然後自動控制舊的RC中的Pod副本數逐漸減少為0,同時新的RC中的Pod副本數從0逐漸增加到附加值,但滾動升級中Pod副本數(包括新Pod和舊Pod)保持原預期值。 10.1. 通過設定檔實現
redis-master-controller-v2.yaml
apiVersion: v1kind: ReplicationControllermetadata: name: redis-master-v2 labels: name: redis-master version: v2spec: replicas: 1 selector: name: redis-master version: v2 template: metadata: labels: name: redis-master version: v2 spec: containers: - name: master image: kubeguide/redis-master:2.0 ports: - containerPort: 6379
注意事項: RC的名字(name)不能與舊RC的名字相同 在selector中應至少有一個Label與舊的RC的Label不同,以標識其為新的RC。例如本例中新增了version的Label。
運行kubectl rolling-update
kubectl rolling-update redis-master -f redis-master-controller-v2.yaml
10.2. 通過kubectl rolling-update命令實現
kubectl rolling-update redis-master --image=redis-master:2.0
與使用設定檔實現不同在於,該執行結果舊的RC被刪除,新的RC仍使用舊的RC的名字。 10.3. 升級復原
kubectl rolling-update加參數–rollback實現復原操作
kubectl rolling-update redis-master --image=kubeguide/redis-master:2.0 --rollback
參考《Kubernetes權威指南》