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