ASP.NET Core on K8S深入學習(9)Secret & Configmap
- 2019 年 10 月 3 日
- 筆記
本篇已加入《.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》