從零開始入門 K8s | 應用配置管理

1、需求來源

背景問題

首先一塊兒來看一下需求來源。你們應該都有過這樣的經驗,就是用一個容器鏡像來啓動一個 container。要啓動這個容器,其實有不少須要配套的問題待解決:docker

  • 第一,好比說一些可變的配置。由於咱們不可能把一些可變的配置寫到鏡像裏面,當這個配置須要變化的時候,可能須要咱們從新編譯一次鏡像,這個確定是不能接受的;
  • 第二就是一些敏感信息的存儲和使用。好比說應用須要使用一些密碼,或者用一些 token;
  • 第三就是咱們容器要訪問集羣自身。好比我要訪問 kube-apiserver,那麼自己就有一個身份認證的問題;
  • 第四就是容器在節點上運行以後,它的資源需求;
  • 第五個就是容器在節點上,它們是共享內核的,那麼它的一個安全管控怎麼辦?
  • 最後一點咱們說一下容器啓動以前的一個前置條件檢驗。好比說,一個容器啓動以前,我可能要確認一下 DNS 服務是否是好用?又或者確認一下網絡是否是聯通的?那麼這些其實就是一些前置的校驗。

Pod 的配置管理

在 Kubernetes 裏面,它是怎麼作這些配置管理的呢?以下圖所示:json

file

  • 可變配置就用 ConfigMap;
  • 敏感信息是用 Secret;
  • 身份認證是用 ServiceAccount 這幾個獨立的資源來實現的;
  • 資源配置是用 Resources;
  • 安全管控是用 SecurityContext;
  • 前置校驗是用 InitContainers 這幾個在 spec 裏面加的字段,來實現的這些配置管理。

2、ConfigMap

ConfigMap 介紹

下面咱們來介紹第一個部分,就是 ConfigMap。咱們先來介紹 ConfigMap 它是用來作什麼的、以及它帶來的一個好處。它其實主要是管理一些可變配置信息,好比說咱們應用的一些配置文件,或者說它裏面的一些環境變量,或者一些命令行參數。bootstrap

它的好處在於可讓一些可變配置和容器鏡像進行解耦,這樣也保證了容器的可移植性。看一下下圖中右邊的編排文件截圖。api

file

這是 ConfigMap 自己的一個定義,它包括兩個部分:一個是 ConfigMap 元信息,咱們關注 name 和 namespace 這兩個信息。接下來這個 data 裏面,能夠看到它管理了兩個配置文件。它的結構實際上是這樣的:從名字看 ConfigMap 中包含 Map 單詞,Map 其實就是 key:value,key 是一個文件名,value 是這個文件的內容。安全

ConfigMap 建立

看過介紹以後,再具體看一下它是怎麼建立的。咱們推薦用 kubectl 這個命令來建立,它帶的參數主要有兩個:一個是指定 name,第二個是 DATA。其中 DATA 能夠經過指定文件或者指定目錄,以及直接指定鍵值對,下面能夠看一下這個例子。微信

file

指定文件的話,文件名就是 Map 中的 key,文件內容就是 Map 中的 value。而後指定鍵值對就是指定數據鍵值對,即:key:value 形式,直接映射到 Map 的 key:value。網絡

ConfigMap 使用

建立完了以後,應該怎麼使用呢?併發

file

如上圖所示,主要是在 pod 裏來使用 ConfigMap:less

  • 第一種是環境變量。環境變量的話經過 valueFrom,而後 ConfigMapKeyRef 這個字段,下面的 name 是指定 ConfigMap 名,key 是 ConfigMap.data 裏面的 key。這樣的話,在 busybox 容器啓動後容器中執行 env 將看到一個 SPECIALLEVELKEY 環境變量;
  • 第二個是命令行參數。命令行參數實際上是第一行的環境變量直接拿到 cmd 這個字段裏面來用;
  • 最後一個是經過 volume 掛載的方式直接掛到容器的某一個目錄下面去。上面的例子是把 special-config 這個 ConfigMap 裏面的內容掛到容器裏面的 /etc/config 目錄下,這個也是使用的一種方式。

ConfigMap 注意要點

如今對 ConfigMap 的使用作一個總結,以及它的一些注意點,注意點一共列了如下五條:wordpress

  1. ConfigMap 文件的大小。雖說 ConfigMap 文件沒有大小限制,可是在 ETCD 裏面,數據的寫入是有大小限制的,如今是限制在 1MB 之內;
  2. 第二個注意點是 pod 引入 ConfigMap 的時候,必須是相同的 Namespace 中的 ConfigMap,前面其實能夠看到,ConfigMap.metadata 裏面是有 namespace 字段的;
  3. 第三個是 pod 引用的 ConfigMap。假如這個 ConfigMap 不存在,那麼這個 pod 是沒法建立成功的,其實這也表示在建立 pod 前,必須先把要引用的 ConfigMap 建立好;
  4. 第四點就是使用 envFrom 的方式。把 ConfigMap 裏面全部的信息導入成環境變量時,若是 ConfigMap 裏有些 key 是無效的,好比 key 的名字裏面帶有數字,那麼這個環境變量實際上是不會注入容器的,它會被忽略。可是這個 pod 自己是能夠建立的。這個和第三點是不同的方式,是 ConfigMap 文件存在基礎上,總體導入成環境變量的一種形式;
  5. 最後一點是:什麼樣的 pod 才能使用 ConfigMap?這裏只有經過 K8s api 建立的 pod 才能使用 ConfigMap,好比說經過用命令行 kubectl 來建立的 pod,確定是可使用 ConfigMap 的,但其餘方式建立的 pod,好比說 kubelet 經過 manifest 建立的 static pod,它是不能使用 ConfigMap 的。

3、Secret

Secret 介紹

如今咱們講一下 Secret,Secret 是一個主要用來存儲密碼 token 等一些敏感信息的資源對象。其中,敏感信息是採用 base-64 編碼保存起來的,咱們來看下圖中 Secret 數據的定義。

file

元數據的話,裏面主要是 name、namespace 兩個字段;接下來是 type,它是很是重要的一個字段,是指 Secret 的一個類型。Secret 類型種類比較多,下面列了經常使用的四種類型:

  • 第一種是 Opaque,它是普通的 Secret 文件;
  • 第二種是 service-account-token,是用於 service-account 身份認證用的 Secret;
  • 第三種是 dockerconfigjson,這是拉取私有倉庫鏡像的用的一種 Secret;
  • 第四種是 bootstrap.token,是用於節點接入集羣校驗用的 Secret。

再接下來是 data,是存儲的 Secret 的數據,它也是 key-value 的形式存儲的。

Secret 建立

接下來咱們看一下 Secret 的建立。

file

如上圖所示,有兩種建立方式:

  • 系統建立:好比 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 來實現。

file

咱們先來看一下掛載到用戶指定目錄的方式:

  • 第一種方式:如上圖左側所示,用戶直接指定,把 mysecret 掛載到容器 /etc/foo 目錄下面;
  • 第二種方式:如上圖右側所示,系統自動生成,把 serviceaccount-secret 自動掛載到容器 /var/run/secrets/kubernetes.io/serviceaccount 目錄下,它會生成兩個文件,一個是 ca.crt,一個是 token。這是兩個保存了認證信息的證書文件。

使用私有鏡像庫

下面看一下用 Secret 來使用私有鏡像倉庫。首先,私有鏡像倉庫的信息是存儲在 Secret 裏面的(具體參照上述的Secret建立章節),而後拉取私有倉庫鏡像,那麼經過下圖中兩種方法的配置就能夠:

  • 第一種方式:以下圖左側所示,直接在 pod 裏面,經過 imagePullSecrets 字段來配置;
  • 第二種方式是自動注入。用戶提早在 pod 會使用的 serviceaccount 裏配置 imagePullSecrets,Pod 時系統自動注入這個 imagePullSecrets。

file

Secret 使用注意要點

最後來看一下 Secret 使用的一些注意點,下面列了三點:

  1. 第一個是 Secret 的文件大小限制。這個跟 ConfigMap 同樣,也是 1MB;
  2. 第二個是 Secret 採用了 base-64 編碼,可是它跟明文也沒有太大區別。因此說,若是有一些機密信息要用 Secret 來存儲的話,仍是要很慎重考慮。也就是說誰會來訪問你這個集羣,誰會來用你這個 Secret,仍是要慎重考慮,由於它若是可以訪問這個集羣,就能拿到這個 Secret。
    若是是對 Secret 敏感信息要求很高,對加密這塊有很強的需求,推薦可使用 Kubernetes 和開源的 vault作一個解決方案,來解決敏感信息的加密和權限管理。
  3. 第三個就是 Secret 讀取的最佳實踐,建議不要用 list/watch,若是用 list/watch 操做的話,會把 namespace 下的全部 Secret 所有拉取下來,這樣其實暴露了更多的信息。推薦使用 GET 的方法,這樣只獲取你本身須要的那個 Secret。

4、ServiceAccount

ServiceAccount 介紹

接下來,咱們講一下 ServiceAccount。ServiceAccount 首先是用於解決 pod 在集羣裏面的身份認證問題,身份認證信息是存在於 Secret 裏面。

file

先看一下上面的左側截圖,能夠看到最下面的紅框裏,有一個 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 要訪問集羣的時候,它是怎麼來利用這個文件的呢?咱們看一下下面的代碼截圖:

file

咱們在 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 的相關知識,咱們在後面的課程裏面會詳細介紹,你們能夠關注一下。

5、Resource

容器資源配合管理

下面介紹一下 Resource,即:容器的一個資源配置管理。

目前內部支持類型有三種:CPU、內存,以及臨時存儲。當用戶以爲這三種不夠,有本身的一些資源,好比說 GPU,或者其餘資源,也能夠本身來定義,但配置時,指定的數量必須爲整數。目前資源配置主要分紅 request 和 limit 兩種類型,一個是須要的數量,一個是資源的界限。CPU、內存以及臨時存儲都是在 container 下的 Resource 字段裏進行一個聲明。

file

舉個例子,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 的。

6、SecurityContext

SecurityContext 介紹

SecurityContext 主要是用於限制容器的一個行爲,它能保證系統和其餘容器的安全。這一塊的能力不是 Kubernetes 或者容器 runtime 自己的能力,而是 Kubernetes 和 runtime 經過用戶的配置,最後下傳到內核裏,再經過內核的機制讓 SecurityContext 來生效。因此這裏介紹的內容,會比較簡單或者說比較抽象一點。

SecurityContext 主要分爲三個級別:

  • 第一個是容器級別,僅對容器生效;
  • 第二個是 pod 級別,對 pod 裏全部容器生效;
  • 第三個是集羣級別,就是 PSP,對集羣內全部 pod 生效。

權限和訪問控制設置項,如今一共列有七項(這個數量後續可能會變化):

  1. 第一個就是經過用戶 ID 和組 ID 來控制文件訪問權限;
  2. 第二個是 SELinux,它是經過策略配置來控制用戶或者進程對文件的訪問控制;
  3. 第三個是特權容器;
  4. 第四個是 Capabilities,它也是給特定進程來配置一個 privileged 能力;
  5. 第五個是 AppArmor,它也是經過一些配置文件來控制可執行文件的一個訪問控制權限,好比說一些端口的讀寫;
  6. 第六個是一個對系統調用的控制;
  7. 第七個是對子進程可否獲取比父親更多的權限的一個限制。

最後其實都是落到內核來控制它的一些權限。

file

上圖是對 pod 級別和容器級別配置 SecurityContext 的一個例子,若是你們對這些內容有更多的需求,能夠根據這些信息去搜索更深刻的資料來學習。

7、InitContainer

InitContainer 介紹

接下來看一下 InitContainer,首先介紹 InitContainer 和普通 container 的區別,有如下三點內容:

  1. InitContainer 首先會比普通 container 先啓動,而且直到全部的 InitContainer 執行成功後,普通 container 纔會被啓動;
  2. InitContainer 之間是按定義的次序去啓動執行的,執行成功一個以後再執行第二個,而普通的 container 是併發啓動的;
  3. InitContainer 執行成功後就結束退出,而普通容器可能會一直在執行。它多是一個 longtime 的,或者說失敗了會重啓,這個也是 InitContainer 和普通 container 不一樣的地方。

根據上面三點內容,咱們看一下 InitContainer 的一個用途。它其實主要爲普通 container 服務,好比說它能夠爲普通 container 啓動以前作一個初始化,或者爲它準備一些配置文件, 配置文件多是一些變化的東西。再好比作一些前置條件的校驗,如網絡是否聯通。

file

上面的截圖是 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等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的技術公衆號。

相關文章
相關標籤/搜索