發布時間: 2021-11-09 16:50:11
環境變量 env,相信每個運維工程師都耳熟能詳并能在 linux 環境下嫻熟應用,但在 k8s集群環境中,靈活應用環境變量并不是一件很容易的事情,需要考慮的東西遠比 linux 環境下多。
用得好,可以維持發布、監控和日志中心等運維平臺的統一規范與邏輯,降低k8s 集群管理成本,否則將增加運維難度,同時給故障診斷帶來不必要的干擾。
一、靜態環境變量
1、顯式定義
可以直接在 Dockerfile 中定義環境變量,語法為 ENV,比如我們為了設定容器時區,往往會在鏡像 Dockerfile 里面設定“ENV TZ=Asia/Shanghai”,或者預先指定一個環境變量用于后續處理,比如在鏡像里指定一個JVM 的預置運行參數:
ENV JVM_OPTS="-Xms1024m -Xmx1024m -Xmn386m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Xss256k"
2、隱式包含
除了顯式定義環境變量,也可以在鏡像里從其它文件引入。比如 tomcat 的官方鏡像,tomcat 的啟動腳本為 catalina.sh,catalina.sh 里面會去調用 setenv.sh,這個里面可以定義環境變量。
二、動態環境變量
靜態環境變量由于缺乏靈活性,往往不能滿足實際工作中的運維需求,應用較多的是動態環境變量。需要注意的是:動態環境變量的語義不能與靜態的發生沖突,比如我們在 Dockerfile 中定義一個環境變量 APP_NAME,它的意思是微服務名稱,后面可以覆蓋其內容,但不能改變它的含義。下面基于運維場景,列舉兩種對于 k8s 動態環境變量的典型應用:
1、在微服務部署中的應用
通過發布平臺結合helm等工具注入環境變量,前面提到的環境變量JVM_OPTS,針對同一個微服務,不同環境往往需要配置不同的內存容量,比如測試環境配置為512M,生產為2G。如何利用環境變量來統一配置邏輯呢?處理過程如下:
以 Jenkins pipeline 為例,其定義是一種 groove 腳本語言,可以直接在里面用 def 語法定義變量(或者基于用戶下拉框選項等),然后用 helm set 的方式注入到 k8s deployment,實現多環境配置邏輯統一。以下為部分配置片段:
1)、Jenkins流水線配置多分支
2)、helm模板注入
3)、啟動腳本應用
在 docker-entrypoint.sh 啟動腳本中正式應用前面的環境變量:
2、在微服務日志中的應用
在應用日志處理過程中,往往需要知道一些k8s元數據,比如 pod 所在命名空間等,這種情況顯然無法使用靜態環境變量來處理,也是需要在pod啟動的時候動態注入,helm模板如下:
三、基于 configmap 的環境變量
《k8s concepts》中關于configmap的定義如下:A ConfigMap is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume。
顯然,這里的意思是我們可以使用 configmap 的數據,將其作為環境變量。在實際運維過程中,如何使用呢?可以通過 configMapKeyRef 引用 configmap 的 key 值,將其注入到 env 中,也可以直接掛載基于configmap的配置文件,將其封裝為動態環境變量。比如,我們有一個log4j2的configmap,里面是項目組基于log4j2日志框架的配置,在helm模板中掛載如下:
后面也是類似之前的處理,把這個 mount 到的文件作為環境變量引入到啟動腳本。一般來說,項目組的日志框架和格式定型后,很少會再有變化,如此處理,開發人員不再需要專門維護 log4j2 配置文件。需要注意的是:一般微服務架構都有自己的配置中心,比如nacos 或者 apollo 等,業務配置信息建議一定要放到配置中心里面去,不要放進configmap。
四、小結
合理使用k8s環境變量不僅有利于統一運維邏輯,降低復雜性,而且可以較大限度復用已有規則規范,做到極簡化配置。
下一篇: Angular v13 現已推出