您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關Kubernetes中的Pod怎么用,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
Pod是Kubernetes系統的基礎單元,是資源對象模型中可由用戶創建或部署的最小組件,也是在Kubernetes系統上運行容器化應用的資源對象。
Docker推薦采用單容器單進程的方式運行,但由于容器間的隔離機制,各容器進程間又無法實現IPC(Inter-Process Communication)通信。這就導致功能相關的容器之間通信困難,比如主容器與負責日志收集的容器之間的通信。而Pod資源抽象正是用來解決此類問題的組件,Pod對象是一組容器的集合,這些容器共享Network、UTS(UNIX Time-sharing System)及IPC名稱空間,因此具有相同的域名、主機名和網絡接口,并可通過IPC直接通信。 為一個Pod對象中的各容器提供網絡名稱空間等共享機制的是底層基礎容器pause。 盡管Pod支持運行多個容器,但作為最佳實踐,除非多個進程之間具有密切的關系,否則都應該將其構建到多個Pod中,這樣多個Pod可被調度至多個不同的主機運行,提高了資源利用率,也便于規模的伸縮。
多個進程之間具有密切的關系時,一般按照邊車模型來組織多個容器,邊車即為Pod的主應用容器提供協同的輔助應用容器,典型的應用場景是將主應用容器中的日志使用agent收集至日志服務器中時,可以將agent運行為輔助應用容器。
Pod的配置清單舉例:
apiVersion: v1 kind: Pod metadata: name: pod-example spec: containers: - name: myapp image: ikubernetes/myapp:v2
其中spec字段下,containers為及其子字段name為必選項,image在手動場景Pod時必選,在但在被高級別管理資源如Deployment控制時可選,因為這個字段可能會被覆蓋。
Pod的核心功能是運行容器,而 通過image.imagePullPolicy可以自定義鏡像的獲取策略。
Always:鏡像標簽為“latest”或鏡像不存在時總是從指定的倉庫中獲取鏡像
IfNotPresent:僅當本地鏡像缺失時才從目標倉庫下載鏡像
Never:禁止從倉庫下載鏡像,即僅使用本地鏡像
spec: containers: - name: myapp image: ikubernetes/myapp:v2 imagePullPolicy: Always
對于標簽為“latest”的鏡像文件,其默認的鏡像獲取策略即為“Always”,而對于其他標簽的鏡像,其默認策略則為“IfNotPresent”。
在Pod中暴露端口與為Docker容器暴露端口的意義不一樣: 在Docker的網絡模型中,使用默認網絡的容器化應用需通過NAT機制將其“暴露”(expose)到外部網絡中才能被其他節點之上的容器客戶端所訪問; 而在K8S中,各Pod的IP地址已經處于同一網絡平面,無論是否為容器暴露端口,都不會影響集群中其他節點之上的Pod客戶端對其進行訪問,所以暴露的端口只是信息性數據,而且顯式指定容器端口也方便調用。
spec: containers: - name: myapp image: ikubernetes/myapp:v2 ports: - name: http containerPort: 80 protocol: TCP
這里的配置指定暴露容器上的TCP端口80,并將其命名為http。 Pod對象的IP地址僅在當前集群內可達,它們無法直接接收來自集群外部客戶端的請求流量,盡管它們的服務可達性不受工作節點邊界的約束,但依然受制于集群邊界。如何讓集群外部訪問到Pod對象,將在后面學習。
command字段能夠指定不同于鏡像默認運行的應用程序,并且可以同時使用args字段進行參數傳遞,它們將覆蓋鏡像中的默認定義。不過,如果僅為容器定義了args字段,那么它將作為參數傳遞給鏡像中默認指定運行的應用程序;如果僅為容器定義了command字段,那么它將覆蓋鏡像中定義的程序及參數,并以無參數方式運行應用程序。
spec: containers: - name: myapp image: ikubernetes/myapp:v2 imagePullPolicy: Never command: ["/bin/sh"] args: ["-c", "while true; do sleep 30; done"]
環境變量也是向容器化應用傳遞配置的一種方式,向Pod對象中的容器環境變量傳遞數據的方法有兩種:env和envFrom,這里只介紹第一種方式,第二種方式將在介紹ConfigMap和Secret資源時進行說明。環境變量通常由name和value字段構成。
spec: containers: - name: myapp image: ikubernetes/myapp:v2 env: - name: REDIS_HOST value: do.macOS - name: LOG_LEVEL value: info
標簽選擇器可以對附帶標簽的資源對象進行挑選,并進行所需要的操作。一個對象可擁有不止一個標簽,而同一個標簽也可被添加至多個資源之上。 可以為資源附加多個不同緯度的標簽以實現靈活的資源分組管理功能,例如,版本標簽、環境標簽、分層架構標簽等,用于交叉標識同一個資源所屬的不同版本、環境及架構層級等。 定義標簽示例:
apiVersion: v1 kind: Pod metadata: name: pod-example labels: env: qa tier: frontend
資源創建后,在kubectl get pods
命令中添加--show-labels
選項就可顯示lables信息。 -L <key1>, <key2>
選項可增加對應的列信息。 直接管理活動對象的標簽:
kubectl label pods/pod-example release=beta
為pod-example添加了release=beta,如果要修改已經存在的減值對,需要添加--overwrite
選項。
標簽選擇器用于表達標簽的查詢條件或選擇標準,Kubernetes API目前支持兩個選擇器:基于
equality-based,可用操作符有“=”“==”和“! =”三種,前兩種等價
set-based,支持in、notin和exists三種操作符,此外還有可以只指定KEY來篩選所有存在此鍵名標簽的資源,!KEY則篩選所有不存在此鍵名標簽的資源 使用標簽選擇器時遵循以下邏輯:
同時指定的多個選擇器之間的邏輯關系為“與”操作
使用空值的標簽選擇器意味著每個資源對象都將被選中
空的標簽選擇器將無法選出任何資源。
Kubernetes的諸多資源對象必須以標簽選擇器的方式關聯到Pod資源對象,例如Service、Deployment和ReplicaSet類型的資源等,可以在spec字段通過嵌套的“selector”字段來指定選擇器,有兩種方式:
matchLabels:通過直接給定鍵值對來指定標簽選擇器
matchExpressions:基于表達式指定的標簽選擇器列表,每個選擇器都形如“{key:KEY_NAME, operator: OPERATOR,values: [VALUE1, VALUE2, …]}”,選擇器列表間為“邏輯與”關系;使用In或NotIn操作符時,其values不強制要求為非空的字符串列表,而使用Exists或DostNotExist時,其values必須為空。 格式舉例:
selector: matchLabels: component: redis matchExpressions: - {key: tier, operator: In, values: [cache]} - {key: environment, operator: Exists, values:}
標簽之外,Pod與其他各種資源還能使用資源注解(annotation),也是鍵值類型的數據,不過它不能用于標簽及挑選Kubernetes對象,僅可用于為資源提供“元數據”信息。另外,注解中的元數據不受字符數量的限制,可以為結構化或非結構化形式,而且對字符類型也沒有限制。 Annotation中放置構建、發行或鏡像相關的信息,指向日志、監控、分析或審計倉庫的地址,或者由客戶端庫或工具程序生成的用于調試目的的信息:如名稱、版本、構建信息等信息。
查看資源注解 使用kubectl get -o yaml
和kubectl describe
命令均能顯示資源的注解信息。
kubectl describe pods pod-example | grep "Annotations"
管理資源注解 在配置清單中定義annotations:
apiVersion: v1 kind: Pod metadata: name: pod-example annotations: created-by: "cluster admin"
追加annotations:
kubectl annotate pods pod-example created-by2="admin"
Pod的生命周期如圖:
Pod對象總是應該處于其生命進程中以下幾個Phase(階段)之一:
Pending:API Server創建了Pod資源對象并已存入etcd中,但它尚未被調度完成,或者仍處于從倉庫下載鏡像的過程中。?
Running:Pod已經被調度至某節點,并且所有容器都已經被kubelet創建完成。?
Succeeded:Pod中的所有容器都已經成功終止并且不會被重啟。?
Failed:所有容器都已經終止,但至少有一個容器終止失敗,即容器返回了非0值的退出狀態或已經被系統終止。?
Unknown:API Server無法正常獲取到Pod對象的狀態信息,通常是由于其無法與所在工作節點的kubelet通信所致。
Pod的創建過程是指Pod自身及其主容器及其輔助容器創建的過程。
用戶通過kubectl或其他API客戶端提交PodSpec給API Server。
API Server嘗試著將Pod對象的相關信息存入etcd中,待寫入操作執行完成,API Server即會返回確認信息至客戶端。
API Server開始反映etcd中的狀態變化。
所有的Kubernetes組件均使用“watch”機制來跟蹤檢查API Server上的相關的變動。
kube-scheduler(調度器)通過其“watcher”覺察到API Server創建了新的Pod對象但尚未綁定至任何工作節點。
kube-scheduler為Pod對象挑選一個工作節點并將結果信息更新至API Server。
調度結果信息由API Server更新至etcd存儲系統,而且API Server也開始反映此Pod對象的調度結果。
Pod被調度到的目標工作節點上的kubelet嘗試在當前節點上調用Docker啟動容器,并將容器的結果狀態回送至API Server。
API Server將Pod狀態信息存入etcd系統中。
在etcd確認寫入操作成功完成后,API Server將確認信息發送至相關的kubelet,事件將通過它被接受。
除了創建應用容器(主容器及其輔助容器)之外,用戶還可以為Pod對象定義其生命周期中的多種行為,如用于初始化的容器、存活性探測及就緒性探測等
用于初始化的容器(init container)是應用程序的主容器啟動之前要運行的容器,常用于為主容器執行一些預置操作,典型的應用如:
用于運行特定的工具程序,出于安全等方面的原因,這些程序不適于包含在主容器鏡像中。
提供主容器鏡像中不具備的工具程序或自定義代碼。
為容器鏡像的構建和部署人員提供了分離、獨立工作的途徑,使得他們不必協同起來制作單個鏡像文件。
初始化容器和主容器處于不同的文件系統視圖中,因此可以分別安全地使用敏感數據,例如Secrets資源。
初始化容器要先于應用容器串行啟動并運行完成,因此可用于延后應用容器的啟動直至其依賴的條件得到滿足。
在資源清單中通過initContainers字段定義:
spec: containers: - name: myapp image: ikubernetes/myapp:v2 initContainers: - name: init-something image: busybox command: ['sh', '-c', 'sleep 10']
Kubernetes為容器提供了兩種生命周期鉤子:
postStart:在容器創建完成之后立即運行,但是Kubernetes無法確保它一定會在容器中的ENTRYPOINT之前運行。
preStop:在容器終止操作之前立即運行,它以同步的方式調用,因此在其完成之前會阻塞刪除容器的操作。
鉤子函數的實現方式有“Exec”和“HTTP”兩種,前一種在鉤子事件觸發時直接在當前容器中運行由用戶定義的命令,后一種則是在當前容器中向某URL發起HTTP請求。鉤子函數定義在容器的spec.lifecycle字段。
容器程序發生崩潰或容器申請超出限制的資源等原因都可能會導致Pod對象的終止,此時是否應該重建該Pod對象則取決于其重啟策略(restartPolicy)屬性的定義。
Always:只要Pod對象終止就將其重啟,此為默認設定。
OnFailure:僅在Pod對象出現錯誤時方才將其重啟。
Never:從不重啟。
容器在重啟失敗后,之后的重啟將有一段時間的延遲,且延遲時間越來越長,依次為10秒、20秒、40秒、80秒、160秒、300秒。
用戶發送刪除Pod對象的命令。
API服務器中的Pod對象會隨著時間的推移而更新,在寬限期內(默認為30秒),Pod被視為“dead”。
將Pod標記為“Terminating”狀態。
(與第3步同時運行)kubelet在監控到Pod對象轉為“Terminating”狀態的同時啟動Pod關閉過程。
(與第3步同時運行)端點控制器監控到Pod對象的關閉行為時將其從所有匹配到此端點的Service資源的端點列表中移除。
如果當前Pod對象定義了preStop鉤子處理器,則在其標記為“terminating”后即會以同步的方式啟動執行;如若寬限期結束后,preStop仍未執行結束,則第2步會被重新執行并額外獲取一個時長為2秒的小寬限期。
Pod對象中的容器進程收到TERM信號。
寬限期結束后,若存在任何一個仍在運行的進程,那么Pod對象即會收到SIGKILL信號。
Kubelet請求API Server將此Pod資源的寬限期設置為0從而完成刪除操作,它變得對用戶不再可見。
如果在等待進程終止的過程中,kubelet或容器管理器發生了重啟,那么終止操作會重新獲得一個滿額的刪除寬限期并重新執行刪除操作。
kubelet可基于存活性探測判定何時需要重啟一個容器。可通過spec.containers.livenessProbe定義,支持三種探測方法:
exec
httpGet
tcpSocket
exec類型的探針通過在目標容器中執行由用戶自定義的命令來判定容器的健康狀態,若命令狀態返回值為0則表示“成功”通過檢測,其它值均為“失敗”狀態。它只有一個可用屬性“command”,用于指定要執行的命令,示例:
apiVersion: v1 kind: Pod metadata: name: liveness-exec-demo labels: test: liveness-exec-demo spec: containers: - name: liveness-exec-demo image: busybox args: ["/bin/sh", "-c", " touch /tmp/healthy;sleep 60; rm -rf /tmp/healthy;sleep 600"] livenessProbe: exec: command: ["test", "-e", "/tmp/healthy"]
這段配置清單基于busybox鏡像啟動一個容器,并執行args定義的命令,此命令在容器啟動時創建/tmp/healthy文件,并于60秒之后將其刪除。存活性探針運行“test -e/tmp/healthy”命令檢查/tmp/healthy文件的存在性,若文件存在則返回狀態碼0,表示成功通過測試。 所以60秒后使用describe命令可以看到容器被重啟的event。
httpGet方式是向目標容器發起一個HTTP GET請求,根據其響應碼進行結果判定,2xx或3xx時表示檢測通過。 可配置字段有:
host,請求的主機地址,默認為Pod IP,也可以在httpHeaders中使用“Host:”來定義。
port,請求的端口,必選字段。
httpHeaders,自定義的請求報文頭。
path,請求的HTTP資源路徑。
scheme:建立連接使用的協議,僅可為HTTP或HTTPS,默認為HTTP。
示例
apiVersion: v1 kind: Pod metadata: name: liveness-http-demo labels: test: liveness-http-demo spec: containers: - name: liveness-http-demo image: nginx:1.12-alpine ports: - name: http containerPort: 80 lifecycle: postStart: exec: command: ["/bin/sh", "-c", " echo Healthy > /usr/share/nginx/html/healthz"] livenessProbe: httpGet: path: /healthz port: http scheme: HTTP
這個配置清單通過postStart hook創建了一個專用于httpGet測試的頁面文件healthz。而為httpGet探測指定的路徑為“/healthz”,地址默認為Pod IP,端口使用了容器中定義的端口名稱http。 啟動容器后健康檢查是正常的,但執行如下命令刪除healthz頁面后,可在event中看到Container liveness-http-demo failed liveness probe, will be restarted
。
kubectl exec liveness-http-demo rm /usr/share/nginx/html/healthz
一般應為HTTP探測操作定義專用的URL路徑,此URL路徑對應的Web資源應該以輕量化的方式在內部對應用程序的各關鍵組件進行全面檢測以確保它們可正常向客戶端提供完整的服務。
基于TCP的存活性探測用于向容器的特定端口發起TCP請求并嘗試建立連接,連接建立成功即為通過檢測。相比較來說,它比基于HTTP的探測要更高效、更節約資源,但精準度較低。 可配置字段有:
host,請求連接的目標IP地址,默認為Pod IP。
port,請求連接的目標端口,必選字段。
舉例:
spec: containers: - name: liveness-tcp-demo image: nginx:1.12-alpine livenessProbe: tcpSocket: port: 80
對于配置了liveness的pod,通過describe命令可以看到類似這樣的信息,有delay、timeout等配置,由于之前沒有指定所以都為默認值:
Liveness: tcp-socket :80 delay=0s timeout=1s period=10s #success=1 #failure=3
initialDelaySeconds,存活性探測延遲時長,即容器啟動多久之后再開始第一次探測操作,顯示為delay屬性,默認為0秒,整型
timeoutSeconds,存活性探測的超時時長,顯示為timeout屬性,默認為1s,整型,最小1s
periodSeconds,存活性探測的頻度,顯示為period屬性,整型,默認為10s,最小值為1s;過高的頻率會對Pod對象帶來較大的額外開銷,而過低的頻率又會使得對錯誤的反應不及時
successThreshold,處于失敗狀態時,探測操作至少連續多少次的成功才被認為是通過檢測,顯示為#success屬性,默認值為1,最小值也為1,整型
failureThreshold:處于成功狀態時,探測操作至少連續多少次的失敗才被視為是檢測不通過,顯示為#failure屬性,默認值為3,最小值為1,整型。
另外,liveness檢測僅對當前服務有效,比如但后端服務(如數據庫或緩存服務)導致故障時,重啟當前服務并不能解決問題,但它卻會被一次次重啟,直到后端服務恢復正常為止。
Pod對象啟動后,容器應用通常需要一段時間才能完成其初始化過程,例如加載配置或數據,甚至有些程序還需要預熱的過程。因此應該避免在Pod對象啟動后立即讓其處理客戶端請求,而是等待容器初始化工作執行完成并轉為Ready狀態,尤其是存在其他提供相同服務的Pod對象的場景更是如此。 就緒性探測是用來判斷容器就緒與否的周期性操作,探測操作返回“success”狀態時,就認為容器已經就緒。 與liveness探測類似,它也支持三種方式,但定義時使用的屬性名為readinessProbe。 舉例:
apiVersion: v1 kind: Pod metadata: name: readiness-tcp-demo labels: test: readiness-tcp-demo spec: containers: - name: readiness-tcp-demo image: nginx:1.12-alpine readinessProbe: tcpSocket: port: 80
未定義就緒性探測的Pod對象在Pod進入“Running”狀態后將立即就緒。生產實踐中,必須為需要時間進行初始化容器以及關鍵性Pod資源中的容器定義就緒性探測。
K8S中可由容器或Pod請求或消費的“計算資源”是指CPU和內存,其中CPU屬于可壓縮(compressible)型資源,可按需收縮,而內存則是不可壓縮型資源,對其執行收縮操作可能會導致無法預知的問題。 目前資源隔離屬于容器級別,所以CPU和內存資源的配置需要在Pod中的容器上進行,支持兩種屬性:
requests,定義了其請求的確保可用值,即容器運行可能用不到這些額度的資源,但用到時必須要確保有如此多的資源可用;
limits,限制資源可用的最大值
在K8S中,1個單位的CPU相當于虛擬機上的1顆虛擬CPU(vCPU)或物理機上的一個超線程(Hyperthread,或稱為一個邏輯CPU),它支持分數計量方式,一個核心(1 core)相當于1000個微核心(millicores),因此500m相當于是0.5個核心。內存的計量方式與日常使用方式相同,默認單位是字節,也可以使用E(Ei)、P(Pi)、T(Ti)、G(Gi)、M(Mi)和K(Ki)作為單位后綴。
apiVersion: v1 kind: Pod metadata: name: stress-demo spec: containers: - name: stress-demo image: ikubernetes/stress-ng command: ["/usr/bin/stress-ng", "-m 1", "-c 1", "--metrics-brief"] resources: requests: memory: "128Mi" cpu: "200m"
以上的配置清單定義了容器的資源需求為128M內存、200m(0.2)個CPU核心。它運行stress-ng(一個多功能系統壓力測工具)鏡像啟動一個進程(-m 1)進行內存性能壓力測試,再啟動一個專用的CPU壓力測試進程(-c 1)。 然后使用kubectl exec stress-demo -- top
命令來查看資源的使用情況,在我的電腦(6核,內存16G)上顯示的內存占用為262m,CPU占用2*17%(約等于2/6,因為兩個測試線程分布于兩個CPU核心以滿載的方式運行),都遠高于requests中定義的值,這是因為當前資源充裕,一旦 資源緊張時,節點僅保證容器有五分之一個CPU核心可用,對于有著6個核心的節點來說,它的占用率約為3.33%,多占用的資源會被壓縮。內存為非可壓縮型資源,所以此Pod在內存資源緊張時可能會因OOM被殺死(killed)。 如果沒有定義requests,那么在CPU資源緊張時,可能會被其它Pod壓縮至極低的水平,甚至會達到Pod不能夠被調度運行的境地,而不可壓縮型的內存資源,則可能因OOM導致進程被殺死。因此在Kubernetes系統上運行關鍵型業務相關的Pod時必須使用requests屬性為容器定義資源的確保可用量。
集群中的每個節點擁有的CPU和內存資源是固定的,Kubernetes的調度器在調度Pod時,會根據容器的requests屬性來判定哪些節點可接收運行當前的Pod資源,而對于一個節點的資源來說,每運行一個Pod對象,其requests中定義的請求量都要被預留,直到給所有Pod對象分配完為止。
通過定義資源需求可以保證容器的最少資源量,如果要限制容器使用資源的上限,則需要定義資源限制。 如果定義了資源限制,則容器進程無法獲得超出其CPU配額的可用時間,而進程申請分配超出其limits定義的內存資源時,它將被OOM killer殺死。
Kubernetes允許節點資源對limits的過載使用,這意味著節點無法同時滿足其上的所有Pod對象以資源滿載的方式運行。于是就需要確定Pod對象的優先級,在內存資源緊缺時,先終止低優先級的Pod對象。 Pod對象的優先級是根據requests和limits屬性確定的,分為三個級別或QoS(Quality of Service):
Guaranteed,Pod中所有容器對所有資源類型都定義了Limits和Requests,而且Limits值等于Requests值且不為0,Requests值未定義時默認等于Limits,優先級最高。
BestEffort,沒有為任何一個容器設置requests或limits屬性的Pod資源屬于這一類,優先級最低。
Burstable,不為Guaranteed和BestEffort時,優先級中等。
只適用于內存資源緊缺時,CPU資源無法得到滿足時,Pod僅僅是暫時獲取不到相應的資源而已。
以上就是Kubernetes中的Pod怎么用,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。