K8S系列之-ConfigMap和Secret(1)

108 阅读11分钟

ConfigMap和Secret

ConfigMap的概念

用来存储配置文件的 kubernetes 资源对象,配置内容都存储在 etcd 中

ConfigMap创建方式

  1. 通过直接在命令行中指定 configmap 参数创建,即--from-literal
root@master:/home/guanwu/k8s/cm# kubectl create configmap test-config1 --from-literal=db.host=10.5.10.116 --from-literal=db.port='3306'
 configmap/test-config1 created
 root@master:/home/guanwu/k8s/cm# k get cm test-config1
 NAME           DATA   AGE
 test-config1   2      9s
 root@master:/home/guanwu/k8s/cm# k describe cm test-config1
 Name:         test-config1
 Namespace:    test
 Labels:       <none>
 Annotations:  <none>

 Data
 ====
 db.host:
 ----
 10.5.10.116
 db.port:
 ----
 3306

 BinaryData
 ====

 Events:  <none>
  1. 通过指定文件创建,即将一个配置文件创建为一个 ConfigMap --from-file=<文件>
root@master:/home/guanwu/k8s/cm# cat test-config2
db.host=10.5.10.116
db.port=3306
root@master:/home/guanwu/k8s/cm# kubectl create configmap test-config2 --from-env-        file=./test-config2
configmap/test-config2 created
root@master:/home/guanwu/k8s/cm# k get cm test-config2 -o yaml
apiVersion: v1
data:
 db.host: 10.5.10.116
 db.port: "3306"
kind: ConfigMap
metadata:
 creationTimestamp: "2024-01-10T14:42:55Z"
 name: test-config2
 namespace: test
 resourceVersion: "349424"
 uid: d0451b58-6339-4bb1-9b21-9a22a2899a81
   
  1. 通过指定目录创建,即将一个目录下的所有配置文件创建为一个 ConfigMap,--from-file=< 目录>
    使用find命令查看test目录下的两个子文件
 root@master:/home/guanwu/k8s/cm# find test -type f -exec bash -c 'basename $0;cat $0;echo       "==="' {} \;
 sub-config1
 sub1.host=10.2.2.2
 sub1.port=8080
 ===
 sub-config2
 sub2.host=10.2.2.3
 sub1.port=8081
 ===
 root@master:/home/guanwu/k8s/cm# kubectl create configmap test-config3 --from-file=./test
 configmap/test-config3 created

可以看到name为test-config3的cm已经创建,test目录下的sub-config1和sub-config2都已经创建,如下所示:

root@master:/home/guanwu/k8s/cm# kubectl get cm test-config3  -o yaml
apiVersion: v1
data:
  sub-config1: |
    sub1.host=10.2.2.2
    sub1.port=8080
  sub-config2: |
    sub2.host=10.2.2.3
    sub1.port=8081
kind: ConfigMap
metadata:
  creationTimestamp: "2024-01-10T14:52:16Z"
  name: test-config3
  namespace: test
  resourceVersion: "350571"
  uid: 2167537c-126f-4b1f-b9ad-ffbc46c7dced
  1. 事先写好标准的 configmap 的 yaml 文件,然后 kubectl create -f 创建
root@master:/home/guanwu/k8s/cm# cat test-config4.yaml 
apiVersion: v1
data:
  sub-config3: |
    sub1.host=10.2.2.2
    sub1.port=8080
  sub-config4: |
    sub2.host=10.2.2.3
    sub1.port=8081
kind: ConfigMap
metadata:
  name: test-config4
  namespace: test
root@master:/home/guanwu/k8s/cm# k apply -f test-config4.yaml 
configmap/test-config4 created
root@master:/home/guanwu/k8s/cm# k get cm test-config4 -o yaml
apiVersion: v1
data:
  sub-config3: |
    sub1.host=10.2.2.2
    sub1.port=8080
  sub-config4: |
    sub2.host=10.2.2.3
    sub1.port=8081
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"sub-config3":"sub1.host=10.2.2.2\nsub1.port=8080\n","sub-config4":"sub2.host=10.2.2.3\nsub1.port=8081\n"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"test-config4","namespace":"test"}}
  creationTimestamp: "2024-01-10T14:59:23Z"
  name: test-config4
  namespace: test
  resourceVersion: "351437"
  uid: b1c4d73d-c1a5-472e-bc05-aed2fff51195
root@master:/home/guanwu/k8s/cm# 

ConfigMap的主要使用形式

1. 容器的环境变量和启动命令使用

创建configmap,可以看到configmap定义了两个变量SPECIAL_LEVEL和SPECIAL_TYPE,value分别为T0和T1

root@master:/home/guanwu/k8s/configmap# k create cm special-config --from-literal=SPECIAL_LEVEL=T0 --from-literal=SPECIAL_TYPE=T1
configmap/special-config created
root@master:/home/guanwu/k8s/configmap# k get cm special-config -o yaml
apiVersion: v1
data:
  SPECIAL_LEVEL: T0
  SPECIAL_TYPE: T1
kind: ConfigMap
metadata:
  creationTimestamp: "2024-01-11T13:42:29Z"
  name: special-config
  namespace: test
  resourceVersion: "360475"
  uid: 68b46324-ea71-46a2-99a3-467e66eab5d6

创建pod,可以看到,执行kubectl logs dapi-test-pod命令时,输出的两个值是configmap定义的值

root@master:/home/guanwu/k8s/configmap# cat busybox.yaml 
apiVersion: v1
kind: Pod
metadata:
 name: dapi-test-pod
spec:
 containers:
   - name: test-container
     image: busybox
     command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
     env:
     - name: SPECIAL_LEVEL_KEY
       valueFrom:
         configMapKeyRef:
           name: special-config
           key: SPECIAL_LEVEL
     - name: SPECIAL_TYPE_KEY
       valueFrom:
         configMapKeyRef:
           name: special-config
           key: SPECIAL_TYPE
 restartPolicy: Never
root@master:/home/guanwu/k8s/configmap# k apply -f busybox.yaml 
pod/dapi-test-pod created
root@master:/home/guanwu/k8s/configmap# k  logs dapi-test-pod
T0 T1
root@master:/home/guanwu/k8s/configmap# 

2. Volume形式使用 创建cm

root@master:/home/guanwu/k8s/configmap# cat game-demo-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: game-demo
data:
  # 类属性键;每一个键都映射到一个简单的值
  player_initial_lives: "3"
  ui_properties_file_name: "user-interface.properties"

  # 类文件键
  game.properties: |
    enemy.types=aliens,monsters
    player.maximum-lives=5
  user-interface.properties: |
    color.good=purple
    color.bad=yellow
    allow.textmode=true
root@master:/home/guanwu/k8s/configmap# k apply -f game-demo-config.yaml 
configmap/game-demo unchanged

在容器中使用

root@master:/home/guanwu/k8s/configmap# cat configure-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod
spec:
  containers:
    - name: demo
      image: busybox
      command: ["sleep", "3600"]
      env:
        # 定义环境变量
        - name: PLAYER_INITIAL_LIVES # 请注意这里和 ConfigMap 中的键名是不一样的
          valueFrom:
            configMapKeyRef:
              name: game-demo           # 这个值来自 ConfigMap
              key: player_initial_lives # 需要取值的键
        - name: UI_PROPERTIES_FILE_NAME
          valueFrom:
            configMapKeyRef:
              name: game-demo
              key: ui_properties_file_name
      volumeMounts:
      - name: config
        mountPath: "/config"
        readOnly: true
  volumes:
  # 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中
  - name: config
    configMap:
      # 提供你想要挂载的 ConfigMap 的名字
      name: game-demo
      # 来自 ConfigMap 的一组键,将被创建为文件
      items:
      - key: "game.properties"
        path: "game.properties"
      - key: "user-interface.properties"
        path: "user-interface.properties"

创建容器并进入容器,可以看到容器/config目录下创建了两个配置文件,并打印环境变量

root@master:/home/guanwu/k8s/configmap# k apply -f configure-pod.yaml 
pod/configmap-demo-pod created
root@master:/home/guanwu/k8s/configmap# k exec -it configmap-demo-pod  -- sh
/ # 
/ # ls /config
game.properties            user-interface.properties
/config # cat /config/game.properties 
enemy.types=aliens,monsters
player.maximum-lives=5
/config # cat /config/user-interface.properties 
color.good=purple
color.bad=yellow
allow.textmode=true
/config # echo $PLAYER_INITIAL_LIVES
3
/config # echo $UI_PROPERTIES_FILE_NAME
user-interface.properties
/config # 

如果纯粹将configMap当文件使用也是可以的,game-demo下的每个key都会创建相应的文件

root@master:/home/guanwu/k8s/configmap# cat configure-pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: configmap-demo-pod-2
spec:
  containers:
    - name: demo
      image: busybox
      command: ["sleep", "3600"]
      volumeMounts:
      - name: config
        mountPath: "/config"
        readOnly: true
  volumes:
  # 你可以在 Pod 级别设置卷,然后将其挂载到 Pod 内的容器中
  - name: config
    configMap:
      # 提供你想要挂载的 ConfigMap 的名字
      name: game-demo


root@master:/home/guanwu/k8s/configmap# k apply -f configure-pod2.yaml 
pod/configmap-demo-pod-2 created
root@master:/home/guanwu/k8s/configmap# k exec -it configmap-demo-pod-2  -- sh
/ # 
/ # ls /config
game.properties            player_initial_lives       ui_properties_file_name    user-interface.properties

Secret类型

在k8s官方文档找到Secret的说明:

Secret 是一种包含少量敏感信息例如密码、令牌或密钥的对象。 这样的信息可能会被放在 Pod 规约中或者镜像中。 使用 Secret 意味着你不需要在应用程序代码中包含机密数据。

由于创建 Secret 可以独立于使用它们的 Pod, 因此在创建、查看和编辑 Pod 的工作流程中暴露 Secret(及其数据)的风险较小。 Kubernetes 和在集群中运行的应用程序也可以对 Secret 采取额外的预防措施, 例如避免将敏感数据写入非易失性存储。

Secret 类似于 ConfigMap 但专门用于保存机密数据。

Secret的几种类型

内置类型用法
Opaque用户定义的任意数据
kubernetes.io/service-account-token服务账号令牌
kubernetes.io/dockercfg~/.dockercfg 文件的序列化形式
kubernetes.io/dockerconfigjson~/.docker/config.json 文件的序列化形式
kubernetes.io/basic-auth用于基本身份认证的凭据
kubernetes.io/ssh-auth用于 SSH 身份认证的凭据
kubernetes.io/tls用于 TLS 客户端或者服务器端的数据
bootstrap.kubernetes.io/token启动引导令牌数据

Secret创建方式

  1. kubectl命令创建, 可以看到密码被base64编码了
root@master:/home/guanwu/k8s/configmap# kubectl create secret generic test --from-literal=username=admin --from-literal=passw
ord=1f2d1e2e67df
secret/test created
root@master:/home/guanwu/k8s/configmap# k get secret test -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2024-01-11T14:30:06Z"
  name: test
  namespace: test
  resourceVersion: "367766"
  uid: dbaf81b2-a482-4e02-972f-4ec9a91ea02b
type: Opaque
root@master:/home/guanwu/k8s/configmap# echo 'MWYyZDFlMmU2N2Rm' | base64  -d | tee && echo
1f2d1e2e67df
  1. yaml文件创建
root@master:/home/guanwu/k8s/configmap# echo -n 'admin' | base64 
YWRtaW4=
root@master:/home/guanwu/k8s/configmap# echo -n '1f2d1e2e67df' | base64 
MWYyZDFlMmU2N2Rm
root@master:/home/guanwu/k8s/configmap# cat mysecret.yaml 
apiVersion: v1
kind: Secret
metadata:
 name: mysecret
type: Opaque
data:
 username: YWRtaW4=
 password: MWYyZDFlMmU2N2Rm
root@master:/home/guanwu/k8s/configmap# k apply -f mysecret.yaml 
secret/mysecret created
root@master:/home/guanwu/k8s/configmap# k get secret 
NAME         TYPE                DATA   AGE
mysecret     Opaque              2      93s
test         Opaque              2      10m
tls-secret   kubernetes.io/tls   2      22d

Secret 使用方式

  1. 以环境变量方式 ,创建Pod

apiVersion: v1
kind: Pod
metadata:
 name: secret-test-pod
spec:
 containers:
   - name: test-container
     image: busybox
     command: [ "/bin/sh", "-c", "echo ${SECRET_USERNAME}:${SECRET_PASSWORD}" ]
     env:
     - name: SECRET_USERNAME
       valueFrom:
         secretKeyRef:
           name: mysecret
           key: username
     - name: SECRET_PASSWORD
       valueFrom:
         secretKeyRef:
           name: mysecret
           key: password
 restartPolicy: Never

验证,可以看到命令输出的时username和password的值

root@master:/home/guanwu/k8s/configmap# k apply -f busybox-secret.yaml 
pod/secret-test-pod created
root@master:/home/guanwu/k8s/configmap# k get pod secret-test-pod
NAME              READY   STATUS      RESTARTS   AGE
secret-test-pod   0/1     Completed   0          36s
root@master:/home/guanwu/k8s/configmap# k logs secret-test-pod
admin:1f2d1e2e67df
  1. 以 Volume 方式 创建secret

apiVersion: v1
kind: Secret
metadata:
  name: test-secret
data:
  username: bXktYXBw
  password: Mzk1MjgkdmRnN0pi

创建Pod

apiVersion: v1
kind: Secret
metadata:
  name: test-secret
data:
  username: bXktYXBw
  password: Mzk1MjgkdmRnN0pi

创建pod

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
spec:
  containers:
    - name: test-container
      image: nginx:1.9
      volumeMounts:
        - name: secret-volume
          mountPath: /etc/secret-volume
          readOnly: true
  volumes:
    - name: secret-volume
      secret:
        secretName: test-secret

验证,进入容器后,可以看到/etc/secret-volume目录下多了两个文件,分别是password和username

root@master:/home/guanwu/k8s/configmap# k  apply -f secret-pod.yaml 
pod/secret-test-pod configured
root@master:/home/guanwu/k8s/configmap# k get pod secret-test-pod
NAME              READY   STATUS    RESTARTS   AGE
secret-test-pod   1/1     Running   0          2m5s
root@master:/home/guanwu/k8s/configmap# k exec -it secret-test-pod -- sh
# ls /etc/secret-volume
password  username
# cat /etc/secret-volume/password
39528$vdg7Jb#   
# cat /etc/secret-volume/password && echo
39528$vdg7Jb
# cat /etc/secret-volume/username && echo
my-app
# 

Secret使用场景

作为容器环境变量

可以参考Secret的使用方式

带 SSH 密钥的 Pod

root@master:/home/guanwu/k8s/configmap# kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/root/.ssh/id
_rsa --from-file=ssh-publickey=/root/.ssh/id_rsa.pub
secret/ssh-key-secret created
root@master:/home/guanwu/k8s/configmap# k get secret
NAME             TYPE                DATA   AGE
mysecret         Opaque              2      34m
ssh-key-secret   Opaque              2      7s
test             Opaque              2      43m
test-secret      Opaque              2      10m
tls-secret       kubernetes.io/tls   2      22d
root@master:/home/guanwu/k8s/configmap# k get secret ssh-key-secret -o yaml
apiVersion: v1
data:
  ssh-privatekey: LS0tLS1CRUdJTiBPUEVOU1NIIFB... #省略
  ssh-publickey: c3NoLXJzYSBBQUFBQjNOe... # 省略
kind: Secret
metadata:
  creationTimestamp: "2024-01-11T15:13:31Z"
  name: ssh-key-secret
  namespace: test
  resourceVersion: "374410"
  uid: 54fae324-7cee-4864-b2bb-fe7e3acd4900
type: Opaque

创建pod

apiVersion: v1
kind: Pod
metadata:
  name: secret-test-pod
  labels:
    name: secret-test
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: ssh-key-secret
  containers:
  - name: ssh-test-container
    image: nginx:1.9
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"

可以看到,/etc/secret-volume目录下有ssh所需要的两个文件

root@master:/home/guanwu/k8s/configmap# k apply -f secret-test-pod.yaml 
pod/secret-test-pod created
root@master:/home/guanwu/k8s/configmap# k get pod  secret-test-pod
NAME              READY   STATUS    RESTARTS   AGE
secret-test-pod   1/1     Running   0          49s
root@master:/home/guanwu/k8s/configmap# k exec -it secret-test-pod  -- sh
# ls /etc/secret-volume
ssh-privatekey  ssh-publickey
# 

使用 Secret 为 Pod 提供生产环境或测试环境的凭据

你可以创建一个带有 secretGenerator 字段的 kustomization.yaml 文件或者运行 kubectl create secret 来创建 Secret。 分别为生产和测试创建secret

生产使用

kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11

测试使用

kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests

创建

root@master:/home/guanwu/k8s/configmap# kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret/prod-db-secret created
root@master:/home/guanwu/k8s/configmap# kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret/test-db-secret created
root@master:/home/guanwu/k8s/configmap# k get secret
NAME             TYPE                DATA   AGE
mysecret         Opaque              2      47m
prod-db-secret   Opaque              2      16s
ssh-key-secret   Opaque              2      13m
test             Opaque              2      56m
test-db-secret   Opaque              2      7s
test-secret      Opaque              2      23m
tls-secret       kubernetes.io/tls   2      22d
root@master:/home/guanwu/k8s/configmap# 

cat <<EOF > pod.yaml
apiVersion: v1
kind: List
items:
- kind: Pod
  apiVersion: v1
  metadata:
    name: prod-db-client-pod
    labels:
      name: prod-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: prod-db-secret
    containers:
    - name: db-client-container
      image: nginx:1.9
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
- kind: Pod
  apiVersion: v1
  metadata:
    name: test-db-client-pod
    labels:
      name: test-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: test-db-secret
    containers:
    - name: db-client-container
      image: nginx:1.9
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
EOF

执行创建生产和测试Pod命令

root@master:/home/guanwu/k8s/configmap# k apply -f pod.yaml 
pod/prod-db-client-pod created
pod/test-db-client-pod created

验证生成的pod是否成功挂载secret

root@master:/home/guanwu/k8s/configmap# pods=$(k get pods | grep db-client | awk -F ' ' ' {print $1}')
root@master:/home/guanwu/k8s/configmap# for pod in ${pods[@]}; do echo $pod; done
prod-db-client-pod
test-db-client-pod
root@master:/home/guanwu/k8s/configmap# k apply -f pod.yaml 
pod/prod-db-client-pod created
pod/test-db-client-pod created
iluvtestsroot@master:/home/guanwu/k8s/configmap# for pod in ${pods[@]}; do echo $pod; kubectl exec -t $pod -- bash -c "ls /etc/secret-volume; cat /etc/secret-volume/username; cat /etc/secret-volume/password" && echo; done
prod-db-client-pod
password
username
produserY4nys7f11
test-db-client-pod
password
username
testuseriluvtests
root@master:/home/guanwu/k8s/configmap# 
## 参考
https://kubernetes.io/zh-cn/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod