注:以下所有問題,均爲自己總結,若有錯誤之處,還請指出。
- 1、 k8s是什麼?請說出你的瞭解?
答:Kubenetes是一個針對容器應用,進行自動部署,彈性伸縮和管理的開源系統。主要功能是生產環境中的容器編排。
K8S是Google公司推出的,它來源於由Google公司內部使用了15年的Borg系統,集結了Borg的精華。
- 2、 K8s架構的組成是什麼?
答:和大多數分佈式系統一樣,K8S集羣至少需要一個主節點(Master)和多個計算節點(Node)。
主節點主要用於暴露API,調度部署和節點的管理;
計算節點運行一個容器運行環境,一般是docker環境(類似docker環境的還有rkt),同時運行一個K8s的代理(kubelet)用於和master通信。計算節點也會運行一些額外的組件,像記錄日誌,節點監控,服務發現等等。計算節點是k8s集羣中真正工作的節點。
K8S架構細分:
1、Master節點(默認不參加實際工作):
Kubectl:客戶端命令行工具,作爲整個K8s集羣的操作入口;
Api Server:在K8s架構中承擔的是“橋樑”的角色,作爲資源操作的唯一入口,它提供了認證、授權、訪問控制、API註冊和發現等機制。客戶端與k8s羣集及K8s內部組件的通信,都要通過Api Server這個組件;
Controller-manager:負責維護羣集的狀態,比如故障檢測、自動擴展、滾動更新等;
Scheduler:負責資源的調度,按照預定的調度策略將pod調度到相應的node節點上;
Etcd:擔任數據中心的角色,保存了整個羣集的狀態;
2、Node節點:
Kubelet:負責維護容器的生命週期,同時也負責Volume和網絡的管理,一般運行在所有的節點,是Node節點的代理,當Scheduler確定某個node上運行pod之後,會將pod的具體信息(image,volume)等發送給該節點的kubelet,kubelet根據這些信息創建和運行容器,並向master返回運行狀態。(自動修復功能:如果某個節點中的容器宕機,它會嘗試重啓該容器,若重啓無效,則會將該pod殺死,然後重新創建一個容器);
Kube-proxy:Service在邏輯上代表了後端的多個pod。負責爲Service提供cluster內部的服務發現和負載均衡(外界通過Service訪問pod提供的服務時,Service接收到的請求後就是通過kube-proxy來轉發到pod上的);
container-runtime:是負責管理運行容器的軟件,比如docker
Pod:是k8s集羣裏面最小的單位。每個pod裏邊可以運行一個或多個container(容器),如果一個pod中有兩個container,那麼container的USR(用戶)、MNT(掛載點)、PID(進程號)是相互隔離的,UTS(主機名和域名)、IPC(消息隊列)、NET(網絡棧)是相互共享的。我比較喜歡把pod來當做豌豆夾,而豌豆就是pod中的container;
- 3、 容器和主機部署應用的區別是什麼?
答:容器的中心思想就是秒級啓動;一次封裝、到處運行;這是主機部署應用無法達到的效果,但同時也更應該注重容器的數據持久化問題。
另外,容器部署可以將各個服務進行隔離,互不影響,這也是容器的另一個核心概念。
- 4、請你說一下kubenetes針對pod資源對象的健康監測機制?
答:K8s中對於pod資源對象的健康狀態檢測,提供了三類probe(探針)來執行對pod的健康監測:
1) livenessProbe探針
可以根據用戶自定義規則來判定pod是否健康,如果livenessProbe探針探測到容器不健康,則kubelet會根據其重啓策略來決定是否重啓,如果一個容器不包含livenessProbe探針,則kubelet會認爲容器的livenessProbe探針的返回值永遠成功。
2) ReadinessProbe探針
同樣是可以根據用戶自定義規則來判斷pod是否健康,如果探測失敗,控制器會將此pod從對應service的endpoint列表中移除,從此不再將任何請求調度到此Pod上,直到下次探測成功。
3) startupProbe探針
啓動檢查機制,應用一些啓動緩慢的業務,避免業務長時間啓動而被上面兩類探針kill掉,這個問題也可以換另一種方式解決,就是定義上面兩類探針機制時,初始化時間定義的長一些即可。
每種探測方法能支持以下幾個相同的檢查參數,用於設置控制檢查時間:
initialDelaySeconds:初始第一次探測間隔,用於應用啓動的時間,防止應用還沒啓動而健康檢查失敗
periodSeconds:檢查間隔,多久執行probe檢查,默認爲10s;
timeoutSeconds:檢查超時時長,探測應用timeout後爲失敗;
successThreshold:成功探測閾值,表示探測多少次爲健康正常,默認探測1次。
上面兩種探針都支持以下三種探測方法:
1)Exec:通過執行命令的方式來檢查服務是否正常,比如使用cat命令查看pod中的某個重要配置文件是否存在,若存在,則表示pod健康。反之異常。
Exec探測方式的yaml文件語法如下:
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe: #選擇livenessProbe的探測機制
exec: #執行以下命令
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5 #在容器運行五秒後開始探測
periodSeconds: 5 #每次探測的時間間隔爲5秒
在上面的配置文件中,探測機制爲在容器運行5秒後,每隔五秒探測一次,如果cat命令返回的值爲“0”,則表示健康,如果爲非0,則表示異常。
2)Httpget:通過發送http/htps請求檢查服務是否正常,返回的狀態碼爲200-399則表示容器健康(注http get類似於命令curl -I)。
Httpget探測方式的yaml文件語法如下:
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
livenessProbe: #採用livenessProbe機制探測
httpGet: #採用httpget的方式
scheme:HTTP #指定協議,也支持https
path: /healthz #檢測是否可以訪問到網頁根目錄下的healthz網頁文件
port: 8080 #監聽端口是8080
initialDelaySeconds: 3 #容器運行3秒後開始探測
periodSeconds: 3 #探測頻率爲3秒
上述配置文件中,探測方式爲項容器發送HTTP GET請求,請求的是8080端口下的healthz文件,返回任何大於或等於200且小於400的狀態碼錶示成功。任何其他代碼表示異常。
3)tcpSocket:通過容器的IP和Port執行TCP檢查,如果能夠建立TCP連接,則表明容器健康,這種方式與HTTPget的探測機制有些類似,tcpsocket健康檢查適用於TCP業務。
tcpSocket探測方式的yaml文件語法如下:
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
#這裏兩種探測機制都用上了,都是爲了和容器的8080端口建立TCP連接
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
在上述的yaml配置文件中,兩類探針都使用了,在容器啓動5秒後,kubelet將發送第一個readinessProbe探針,這將連接容器的8080端口,如果探測成功,則該pod爲健康,十秒後,kubelet將進行第二次連接。
除了readinessProbe探針外,在容器啓動15秒後,kubelet將發送第一個livenessProbe探針,仍然嘗試連接容器的8080端口,如果連接失敗,則重啓容器。
探針探測的結果無外乎以下三者之一:
Success:Container通過了檢查;
Failure:Container沒有通過檢查;
Unknown:沒有執行檢查,因此不採取任何措施(通常是我們沒有定義探針檢測,默認爲成功)。
若覺得上面還不夠透徹,可以移步其官網文檔:https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/
- 5、 如何控制滾動更新過程?
答:
可以通過下面的命令查看到更新時可以控制的參數:
[root@master yaml]# kubectl explain deploy.spec.strategy.rollingUpdate
maxSurge :此參數控制滾動更新過程,副本總數超過預期pod數量的上限。可以是百分比,也可以是具體的值。默認爲1。
(上述參數的作用就是在更新過程中,值若爲3,那麼不管三七二一,先運行三個pod,用於替換舊的pod,以此類推)
maxUnavailable:此參數控制滾動更新過程中,不可用的Pod的數量。 (這個值和上面的值沒有任何關係,舉個例子:我有十個pod,但是在更新的過程中,我允許這十個pod中最多有三個不可用,那麼就將這個參數的值設置爲3,在更新的過程中,只要不可用的pod數量小於或等於3,那麼更新過程就不會停止)。
- 6、K8s中鏡像的下載策略是什麼?
答:可通過命令“kubectl explain pod.spec.containers”來查看imagePullPolicy這行的解釋。
K8s的鏡像下載策略有三種:Always、Never、IFNotPresent;
Always:鏡像標籤爲latest時,總是從指定的倉庫中獲取鏡像;
Never:禁止從倉庫中下載鏡像,也就是說只能使用本地鏡像;
IfNotPresent:僅當本地沒有對應鏡像時,才從目標倉庫中下載。
默認的鏡像下載策略是:當鏡像標籤是latest時,默認策略是Always;當鏡像標籤是自定義時(也就是標籤不是latest),那麼默認策略是IfNotPresent。
- 7、 image的狀態有哪些?
Running:Pod所需的容器已經被成功調度到某個節點,且已經成功運行,
Pending:APIserver創建了pod資源對象,並且已經存入etcd中,但它尚未被調度完成或者仍然處於倉庫中下載鏡像的過程
Unknown:APIserver無法正常獲取到pod對象的狀態,通常是其無法與所在工作節點的kubelet通信所致。
- 8、 pod的重啓策略是什麼?
答:可以通過命令“kubectl explain pod.spec”查看pod的重啓策略。(restartPolicy字段)
Always:但凡pod對象終止就重啓,此爲默認策略。
OnFailure:僅在pod對象出現錯誤時才重啓
- 9、 Service這種資源對象的作用是什麼?
答:用來給相同的多個pod對象提供一個固定的統一訪問接口,常用於服務發現和服務訪問。
- 10、版本回滾相關的命令?
[root@master httpd-web]# kubectl apply -f httpd2-deploy1.yaml --record
#運行yaml文件,並記錄版本信息;
[root@master httpd-web]# kubectl rollout history deployment httpd-devploy1
#查看該deployment的歷史版本
[root@master httpd-web]# kubectl rollout undo deployment httpd-devploy1 --to-revision=1
#執行回滾操作,指定回滾到版本1
#在yaml文件的spec字段中,可以寫以下選項(用於限制最多記錄多少個歷史版本):
spec:
revisionHistoryLimit: 5
#這個字段通過 kubectl explain deploy.spec 命令找到revisionHistoryLimit <integer>行獲得
- 11、 標籤與標籤選擇器的作用是什麼?
標籤:是當相同類型的資源對象越來越多的時候,爲了更好的管理,可以按照標籤將其分爲一個組,爲的是提升資源對象的管理效率。
標籤選擇器:就是標籤的查詢過濾條件。目前API支持兩種標籤選擇器:
基於等值關係的,如:“=”、“”“==”、“!=”(注:“==”也是等於的意思,yaml文件中的matchLabels字段);
基於集合的,如:in、notin、exists(yaml文件中的matchExpressions字段);
注:in:在這個集合中;notin:不在這個集合中;exists:要麼全在(exists)這個集合中,要麼都不在(notexists);
使用標籤選擇器的操作邏輯:
在使用基於集合的標籤選擇器同時指定多個選擇器之間的邏輯關係爲“與”操作(比如:- {key: name,operator: In,values: [zhangsan,lisi]} ,那麼只要擁有這兩個值的資源,都會被選中);
使用空值的標籤選擇器,意味着每個資源對象都被選中(如:標籤選擇器的鍵是“A”,兩個資源對象同時擁有A這個鍵,但是值不一樣,這種情況下,如果使用空值的標籤選擇器,那麼將同時選中這兩個資源對象)
空的標籤選擇器(注意不是上面說的空值,而是空的,都沒有定義鍵的名稱),將無法選擇出任何資源;
在基於集合的選擇器中,使用“In”或者“Notin”操作時,其values可以爲空,但是如果爲空,這個標籤選擇器,就沒有任何意義了。
兩種標籤選擇器類型(基於等值、基於集合的書寫方法):
selector:
matchLabels: #基於等值
app: nginx
matchExpressions: #基於集合
- {key: name,operator: In,values: [zhangsan,lisi]} #key、operator、values這三個字段是固定的
- {key: age,operator: Exists,values:} #如果指定爲exists,那麼values的值一定要爲空
- 12、 常用的標籤分類有哪些?
標籤分類是可以自定義的,但是爲了能使他人可以達到一目瞭然的效果,一般會使用以下一些分類:
版本類標籤(release):stable(穩定版)、canary(金絲雀版本,可以將其稱之爲測試版中的測試版)、beta(測試版);
環境類標籤(environment):dev(開發)、qa(測試)、production(生產)、op(運維);
應用類(app):ui、as、pc、sc;
架構類(tier):frontend(前端)、backend(後端)、cache(緩存);
分區標籤(partition):customerA(客戶A)、customerB(客戶B);
品控級別(Track):daily(每天)、weekly(每週)。
- 13、 有幾種查看標籤的方式?
答:常用的有以下三種查看方式:
[root@master ~]# kubectl get pod --show-labels #查看pod,並且顯示標籤內容
[root@master ~]# kubectl get pod -L env,tier #顯示資源對象標籤的值
[root@master ~]# kubectl get pod -l env,tier #只顯示符合鍵值資源對象的pod,而“-L”是顯示所有的pod
- 14、 添加、修改、刪除標籤的命令?
#對pod標籤的操作
[root@master ~]# kubectl label pod label-pod abc=123 #給名爲label-pod的pod添加標籤
[root@master ~]# kubectl label pod label-pod abc=456 --overwrite #修改名爲label-pod的標籤
[root@master ~]# kubectl label pod label-pod abc- #刪除名爲label-pod的標籤
[root@master ~]# kubectl get pod --show-labels
#對node節點的標籤操作
[root@master ~]# kubectl label nodes node01 disk=ssd #給節點node01添加disk標籤
[root@master ~]# kubectl label nodes node01 disk=sss –overwrite #修改節點node01的標籤
[root@master ~]# kubectl label nodes node01 disk- #刪除節點node01的disk標籤
- 15、 DaemonSet資源對象的特性?
DaemonSet這種資源對象會在每個k8s集羣中的節點上運行,並且每個節點只能運行一個pod,這是它和deployment資源對象的最大也是唯一的區別。所以,在其yaml文件中,不支持定義replicas,除此之外,與Deployment、RS等資源對象的寫法相同。
它的一般使用場景如下:
在去做每個節點的日誌收集工作;
監控每個節點的的運行狀態;
- 16、 說說你對Job這種資源對象的瞭解?
答:Job與其他服務類容器不同,Job是一種工作類容器(一般用於做一次性任務)。使用常見不多,可以忽略這個問題。
#提高Job執行效率的方法:
spec:
parallelism: 2 #一次運行2個
completions: 8 #最多運行8個
template:
metadata:
- 17、描述一下pod的生命週期有哪些狀態?
Pending:表示pod已經被同意創建,正在等待kube-scheduler選擇合適的節點創建,一般是在準備鏡像;
Running:表示pod中所有的容器已經被創建,並且至少有一個容器正在運行或者是正在啓動或者是正在重啓;
Succeeded:表示所有容器已經成功終止,並且不會再啓動;
Failed:表示pod中所有容器都是非0(不正常)狀態退出;
Unknown:表示無法讀取Pod狀態,通常是kube-controller-manager無法與Pod通信。
- 18、 創建一個pod的流程是什麼?
答:
1) 客戶端提交Pod的配置信息(可以是yaml文件定義好的信息)到kube-apiserver;
2) Apiserver收到指令後,通知給controller-manager創建一個資源對象;
3) Controller-manager通過api-server將pod的配置信息存儲到ETCD數據中心中;
4) Kube-scheduler檢測到pod信息會開始調度預選,會先過濾掉不符合Pod資源配置要求的節點,然後開始調度調優,主要是挑選出更適合運行pod的節點,然後將pod的資源配置單發送到node節點上的kubelet組件上。
5) Kubelet根據scheduler發來的資源配置單運行pod,運行成功後,將pod的運行信息返回給scheduler,scheduler將返回的pod運行狀況的信息存儲到etcd數據中心。
- 19、 刪除一個Pod會發生什麼事情?
答:Kube-apiserver會接受到用戶的刪除指令,默認有30秒時間等待優雅退出,超過30秒會被標記爲死亡狀態,此時Pod的狀態Terminating,kubelet看到pod標記爲Terminating就開始了關閉Pod的工作;
關閉流程如下:
1、 pod從service的endpoint列表中被移除;
2、 如果該pod定義了一個停止前的鉤子,其會在pod內部被調用,停止鉤子一般定義瞭如何優雅的結束進程;
3、 進程被髮送TERM信號(kill -14)
4、 當超過優雅退出的時間後,Pod中的所有進程都會被髮送SIGKILL信號(kill -9)。
- 20、 K8s的Service是什麼?
答:Pod每次重啓或者重新部署,其IP地址都會產生變化,這使得pod間通信和pod與外部通信變得困難,這時候,就需要Service爲pod提供一個固定的入口。
Service的Endpoint列表通常綁定了一組相同配置的pod,通過負載均衡的方式把外界請求分配到多個pod上
- 21、 k8s是怎麼進行服務註冊的?
答:Pod啓動後會加載當前環境所有Service信息,以便不同Pod根據Service名進行通信。
- 22、 k8s集羣外流量怎麼訪問Pod?
答:可以通過Service的NodePort方式訪問,會在所有節點監聽同一個端口,比如:30000,訪問節點的流量會被重定向到對應的Service上面。
- 23、 k8s數據持久化的方式有哪些?
答:1)EmptyDir(空目錄):沒有指定要掛載宿主機上的某個目錄,直接由Pod內保部映射到宿主機上。類似於docker中的manager volume。
主要使用場景:
1) 只需要臨時將數據保存在磁盤上,比如在合併/排序算法中;
2) 作爲兩個容器的共享存儲,使得第一個內容管理的容器可以將生成的數據存入其中,同時由同一個webserver容器對外提供這些頁面。
emptyDir的特性:
同個pod裏面的不同容器,共享同一個持久化目錄,當pod節點刪除時,volume的數據也會被刪除。如果僅僅是容器被銷燬,pod還在,則不會影響volume中的數據。
總結來說:emptyDir的數據持久化的生命週期和使用的pod一致。一般是作爲臨時存儲使用。
2)Hostpath:將宿主機上已存在的目錄或文件掛載到容器內部。類似於docker中的bind mount掛載方式。
這種數據持久化方式,運用場景不多,因爲它增加了pod與節點之間的耦合。
一般對於k8s集羣本身的數據持久化和docker本身的數據持久化會使用這種方式,可以自行參考apiService的yaml文件,位於:/etc/kubernetes/main…目錄下。
3)PersistentVolume(簡稱PV):
基於NFS服務的PV,也可以基於GFS的PV。它的作用是統一數據持久化目錄,方便管理。
在一個PV的yaml文件中,可以對其配置PV的大小,
指定PV的訪問模式:
ReadWriteOnce:只能以讀寫的方式掛載到單個節點;
ReadOnlyMany:能以只讀的方式掛載到多個節點;
ReadWriteMany:能以讀寫的方式掛載到多個節點。,
以及指定pv的回收策略:
recycle:清除PV的數據,然後自動回收;
Retain:需要手動回收;
delete:刪除雲存儲資源,雲存儲專用;
#PS:這裏的回收策略指的是在PV被刪除後,在這個PV下所存儲的源文件是否刪除)。
若需使用PV,那麼還有一個重要的概念:PVC,PVC是向PV申請應用所需的容量大小,K8s集羣中可能會有多個PV,PVC和PV若要關聯,其定義的訪問模式必須一致。定義的storageClassName也必須一致,若羣集中存在相同的(名字、訪問模式都一致)兩個PV,那麼PVC會選擇向它所需容量接近的PV去申請,或者隨機申請。