从零开始入门 K8s | 应用配置管理
一、需求來源
背景問題
首先一起來看一下需求來源。大家應該都有過這樣的經驗,就是用一個容器鏡像來啟動一個 container。要啟動這個容器,其實有很多需要配套的問題待解決:
- 第一,比如說一些可變的配置。因為我們不可能把一些可變的配置寫到鏡像里面,當這個配置需要變化的時候,可能需要我們重新編譯一次鏡像,這個肯定是不能接受的;
- 第二就是一些敏感信息的存儲和使用。比如說應用需要使用一些密碼,或者用一些 token;
- 第三就是我們容器要訪問集群自身。比如我要訪問 kube-apiserver,那么本身就有一個身份認證的問題;
- 第四就是容器在節點上運行之后,它的資源需求;
- 第五個就是容器在節點上,它們是共享內核的,那么它的一個安全管控怎么辦?
- 最后一點我們說一下容器啟動之前的一個前置條件檢驗。比如說,一個容器啟動之前,我可能要確認一下 DNS 服務是不是好用?又或者確認一下網絡是不是聯通的?那么這些其實就是一些前置的校驗。
Pod 的配置管理
在 Kubernetes 里面,它是怎么做這些配置管理的呢?如下圖所示:
- 可變配置就用 ConfigMap;
- 敏感信息是用 Secret;
- 身份認證是用 ServiceAccount 這幾個獨立的資源來實現的;
- 資源配置是用 Resources;
- 安全管控是用 SecurityContext;
- 前置校驗是用 InitContainers 這幾個在 spec 里面加的字段,來實現的這些配置管理。
二、ConfigMap
ConfigMap 介紹
下面我們來介紹第一個部分,就是 ConfigMap。我們先來介紹 ConfigMap 它是用來做什么的、以及它帶來的一個好處。它其實主要是管理一些可變配置信息,比如說我們應用的一些配置文件,或者說它里面的一些環境變量,或者一些命令行參數。
它的好處在于可以讓一些可變配置和容器鏡像進行解耦,這樣也保證了容器的可移植性。看一下下圖中右邊的編排文件截圖。
這是 ConfigMap 本身的一個定義,它包括兩個部分:一個是 ConfigMap 元信息,我們關注 name 和 namespace 這兩個信息。接下來這個 data 里面,可以看到它管理了兩個配置文件。它的結構其實是這樣的:從名字看 ConfigMap 中包含 Map 單詞,Map 其實就是 key:value,key 是一個文件名,value 是這個文件的內容。
ConfigMap 創建
看過介紹之后,再具體看一下它是怎么創建的。我們推薦用 kubectl 這個命令來創建,它帶的參數主要有兩個:一個是指定 name,第二個是 DATA。其中 DATA 可以通過指定文件或者指定目錄,以及直接指定鍵值對,下面可以看一下這個例子。
指定文件的話,文件名就是 Map 中的 key,文件內容就是 Map 中的 value。然后指定鍵值對就是指定數據鍵值對,即:key:value 形式,直接映射到 Map 的 key:value。
ConfigMap 使用
創建完了之后,應該怎么使用呢?
如上圖所示,主要是在 pod 里來使用 ConfigMap:
- 第一種是環境變量。環境變量的話通過 valueFrom,然后 ConfigMapKeyRef 這個字段,下面的 name 是指定 ConfigMap 名,key 是 ConfigMap.data 里面的 key。這樣的話,在 busybox 容器啟動后容器中執行 env 將看到一個 SPECIALLEVELKEY 環境變量;
- 第二個是命令行參數。命令行參數其實是第一行的環境變量直接拿到 cmd 這個字段里面來用;
- 最后一個是通過 volume 掛載的方式直接掛到容器的某一個目錄下面去。上面的例子是把 special-config 這個 ConfigMap 里面的內容掛到容器里面的 /etc/config 目錄下,這個也是使用的一種方式。
ConfigMap 注意要點
現在對 ConfigMap 的使用做一個總結,以及它的一些注意點,注意點一共列了以下五條:
三、Secret
Secret 介紹
現在我們講一下 Secret,Secret 是一個主要用來存儲密碼 token 等一些敏感信息的資源對象。其中,敏感信息是采用 base-64 編碼保存起來的,我們來看下圖中?Secret?數據的定義。
元數據的話,里面主要是 name、namespace 兩個字段;接下來是 type,它是非常重要的一個字段,是指 Secret 的一個類型。Secret 類型種類比較多,下面列了常用的四種類型:
- 第一種是 Opaque,它是普通的 Secret 文件;
- 第二種是 service-account-token,是用于 service-account 身份認證用的 Secret;
- 第三種是 dockerconfigjson,這是拉取私有倉庫鏡像的用的一種 Secret;
- 第四種是 bootstrap.token,是用于節點接入集群校驗用的 Secret。
再接下來是 data,是存儲的 Secret 的數據,它也是 key-value 的形式存儲的。
Secret 創建
接下來我們看一下 Secret 的創建。
如上圖所示,有兩種創建方式:
- 系統創建:比如 K8s 為每一個 namespace 的默認用戶(default ServiceAccount)創建 Secret;
- 用戶手動創建:手動創建命令,推薦 kubectl 這個命令行工具,它相對 ConfigMap 會多一個 type 參數。其中 data 也是一樣,它也是可以指定文件和鍵值對的。type 的話,要是不指定,就默認是 Opaque 類型。
上圖中兩個例子。第一個是通過指定文件,創建了一個拉取私有倉庫鏡像的 Secret,指定的文件是 /root/.docker/config.json。type 的話指定的是 dockerconfigjson,另外一個我們指定鍵值對,我們 type 沒有指定,默認是 Opaque。鍵值對是 key:value 的形式,其中對 value 內容進行 base64 加密。創建 Secret 就是這么一個情況。
Secret 使用
創建完 Secret 之后,再來看一下如何使用它。它主要是被 pod 來使用,一般是通過 volume 形式掛載到容器里指定的目錄,然后容器里的業務進程再到目錄下讀取 Secret 來進行使用。另外在需要訪問私有鏡像倉庫時,也是通過引用 Secret 來實現。
我們先來看一下掛載到用戶指定目錄的方式:
- 第一種方式:如上圖左側所示,用戶直接指定,把 mysecret 掛載到容器 /etc/foo 目錄下面;
- 第二種方式:如上圖右側所示,系統自動生成,把 serviceaccount-secret 自動掛載到容器 /var/run/secrets/kubernetes.io/serviceaccount 目錄下,它會生成兩個文件,一個是 ca.crt,一個是 token。這是兩個保存了認證信息的證書文件。
使用私有鏡像庫
下面看一下用 Secret 來使用私有鏡像倉庫。首先,私有鏡像倉庫的信息是存儲在 Secret 里面的(具體參照上述的Secret創建章節),然后拉取私有倉庫鏡像,那么通過下圖中兩種方法的配置就可以:
- 第一種方式:如下圖左側所示,直接在 pod 里面,通過 imagePullSecrets 字段來配置;
- 第二種方式是自動注入。用戶提前在 pod 會使用的 serviceaccount 里配置 imagePullSecrets,Pod 時系統自動注入這個 imagePullSecrets。
Secret 使用注意要點
最后來看一下 Secret 使用的一些注意點,下面列了三點:
如果是對 Secret 敏感信息要求很高,對加密這塊有很強的需求,推薦可以使用?Kubernetes 和開源的 vault做一個解決方案,來解決敏感信息的加密和權限管理。
四、ServiceAccount
ServiceAccount 介紹
接下來,我們講一下 ServiceAccount。ServiceAccount 首先是用于解決 pod 在集群里面的身份認證問題,身份認證信息是存在于 Secret 里面。
先看一下上面的左側截圖,可以看到最下面的紅框里,有一個 Secret 字段,它指定 ServiceAccount 用哪一個 Secret,這個是 K8s 自動為 ServiceAccount 加上的。然后再來看一下上圖中的右側截圖,它對應的 Secret 的 data 里有兩塊數據,一個是 ca.crt,一個是 token。ca.crt 用于對服務端的校驗,token 用于 Pod 的身份認證,它們都是用 base64 編碼過的。然后可以看到 metadata 即元信息里,其實是有關聯 ServiceAccount 信息的(這個 secret 被哪個 ServiceAccount 使用)。最后我們注意一下 type,這個就是 service-account-token 這種類型。
舉例:Pod 里的應用訪問它所屬的 K8s 集群
介紹完 ServiceAccount 以及它對應的 secret 后,我們來看一下,pod 是怎么利用 ServiceAccount 或者說它是怎么利用 secret 來訪問所屬 K8s 集群的。其實 pod 創建的時候,首先它會把這個 secret 掛載到容器固定的目錄下,這是 K8s 功能上實現的。它要把這個 ca.crt 和 token 這兩個文件掛載到固定目錄下面。pod 要訪問集群的時候,它是怎么來利用這個文件的呢?我們看一下下面的代碼截圖:
我們在 Go 里面實現 Pod 訪問 K8s 集群時,一般直接會調一個 InClusterConfig 方法,來生成這個訪問服務 Client 的一些信息。然后可以看一下,最后這個 Config 里面有兩部分信息:
- 一個是 tlsClientConfig,這個主要是用于 ca.crt 校驗服務端;
- 第二個是 Bearer Token,這個就是 pod 的身份認證。在服務端,會利用 token 對 pod 進行一個身份認證。
再次回到上圖左側。認證完之后 pod 的身份信息會有兩部分:一個是 Group,一個是 User。身份認證是就是認證這兩部分信息。接著可以使用 RBAC 功能,對 pod 進行一個授權管理。
假如 RBAC 沒有配置的話,默認的 pod 具有資源 GET 權限,就是可以從所屬的 K8s 集群里 get 數據。如果是需要更多的權限,那么就需要自行配置 RBAC 。RBAC 的相關知識,我們在后面的課程里面會詳細介紹,大家可以關注一下。
五、Resource
容器資源配合管理
下面介紹一下 Resource,即:容器的一個資源配置管理。
目前內部支持類型有三種:CPU、內存,以及臨時存儲。當用戶覺得這三種不夠,有自己的一些資源,比如說 GPU,或者其他資源,也可以自己來定義,但配置時,指定的數量必須為整數。目前資源配置主要分成 request 和 limit 兩種類型,一個是需要的數量,一個是資源的界限。CPU、內存以及臨時存儲都是在 container 下的 Resource 字段里進行一個聲明。
舉個例子,wordpress 容器的資源需求,一個是 request ,一個是 limits,它分別對需要的資源和資源臨界進行一個聲明。
Pod 服務質量 (QoS) 配置
根據 CPU 對容器內存資源的需求,我們對 pod 的服務質量進行一個分類,分別是?Guaranteed、Burstable?和?BestEffort。
- Guaranteed :pod 里面每個容器都必須有內存和 CPU 的 request 以及 limit 的一個聲明,且 request 和 limit 必須是一樣的,這就是 Guaranteed;
- Burstable:Burstable 至少有一個容器存在內存和 CPU 的一個 request;
- BestEffort:只要不是 Guaranteed 和 Burstable,那就是 BestEffort。
那么這個服務質量是什么樣的呢?資源配置好后,當這個節點上 pod 容器運行,比如說節點上 memory 配額資源不足,kubelet會把一些低優先級的,或者說服務質量要求不高的(如:BestEffort、Burstable)pod 驅逐掉。它們是按照先去除 BestEffort,再去除 Burstable 的一個順序來驅逐 pod 的。
六、SecurityContext
SecurityContext 介紹
SecurityContext 主要是用于限制容器的一個行為,它能保證系統和其他容器的安全。這一塊的能力不是 Kubernetes 或者容器 runtime 本身的能力,而是 Kubernetes 和 runtime 通過用戶的配置,最后下傳到內核里,再通過內核的機制讓 SecurityContext 來生效。所以這里介紹的內容,會比較簡單或者說比較抽象一點。
SecurityContext 主要分為三個級別:
- 第一個是容器級別,僅對容器生效;
- 第二個是 pod 級別,對 pod 里所有容器生效;
- 第三個是集群級別,就是 PSP,對集群內所有 pod 生效。
權限和訪問控制設置項,現在一共列有七項(這個數量后續可能會變化):
最后其實都是落到內核來控制它的一些權限。
上圖是對 pod 級別和容器級別配置 SecurityContext 的一個例子,如果大家對這些內容有更多的需求,可以根據這些信息去搜索更深入的資料來學習。
七、InitContainer
InitContainer 介紹
接下來看一下 InitContainer,首先介紹 InitContainer 和普通 container 的區別,有以下三點內容:
根據上面三點內容,我們看一下 InitContainer 的一個用途。它其實主要為普通 container 服務,比如說它可以為普通 container 啟動之前做一個初始化,或者為它準備一些配置文件, 配置文件可能是一些變化的東西。再比如做一些前置條件的校驗,如網絡是否聯通。
上面的截圖是 flannel 組件的 InitContainer 的一個配置,它的 InitContainer 主要是為 kube-flannel 這個普通容器啟動之前準備一些網絡配置文件。
本文總結
- ConfigMap 和 Secret: 首先介紹了 ConfigMap 和 Secret 的創建方法和使用場景,然后對 ConfigMap 和 Secret 的常見使用注意點進行了分類和整理。最后介紹了私有倉庫鏡像的使用和配置;
- Pod 身份認證: 首先介紹了 ServiceAccount 和 Secret 的關聯關系,然后從源碼角度對 Pod 身份認證流程和實現細節進行剖析,同時引出了 Pod 的權限管理(即 RBAC 的配置管理);
- 容器資源和安全: 首先介紹了容器常見資源類型 (CPU/Memory) 的配置,然后對 Pod 服務質量分類進行詳細的介紹。同時對 SecurityContext 有效層級和權限配置項進行簡要說明;
- InitContainer: 首先介紹了 InitContainer 和普通 container 的區別以及 InitContainer 的用途。然后基于實際用例對 InitContainer 的用途進行了說明。
阿里巴巴云原生微信公眾號(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的技術公眾號。
總結
以上是生活随笔為你收集整理的从零开始入门 K8s | 应用配置管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安全容器的发展与思考
- 下一篇: 关于容器迁移、运维、查错与监控,你想知道