pod基本概念
最小部署單元
可以包含多個容器
一個pod中的容器可以共享網絡命名空間
pod是短暫的(可能做一次滾動更新,IP就可能發生變化)
適合放在一個pod中的應用
兩個應用之間發生文件交互
比如有兩個應用需要共享數據,那么如果通過外部存儲共享的方式,受到網絡之類的影響,性能較差,可以用到pod中的數據卷進行數據交互
兩個應用需要通過127.0.0.1或者socket通信(比如:nginx+php)
兩個應用需要發生頻繁的調用
Pod常用命令
查看pod
kubectl get po
-o wide 顯示較詳細信息
-n 指定命名空間
查看service
kubectl get service
刪除pod命令
kubectl delete pod {pod名稱}
刪除當前目錄下所有yaml文件生成的pod
kubectl delete -f .
kubectl delete -f {yaml文件名}:刪除該yaml文件生成的pod,不會刪除yaml文件
如果pod反復重啟無法刪除,則刪除對應控制器
如:kubectl get deployment 獲取對應pod的name
kubectl delete {控制器類型} {name前綴}
刪除service
kubectl delete service {service名稱}
查看pod創建、啟動的信息
kubectl describe pod TYPE/NAME
如:kubectl describe pod web-deployment-667d4bd8df-tv2c9
查看容器日志,觀察有沒有異常的日志
kubectl logs TYPE/NAME
如:kubectl logs web-deployment-667d4bd8df-tv2c9
如果有兩個容器:
最后指定[-c CONTAINER]
如:kubectl logs web-deployment-667d4bd8df-tv2c9 -c web2
如果一個pod中有多個容器,想進入不同的容器或看不同容器的日志,使用-c指定
kubectl exec -ti {pod名稱} -c {容器名稱} -- sh
kubectl logs {pod名稱} -c {容器名稱}
容器的名稱在yaml文件中查看
pod已經啟動,進入調試應用
kubectl exec POD [-c CONTAINER] -- COMMAND [args...]
pod中的容器分類
Infrastructure Container:基礎容器
維護整個Pod網絡空間
InitContainers:初始化容器
先於業務容器開始執行,最先啟動的容器
Containers:業務容器
並行啟動
Pod 的實現原理
Pod 里的所有容器,共享的是同一個 Network Namespace,並且可以聲明共享同一個 Volume,其實就是一組共享了某些資源的容器
容器的本質是進程,Pod,實際上是在扮演傳統基礎設施里“虛擬機”的角色;而容器,則是這個虛擬機里運行的用戶程序。
Pod 里的所有容器,共享的是同一個 Network Namespace,並且可以聲明共享同一個 Volume,其實就是一組共享了某些資源的容器
容器的本質是進程,Pod,實際上是在扮演傳統基礎設施里“虛擬機”的角色;而容器,則是這個虛擬機里運行的用戶程序。
pod文件釋義
apiVersion: apps/v1 kind: Deployment metadata: name: web-deployment annotations: kubernetes.io/change-cause: "django.v1" #記錄到revision中的內容,方便回滾 spec: # 副本數,一個副本代表啟一個容器,如果一個pod掛了,那么會在其他副本再啟一個 replicas: 3 selector: matchLabels: # 標簽選擇器,一般寫兩個,上面項目名,下面應用名 project: blog app: django template: metadata: labels: project: blog app: django spec: # 打標簽,資源調度使用 nodeSelector: disktype: "ssd" containers: - name: web image: django# 鏡像拉取策略 imagePullPolicy: IfNotPresent # 資源限制 resources: # 容器最大使用資源,pod內存如果超出limits,會被k8s kill掉 # 最好都設置資源限制和請求資源值,因為沒有限制pod會超出當前node承載能力的話,會造成資源爭搶 limits: # 1000m表示一核,500m表示0.5核 cpu: 1000m memory: 512M # 請求的資源值,k8s會根據這個值調度到能容納的node requests: cpu: 900m memory: 500M # 存活健康檢查 livenessProbe: exec: command: - cat - /tmp/healthy # 啟動容器后多長時間做健康檢查,單位秒 initialDelaySeconds: 5 # 檢查周期間隔 periodSeconds: 5 # 就緒健康檢查 readinessProbe: exec: command: - cat - /tmp/healthy ports: - containerPort: 80 # 設置容器內的變量 env: - name: ABC value: 123 # 重啟策略 restartPolicy: Always # 如果要啟動第二個容器,下面繼續寫 - name: web2 image: nginx # 如果是私有鏡像倉庫,必須要登陸,這個為了指定登陸私有鏡像倉庫的憑據 imagePullSecrets: -name: myregistrykey
鏡像拉取策略
IfNotPresent:鏡像在宿主機上不存在時才拉取
Always:默認值,每次創建Pod都會重新拉取一次鏡像(即使鏡像已經在宿主機上)
Never:Pod永遠不會主動拉取這個鏡像
一般都會選擇Always
資源限制
為了讓k8s穩定的運行,防止某一個pod占用資源過大導致連接掛掉
CPU
2 = 2000m
1 = 1000m
0.5 = 500m
0.25 = 250m
重啟策略(restartPolicy)
Always:當容器終止退出后,總是重啟容器,默認策略(比如nginx、mysql等需要使用)
OnFailure:當容器異常退出口(退出碼為非0),才重啟容器
Never:當容器終止退出,從不重啟容器(短期運行的應用)
健康檢查(Probe)
Probe有兩種類型
存活檢查(livenessProbe)
如果檢查失敗,將殺死容器,根據Pod的重啟策略來操作
就緒檢查(readinessProbe)
如果檢查失敗,k8s會把Pod從service endpoints中剔除
在生產環境中一般兩個檢查會一起配置,兩個檢查除了名稱不一樣以外,其他都是一樣的
Probe支持一下三種檢查方法(一般通過查進程,端口來判斷)
httpGet
發送HTTP請求,返回200-400范圍狀態碼為存活
# 健康檢查 livenessProbe: httpGet: path: /index.html port: 80 # 啟動容器后多長時間做健康檢查,單位秒 initialDelaySeconds: 5 # 檢查周期間隔 periodSeconds: 5
exec
執行Shell命令返回狀態碼是0為成功
tcpSocket
發起TCP Socket建立成功
pod提供數據卷和infra container解決共享存儲和網絡
共享存儲
比如有A、B兩個容器,都需要讀寫同一個存儲設備,那么一般會用到共享存儲,但共享存儲設備可能不在同一個空間內,會消耗過多的網絡資源等,這時可以將兩個容器部署在同一個Pod內,使用本地的磁盤來做數據交換,比如利用k8s提供的數據卷,A、B兩個容器都讀寫同一個目錄文件完成數據交換
共享網絡
k8s在創建一個pod的時候,會默認創建一個負責網絡的容器(infra container),該容器會有自己的網絡命名空間,這時候把容器A、B加入到這個容器中,就打通了A、B兩個容器的網絡
nodeName
用於將Pod調度到指定的Node上,因為不經過調度器(scheduler ),所以針對污點之類的,nodeName還是可以分配到已設置污點的node上
apiVersion: v1 kind: Pod metadata: name: pod-example labels: app: nginx spec: # 指定分配到k8s-node2節點 nodeName: k8s-node2 containers: - name: nginx image: nginx:1.15
影響pod調度的因素
1、根據request的值查找有足夠資源的node來調度此node
2、nodeSelector:用於將pod調度到匹配Label的node上
給node打標簽
kubectl label nodes {node名稱} key=value
如:kubectl label nodes k8s-node1 disktype=ssd
查看node的標簽
kubectl get node --show-labels
刪除node標簽(最后橫杠,別忘記)
kubectl label nodes k8s-node2 {標簽鍵名}-
如:kubectl label nodes k8s-node1 disktype-
apiVersion: v1 kind: Pod metadata: name: pod-example spec: # 調度到標簽為ssd的node上 nodeSelector: disktype: "ssd" containers: - name: nginx image: nginx:1.15
3、nodeAffinity:類似於nodeSelector,可以根據節點上的標簽來約束Pod可以調度到哪些節點
相比nodeSelector:
匹配有更多的邏輯組合,不只是字符串的完全相等
調度分為軟策略和硬策略,而不是硬性要求
硬: 必須滿足,否則啟動不成功
軟:嘗試滿足,不保證
操作符:In、Notln、Exists、DoesNotExist、Gt、Lt
apiVersion: v1 kind: Pod metadata: name: with-node-affinity spec: affinity: nodeAffinity: #硬性要求,如果沒有滿足標簽的node,那么無法啟動 requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: # gpu是鍵 - key: gpu # 意思是哪個node節點含有這個鍵值,就會調度到哪個node operator: In values: # 這是值 - nvidia-tesla #軟性要求 preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: group operator: In values: - ai containers: - name: web image: nginx
4、污點(Taint)
避免pod調度到特定的node上
應用場景:
專用節點
配備了特殊硬件的節點
基於污點的驅逐
設置污點:
kubtctl taint node {node名稱} key=value:effect
如:kubtctl taint node k8s-node1 gpu=yes:NoSchedule
其中[effect]可取值為:
NoSchedule: 一定不能被調度
PreferNoSchedule:盡量不要調度
NoExecute: 不僅不會調度,還會驅逐node上已有的pod,被驅逐的oid自 動分配至別的node
刪除污點:
kubtctl taint node {node名稱} key:[effect]-
查看污點:
kubectl describe node | grep -i taint
污點容忍(Tolerations)
apiVersion: v1 kind: Pod metadata: name: pod-taints spec: containers: - name: pod-taints image: busybox:latest # 可以容忍污點等於no的污點類型,並且污點類型為NoSchedule tolerations: - key: "key" operator: "Equal" value: "no" effect: "NoSchedule"
當node設置了污點以后,配置相同的污點容忍就可以分配到該node上
給Pod設置環境變量:
1、自定義變量
2、來自Pod字段,pod本身會攜帶一些屬性值,比如pod名稱,分配到哪個節點等,可以從pod中引用這個變量,在容器中使用,比如容器有個程序想知道pod運行在哪個節點上,可以用這個實現
3、來自secret、configmap
具體可查看以下鏈接