一、 kubernetes帶來的變革
1. 對于開發(fā)人員
由于公司業(yè)務(wù)多,開發(fā)環(huán)境、測試環(huán)境、預(yù)生產(chǎn)環(huán)境和生產(chǎn)環(huán)境都是隔離的,而且除了生產(chǎn)環(huán)境,為了節(jié)省成本,其他環(huán)境可能是沒有日志收集的,在沒有用k8s的時候,查看線下測試的日志,需要開發(fā)或者測試人員,找到對應(yīng)的機(jī)器,在找到對應(yīng)的容器,然后才能查看日志,在用了k8s之后,開發(fā)和測試可以直接在k8s的dashboard到對應(yīng)的namespace,即可定位到業(yè)務(wù)的容器,然后可以直接通過控制臺查看到對應(yīng)的日志,大大降低了操作時間。
把應(yīng)用部署到k8s之后,代碼的發(fā)布、回滾,以及藍(lán)綠發(fā)布、金絲雀發(fā)布等都變得特別簡單,不僅加快了業(yè)務(wù)代碼迭代的速度,而且全程無需人工干預(yù)。目前我們使用jenkins、gitrunner進(jìn)行發(fā)版或者回滾等,從開發(fā)環(huán)境到測試環(huán)境,到生產(chǎn)環(huán)境,完全遵守一次構(gòu)建,多集群、多環(huán)境部署,通過不同的啟動參數(shù)、不同的環(huán)境變量、不同的配置文件實(shí)現(xiàn)區(qū)分不同的環(huán)境。目前已經(jīng)實(shí)現(xiàn)Python、Java、PHP、NodeJS、Go、.NET Core、Python等多種語言的一鍵式發(fā)版、一鍵式回滾,大大提高了開發(fā)人員的開發(fā)效率。
在使用服務(wù)網(wǎng)格后,開發(fā)人員在開發(fā)應(yīng)用的過程中,不用再關(guān)心代碼的網(wǎng)絡(luò)部分,這些功能都被服務(wù)網(wǎng)格實(shí)現(xiàn),讓開發(fā)人員可以只關(guān)心代碼邏輯部分,即可實(shí)現(xiàn)網(wǎng)絡(luò)部分的功能,比如:斷流、分流、路由、負(fù)載均衡、限速和觸發(fā)故障等功能。
測試過程中,可能同時多套環(huán)境,當(dāng)然也會需要再創(chuàng)建一套測試環(huán)境,之前測試環(huán)境的創(chuàng)建,需要找運(yùn)維或者自行手工搭建。在遷移至k8s集群后,只需要在jenkins上點(diǎn)點(diǎn)鼠標(biāo)即可在k8s集群上創(chuàng)建一套新的測試環(huán)境。
2. 對于運(yùn)維人員
如果你是一名運(yùn)維人員,可能經(jīng)常因?yàn)橐恍┲貜?fù)、繁瑣的工作感覺厭倦。比如:這個需要一套新的測試環(huán)境,那個需要一套新的測試環(huán)境,之前可能需要裝系統(tǒng)、裝依賴環(huán)境、開通權(quán)限等等。而如今,可以直接用鏡像直接部署一套新的測試環(huán)境,甚至全程無需自己干預(yù),開發(fā)人員通過jenkins或者自動化運(yùn)維平臺即可一鍵式創(chuàng)建,大大降低了運(yùn)維成本。
一開始,公司業(yè)務(wù)故障,可能是因?yàn)榛A(chǔ)環(huán)境不一致、依賴不一致、端口沖突等等問題,現(xiàn)在實(shí)現(xiàn)Docker鏡像部署,k8s編排,所有的依賴、基礎(chǔ)都是一樣的,并且環(huán)境的自動化擴(kuò)容、健康檢查、容災(zāi)、恢復(fù)都是全自動的,大大減少了因?yàn)檫@類基礎(chǔ)問題引發(fā)的故障。也有可能公司業(yè)務(wù)是由于服務(wù)器宕機(jī)、網(wǎng)絡(luò)等問題,造成服務(wù)不可用,此類情況均需要運(yùn)維人員及時去修復(fù),而如今,可能在你收到告警信息的時候,k8s已經(jīng)幫你恢復(fù)了。
在沒有使用k8s時,業(yè)務(wù)應(yīng)用的擴(kuò)容和縮容,都需要人工去處理,從采購服務(wù)器、上架、到部署依賴環(huán)境,不僅需要大量的人力物力,而且非常容易在中間過程出現(xiàn)問題,又要花費(fèi)大量的時間去查找問題。成功上架后,還需要在前端反代端添加或該服務(wù)器,而如今,可以利用k8s的彈性計(jì)算,一鍵式進(jìn)行擴(kuò)容和縮容,不僅大大提高了運(yùn)維效率,而且還節(jié)省了不少的服務(wù)器資源,提高了資源利用率。
對于反代配置方面,比如可能你并不會,或者對nginx的配置規(guī)則并不熟悉,一些高級的功能你也不會實(shí)現(xiàn),而如今,利用k8s的ingress即可簡單的實(shí)現(xiàn)那些復(fù)雜的邏輯。并且也不會在遇到nginx少加一個斜杠和多加一個斜杠的問題。
對于負(fù)載均衡方面,之前負(fù)載均衡可能是Nginx、LVS、HAProxy、F5等,云上可能是云服務(wù)商提供的不在均衡機(jī)制。每次添加刪除節(jié)點(diǎn)時,都需要手動去配置前端負(fù)載均衡,手動去匹配后端節(jié)點(diǎn),而如今,使用k8s內(nèi)部的service可以動態(tài)發(fā)現(xiàn)實(shí)現(xiàn)自動管理節(jié)點(diǎn),并且支持自動擴(kuò)容縮容。之前遇到高峰流量時,經(jīng)常服務(wù)器性能不夠,需要臨時加服務(wù)器面對高峰流量,而如今對于高性能k8s集群加上serverless,基本實(shí)現(xiàn)無需管理,自動擴(kuò)容。
對于高可用方面,k8s天生的高可用功能,徹底釋放了雙手,無需再去創(chuàng)建各類高可用工具、檢測檢查腳本。k8s支持進(jìn)程接口級別的健康檢查,如發(fā)現(xiàn)接口超時或者返回值不正確,會自動處理該問題。
對于中間件搭建方面,根據(jù)定義好的資源文件,可以實(shí)現(xiàn)秒級搭建各類中間件高可用集群,并且支持一鍵式擴(kuò)縮容,如Redis、RabbitMQ、Zookeeper等,并且大大減少了出錯的概率。
對于應(yīng)用端口方面,傳統(tǒng)行業(yè)中,一個服務(wù)器可能跑了很多進(jìn)程,每個進(jìn)程都有一個端口,需要人為的去配置端口,并且還需要考慮端口沖突的問題,如果有防火墻的話,還需要配置防火墻,在k8s中,端口統(tǒng)一管理,統(tǒng)一配置,每個應(yīng)用的端口都可設(shè)置成一樣的,之后通過service進(jìn)行負(fù)載均衡,大大降低了端口管理的復(fù)雜度和端口沖突。
無論是對于開發(fā)人員、測試人員還是運(yùn)維人員,k8s的誕生,不僅減少了工作的復(fù)雜性,還減少了各種成本。上述帶來的變革只是其中比較小的一部分,更多優(yōu)點(diǎn)只有用了才能體會到。
二、 kubernetes帶來的挑戰(zhàn)
首先是對于k8s的學(xué)習(xí)本身就是很難的,概念太多,無從入手,可能學(xué)習(xí)了一個月也無法入門,甚至連集群也搭建不出來,使人望而卻步。并且k8s對運(yùn)維的技術(shù)能力要求比較高,已經(jīng)不僅僅局限于傳統(tǒng)運(yùn)維,有時候你可能要修改業(yè)務(wù)代碼等。并且需要掌握的知識也需要很多,你可能需要掌握公司所有使用到的代碼,比如代碼是如何進(jìn)行編譯的、如何正確發(fā)布、如何修改代碼配置文件等,這對于運(yùn)維人員,也是一種挑戰(zhàn)。Kubernetes之所以被叫做k8s,業(yè)界有兩種說法,通俗的說法是k和s之間有8個字母,另一種比較說法是k8s集群至少需要搭建8遍才能搭建成功。當(dāng)然,在實(shí)際使用時,可能不止8遍。k8s的誕生,把運(yùn)維從傳統(tǒng)轉(zhuǎn)變到了DevOps方向,需要面臨的問題會更多,需要面臨的新技術(shù)也有很多,但是當(dāng)你掌握到了k8s的核心使用,就會受益終身。
三、Pod初體驗(yàn)
1.pod簡單介紹
K8s有很多技術(shù)概念,同時對應(yīng)很多API對象,最重要的也是最基礎(chǔ)的是微服務(wù)Pod。Pod是在K8s集群中運(yùn)行部署應(yīng)用或服務(wù)的最小單元,它是可以支持多容器的。Pod的設(shè)計(jì)理念是支持多個容器在一個Pod中共享網(wǎng)絡(luò)地址和文件系統(tǒng),可以通過進(jìn)程間通信和文件共享這種簡單高效的方式組合完成服務(wù)。Pod對多容器的支持是K8s最基礎(chǔ)的設(shè)計(jì)理念。比如你運(yùn)行一個操作系統(tǒng)發(fā)行版的軟件倉庫,一個Nginx容器用來發(fā)布軟件,另一個容器專門用來從源倉庫做同步,這兩個容器的鏡像不太可能是一個團(tuán)隊(duì)開發(fā)的,但是他們一塊兒工作才能提供一個微服務(wù);這種情況下,不同的團(tuán)隊(duì)各自開發(fā)構(gòu)建自己的容器鏡像,在部署的時候組合成一個微服務(wù)對外提供服務(wù)。這就是K8S中的POD。
Pod是K8s集群中所有業(yè)務(wù)類型的基礎(chǔ),可以看作運(yùn)行在K8s集群中的小機(jī)器人,不同類型的業(yè)務(wù)就需要不同類型的小機(jī)器人去執(zhí)行。目前K8s中的業(yè)務(wù)主要可以分為長期伺服型(long-running)、批處理型(batch)、節(jié)點(diǎn)后臺支撐型(node-daemon)和有狀態(tài)應(yīng)用型(stateful application);分別對應(yīng)的小機(jī)器人控制器為Deployment、Job、DaemonSet和StatefulSet。
總結(jié)來說,Pod 是 k8s 系統(tǒng)中可以創(chuàng)建和管理的最小單元,是資源對象模型中由用戶創(chuàng)建或部署的最小資源對象模型,也是在 k8s 上運(yùn)行容器化應(yīng)用的資源對象,其他的資源對象都是用來支撐或者擴(kuò)展 Pod 對象功能的,比如控制器對象是用來管控 Pod 對象的,Service 或者Ingress 資源對象是用來暴露 Pod 引用對象的,PersistentVolume資源對象是用來為 Pod 提供存儲等等,k8s 不會直接處理容器,而是 Pod,Pod 是由一個或多個 container 組成。
Pod 是 Kubernetes 的最重要概念,每一個 Pod 都有一個特殊的被稱為”根容器“的 Pause 容器。Pause 容器對應(yīng)的鏡 像屬于 Kubernetes 平臺的一部分,除了 Pause 容器,每個 Pod 還包含一個或多個緊密相關(guān)的用戶業(yè)務(wù)容器
2.Pod實(shí)現(xiàn)機(jī)制
#1.共享網(wǎng)絡(luò)(通過Pause容器。把其他業(yè)務(wù)容器加入到Pause容器里面,讓所有業(yè)務(wù)容器在同—個名稱空間中,可以實(shí)現(xiàn)網(wǎng)絡(luò)共享)
Pod中可以同時運(yùn)行多個進(jìn)程(作為容器運(yùn)行)協(xié)同工作。同一個Pod中的容器會自動的分配到同一個 node 上。同一個Pod中的容器共享資源、網(wǎng)絡(luò)環(huán)境和依賴,所以它們總是被同時調(diào)度。在一個Pod中同時運(yùn)行多個容器是一種比較高級的用法。只有當(dāng)你的容器需要緊密配合協(xié)作的時候才考慮用這種模式。
#2.共享存儲(引入數(shù)據(jù)卷概念Volumn,使用數(shù)據(jù)卷進(jìn)行持久化存儲)
Pod在設(shè)計(jì)?持就不是作為持久化實(shí)體的。在調(diào)度失敗、節(jié)點(diǎn)故障、缺少資源或者節(jié)點(diǎn)維護(hù)的狀態(tài)下都會死掉會被驅(qū)逐。通常,我們是需要借助類似于Docker存儲卷這樣的資源來做Pod的數(shù)據(jù)久化的。
3.Pod vs 應(yīng)用
每個 Pod 都是應(yīng)用的一個實(shí)例,有專用的 IP
4.Pod vs 容器
一個 Pod 可以有多個容器,彼此間共享網(wǎng)絡(luò)和存儲資源,每個 Pod 中有一個 Pause 容器保存所有的容器狀態(tài), 通過管理 pause 容器,達(dá)到管理 pod 中所有容器的效果
5.Pod vs 節(jié)點(diǎn)
同一個 Pod 中的容器總會被調(diào)度到相同 Node 節(jié)點(diǎn),不同節(jié)點(diǎn)間 Pod 的通信基于虛擬二層網(wǎng)絡(luò)技術(shù)實(shí)現(xiàn)
6.Pod vs Pod
普通的 Pod 和靜態(tài) Pod
四、Pod存在的意義及好處
1.意義
#1.創(chuàng)建容器使用doeker,一個docker對應(yīng)一個容器,一個容器有進(jìn)程。一個容器運(yùn)行一個應(yīng)用程序
#2.Pod是多進(jìn)程設(shè)計(jì),運(yùn)行多個應(yīng)用程序
一個Pod有多個容器,一個容器里面運(yùn)行一個應(yīng)用程序
#3.Pod存在為了親密性應(yīng)用
兩個應(yīng)用之間進(jìn)行交互
網(wǎng)絡(luò)之間調(diào)用
兩個應(yīng)用需要頻繁調(diào)用
2.好處
#1.Pod做為一個可以獨(dú)立運(yùn)行的服務(wù)單元,簡化了應(yīng)用部署的難度,以更高的抽象層次為應(yīng)用部署管提供了極大的方便。
#2.Pod做為最小的應(yīng)用實(shí)例可以獨(dú)立運(yùn)行,因此可以方便的進(jìn)行部署、水平擴(kuò)展和收縮、方便進(jìn)行調(diào)度管理與資源的分配。
#3.Pod中的容器共享相同的數(shù)據(jù)和網(wǎng)絡(luò)地址空間,Pod之間也進(jìn)行了統(tǒng)一的資源管理與分配。
五、Pod特性
1.資源共享
一個 Pod 里的多個容器可以共享存儲和網(wǎng)絡(luò),可以看作一個邏輯的主機(jī)。共享的如namespace,cgroups 或者其他的隔離資源。
多個容器共享同一network namespace,由此在一個 Pod 里的多個容器共享 Pod 的 IP 和端口 namespace,所以一個 Pod 內(nèi)的多個容器之間可以通過 localhost 來進(jìn)行通信,所需要注意的是不同容器要注意不要有端口沖突即可。不同的 Pod 有不同的 IP,不同 Pod 內(nèi)的多個容器之前通信,不可以使用 IPC(如果沒有特殊指定的話)通信,通常情況下使用 Pod 的 IP 進(jìn)行通信。
一個 Pod 里的多個容器可以共享存儲卷,這個存儲卷會被定義為 Pod 的一部分,并且可以掛載到該 Pod 里的所有容器的文件系統(tǒng)上。
2.生命周期短暫
Pod 屬于生命周期比較短暫的組件,比如,當(dāng) Pod 所在節(jié)點(diǎn)發(fā)生故障,那么該節(jié)點(diǎn)上的 Pod 會被調(diào)度到其他節(jié)點(diǎn),但需要注意的是,被重新調(diào)度的 Pod 是一個全新的 Pod,跟之前的Pod 沒有半毛錢關(guān)系。
3.平坦的網(wǎng)絡(luò)
K8s 集群中的所有 Pod 都在同一個共享網(wǎng)絡(luò)地址空間中,也就是說每個 Pod 都可以通過其他 Pod 的 IP 地址來實(shí)現(xiàn)訪問。
六、Pod的資源清單詳解
apiVersion: v1 # 必選,API的版本號
kind: Pod # 必選,類型Pod
metadata: # 必選,元數(shù)據(jù)
name: nginx # 必選,符合RFC 1035規(guī)范的Pod名稱
namespace: web-testing # 可選,不指定默認(rèn)為default,Pod所在的命名空間
labels: # 可選,標(biāo)簽選擇器,一般用于Selector
- app: nginx
annotations: # 可選,注釋列表
- app: nginx
spec: # 必選,用于定義容器的詳細(xì)信息
containers: # 必選,容器列表
- name: nginx # 必選,符合RFC 1035規(guī)范的容器名稱
image: nginx:v1 # 必選,容器所用的鏡像的地址
imagePullPolicy: Always # 可選,鏡像拉取策略
workingDir: /usr/share/nginx/html # 可選,容器的工作目錄
volumeMounts: # 可選,存儲卷配置
- name: webroot # 存儲卷名稱
mountPath: /usr/share/nginx/html # 掛載目錄
readOnly: true # 只讀
ports: # 可選,容器需要暴露的端口號列表
- name: http # 端口名稱
containerPort: 80 # 端口號
protocol: TCP # 端口協(xié)議,默認(rèn)TCP
env: # 可選,環(huán)境變量配置
- name: TZ # 變量名
value: Asia/Shanghai
- name: LANG
value: en_US.utf8
resources: # 可選,資源限制和資源請求限制
limits: # 最大限制設(shè)置
cpu: 1000m
memory: 1024MiB
requests: # 啟動所需的資源
cpu: 100m
memory: 512MiB
readinessProbe: # 可選,容器狀態(tài)檢查
httpGet: # 檢測方式
path: / # 檢查路徑
port: 80 # 監(jiān)控端口
timeoutSeconds: 2 # 超時時間
initialDelaySeconds: 60 # 初始化時間
livenessProbe: # 可選,監(jiān)控狀態(tài)檢查
exec: # 檢測方式
command:
- cat
- /health
httpGet: # 檢測方式
path: /_health
port: 8080
httpHeaders:
- name: end-user
value: jason
tcpSocket: # 檢測方式
port: 80
initialDelaySeconds: 60 # 初始化時間
timeoutSeconds: 2 # 超時時間
periodSeconds: 5 # 檢測間隔
successThreshold: 2 # 檢查成功為2次表示就緒
failureThreshold: 1 # 檢測失敗1次表示未就緒
securityContext: # 可選,限制容器不可信的行為
provoleged: false
restartPolicy: Always # 可選,默認(rèn)為Always
nodeSelector: # 可選,指定Node節(jié)點(diǎn)
region: subnet7
imagePullSecrets: # 可選,拉取鏡像使用的secret
- name: default-dockercfg-86258
hostNetwork: false # 可選,是否為主機(jī)模式,如是,會占用主機(jī)端口
volumes: # 共享存儲卷列表
- name: webroot # 名稱,與上述對應(yīng)
emptyDir: {} # 共享卷類型,空
hostPath: # 共享卷類型,本機(jī)目錄
path: /etc/hosts
secret: # 共享卷類型,secret模式,一般用于密碼
secretName: default-token-tf2jp # 名稱
defaultMode: 420 # 權(quán)限
configMap: # 一般用于配置文件
name: nginx-conf
defaultMode: 420
七、Pod 的基本使用
在 kubernetes 中對運(yùn)行容器的要求為:容器的主程序需要一直在前臺運(yùn)行,而不是后臺運(yùn)行。應(yīng)用需要改造成前臺運(yùn)行的方式。如果我們創(chuàng)建的 Docker 鏡像的啟動命令是后臺執(zhí)行程序,則在 kubelet 創(chuàng)建包含這個容器的 pod 之后運(yùn)行完該命令,即認(rèn)為 Pod 已經(jīng)結(jié)束, 將立刻銷毀該P(yáng)od。如果為該 Pod 定義了 RC,則創(chuàng)建、銷毀會陷入一個無限循環(huán)的過程中。
Pod 可以由 1 個或多個容器組合而成。
1.一個容器組成的 Pod 的 yaml 示例
[root@k8s-master-001 ~]# vi first-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: first-pod
labels:
app: bash
spec:
containers:
- name: bash-container
image: busybox
command: ['sh', '-c', 'echo Hello Kubernetes! && sleep 10']
2.多個容器組成的 Pod 的 yaml 示例
[root@k8s-master-001 ~]# vi second-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: myweb
labels:
name: tomcat-redis
spec:
containers:
- name: tomcat
image: tomcat
ports:
- containerPort: 8080
- name: redis
image: redis
ports:
- containerPort: 6379
3.創(chuàng)建
[root@k8s-master-001 ~]# kubectl apply -f first-pod.yaml
pod/first-pod created
[root@k8s-master-001 ~]# kubectl apply -f second-pod.yaml
pod/myweb created
4.查看
[root@k8s-master-001 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
first-pod 0/1 Completed 3 5m2s
myweb 2/2 Running 0 4m49s
[root@k8s-master-001 ~]# kubectl logs first-pod
Hello Kubernetes
[root@k8s-master-001 ~]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
first-pod 0/1 CrashLoopBackOff 6 14m 10.241.184.2 k8s-node-002 <none> <none>
myweb 2/2 Running 0 13m 10.241.184.3 k8s-node-002 <none> <none>
[root@k8s-master-001 ~]# kubectl describe pod first-pod
Name: first-pod
Namespace: default
Priority: 0
Node: k8s-node-002/172.16.1.114
Start Time: Tue, 28 Sep 2021 14:54:47 +0800
Labels: app=bash
Annotations: Status: Running
IP: 10.241.184.2
IPs:
IP: 10.241.184.2
Containers:
bash-container:
Container ID: docker://6560a18d58bc165464ee7155ab3001a4337a5108098f47fa7f9dfee6b9deed07
Image: busybox
Image ID: docker-pullable://busybox@sha256:f7ca5a32c10d51aeda3b4d01c61c6061f497893d7f6628b92f822f7117182a57
Port: <none>
Host Port: <none>
Command:
sh
-c
echo Hello Kubernetes! && sleep 10
State: Waiting
Reason: CrashLoopBackOff
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Tue, 28 Sep 2021 15:05:52 +0800
Finished: Tue, 28 Sep 2021 15:06:02 +0800
Ready: False
Restart Count: 6
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
Conditions:
Type Status
Initialized True
Ready False
ContainersReady False
PodScheduled True
Volumes:
default-token-cvczf:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-cvczf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 360s
node.kubernetes.io/unreachable:NoExecute for 360s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/first-pod to k8s-node-002
Normal Started 10m (x4 over 14m) kubelet, k8s-node-002 Started container bash-container
Normal Pulling 9m30s (x5 over 14m) kubelet, k8s-node-002 Pulling image "busybox"
Normal Pulled 9m14s (x5 over 14m) kubelet, k8s-node-002 Successfully pulled image "busybox"
Normal Created 9m14s (x5 over 14m) kubelet, k8s-node-002 Created container bash-container
Warning BackOff 4m48s (x26 over 11m) kubelet, k8s-node-002 Back-off restarting failed container
[root@k8s-master-001 ~]# kubectl describe pod myweb
Name: myweb
Namespace: default
Priority: 0
Node: k8s-node-002/172.16.1.114
Start Time: Tue, 28 Sep 2021 14:55:01 +0800
Labels: name=tomcat-redis
Annotations: Status: Running
IP: 10.241.184.3
IPs:
IP: 10.241.184.3
Containers:
tomcat:
Container ID: docker://5659eaf2061c015c57274881b0a95a76edcc88b3d6b2b5c99e15f5da2bc6510b
Image: tomcat
Image ID: docker-pullable://tomcat@sha256:54876d82d30746c5b625a784938864d5b726219e0aace09b3e57ef4dfa85d594
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 28 Sep 2021 14:57:45 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
redis:
Container ID: docker://6e8a571baf372571de70d9e672c3ef8a8e9cfeeab9845d661abd2a80b084585b
Image: redis
Image ID: docker-pullable://redis@sha256:e595e79c05c7690f50ef0136acc9d932d65d8b2ce7915d26a68ca3fb41a7db61
Port: 6379/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 28 Sep 2021 14:58:18 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-cvczf (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-cvczf:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-cvczf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 360s
node.kubernetes.io/unreachable:NoExecute for 360s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled <unknown> default-scheduler Successfully assigned default/myweb to k8s-node-002
Normal Pulling 15m kubelet, k8s-node-002 Pulling image "tomcat"
Normal Pulled 12m kubelet, k8s-node-002 Successfully pulled image "tomcat"
Normal Created 12m kubelet, k8s-node-002 Created container tomcat
Normal Started 12m kubelet, k8s-node-002 Started container tomcat
Normal Pulling 12m kubelet, k8s-node-002 Pulling image "redis"
Normal Pulled 11m kubelet, k8s-node-002 Successfully pulled image "redis"
Normal Created 11m kubelet, k8s-node-002 Created container redis
Normal Started 11m kubelet, k8s-node-002 Started container redis
5.刪除
[root@k8s-master-001 ~]# kubectl delete -f first-pod.yaml
pod "first-pod" deleted
[root@k8s-master-001 ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
myweb 2/2 Running 0 24m
nginx-f89759699-knhc6 1/1 Running 0 26m
[root@k8s-master-001 ~]# kubectl delete pod --all
pod "myweb" deleted
[root@k8s-master-001 ~]# kubectl get pod
No resources found in default namespace.
八、Pod 的分類
1.普通 Pod
普通 Pod 一旦被創(chuàng)建,就會被放入到 etcd 中存儲,隨后會被 Kubernetes Master 調(diào)度到某個具體的 Node 上并進(jìn)行綁定,隨后該 Pod 對應(yīng)的 Node 上的 kubelet 進(jìn)程實(shí)例化成一組相關(guān)的 Docker 容器并啟動起來。在默認(rèn)情 況下,當(dāng) Pod 里某個容器停止時,Kubernetes 會自動檢測到這個問題并且重新啟動這個 Pod 里某所有容器, 如果 Pod 所在的 Node 宕機(jī), 則會將這個 Node 上的所有 Pod 重新調(diào)度到其它節(jié)點(diǎn)上。
2.靜態(tài) Pod
靜態(tài) Pod 是由 kubelet 進(jìn)行管理的僅存在于特定 Node 上的 Pod,它們不能通過 API Server 進(jìn)行管理,無法與 ReplicationController、Deployment 或 DaemonSet 進(jìn)行關(guān)聯(lián),并且kubelet 也無法對它們進(jìn)行健康檢查。
九、Pod的生命周期和重啟策略
Pod 在整個生命周期過程中被系統(tǒng)定義為各種狀態(tài),熟悉 Pod 各種狀態(tài)對于理解如何設(shè)置 Pod的調(diào)度策略、重啟策略是很有必要的。
1.Pod的狀態(tài)
狀態(tài)值 |
描述 |
掛起(Pending) |
API Server創(chuàng)建了pod資源對象已存入etcd中,但它尚未被調(diào)度完成,或者仍處于從倉庫下載鏡像的過程中。 |
運(yùn)行中(Running) |
Pod已經(jīng)被調(diào)度至某節(jié)點(diǎn),并且所有容器都已經(jīng)被kubelet創(chuàng)建完成 |
成功(Successed/Completed) |
Pod中的所有容器都已經(jīng)成功終止并且不會被重啟 |
失?。‵ailed) |
Pod中的所有容器都已終止了,并且至少有一個容器是因?yàn)槭〗K止。即容器以非0狀態(tài)退出或者被系統(tǒng)禁止。 |
未知(Unknown) |
Api Server無法正常獲取到Pod對象的狀態(tài)信息,通常是由于無法與所在工作節(jié)點(diǎn)的kubelet通信所致。 |
2.Pod的重啟策略
Pod 重啟策略( RestartPolicy )應(yīng)用于 Pod 內(nèi)的所有容器,井且僅在 Pod 所處的 Node 上由kubelet 進(jìn)行判斷和重啟操作。當(dāng)某個容器異常退出或者健康檢查失敗時, kubelet將根據(jù) RestartPolicy 設(shè)置來進(jìn)行相應(yīng)的操作。Pod的重啟策略包括:Always、OnFailure和Never,默認(rèn)值為Always
狀態(tài)值 |
說明 |
Always |
當(dāng)容器失效時,由kubelet自動重啟該容器。 |
OnFailure |
當(dāng)容器終止運(yùn)行且退出碼不為0時,由kubelet自動重啟該容器。 |
Never |
不論容器運(yùn)行狀態(tài)如何,kubelet都不會重啟該容器。 |
kubelet 重啟失效容器的時間間隔以 sync-frequency 乘以 2n 來計(jì)算;例如1、2、4、8倍等,最長延時 5min ,并且在成功重啟后的 10 min 后重置該時間。
Pod的重啟策略與控制方式息息相關(guān),當(dāng)前可用于管理Pod的控制器包括ReplicationController、Job、DaemonSet及直接通過kubelet管理(靜態(tài)Pod)。每種控制器對Pod的重啟策略要求如下:
1.RC和DaemonSet:必須設(shè)置為Always,需要保證該容器持續(xù)運(yùn)行。
2.Job和CronJob:OnFailure或Never,確保容器執(zhí)行完成后不再重啟。
3.kubelet:在Pod失效時自動重啟它,不論將RestartPolicy設(shè)置為什么值,也不會對Pod進(jìn)行健康檢查。
3.常見狀態(tài)轉(zhuǎn)換
Pod包含的容器數(shù) |
Pod當(dāng)前的狀態(tài) |
發(fā)生事件 |
Pod的結(jié)果狀態(tài) |
|
|
|
|
|
RestartPolicy=Always |
RestartPolicy=OnFailure |
RestartPolicy=Never |
包含一個容器 |
Running |
容器成功退出 |
Running |
Succeeded |
Succeeded |
包含一個容器 |
Running |
容器失敗退出 |
Running |
Running |
Failure |
包含兩個容器 |
Running |
1個容器失敗退出 |
Running |
Running |
Running |
包含兩個容器 |
Running |
容器被OOM殺掉 |
Running |
Running |
Failure |
十、Pod 資源配置
每個 Pod 都可以對其能使用的服務(wù)器上的計(jì)算資源設(shè)置限額,Kubernetes 中可以設(shè)置限額的計(jì)算資源有 CPU 與 Memory 兩種,其中 CPU 的資源單位為 CPU 數(shù)量,是一個絕對值而非相對值。Memory 配額也是一個絕對值,它的單 位是內(nèi)存字節(jié)數(shù)。
Kubernetes 里,一個計(jì)算資源進(jìn)行配額限定需要設(shè)定以下兩個參數(shù): Requests 該資源最小申請數(shù)量,系統(tǒng)必須滿足要求 Limits 該資源最大允許使用的量,不能突破,當(dāng)容器試圖使用超過這個量的資源時,可能會被 Kubernetes Kill 并重啟。
1.舉例
apiVersion: v1 # 必選,API的版本號
kind: Pod # 必選,類型Pod
metadata: # 必選,元數(shù)據(jù)
name: nginx # 必選,符合RFC 1035規(guī)范的Pod名稱
namespace: web-testing # 可選,不指定默認(rèn)為default,Pod所在的命名空間
labels: # 可選,標(biāo)簽選擇器,一般用于Selector
- app: nginx
annotations: # 可選,注釋列表
- app: nginx
spec: # 必選,用于定義容器的詳細(xì)信息
containers: # 必選,容器列表
- name: nginx # 必選,符合RFC 1035規(guī)范的容器名稱
image: nginx:v1 # 必選,容器所用的鏡像的地址
imagePullPolicy: Always # 可選,鏡像拉取策略
workingDir: /usr/share/nginx/html # 可選,容器的工作目錄
volumeMounts: # 可選,存儲卷配置
- name: webroot # 存儲卷名稱
mountPath: /usr/share/nginx/html # 掛載目錄
readOnly: true # 只讀
ports: # 可選,容器需要暴露的端口號列表
- name: http # 端口名稱
containerPort: 80 # 端口號
protocol: TCP # 端口協(xié)議,默認(rèn)TCP
env: # 可選,環(huán)境變量配置
- name: TZ # 變量名
value: Asia/Shanghai
- name: LANG
value: en_US.utf8
resources: # 可選,資源限制和資源請求限制
limits: # 最大限制設(shè)置
cpu: 1000m
memory: 1024MiB
requests: # 啟動所需的資源
cpu: 100m
memory: 512MiB
上述代碼表明 nginx 容器申請最少 0.1 個 CPU 以及 512MiB 內(nèi)存,在運(yùn)行過程中容器所能使用的資源配額為 1 個 CPU 以及 1G 內(nèi)存。