k8s 深入篇———— pod 實戰[六]

前言

pod 實戰一下,主要是一些例子。

正文

例子一

pod 實例的選擇:

NodeSelector:是一個供用戶將 Pod 與 Node 進行綁定的字段

NodeName:一旦 Pod 的這個字段被賦值,Kubernetes 項目就會被認爲這個 Pod 已經經過了調度,調度的結果就是賦值的節點名字。

所以,這個字段一般由調度器負責設置,但用戶也可以設置它來“騙過”調度器,當然這個做法一般是在測試或者調試的時候纔會用到。

HostAliases:定義了 Pod 的 hosts 文件(比如 /etc/hosts)裏的內容:

例如:

在這個 Pod 的 YAML 文件中,我設置了一組 IP 和 hostname 的數據。這樣,這個 Pod
啓動後,/etc/hosts 文件的內容將如下所示:

127.0.0.1 localhost
...
10.244.135.10 hostaliases-pod
10.1.2.3 foo.remote
10.1.2.3 bar.remote

如果設置:
shareProcessNamespace=true.

這就意味着這個 Pod 裏的容器要共享 PID Namespace。

而在這個 YAML 文件中,我還定義了兩個容器:一個是 nginx 容器,一個是開啓了 tty 和stdin 的 shell 容器。

然後就運行成功了。

 kubectl exec -it nginx /bin/bash

如果一個 Pod 中有多個容器,使用 kubectl exec 進入容器時需要指定容器名稱。可以使用以下命令指定容器名稱:

kubectl exec -it <pod-name> -c <container-name> sh

其中,`<pod-name>` 是 Pod 的名稱,`<container-name>` 是容器名稱。如果不指定容器名稱,默認進入第一個容器。

那麼我們進入第二個容器看下,因爲第一個容器沒有安裝ps等一些基本的命令。

stdin 是 Kubernetes 中容器的一個屬性,用於指定容器是否需要一個標準輸入(stdin)。

當 stdin 屬性設置爲 true 時,容器會打開一個 STDIN 文件描述符,並等待輸入。這通常用於在容器中運行交互式應用程序,例如 bash shell。

當 stdin 屬性設置爲 false 時,容器不會打開 STDIN 文件描述符,並且不會等待輸入。這通常用於在容器中運行後臺進程,例如 Web 服務器或數據庫。

需要注意的是,如果 stdin 屬性設置爲 true,而容器本身沒有能力處理輸入,那麼容器將會無限期地等待輸入,直到手動停止容器。因此,在使用 stdin 屬性時,需要確保容器本身能夠處理輸入。

使用:

kubectl attach -it nginx -c shell

這裏我們可以看到infra 程序,並且可以看到nginx,是因爲shareProcessNamespace 爲true了。

默認情況下,只有網絡namespace 是共享的。

在這個 Pod 中,我定義了共享宿主機的 Network、IPC 和 PID Namespace。這就意味着,這個 Pod 裏的所有容器,會直接使用宿主機的網絡、直接與宿主機進行 IPC 通信、看到宿主機里正在運行的所有進程。

首先,是 ImagePullPolicy 字段。它定義了鏡像拉取的策略。而它之所以是一個Container 級別的屬性,是因爲容器鏡像本來就是 Container 定義中的一部分。

ImagePullPolicy 的值默認是 Always,即每次創建 Pod 都重新拉取一次鏡像。另外,當容器的鏡像是類似於 nginx 或者 nginx:latest 這樣的名字時,ImagePullPolicy 也會被認爲
Always。
而如果它的值被定義爲 Never 或者 IfNotPresent,則意味着 Pod 永遠不會主動拉取這個鏡像,或者只在宿主機上不存在這個鏡像時才拉取

其次,是 Lifecycle 字段。它定義的是 Container Lifecycle Hooks。顧名思義,Container Lifecycle Hooks 的作用,是在容器狀態發生變化時觸發一系列“鉤子”。

我們來看這樣一個例子:

這是一個來自 Kubernetes 官方文檔的 Pod 的 YAML 文件。它其實非常簡單,只是定義了一個 nginx 鏡像的容器。

不過,在這個 YAML 文件的容器(Containers)部分,你會看到這個容器分別設置了一個 postStart 和 preStop 參數。

這是什麼意思呢?先說 postStart 吧。它指的是,在容器啓動後,立刻執行一個指定的操作。需要明確的是,postStart 定義的操作,雖然是在 Docker 容器 ENTRYPOINT 執行之後,但它並不嚴格保證順序。

也就是說,在 postStart 啓動時,ENTRYPOINT 有可能還沒有結束。

當然,如果 postStart 執行超時或者錯誤,Kubernetes 會在該 Pod 的 Events 中報出該容器啓動失敗的錯誤信息,導致 Pod 也處於失敗的狀態。

而類似地,preStop 發生的時機,則是容器被殺死之前(比如,收到了 SIGKILL 信號)。

而需要明確的是,preStop 操作的執行,是同步的。所以,它會阻塞當前的容器殺死流程,直到這個 Hook 定義操作完成之後,才允許容器被殺死,這跟 postStart 不一樣。

所以,在這個例子中,我們在容器成功啓動之後,在 /usr/share/message 裏寫入了一句“歡迎信息”(即 postStart 定義的操作)。

而在這個容器被刪除之前,我們則先調用了nginx 的退出指令(即 preStop 定義的操作),從而實現了容器的“優雅退出”。

Pod 生命週期的變化,主要體現在 Pod API 對象的Status 部分,這是它除了 Metadata和 Spec 之外的第三個重要字段。

其中,pod.status.phase,就是 Pod 的當前狀態,它有

如下幾種可能的情況:

  1. Pending。這個狀態意味着,Pod 的 YAML 文件已經提交給了 Kubernetes,API 對象已經被創建並保存在 Etcd 當中。但是,這個 Pod 裏有些容器因爲某種原因而不能被順利創建。比如,調度不成功。

  2. Running。這個狀態下,Pod 已經調度成功,跟一個具體的節點綁定。它包含的容器都已經創建成功,並且至少有一個正在運行中。

  3. Succeeded。這個狀態意味着,Pod 裏的所有容器都正常運行完畢,並且已經退出了。這種情況在運行一次性任務時最爲常見。

  4. Failed。這個狀態下,Pod 裏至少有一個容器以不正常的狀態(非 0 的返回碼)退出。

這個狀態的出現,意味着你得想辦法 Debug 這個容器的應用,比如查看 Pod 的 Events和日誌。

  1. Unknown。這是一個異常狀態,意味着 Pod 的狀態不能持續地被 kubelet 彙報給kube-apiserver,這很有可能是主從節點(Master 和 Kubelet)間的通信出現了問題。

更進一步地,Pod 對象的 Status 字段,還可以再細分出一組 Conditions。這些細分狀態的值包括:PodScheduled、Ready、Initialized,以及 Unschedulable。

它們主要用於描述造成當前 Status 的具體原因是什麼。

比如,Pod 當前的 Status 是 Pending,對應的 Condition 是 Unschedulable,這就意味着它的調度出現了問題。

而其中,Ready 這個細分狀態非常值得我們關注:它意味着 Pod 不僅已經正常啓動(Running 狀態),而且已經可以對外提供服務了。這兩者之間(Running 和 Ready)是有區別的,你不妨仔細思考一下。

Pod 的這些狀態信息,是我們判斷應用運行情況的重要標準,尤其是 Pod 進入了非“Running”狀態後,你一定要能迅速做出反應,根據它所代表的異常情況開始跟蹤和定位,而不是去手忙腳亂地查閱文檔

下一節k8s,進階例子。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章