Kubernetes學習筆記(六):使用ConfigMap和Secret配置應用程序

概述

本文的核心是:如何處理應用程序的數據配置。
配置應用程序可使用如下幾種途徑:html

  • 向容器傳遞命令行參數
  • 爲每一個容器配置環境變量
  • 經過特殊的卷將配置文件掛載到容器中

向容器傳遞命令行參數

在Kubernetes中定義容器時,鏡像的ENTRYPOINT和CMD均可以被覆蓋(可是在Docker中,鏡像的ENTRYPOINT是不能覆蓋的)。僅需在容器定義中設置command和args的值。nginx

構建一個鏡像

loopechodate.sh:接收一個時間間隔的參數,追加輸出當前時間到 /tmp/a.txtdocker

#! /bin/sh
trap "exit" SIGINT
echo "interval is : $1"
while :
do
	echo -e "$(date)" >> /tmp/a.txt
	sleep $1
done

Dockerfileapi

FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"]

構建、推送安全

-> [root@kube0.vm] [~] docker build -t registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate .
-> [root@kube0.vm] [~] docker push registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate

運行Pod

# cat config-cli.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-cli
spec:
  containers:
    - name: config-cli
      image: registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate
      args: ["2"]	# 間隔時間2s

建立這個pod,而後查看一下logs服務器

-> [root@kube0.vm] [~] k create -f config-cli.yaml
pod/config-cli created
-> [root@kube0.vm] [~] k exec -it config-cli cat /tmp/a.txt
Sun May 24 15:49:37 UTC 2020
Sun May 24 15:49:39 UTC 2020

爲容器設置環境變量

Kubernetes中經過容器的env屬性定義環境變量,採用$(VAR)語法在環境變量值中引用其餘變量。curl

定義了兩個環境變量FIRST_VAR,和引用了FIRST_VAR的SECOND_VAR。oop

# config-env.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-env
spec:
  containers:
    - name: config-env
      image: nginx:alpine
      env:
      - name: FIRST_VAR
        value: "Hello"
      - name: SECOND_VAR
        value: "$(FIRST_VAR) World!"

建立查看ui

-> [root@kube0.vm] [~] k create -f config-env.yaml
pod/config-env created

-> [root@kube0.vm] [~] k exec config-env env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env
FIRST_VAR=Hello
SECOND_VAR=Hello World!
.......

ConfigMap

ConfigMap本質上是一個鍵值對,值可使短字面量,也能夠是文件this

建立ConfigMap

kubectl create configmap NAME [--from-file=[key=]source] [--from-literal=key1=value1] [--dry-run] [options]

kubectl create命令支持從字面量(--from-literal),文件、目錄(--from-file)、以及環境變量文件(--from-env-file)建立。並且不一樣選項能夠合併,可是--from-env-file不能與--from-literal和--from-file一塊兒指定。

下面是使用字面量、文件、目錄合併建立。

-> [root@kube0.vm] [~] k create configmap mycm --from-literal=interval=3 --from-file=Dockerfile --from-file=/root/configdir
configmap/mycm created

-> [root@kube0.vm] [~] k describe cm mycm
Name:         mycm
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
Dockerfile:
----
FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"]

a.txt:
----
this is configdir/a.txt

b.txt:
----
this is configdir/b.txt

interval:
----
3
Events:  <none>

使用環境變量文件建立

-> [root@kube0.vm] [~] echo -e "env1=1111\nenv2=2222" | tee test.env
env1=1111
env2=2222

-> [root@kube0.vm] [~] k create cm envcm --from-env-file=test.env
configmap/envcm created

-> [root@kube0.vm] [~] k describe cm envcm
Name:         envcm
Namespace:    default
Labels:       <none>
Annotations:  <none>

Data
====
env1:
----
1111
env2:
----
2222
Events:  <none>

傳遞ConfigMap條目做爲環境變量

定義一個Pod,引用了mycm中的兩個key。

# config-env-cm.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-env-cm
spec:
  containers:
    - name: config-env-cm
      image: nginx:alpine
      env:
      - name: INTERVAL
        valueFrom:
          configMapKeyRef:	# 引用configMap中的內容
            name: mycm		# configMap的名字
            key: interval	# 引用哪一個鍵
      - name: ATXT
        valueFrom:
          configMapKeyRef:
            name: mycm
            key: a.txt

建立查看

-> [root@kube0.vm] [~] k create -f config-env-cm.yaml
pod/config-env-cm created

-> [root@kube0.vm] [~] k exec config-env-cm env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env-cm
INTERVAL=3
ATXT=this is configdir/a.txt
....

一次性傳遞ConfigMap全部條目做爲環境變量

# config-env-cmall.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-env-cmall
spec:
  containers:
    - name: config-env-cmall
      image: nginx:alpine
      envFrom:
      - prefix: CONFIG_
        configMapRef:
          name: mycm

建立查看

-> [root@kube0.vm] [~] k create -f config-env-cmall.yaml
pod/config-env-cmall created

-> [root@kube0.vm] [~] k exec config-env-cmall env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=config-env-cmall
CONFIG_interval=3
CONFIG_Dockerfile=FROM alpine
COPY loopechodate.sh /bin/
ENTRYPOINT ["/bin/loopechodate.sh"]
CMD ["5"]

CONFIG_a.txt=this is configdir/a.txt

CONFIG_b.txt=this is configdir/b.txt
........

傳遞ConfigMap條目做爲命令行參數

containers.args沒法直接引用ConfigMap,可是能夠經過$(ENV_VAR_NAME)引用環境變量,間接引用ConfigMap。

# config-cli-cm.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-cli-cm
spec:
  containers:
    - name: config-cli-cm
      image: registry.cn-hangzhou.aliyuncs.com/orzi/loopechodate
      env:
      - name: INTERVAL
        valueFrom:
          configMapKeyRef:
            name: mycm
            key: interval
      args: ["$(INTERVAL)"]

建立查看

-> [root@kube0.vm] [~] k create -f config-cli-cm.yaml
pod/config-cli-cm created

-> [root@kube0.vm] [~] k logs config-cli-cm
interval is : 3

-> [root@kube0.vm] [~] k exec config-cli-cm cat /tmp/a.txt
Mon May 25 05:11:14 UTC 2020
Mon May 25 05:11:17 UTC 2020
Mon May 25 05:11:20 UTC 2020

將ConfigMap條目暴露爲卷

環境變量和命令行參數做爲配置值一般適用於變量值較短的場景。若是想暴露ConfigMap中配置文件,能夠將ConfigMap或者其條目經過卷的形式掛載到容器。

# config-volume-cm.yaml
apiVersion: v1
kind: Pod
metadata:
  name: config-volume-cm
spec:
  containers:
    - name: config-volume-cm
      image: nginx:alpine
      volumeMounts:
      - name: config
        mountPath: /tmp/mycm
        readOnly: true
  volumes:
  - name: config
    configMap:
      name: mycm

建立查看

-> [root@kube0.vm] [~] k create -f config-volume-cm.yaml
pod/config-volume-cm created

-> [root@kube0.vm] [~] k exec config-volume-cm ls /tmp/mycm
Dockerfile
a.txt
b.txt
interval

若是隻想暴露指定的條目,能夠指定volumes.configMap.items

volumes:
  - name: config
    configMap:
      name: mycm
      items:
      - key: interval
        path: interval2

輸出結果是:

-> [root@kube0.vm] [~] k exec config-volume-cm ls /tmp/mycm
interval2

configMap.defaultMode設置訪問權限

掛載文件夾會隱藏該文件夾中已存在的文件,掛載ConfigMap的單獨條目不會隱藏其餘文件

Secret

Secret與ConfigMap同樣都是鍵值對,也能夠做爲環境變量傳遞給容器,條目也能暴露稱爲卷中的文件。可是爲了安全起見,請始終使用Secret卷暴露Secret。Secret只會存儲在內存中,永不寫入物理存儲。Secret條目的內容會被進行Base64編碼。

默認令牌

每一個pod默認都會掛載一個Secret,該Secret包含ca.crt、namespace、token,包含了從Pod內部安全訪問Kubernetes Api服務器所需的所有信息。
先隨便找一個pod查看。

-> [root@kube0.vm] [~] k describe pod config-volume-cm
Name:         config-volume-cm
Namespace:    default
......
    Mounts:
      /tmp/mycm from config (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-5g447 (ro)
......
Volumes:
......
  default-token-5g447:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-5g447
    Optional:    false
......

再查看一下詳情

-> [root@kube0.vm] [~] k describe secrets default-token-5g447
Name:         default-token-5g447
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: bd92a729-ed0a-491d-b600-0f86824ad588

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1025 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1....

使nginx支持https

建立私鑰和證書

-> [root@kube0.vm] [~/cert] openssl genrsa -o https.key 2048
-> [root@kube0.vm] [~/cert] openssl req -new -x509 -key https.key -out https.cert -days 3650 -subj /CN=www.mysecret.com

建立Secret

建立一個類型爲generic的Secret,其餘兩個類型是docker-registry、tls。

-> [root@kube0.vm] [~/cert] echo bar > foo # 後面會用到

-> [root@kube0.vm] [~/cert] k create secret generic mysecret --from-file=./
secret/mysecret created

將ssl.conf放入ConfigMap中

# ssl.conf
server {
    listen              80;
    listen              443 ssl;
    server_name         www.mysecret.com;
    ssl_certificate     certs/https.cert;
    ssl_certificate_key certs/https.key;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}
-> [root@kube0.vm] [~] k create configmap sslcm --from-file=ssl.conf
configmap/sslcm created

建立查看

先看一下描述文件

# https-nginx.yaml
apiVersion: v1
kind: Pod
metadata:
  name: https-nginx
spec:
  containers:
    - name: https-nginx
      image: nginx:alpine
      env:
        - name: FOO
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: foo
      volumeMounts:
      - name: sslcm
        mountPath: /etc/nginx/conf.d/
        readOnly: true
      - name: mysecret
        mountPath: /etc/nginx/certs/
        readOnly: true
      ports:
      - containerPort: 80
      - containerPort: 443
  volumes:
  - name: sslcm
    configMap:
      name: sslcm
      items:
      - key: ssl.conf
        path: https.conf
  - name: mysecret
    secret:
      secretName: mysecret

建立、設置端口轉發

-> [root@kube0.vm] [~] k create -f https-nginx.yaml
pod/https-nginx created

-> [root@kube0.vm] [~] k port-forward https-nginx 443:443
Forwarding from 127.0.0.1:443 -> 443

新開窗口,發送請求

-> [root@kube0.vm] [~] curl -k https://localhost
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
.....

查看Secret經過環境變量暴露的條目

-> [root@kube0.vm] [~] k exec https-nginx env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=https-nginx
FOO=bar
.......

使用私有的鏡像倉庫

使用方法:建立一個docker-registry類型的secret,而後

建立一個docker-registry類型的secret。 --docker-server 用於指定倉庫服務的地址。

k create secret docker-registry dockerregsecret --docker-username=zhangsan --docker-password=123 --docker-email=zhangsan@163.com

在Pod中的containers.imagePullSecrets.name中引用。

apiVersion: v1
kind: Pod
metadata:
  name: private-pod
spec:
  imagePullSecrets:
  - name: dockerregsecret
  containers:
  - image: username/private:tag
    name: main

StringData與二進制數據

採用Base64編碼,使Secret也能存儲二進制數據,而純文本值能夠在secret.StringData中定義,但StringData字段是隻寫的,kubectl get -o yaml查看時會被Base64編碼顯示在data下。

注意事項

  • 在Kubernetes中定義容器時,鏡像的ENTRYPOINT和CMD均可以被覆蓋。可是在Docker中,鏡像的ENTRYPOINT是不能覆蓋的。
  • 能夠將configMapKeyRef.optional設置爲true,這樣即便ConfigMap不存在,容器也能啓動。

小結

  • 對於環境變量:使用valueFrom.configMapKeyRef引用一個ConfigMap條目;使用envFrom.configMapRef引用所有,envFrom.prefix設置前綴。
  • 對於命令行參數:containers.args沒法直接引用ConfigMap,可是能夠經過$(ENV_VAR_NAME)引用環境變量,間接引用了ConfigMap。
  • 掛載文件夾會隱藏該文件夾中已存在的文件,掛載ConfigMap的單獨條目不會隱藏其餘文件
  • 將ConfigMap暴露爲卷能夠達到熱更新的效果。
  • 每一個pod默認都會掛載一個Secret,該Secret包含ca.crt、namespace、token,包含了從Pod內部安全訪問Kubernetes Api服務器所需的所有信息。
  • 採用Base64編碼,使Secret也能存儲二進制數據,而純文本值能夠在secret.StringData中定義,但StringData字段是隻寫的,kubectl get -o yaml查看時會被Base64編碼顯示在data下。
相關文章
相關標籤/搜索