給容器內應用程序傳遞參數的實現方式:
1. 將配置文件直接打包到鏡像中,但這種方式不推薦使用,因為修改配置不夠靈活。
2. 通過定義Pod清單時,指定自定義命令行參數,即設定 args:["命令參數"],這種也
可在啟動Pod時,傳參來修改Pod的應用程序的配置文件.
3. 使用環境變量來給Pod中應用傳參修改配置
但要使用此種方式,必須符合以下前提之一:
1) Pod中的應用程序必須是Cloud Native的應用程序,即支持直接通過環境變量來加載配置信息。
2) 通過定義Entrypoint腳本的預處理變量來修改Pod中應用程序的配置文件,這些Entrypoint腳本
可以使用set,sed,grep等工具來實現修改,但也要確保容器中有這些工具。
4.存儲卷: 我們可將配置信息直接放到存儲卷中,如PV中,Pod啟動時,自動掛載存儲卷到配置文件目錄,
來實現給Pod中應用提供不同的配置。
5. configMap 或 secret
configMap的主要作用:
就是為了讓鏡像 和 配置文件解耦,以便實現鏡像的可移植性和可復用性,因為一個configMap其實就是一系列配置信息的集合,將來可直接注入到Pod中的容器使用,而注入方式有兩種,一種將configMap做為存儲卷,一種是將configMap通過env中configMapKeyRef注入到容器中; configMap是KeyValve形式來保存數據的,如: name=zhangsan 或 nginx.conf="http{server{...}}" 對於configMap的Value的長度是沒有限制的,所以它可以是一整個配置文件的信息。
configMap: 它是K8s中的標准組件,它通過兩種方式實現給Pod傳遞配置參數:
A. 將環境變量直接定義在configMap中,當Pod啟動時,通過env來引用configMap中定義的環境變量。
B. 將一個完整配置文件封裝到configMap中,然后通過共享卷的方式掛載到Pod中,實現給應用傳參。
secret: 它時一種相對安全的configMap,因為它將configMap通過base64做了編碼, 讓數據不是明文直接存儲在configMap中,起到了一定的保護作用,但對Base64進行反編碼,對專業人士來說,沒有任何難度,因此它只是相對安全。
對於configMap中第一種,讓Pod引用configMap中的環境變量的方式:
kubectl explain pods.spec.containers.env #env也可直接定義傳遞給Pod中容器的環境變量,這點需要記住。
env.valueFrom
configMapKeyRef: 可用於定義Pod啟動時引用的configMapKey是哪個。
fieldRef: 也可引用一個字段,為Pod中容器內應用程序的每個環境變量值,如:
metadata.name: 引用Pod的名稱
metadata.namespace: 引用Pod所在的名稱空間名
metadata.labels: 引用Pod的標簽
status.hostIP: 引用Pod所在節點的IP
status.podIP: 引用Pod的IP
resourceFieldRef: 引用一個資源需求 或 資源限制
secretKeyRef: 引用一個secretKey來為Pod傳參
在定義configMap時,通常僅需要定義它的data 或 binaryData(二進制數據),它倆都是map[string]類型的,
所以它們的值都是以hash列表方式存儲的,即key和value沒有直接關系,key就是hash碼。
創建configmap示例:
#命令創建:
kubectl create configmap nginx-config --from-literal=nginx_port=80 --from-literal=server_name=myapp.test.com
kubectl get configmap
kubectl describe cm nginx-config
#使用文件內容來做key的值
vim w3c.conf
server {
server_name bbs.test.com;
listen 80;
root /data/nginx/bbs/
}
#注意:configmap的名稱中不支持下划線!
#這個是定義了一個key叫www, 其值為www.conf的內容.
kubectl create configmap nginx-www --from-file=www=./www.conf
#這是定義了一個key叫www.conf,其值為www.conf的內容
kubectl create configmap nginx-www --from-file=./www.conf
kubectl get cm nginx-www -o yaml
kubectl describe cm nginx-www
#給Pod中的容器傳遞configMap定義的變量的示例: vim pod-configmap.yaml apiVersion: v1 kind: Pod metadata: name: pod-cm-1 namespace: default labels: app: myapp tier: frontend annotations: test.com/created-by: “cluster admin” spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort:80 env: - name: NGINX_SERVER_PORT valueFrom: configMapKeyRef: name: nginx-config key: nginx_port - name:NGINX_SERVER_NAME valueFrom: configMapKeyRef: name: nginx-config key: server_name
#應用這個使用configMap的Pod
kubectl apply -f pod-configmap.yaml
#進入Pod查看configMap傳入的變量
kubectl exec -it pod-cm-1 -- /bin/sh
/ # printenv #查看我們定義的變量有沒有傳遞進來.
#接着我們來修改configmap中可以的值,看能否在Pod馬上生效:
kubectl edit cm nginx-config #將nginx-config這個configmap中的值修改一下.
kubectl describe cm nginx-config #確認edit已經修改了configmap中key的值.
#接着在登陸pod-cm-1 這個Pod中,查看容器中變量的值是否改變了。
#可以看到值是不會改變的,它僅會在創建Pod時,加載一次configmap中的數據.
#通過共享卷的方式來掛載configmap: vim pod-configmap-2.yaml apiVersion: v1 kind: Pod metadata: name: pod-cm-2 namespace: default labels: app: myapp tier: frontend annotations: test.com/created-by: “cluster admin” spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort: 80 volumeMounts: - name: nginxconf mountPath: /etc/nginx/config.d/ #掛載點不存在,Pod會自動創建. readOnly: true #不能讓容器修改配置的內容。 volumes: - name: nginxconf #定義存儲卷的名字為nginxconf configMap: name: nginx-config #要掛載nginx-config這個configMap
#創建Pod
kubectl apply -f pod-configmap-2.yaml
kubectl exec -it pod-cm-2 -- /bin/sh
/ # ls -l /etc/nginx/config.d/
total 0
lrwxrwxrwx 1 root root 17 Jul 21 13:48 nginx_port -> ..data/nginx_port
lrwxrwxrwx 1 root root 18 Jul 21 13:48 server_name -> ..data/server_name
注: 你將可以看到config.d下面創建了兩個連接文件,它們的內容就時nginx-config這個configMap中定義的變量值,連接文件名為key的名字, 連接文件指向的文件其實是新版本的configmap文件,即當configmap文件被修改時,它就會將改變同步到API Server,APIServer在將改變通告給所有引用者,之后引用者的內容也將變成新版本的內容,這樣就可以實現動態更新配置文件了。
#測試動態更新configmap的變量值
kubectl edit cm nginx-config
#修改nginx-config的中server_port為8888 查看Pod中的變化.
不過要有點耐心,因為APIServer通告完成是需要時間的。
通常若非敏感數據,均可使用明文存儲的configMap來做,若涉及到密碼,私鑰等數據時,一定要使用secret類型.
而secret類型有三種:
generic: 通用類型,通常用於存儲密碼數據。
tls:此類型僅用於存儲私鑰和證書。
docker-registry: 若要保存docker倉庫的認證信息的話,就必須使用此種類型來創建。
#創建一個mysql-root-password的secret:
kubectl create secret generic mysql-root-password --from-literal=password=MyP@ss.8*9
注: 這就定義了一個generic類型的secret, 名字是mysql-root-password, key是password,值是MyP@ss.8*9
kubectl get secret
kubectl describe secret mysql-root-password
kubectl get secret mysql-root-password -o yaml #可看到password這個key的值是加密的.
#但secret的加密是一種偽加密,它僅僅是將數據做了base64的編碼.
echo password這個Key的值 | base64 -d #-d:是解碼, 這樣就可以看到base64加碼后的明文密碼了。
#創建一個引用secret的Pod清單: vim pod-secret-1.yaml apiVersion: v1 kind: Pod metadata: name: pod-secret-1 namespace: default labels: app: myapp tier: frontend annotations: test.com/created-by: “cluster admin” spec: containers: - name: myapp image: ikubernetes/myapp:v1 ports: - name: http containerPort:80 env: - name: MYSQL_ROOT_PASSWORD #它是Pod啟動成功后,Pod中容器的環境變量名. valueFrom: secretKeyRef: name: mysql-root-password #這是secret的對象名 key: password #它是secret中的key名
#創建導入secret內容的Pod:
kubectl apply -f pod-secret.yaml
kubectl exec pod-secret-1 -- printenv |grep ‘MYSQL_ROOT_PASSWORD’ #可以看到注入到容器中的secret是明文存儲的.
擴展:
CoreOS:
這個組織開發了一個K8s組件,叫Operator(運維工程師),它可以讓運維工程師將一些更加復雜的處理邏輯封裝在Operator中,這樣Operator就可以幫我們完成更加復雜的任務了。