html
Pod
資源對象是一種集合了一到多個應用容器、存儲資源、專用IP
及支撐容器運行的其餘選項的邏輯組件,如圖所示。Pod
表明着Kubernetes
的部署單元及原子運行單元,即一個應用程序的單一運行實例,它一般由共享資源且關係緊密的一個或多個應用容器組成。前端
Kubernetes
的網絡模型要求其各Pod
對象的IP
地址位於同一網絡平面內(同一IP
網段),各Pod
之間可以使用其IP
地址直接進行通訊,不管它們運行於集羣內的哪一個工做節點上,這些Pod
對象都像運行於同一局域網中的多個主機。node不過,
Pod
對象中的各進程均運行於彼此隔離的容器中,並於容器間共享兩種關鍵資源:網絡和存儲卷。nginx
網絡:每一個
Pod
對象都會被分配一個集羣內專用的IP
地址,也稱爲Pod IP
,同一Pod
內部的全部容器共享Pod
對象的Network
和UTS
名稱空間,其中包括主機名、IP
地址和端口等。所以,這些容器間的通訊能夠基於本地迴環接口lo
進行,而與Pod
外的其餘組件的通訊則須要使用Service
資源對象的ClusterIP
及相應的端口完成。web存儲卷:用戶能夠爲
Pod
對象配置一組「存儲卷」資源,這些資源能夠共享給其內部的全部容器使用,從而完成容器間數據的共享。存儲卷還能夠確保在容器終止後重啓,甚至是被刪除後也能確保數據不會丟失,從而保證了生命週期內的Pod
對象數據的持久化存儲。編程
一個
Pod
對象表明某個應用程序的一個特定實例,若是須要擴展應用程序,則意味着爲此應用程序同時建立多個Pod
實例,每一個實例均表明應用程序的一個運行的「副本」(replica
)。這些副本化的Pod
對象的建立和管理一般由另外一組稱爲「控制器」(Controller
)的對象實現,例如,Deployment
控制器對象。後端建立
Pod
時,還可使用Pod Preset
對象爲Pod
注入特定的信息,如ConfigMap
、Secret
、存儲卷、掛載卷和環境變量等。有了Pod Preset
對象,Pod
模板的建立者就無須爲每一個模板顯示提供全部信息,所以,也就無須事先了解須要配置的每一個應用的細節便可完成模板定義。緩存基於指望的目標狀態和各節點的資源可用性,
Master
會將Pod
對象調度至某選定的工做節點運行,工做節點於指向的鏡像倉庫(image register
)下載鏡像,並於本地的容器運行時環境中啓動容器。Master
會將整個集羣的狀態保存於etcd
中,並經過API Server
共享給集羣的各組件及客戶端。網絡
app
但
Pod
對象自己並不具備「自愈」功能,如果由於工做節點甚至是調度器自身致使了運行失敗,那麼它將會被刪除;一樣,資源耗盡或節點故障致使的回收操做也會刪除相關的Pod
對象。在設計上,Kubernetes
使用」控制器「實現對一次性的(用後即棄)Pod
對象的管理操做,例如,要確保部署的應用程序的Pod副本數量嚴格反映用戶指望的數目,以及基於Pod
模板來建立Pod
對象等,從而實現Pod
對象的擴縮容、滾動更新和自愈能力等。例如,某節點發生故障時,相關的控制器會將此節點上運行的Pod
對象從新調度到其餘節點進行重建。控制器自己也是一種資源類型,它有着多種實現,其中與工做負載相關的實現如
Replication Controller
、Deployment
、StatefulSet
、DaemonSet
和Jobs
等,也可統稱它們爲Pod
控制器。
Pod
控制器的定義一般由指望的副本數量、Pod
模板和標籤選擇器(Label Selector
)組成。Pod
控制器會根據標籤選擇器對Pod
對象的標籤進行匹配檢查,全部知足選擇條件的Pod
對象都將受控於當前控制器並計入其副本總數,並確保此數目可以精確反映指望的副本數。
換言之,
Service
是「微服務」的一種實現,事實上它是一種抽象:經過規則定義出由多個Pod
對象組合而成的邏輯集合,並附帶訪問這組Pod
對象的策略。Service
對象挑選、關聯Pod
對象的方式同Pod
控制器同樣,都是要基於Label Selector
進行定義,其示意圖以下
集羣內的
Pod
對象可直接請求此類的Cluster IP
,例如,圖中來自Pod client
的訪問請求便可以Service
的Cluster IP
做爲目標地址,但集羣網絡屬於私有網絡地址,它們僅在集羣內部可達。將集羣外部的訪問流量引入集羣內部的經常使用方法是經過節點網絡進行,實現方法是經過工做節點的IP
地址和某端口(NodePort
)接入請求並將其代理至相應的Service
對象的Cluster IP
上的服務端口,然後由Service
對象將請求代理至後端的Pod
對象的Pod IP
及應用程序監聽的端口。所以,圖中的External Clients
這種來自集羣外部的客戶端沒法直接請求此Service
提供的服務,而是須要事先經由某一個工做節點(如NodeY
)的IP
地址進行,這類請求須要兩次轉發才能到達目標Pod
對象,所以在通訊效率上必然存在負面影響。事實上,
NodePort
會部署於集羣中的每個節點,這就意味着,集羣外部的客戶端經過任何一個工做節點的IP
地址來訪問定義好的NodePort
均可以到達相應的Service
對象。此種場景下,若是存在集羣外部的一個負載均衡器,便可將用戶請求負載均衡至集羣中的部分或者全部節點。這是一種稱爲「LoadBalancer」
類型的Service
,它一般是由Cloud Provider
自動建立並提供的軟件負載均衡器,不過,也能夠是有管理員手工配置的諸如F5
一類的硬件設備。簡單來講,
Service
主要有三種經常使用類型:第一種是僅用於集羣內部通訊的ClusterIP
類型;第二種是接入集羣外部請求的NodePort
類型,它工做與每一個節點的主機IP
之上;第三種是LoadBalancer
類型,它能夠把外部請求負載均衡至多個Node
的主機IP
的NodePort
之上。此三種類型中,每一種都以其前一種爲基礎才能實現,並且第三種類型中的LoadBalancer
須要協同集羣外部的組件才能實現,而且此外部組件並不接受Kubernetes
的管理。
在
Kubernetes
集羣上自主運行的Pod
對象在非計劃內終止後,其生命週期即告結束,用戶須要再次手動建立相似的Pod
對象才能確保其容器中的依然可得。對於Pod
數量衆多的場景,尤爲是對微服務業務來講,用戶必將疲於應付此類需求。Kubernetes
的工做負載(workload
)類型的控制器可以自動確保由其管控的Pod
對象按用戶指望的方式運行,所以,Pod的建立和管理大多會經過這種類型的控制器來進行,包括Deployment
、ReplicasSet
、ReplicationController
等。
1)建立Deployment控制器對象
kubectl run
命令可用於命令行直接建立Deploymen
t控制器,並以--image
選項指定的鏡像運行Pod
中的容器,--dry-run
選項能夠用於命令的測試,但並不真正執行資源對象的建立過程。
# 建立一個名字叫作nginx的deployment控制器,並指定pod鏡像使用nginx:1.12版本,並暴露容器內的80端口,並指定副本數量爲1個,並先經過--dry-run測試命令是否錯誤。 [root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --port=80 --replicas=1 --dry-run=true [root@k8s-master ~]# kubectl run nginx --image=nginx:1.12 --port=80 --replicas=1 deployment.apps/nginx created [root@k8s-master ~]# kubectl get pods #查看全部pod對象 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-9z4f4 1/1 Running 0 89s ###參數說明: --image 指定須要使用到的鏡像。 --port 指定容器須要暴露的端口。 --replicas 指定目標控制器對象要自動建立Pod對象的副本數量。
2)打印資源對象的相關信息
kubectl get
命令可用來獲取各類資源對象的相關信息,它既能顯示對象類型特有格式的簡要信息,也能按照指定格式爲YAML
或JSON
的詳細信息,或者使用Go
模板自定義要顯示的屬性及信息等。
[root@k8s-master ~]# kubectl get deployment #查看全部deployment控制器對象 NAME READY UP-TO-DATE AVAILABLE AGE nginx 1/1 1 1 66s ###字段說明: NAME 資源對象名稱 READY 指望由當前控制器管理的Pod對象副本數及當前已有的Pod對象副本數 UP-TO-DATE 更新到最新版本定義的Pod對象的副本數量,在控制器的滾動更新模式下,表示已經完成版本更新的Pod對象的副本數量 AVAILABLE 當前處於可用狀態的Pod對象的副本數量,便可正常提供服務的副本數。 AGE Pod的存在時長 說明:Deployment資源對象經過ReplicaSet控制器實例完成對Pod對象的控制,而非直接控制。另外,經過控制器建立的Pod對象都會被自動附加一個標籤。格式爲「run=<Controller_Name>」。 [root@k8s-master ~]# kubectl get deployment -o wide #查看deployment控制器對象的詳細信息 NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR nginx 1/1 1 1 69m nginx nginx:1.12 run=nginx [root@k8s-master ~]# kubectl get pods #查看pod資源 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-9z4f4 1/1 Running 0 72m [root@k8s-master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 73m 10.244.1.12 k8s-node1 <none> <none> ###字段說明: NAME pode資源對象名稱 READY pod中容器進程初始化完成並可以正常提供服務時即爲就緒狀態,此字段用於記錄處於就緒狀態的容器數量 STATUS pod的當前狀態,其值有Pending、Running、Succeeded、Failed和Unknown等其中之一 RESTARTS Pod重啓的次數 IP pod的IP地址,一般由網絡插件自動分配 NODE pod被分配的節點。
3)訪問Pod對象
這裏部署的是
pod
是運行的爲nginx
程序,因此咱們能夠訪問是否ok
,在kubernetes
集羣中的任意一個節點上均可以直接訪問Pod
的IP
地址。
[root@k8s-master ~]# kubectl get pods -o wide #查看pod詳細信息 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 88m 10.244.1.12 k8s-node1 <none> <none> [root@k8s-master ~]# curl 10.244.1.12 #kubernetes集羣的master節點上訪問 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> [root@k8s-node2 ~]# curl 10.244.1.12 #kubernetes集羣的node節點上訪問 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
[root@k8s-master ~]# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-9z4f4 1/1 Running 0 99m 10.244.1.12 k8s-node1 <none> <none> [root@k8s-master ~]# kubectl delete pods nginx-685cc95cd4-9z4f4 #刪除上面的pod pod "nginx-685cc95cd4-9z4f4" deleted [root@k8s-master ~]# kubectl get pods -o wide #能夠看出,當上面pod剛刪除,接着deployment控制器又立刻建立了一個新的pod,且此次分配在k8s-node2節點上了。 NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES nginx-685cc95cd4-z5z9p 1/1 Running 0 89s 10.244.2.14 k8s-node2 <none> <none> [root@k8s-master ~]# curl 10.244.1.12 #訪問以前的pod,能夠看到已經不能訪問 curl: (7) Failed connect to 10.244.1.12:80; 沒有到主機的路由 [root@k8s-master ~]# [root@k8s-master ~]# curl 10.244.2.14 #訪問新的pod,能夠正常訪問 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
簡單來講,一個
Service
對象可視做經過其標籤選擇器過濾出的一組Pod
對象,並可以爲此組Pod
對象監聽的套接字提供端口代理及調度服務。就比如上面作的測試,若是沒有Service
,那麼每次都得去訪問pod
對象本身的地址等。且那還只是建立了一個pod
對象,若是是多個。那麼該如何是好?故使用Service
解決此問題。
1)建立Service對象(將Service端口代理至Pod端口示例)
"kubectl expose"
命令可用於建立Service
對象以將應用程序「暴露」(expose
)於網絡中。
#方法一 [root@k8s-master ~]# kubectl expose deployment nginx --name=nginx-svc --port=80 --target-port=80 --protocol=TCP #爲deployment的nginx建立service,取名叫nginx-svc,並經過service的80端口轉發至容器的80端口上。 service/nginx-svc exposed #方法二 [root@k8s-master ~]# kubectl expose deployment/nginx --name=nginx-svc --port=80 --target-port=80 --protocol=TCP service/nginx-svc exposed ###參數說明: --name 指定service對象的名稱 --port 指定service對象的端口 --target-port 指定pod對象容器的端口 --protocol 指定協議 [root@k8s-master ~]# kubectl get svc #查看service對象。或者kubectl get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 25h nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 41s
# master節點上經過ServiceIP進行訪問 [root@k8s-master ~]# curl 10.109.54.136 <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html> #新建一個客戶端pod進行訪問,這裏這個客戶端使用busybox鏡像,且pod副本數量爲1個,-it表示進入終端模式。--restart=Never,表示從不重啓。 [root@k8s-master ~]# kubectl run client --image=busybox --replicas=1 -it --restart=Never If you don't see a command prompt, try pressing enter. / # wget -O - -q 10.109.54.136 #訪問上面建立的(service)nginx-svc的IP <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...... / # / # wget -O - -q nginx-svc #訪問上面建立的(service)名稱nginx-svc <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title>
2)建立Service對象(將建立的Pod對象使用「NodePort」類型的服務暴露到集羣外部)
[root@k8s-master ~]# kubectl run mynginx --image=nginx:1.12 --port=80 --replicas=2 #建立一個deployments控制器並使用nginx鏡像做爲容器運行的應用。 [root@k8s-master ~]# kubectl get pods #查看建立的pod NAME READY STATUS RESTARTS AGE client 1/1 Running 0 15h mynginx-68676f64-28fm7 1/1 Running 0 24s mynginx-68676f64-9q8dj 1/1 Running 0 24s nginx-685cc95cd4-z5z9p 1/1 Running 0 16h [root@k8s-master ~]# [root@k8s-master ~]# kubectl expose deployments/mynginx --type="NodePort" --port=80 --name=mynginx-svc #建立一個service對象,並將mynginx建立的pod對象使用NodePort類型暴露到集羣外部。 service/mynginx-svc exposed [root@k8s-master ~]# [root@k8s-master ~]# kubectl get svc #查看service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 41h mynginx-svc NodePort 10.111.89.58 <none> 80:30884/TCP 10s nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 15h ###字段說明: PORT(S) 這裏的mynginx-svc對象能夠看出,集羣中各工做節點會捕獲發往本地的目標端口爲30884的流量,並將其代理至當前service對象的80端口。因而集羣外部的用戶可使用當前集羣中任一節點的此端口來請求Service對象上的服務。 [root@k8s-master ~]# [root@k8s-master ~]# netstat -nlutp |grep 30884 #查看master節點上是否有監聽上面的30884端口 tcp6 0 0 :::30884 :::* LISTEN 7340/kube-proxy [root@k8s-node1 ~]# [root@k8s-node1 ~]# netstat -nlutp |grep 30884 #查看node節點是否有監聽上面的30884端口 tcp6 0 0 :::30884 :::* LISTEN 2537/kube-proxy
3)Service資源對象的描述
[root@k8s-master ~]# kubectl describe service mynginx-svc Name: mynginx-svc Namespace: default Labels: run=mynginx Annotations: <none> Selector: run=mynginx Type: NodePort IP: 10.111.89.58 Port: <unset> 80/TCP TargetPort: 80/TCP NodePort: <unset> 30884/TCP Endpoints: 10.244.1.14:80,10.244.2.15:80 Session Affinity: None External Traffic Policy: Cluster Events: <none> ###字段說明: Selector 當前Service對象使用的標籤選擇器,用於選擇關聯的Pod對象 Type 即Service的類型,其值能夠是ClusterIP、NodePort和LoadBalancer等其中之一 IP 當前Service對象的ClusterIP Port 暴露的端口,即當前Service用於接收並響應的端口 TargetPort 容器中的用於暴露的目標端口,由Service Port路由請求至此端口 NodePort 當前Service的NodePort,它是否存在有效值與Type字段中的類型相關 Endpoints 後端端點,即被當前Service的Selector挑中的全部Pod的IP及其端口 Session Affinity 是否啓用會話粘性 External Traffic Policy 外部流量的調度策略
Service
對象內建的負載均衡機制可在其後端副本數量不止一個時自動進行流量分發,它還會自動監控關聯到的Pod
的健康狀態,以確保將請求流量分發至可用的後端Pod
對象。若某Deployment
控制器管理包含多個Pod
實例,則必要時用戶還能夠爲其使用「滾動更新」機制將其容器鏡像升級到新的版本或變動那些支持動態修改的Pod
屬性。使用
kubect run
命令建立Deployment
對象時,「--replicas=」
選項可以指定由該對象建立或管理的Pod
對象副本的數量,且其數量支持運行時進行修改,並當即生效。「kubectl scale」
命令就是專用於變更控制器應用規模的命令,它支持對Deployment
資源對象的擴容和縮容操做。
[root@k8s-master ~]# kubectl get pods -l run=nginx #查看標籤run=nginx的pod NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-z5z9p 1/1 Running 0 17h [root@k8s-master ~]# [root@k8s-master ~]# kubectl scale deployments/nginx --replicas=3 #將其擴容到3個 deployment.extensions/nginx scaled [root@k8s-master ~]# [root@k8s-master ~]# kubectl get pods -l run=nginx #再次查看 NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-f2cwb 1/1 Running 0 5s nginx-685cc95cd4-pz9dk 1/1 Running 0 5s nginx-685cc95cd4-z5z9p 1/1 Running 0 17h [root@k8s-master ~]# [root@k8s-master ~]# kubectl describe deployments/nginx #查看Deployment對象nginx詳細信息 Name: nginx Namespace: default CreationTimestamp: Thu, 29 Aug 2019 15:29:31 +0800 Labels: run=nginx Annotations: deployment.kubernetes.io/revision: 1 Selector: run=nginx Replicas: 3 desired | 3 updated | 3 total | 3 available | 0 unavailable StrategyType: RollingUpdate ... #由nginx自動建立的pod資源所有擁有同一個標籤選擇器「run=nginx」,所以,前面建立的Service資源對象nginx-svc的後端端點也已經經過標籤選擇器自動擴展到了這3個Pod對象相關的端點 [root@k8s-master ~]# kubectl describe service/nginx-svc Name: nginx-svc Namespace: default Labels: run=nginx Annotations: <none> Selector: run=nginx Type: ClusterIP IP: 10.109.54.136 Port: <unset> 80/TCP TargetPort: 80/TCP Endpoints: 10.244.1.15:80,10.244.2.14:80,10.244.2.16:80 Session Affinity: None Events: <none>
縮容的方式和擴容類似,只不過是將
Pod
副本的數量調至比原來小的數字便可。例如將nginx
的pod
副本縮減至2個
[root@k8s-master ~]# kubectl scale deployments/nginx --replicas=2 deployment.extensions/nginx scaled [root@k8s-master ~]# [root@k8s-master ~]# kubectl get pods -l run=nginx NAME READY STATUS RESTARTS AGE nginx-685cc95cd4-pz9dk 1/1 Running 0 10m nginx-685cc95cd4-z5z9p 1/1 Running 0 17h
[root@k8s-master ~]# kubectl get services #查看當前全部的service對象 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 43h mynginx-svc NodePort 10.111.89.58 <none> 80:30884/TCP 96m nginx-svc ClusterIP 10.109.54.136 <none> 80/TCP 17h [root@k8s-master ~]# kubectl delete service nginx-svc #刪除service對象nginx-svc
[root@k8s-master ~]# kubectl delete deployment --all deployment.extensions "mynginx" deleted
注意:受控於控制器的Pod
對象在刪除後會被重建,刪除此類對象須要直接刪除其控制器對象。不過,刪除控制器時若不想刪除其Pod
對象,可在刪除命令上使用「--cascade=false「
選項。
雖然直接命令式管理的相關功能強大且適合用於操縱
Kubernetes
資源對象,但其明顯的缺點是缺少操做行爲以及待運行對象的可信源。另外,直接命令式管理資源對象存在較大的侷限性,它們在設置資源對象屬性方面提供的配置能力至關有限,並且還有很多資源並不支持命令操做進行建立,例如,用戶沒法建立帶有多個容器的Pod
對象,也沒法爲Pod
對象建立存儲卷。所以,管理資源對象更有效的方式是基於保存有對象配置信息的配置清單來進行。