天天看點

K8S面試題-第一彈

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,那麼更新過程就不會停止)。

推薦:

250期面試題精選

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的流程是什麼?

  • 用戶端送出Pod的配置資訊(可以是yaml檔案定義好的資訊)到kube-apiserver;
  • Apiserver收到指令後,通知給controller-manager建立一個資源對象;
  • Controller-manager通過api-server将pod的配置資訊存儲到ETCD資料中心中;
  • Kube-scheduler檢測到pod資訊會開始排程預選,會先過濾掉不符合Pod資源配置要求的節點,然後開始排程調優,主要是挑選出更适合運作pod的節點,然後将pod的資源配置單發送到node節點上的kubelet元件上。
  • Kubelet根據scheduler發來的資源配置單運作pod,運作成功後,将pod的運作資訊傳回給scheduler,scheduler将傳回的pod運作狀況的資訊存儲到etcd資料中心。

19、 删除一個Pod會發生什麼事情?

答:Kube-apiserver會接受到使用者的删除指令,預設有30秒時間等待優雅退出,超過30秒會被标記為死亡狀态,此時Pod的狀态Terminating,kubelet看到pod标記為Terminating就開始了關閉Pod的工作;

關閉流程如下:

  • pod從service的endpoint清單中被移除;
  • 如果該pod定義了一個停止前的鈎子,其會在pod内部被調用,停止鈎子一般定義了如何優雅的結束程序;
  • 程序被發送TERM信号(kill -14)
  • 當超過優雅退出的時間後,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。

主要使用場景:

  • 隻需要臨時将資料儲存在磁盤上,比如在合并/排序算法中;
  • 作為兩個容器的共享存儲,使得第一個内容管理的容器可以将生成的資料存入其中,同時由同一個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去申請,或者随機申請。

繼續閱讀