7.1 配置容器化應(yīng)用程序
回顧如何傳遞配置數(shù)據(jù)給運行在Kubernetes中的應(yīng)用程序之前,首先來看一下容器化應(yīng)用通常是如何被配置的。
開發(fā)一款新應(yīng)用程序的初期,除了將配置嵌入應(yīng)用本身,通常會以命令行參數(shù)的形式配置應(yīng)用收捣。隨著配置選項數(shù)量的逐漸增多,將配置文件化庵楷。
另一種通用的傳遞配置選項給容器化應(yīng)用程序的方法是借助環(huán)境變量罢艾。應(yīng)用程序主動查找某一特定環(huán)境變量的值,而非讀取配置文件或者解析命令行參數(shù)嫁乘。例如昆婿,MySQL官方鏡像內(nèi)部通過環(huán)境變量 MYSQL_ROOT_PASSWORD
設(shè)置超級用戶root的密碼球碉。
為何環(huán)境變量的方案會在容器環(huán)境下如此常見蜓斧?通常直接在Docker容器中采用配置文件的方式是有些許困難的,往往需要將配置文件打入容器鏡像睁冬,抑或是掛載包含該文件的卷挎春。顯然,前者類似于在應(yīng)用程序源代碼中硬編碼配置豆拨,每次修改完配置之后需要重新構(gòu)建鏡像直奋。除此之外,任何擁有鏡像訪問權(quán)限的人可以看到配置文件中包含的敏感信息施禾,如證書和密鑰脚线。相比之下,掛載卷的方式更好弥搞,然而在容器啟動之前需確保配置文件已寫入響應(yīng)的卷中邮绿。
如果你已經(jīng)閱讀過前面的章節(jié),可能會想到采用gitRepo卷作為配置源荤胁。這并不是一個壞主意酌泰,通過它可以保持配置的版本化摩疑,并且能比較容易地按需回滾配置。然而有一種更加簡便的方法能將配置數(shù)據(jù)置于Kubernetes的頂級資源對象中挖胃,并可與其他資源定義存入同一Git倉庫或者基于文件的存儲系統(tǒng)中。用以存儲配置數(shù)據(jù)的Kubernetes資源稱為ConfigMap。我們將會在本章學(xué)習(xí)如何使用它酱鸭。
無論你是否在使用ConfigMap存儲配置數(shù)據(jù)吗垮,以下方法均可被用作配置你的應(yīng)用程序:
- 向容器傳遞命令行參數(shù)
- 為每個容器設(shè)置自定義環(huán)境變量
- 通過特殊類型的卷將配置文件掛載到容器中
接下來的幾節(jié)中將會介紹這些方法。開始介紹之前凛辣,首先從安全角度觀察一下配置選項抱既。盡管絕大多數(shù)配置選項并未包含敏感信息,少量配置依舊可能含有證書扁誓、私鑰防泵,以及其他需要保持安全的相似數(shù)據(jù)。該類型數(shù)據(jù)需要被特殊對待蝗敢。這也是為何Kubernetes提供另一種稱作Secret的一級對象的原因捷泞。我們將在本章節(jié)末尾學(xué)習(xí)到它。
7.2 向容器傳遞命令行參數(shù)
迄今為止所有示例中容器運行的命令都是鏡像中默認定義的寿谴。Kubernetes可在pod的容器中定義并覆蓋命令以滿足運行不同的可執(zhí)行程序锁右,或者是以不同的命令Kubernetes可在pod的容器中定義并覆蓋命令來運行不同的可執(zhí)行程序,或者是以不同的命令行參數(shù)集運行⊙忍現(xiàn)在我們來看一下應(yīng)該如何操作咏瑟。
7.2.1 在Docker中定義命令與參數(shù)
首先需要闡明的是,容器中運行的完整指令由兩部分組成:命令與參數(shù)痪署。
了解ENTRYPOINT與CMD
Dockerfile中的兩種指令分別定義命令與參數(shù)這兩個部分:
- ENTRYPOINT定義容器啟動時被調(diào)用的可執(zhí)行程序码泞。
- CMD指定傳遞給ENTRYPOINT的參數(shù)。
盡管可以直接使用CMD指令指定鏡像運行時想要執(zhí)行的命令狼犯,正確的做法依舊是借助ENTRYPOINT指令余寥,僅僅用CMD指定所需的默認參數(shù)。這樣悯森,鏡像可以直接運行宋舷,無須添加任何參數(shù):
$ docker run <image>
或者是添加一些參數(shù),覆蓋Dockerile中任何由CMD指定的默認參數(shù)值:
$ docker run <image> <arguments>
了解shell與exec形式的區(qū)別
上述兩條指令均支持以下兩種形式:
- shell形式——如ENTRYPOINT node app.js瓢姻。
- exec形式——如ENTRYPOINT["node","app.js"]祝蝠。
兩者的區(qū)別在于指定的命令是否是在shell中被調(diào)用。 對于第2章中創(chuàng)建的kubia鏡像幻碱,如果使用exec形式的ENTRYPOINT指令:
ENTRYPOINT ["node", "app.js"]
可以從容器中的運行進程列表看出:這里是直接運行node進程绎狭,而并非在shell中執(zhí)行。
$ docker exec 4675d ps x
如果采用shell形式(ENTRYPOINT node app.js)收班,容器進程如下所示:
$ docker exec -it e4bad ps x
可以看出坟岔,主進程(PID 1)是shell進程而非node進程,node進程(PID 7)于shell中啟動摔桦。shell進程往往是多余的社付,因此通吵衅#可以直接采用exec形式的ENTRYPOINT指令。
可配置化fortune鏡像中的間隔參數(shù)
讓我們通過修改fortune腳本與鏡像Dockerfile使循環(huán)的延遲間隔可配置鸥咖。如下面這段代碼所示燕鸽,在fortune腳本中添加VARIABLE變量并用第一個命令行參數(shù)對其初始化。
代碼清單7.1 通過參數(shù)可配置化fortune腳本中的循環(huán)間隔: fortune-args/fortuneloop.sh
#!/bin/bash
trap "exit" SIGINT
INTERVAL=$1
echo Configured to generate new fortune every $INTERVAL seconds
mkdir -p /var/htdocs
while :
do
echo $(date) Writing fortune to /var/htdocs/index.html
/usr/games/fortune > /var/htdocs/index.html
sleep $INTERVAL
done
你應(yīng)該已經(jīng)添加或修改了以粗體顯示行√淅保現(xiàn)在修改Dockerfile啊研,采用exec形式的ENTRYPOINT指令,以及利用CMD設(shè)置間隔的默認值為10鸥拧,如下面的代碼清單所示党远。
代碼清單7.2 修改fortune鏡像的Dockerfile: fortune-args/Dockerfile
FROM ubuntu:latest
RUN apt-get update ; apt-get -y install fortune
ADD fortuneloop.sh /bin/fortuneloop.sh
ENTRYPOINT ["/bin/fortuneloop.sh"] #exec形式的ENTRYPOINT指令
CMD ["10"] #可執(zhí)行程序的默認參數(shù)
現(xiàn)在可以重新構(gòu)建鏡像并推送至Docker Hub。這里將鏡像的tag由latest修改為args:
$ docker build -t docker.io/luksa/fortune:args .
$ docker push docker.io/luksa/fortune:args
可以用Docker在本地啟動該鏡像并進行測試:
$ docker run -it jliudong/fortune:args
Configured to generate new fortune every 10 seconds
Fri Feb 26 00:18:59 UTC 2021 Writing fortune to /var/htdocs/index.html
Fri Feb 26 00:19:09 UTC 2021 Writing fortune to /var/htdocs/index.html
注意 可以通過Ctrl+C組合鍵來停止腳本富弦。
也可以傳遞一個間隔參數(shù)覆蓋默認睡眠間隔值:
$ docker run -it jliudong/fortune:args 15
Configured to generate new fortune every 10 seconds
Sun Jul 11 09:40:17 UTC 2021 Writing fortune to /var/htdocs/index.html
Sun Jul 11 09:40:27 UTC 2021 Writing fortune to /var/htdocs/index.html
現(xiàn)在可以確保鏡像能夠正確應(yīng)用傳遞給它的參數(shù)沟娱。讓我們來看一下在pod中如何使用它。
7.2.2 在Kubernetes中覆蓋命令和參數(shù)
在Kubernetes中定義容器時腕柜,鏡像的ENTRYPOINT和CMD均可以被覆蓋济似,僅需在容器定義中設(shè)置屬性command和args的值,如下面的代碼清單所示盏缤。
代碼清單7.3 指定自定義命令與參數(shù)的pod定義
kind: Pod
spec:
containers:
- image: some/image
command: ["/bin/command"]
args: ["arg1", "arg2", "arg3"]
絕大多數(shù)情況下砰蠢,只需要設(shè)置自定義參數(shù)。命令一般很少被覆蓋唉铜,除非針對一些未定義ENTRYPOINT的通用鏡像台舱,例如busybox。
注意 command和args字段在pod創(chuàng)建后無法被修改打毛。 上述的兩條Dockerfile指令與等同的pod規(guī)格字段如表7.1所示柿赊。
表7.1 在Docker與Kubernetes中指定可執(zhí)行程序及其參數(shù)
Docker | Kubernetes | 描述 |
---|---|---|
ENTRYPOINT | command | 容器中運行的可執(zhí)行文件 |
CMD | args | 傳給可執(zhí)行文件的參數(shù) |
用自定義間隔值運行fortune pod
為了能夠用自定義的延遲間隔值運行fortune pod俩功,首先復(fù)制文件fortune-pod.yaml并重命名為fortune-pod-args.yaml幻枉,然后修改它,如下面的代碼清單所示诡蜓。
代碼清單7.4 在pod定義中傳遞參數(shù)值:fortune-pod-args.yaml
apiVersion: v1
kind: Pod
metadata:
name: fortune2s #修改pod名稱
spec:
containers:
- image: luksa/fortune:args
args: ["2"]
name: html-generator
volumeMounts:
- name: html
mountPath: /var/htdocs
- image: nginx:alpine
name: web-server
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
volumes:
- name: html
emptyDir: {}
現(xiàn)在你已經(jīng)在容器定義中添加了args數(shù)組參數(shù)熬甫,可以嘗試創(chuàng)建該pod。數(shù)組值會在pod運行時作為命令行參數(shù)傳遞給容器蔓罚。
少量參數(shù)值的設(shè)置可以使用上述的數(shù)組表示椿肩。多參數(shù)值情況下可以采用如下標(biāo)記:
args:
- foo
- bar
- "15"
提示 字符串值無須用引號標(biāo)記,數(shù)值需要豺谈。
通過命令行參數(shù)指定參數(shù)值是給容器傳遞配置選項的其中一種手段郑象。接下來將學(xué)習(xí)如何通過環(huán)境變量完成配置。