1. 程式人生 > >ASP.NET Core on K8S深入學習(9)Secret & Configmap

ASP.NET Core on K8S深入學習(9)Secret & Configmap

本篇已加入《.NET Core on K8S學習實踐系列文章索引》,可以點選檢視更多容器化技術相關係列文章。

一、Secret

1.1 關於Secret

  在應用啟動過程中需要一些敏感資訊,比如資料庫使用者名稱、密碼,如果直接明文儲存在容器映象中是不安全的,K8S提供的方案是Secret。

  

  Secret 會以密文的方式儲存資料,避免了直接在配置檔案中儲存敏感資訊。

  Secret 會以 Volume 的形式被 mount 到 Pod,容器可通過檔案的方式使用 Secret 中的敏感資料,也可以使用環境變數的方式使用。

1.2 建立與檢視Secret

  這裡假設我們要建立一個包含以下資訊的Secret:

  (1)使用者名稱:Edison

  (2)密碼:EDC123456*

  有4種方法來建立Secret:

  (1)通過 --from-literal:

kubectl create secret generic mysecret --from-literal=username=Edison --from-literal=password=EDC123456*

  PS:每個 --from-literal 對應一個資訊條目

  (2)通過 --from-file:

echo -n Edison > ./username
echo -n EDC123456* > ./password
kubectl create secret generic mysecret --from-file=./username --from-file=./password

  PS:每個檔案內容對應一個資訊條目

  (3)通過 --from-env-file:

cat << EOF > env.txt
username=Edison
password=EDC123456*
EOF
kubectl create secret generic mysecret --from-env-file=env.txt

  PS:檔案 env.txt 中每行 Key=Value 對應一個資訊條目

  (4)通過YAML配置檔案建立:(推薦方式)

  由於配置檔案中的敏感資料必須是通過base64編碼後的結果,因此需要獲取base64編碼後的值:

  

  下面就是這個YAML檔案的內容:

apiVersion: v1
kind: Secret
metadata:
  name: edc-secret
data:
  username: RWRpc29u
  password: RURDMTIzNDU2Kg==

  通過kubectl apply來建立Secret:

  

   建立成功後,驗證一下,檢視一下這個Secret:

kubectl get secret edc-secret      // 檢視存在的secret
kubectl describe secret edc-secret  // 檢視條目的Key
kubectl edit secret edc-secret     // 檢視條目的Value

  

   將Value進行base64反編碼,如下所示,與預期一致:

  

1.3 在Pod中使用Secret

  K8S中Pod中使用Secret有兩種方式,一是Volume方式,二是環境變數的方式。

  (1)Volume方式

  這裡我們以一個示例演示一下如何通過Volume方式使用Secret,首先定義一個Pod:

apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: secret-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: edc-secret

  該Pod中會使用到剛剛定義的secret(edc-secret),然後volumeMounts定義了將foo mount到容器中的路徑為/etc/foo的目錄下,並且指定了讀寫許可權為只讀。

  通過kubectl apply建立之後,我們試著在容器中讀取secret來驗證一下,如下圖所示:

  

  可以看到,K8S為每條敏感資料建立了一個檔案,而且其Value是以明文存放的。

  當然,你也可以自定義存放資料的目錄,如下配置所示:

apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: secret-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: edc-secret
      items:
      - key: username
        path: /edc-group/username
      - key: password
        path: /edc-group/password

  這時,該secret就會存放於/etc/foo/edc-group/username 和 /etc/foo/edc-group/password 兩個目錄下了。

  (2)動態更新

  以Volume方式使用Secret,其中一個優點就是支援動態更新。例如,我們將Secret更新一下,重新應用到K8S中:

apiVersion: v1
kind: Secret
metadata:
  name: edc-secret
data:
  username: RWRpc29u
  password: YWJjZGVmZyo=    // 換為了 abcdefg*

  通過kubectl apply重新應用之後,等待一段時間後,再次進入容器中驗證:

  

   已經改為了 abcdefg*,符合預期。

  (2)環境變數方式

  通過Volume使用Secret看起來稍微麻煩了一點,容器必須通過檔案讀取資料。K8S提供了另外一種方式,那就是環境變數方式。

  下面仍以上面的例子為例,修改配置檔案:

apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: secret-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    env:
      - name: EDC_SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: edc-secret
            key: username
      - name: EDC_SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: edc-secret
            key: password

  通過kubectl apply應用之後,進入容器驗證一下:

  

   可以看到,可以方便地通過環境變數獲取到Value。

 PS:需要注意的也是,雖然通過環境變數讀取Secret比較方便,但是無法支援Secret動態更新!

二、Configmap

2.1 關於Configmap

  上面提到的Secret可以為Pod提供機密資料的儲存,而對於一些非機密敏感的資料,像一些應用的配置資訊啊神馬的,則可以使用Configmap。

  Configmap的建立與使用方式與Secret非常類似,不同點只在於資料以明文形式存放(不過,我覺得Secret的密文形式也並不密文,只能算得上是簡單編碼)。

  

2.2 建立Configmap

  和Secret一樣,可以通過 --from-literal,--from-file 和 --from-env-file來建立,這裡我們跳過,直接說下我們最常用的yaml配置檔案的方式。

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-configmap
data:
  LogLevel: Error
  LogFile: service-timestamp.log
  AllowedHosts: edc.com

2.3 使用Configmap

  和Secret一樣,也可以通過Volume 或 環境變數兩種方式來使用Configmap。

  (1)Volume方式

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo
spec:
  containers:
  - name: configmap-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    configMap:
      name: service-configmap

  (2)環境變數方式

apiVersion: v1
kind: Pod
metadata:
  name: secret-demo
spec:
  containers:
  - name: secret-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    env:
      - name: SERVICE_LOG_LEVEL
        valueFrom:
          configMapKeyRef:
            name: service-configmap
            key: LogLevel
      - name: SERVICE_LOG_FILE
        valueFrom:
          configMapKeyRef:
            name: service-configmap
            key: LogFile
      - name: SERVICE_ALLOWED_HOSTS
        valueFrom:
          configMapKeyRef:
            name: service-configmap
            key: AllowedHosts

2.4 最佳實踐

  大多數情況下,大家建議的最佳實踐是:

  (1)建立ConfigMap採用YAML配置方式 => 便於複用和版本管理

  (2)讀取ConfigMap採用Volume方式 => 便於配置動態更新

  下面我們建立一個Configmap,其YAML內容如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-configmap
data:
  appsettings.json: |
    LogHandler: NLogHandler
    LogLevel: Error
    LogFile: %hostname-%timestamp.log

  這裡注意別忘了:後面的 | 符號,然後建立&檢視Configmap:

  

   如果想要在Pod中使用此Configmap,可以在YAML配置如下:

apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo
spec:
  containers:
  - name: configmap-demo-pod
    image: busybox
    args:
    - /bin/sh
    - -c
    - sleep 10; touch /tmp/healthy; sleep 30000
    volumeMounts:
    - name: configmap
      mountPath: "/etc/configmap"
  volumes:
  - name: configmap
    configMap:
      name: service-configmap
      items:
        - key: appsettings.json
          path: appsettings.json

  這裡將Volume mount到了容器的 /etc/configmap 目錄中,下面我們驗證一下:

  

  這時我們將configmap更新一下,如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: service-configmap
data:
  appsettings.json: |
    Logging:
      LogLevel:
        Default: "Error"
    AllowedHosts: "*"

  通過kubectl apply更新一下configmap,然後再到pod中驗證是否動態更新:

  

   可以看出,已經動態更新,符合預期!

2.5 ASP.NET Core appSettings

  我們在ASP.NET Core中的配置都是寫在appSettings.json檔案中,如何將appSettings.json轉換為ConfigMap呢?聖傑已經總結歸納為了《.NET Core使用K8S Configmap的正確姿勢》一文,有興趣的讀者可以參考此文。

三、小結

  本文探索了在K8S中如何進行配置管理,如果需要密文配置,可以使用Secret,如果是一般應用配置,可以使用ConfigMap。雖然Secret和ConfigMap都定義了好幾種定義方式,但是我們一般採用YAML配置建立和Volume方式讀取,因為Volume方式可以支援動態更新。最後,通過分享聖傑的一篇文章,介紹瞭如何在ASP.NET Core下使用Configmap的方式,希望對你有幫助!

參考資料

(1)CloudMan,《每天5分鐘玩轉Kubernetes》

(2)李振良,《一天入門Kubernets教程》

(3)馬哥(馬永亮),《Kubernetes快速入門》

(4)benjamin楊,《K8S通過Secret管理敏感資訊》

(5)伊凡的一天,《K8S物件之Secret》

 

作者:周旭龍

出處:https://edisonchou.cnblogs.com

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。