作用: 将配置文件和程序分离 ,也是云原生的要素
ConfigMap - 用于明文存储、或者变量存储
Secret - 用于密码存储

限制: 不同namespace下的cm和secret相互隔离(可重名创建)
调度类型的资源 比如deployment要使用configmap时 需要和configmap资源在同一namespace下、否则挂载失败
限制: 以环境变量方式使用的 ConfigMap 数据不会被自动更新。 更新这些数据需要将 Pod删除重建 ,重启业务也不好使,因为数据是在Pod创建时加载进去的。
限制: 使用 ConfigMap 作为 subPath 卷挂载的容器将不会收到 ConfigMap 的更新。

ConfiMap

Configmap创建文件

  • 创建配置文件
mkdir config
[root@k8s-master01 config]# cat test1.conf 
k8s.io=true
return=false
[root@k8s-master01 config]# cat test2.conf 
user=root
password=123qq...A

  • 创建configmap
# ./config 会将路径下的所有文件纳入到configmap中
# ./config/a.txt 也可以单独指定某个文件
kubectl create cm configmap --from-file=./config
kubectl get cm
NAME               DATA   AGE
configmap          2      7s
kube-root-ca.crt   1      6d



[root@k8s-master01 pod]# kubectl get cm configmap -o yaml
apiVersion: v1
data:
  test1.conf: |
    k8s.io=true
    return=false
  test2.conf: |
    user=root
    password=123qq...A
kind: ConfigMap
metadata:
  creationTimestamp: "2023-11-25T11:13:26Z"
  name: configmap
  namespace: default
  resourceVersion: "383299"
  uid: b1fd4feb-2803-4b1d-a11e-205c370ac39b

Configmap创建环境变量

  • 创建变量
  • 如果有程序需要使用环境变量也可以用configmap来管理
方式1
[root@k8s-master01 config]# cat env1.conf 
level=info
logrote=3

[root@k8s-master01 config]# kubectl create cm env --from-env-file=env1.conf

[root@k8s-master01 config]# kubectl get cm/env -o yaml
apiVersion: v1
data:
  level: info
  logrote: "3"
kind: ConfigMap
metadata:
  creationTimestamp: "2023-11-25T11:27:43Z"
  name: env
  namespace: default
  resourceVersion: "385176"
  uid: 5ac5da16-0efa-4f9a-a75b-1d998a6697e7

方式2
kubectl create cm env-literal \
--from-literal=user=root \
--from-literal=always=True

[root@k8s-master01 config]# kubectl get cm/env-literal -o yaml
apiVersion: v1
data:
  always: "True"
  user: root
kind: ConfigMap
metadata:
  creationTimestamp: "2023-11-25T11:31:45Z"
  name: env-literal
  namespace: default
  resourceVersion: "385703"
  uid: 185b5ec1-9eb2-42cb-a8d4-9e9f7ca2133a

变量使用问题和总结
  • 创建时指定–from-env-file 注定就是做环境变量使用的
  • 创建时指定–from-file 注定就是做文件挂载的
  • 如果你的文件是这样?
[root@k8s-master01 pod]# cat a.txt 
a=123
v1=222
ccc # 故意不写成key=value格式

# 创建env的cm
详细内容是这样的
[root@k8s-master01 pod]# kubectl get cm/test -o yaml
apiVersion: v1
data:
  a: "123"
  ccc: "" # 注意ccc的值是空
  v1: "222"
kind: ConfigMap

  • 另外还有一个现象就是如果你是指定的–from-file那get yaml的时候多半有个 | 它的key是文件名称,这时候你想使用这里的变量v1来传入容器、多半会报错的
[root@k8s-master01 pod]# kubectl get cm/test -o yaml
apiVersion: v1
data:
  a.txt: |
    a=123
    v1=222
kind: ConfigMap

Configmap使用之valueFrom

  • 创建一个deployment
cat dp-cm.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dp-cm
  name: dp-cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dp-cm
  template:
    metadata:
      labels:
        app: dp-cm
    spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        env:
        - name: LIVES # 容器中Key的名称
          valueFrom: # value从哪拿
            configMapKeyRef:
              name: env # 从env这个configmap中拿
              key: logrote  # 拿logrote的value 赋值给 LIVES

# 查看env这个configmap
[root@k8s-master01 pod]# kubectl get cm | grep env
env                2      24m


# 查看env详情:
[root@k8s-master01 pod]# kubectl get cm/env -o yaml
apiVersion: v1
data:
  level: info
  logrote: "3"
kind: ConfigMap
metadata:
  creationTimestamp: "2023-11-25T11:27:43Z"
  name: env
  namespace: default
  resourceVersion: "385176"
  uid: 5ac5da16-0efa-4f9a-a75b-1d998a6697e7

logrote对应的value是3

# 在容器中验证 符合预期

kubectl exec -it dp-cm-558d7d9fb5-clv56  -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=dp-cm-558d7d9fb5-clv56
NGINX_VERSION=1.15.12
LIVES=3

Configmap使用之envFrom

常用

  • 使用envfrom将所有configMap中的数据定义为容器的环境变量,configMap中的键成为Pod中环境变量的名称
# 截取部分
spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        envFrom:
        - configMapRef:
            name: env
          prefix: fromcm # 变量前缀可不写
	
# 创建deployment
kubectl apply -f dp-cm.yaml 

# 验证
kubectl exec -it dp-cm-6db659fc54-rlw9g  -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=dp-cm-6db659fc54-rlw9g
NGINX_VERSION=1.15.12
fromcmpassword=123qqq...A
fromcmlevel=info
fromcmlogrote=7


Configmap使用之以文件的形式挂载(多个文件)

  • 如果指定的路径 容器内存在,容器里的路径就会被覆盖
  • configmap更新 容器会更新
#  创建configmap
[root@k8s-master01 more_conf]# pwd
/root/pod/more_conf
[root@k8s-master01 more_conf]# ls
deploy-ingress.yaml  dp-cm.yaml  ingress.yaml  man_port.yaml  nd.yaml  nginx.yaml  secret.yaml  sts.yaml  svc_hd.yaml  svc_ser.yaml  whdp.yaml

kubectl create cm more-conf --from-file=./more_conf/ # 创建configmap
kubectl get cm/more-conf -o yaml # 每个文件名是key名称 value则是对应的文件内容
# 修改deployment 挂载文件
[root@k8s-master01 pod]# cat dp-cm.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dp-cm
  name: dp-cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dp-cm
  template:
    metadata:
      labels:
        app: dp-cm
    spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        volumeMounts:
          - name: more-conf-volume
            mountPath: /etc/kolla
      volumes:
      - name: more-conf-volume # volume的名称
        configMap: # 使用configmap的挂载方式
          name: more-conf # 指定configmap的名称




# 进入容器查看挂载文件
[root@k8s-master01 pod]# kubectl exec -it dp-cm-6dc4b68f9f-qbkhb -- sh
/ # ls /etc/kolla/
deploy-ingress.yaml  ingress.yaml         nd.yaml              secret.yaml          svc_hd.yaml          whdp.yaml
dp-cm.yaml           man_port.yaml        nginx.yaml           sts.yaml             svc_ser.yaml

Configmap使用之以文件的形式挂载(单个文件)

  • 如果指定的路径 容器内存在,容器里的路径就会被覆盖
  • configmap更新 容器会更新
1. 创建configmap
这里引用上方的configmap
[root@k8s-master01 pod]# kubectl get cm/more-conf
NAME        DATA   AGE
more-conf   11     6h48m

2. 更新deployment 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dp-cm
  name: dp-cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dp-cm
  template:
    metadata:
      labels:
        app: dp-cm
    spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        volumeMounts:
          - name: more-conf-volume
            mountPath: /etc/kolla/
      volumes:
      - name: more-conf-volume # volume的名称
        configMap: # 使用configmap的挂载方式
          name: more-conf # 指定configmap的名称
          items: # # 来自 ConfigMap 的一组键,将被创建为文件
          - key: deploy-ingress.yaml
            path: deploy-ingress.yaml 
          - key .... # 可以指定多个

3. 验证:
[root@k8s-master01 pod]# kubectl exec -it dp-cm-d976b6568-5t4bh -- ls /etc/kolla
deploy-ingress.yaml

上面的例子定义了一个卷并将它作为/etc/kolla/ 文件夹挂载到 demo 容器内, 创建一个文件,/etc/kolla/deploy-ingress.yaml, 尽管 ConfigMap 中包含了多个键。 这是因为 Pod 定义中在 volumes 节指定了一个 items 数组。 如果你完全忽略 items 数组,则 ConfigMap 中的每个键都会变成一个与该键同名的文件, 因此你会得到11个文件。


Configmap配置文件之修改

想修改配置文件?
两种方法:

  1. 直接edit cm ,容器内大概30s-1min左右会更新
  2. 修改configmap后端对应的文件(但是前提是configmap的引用没有使用subpath、如果你是文件subPath的方式挂载 容器里是不会更新的)
# 比如这里2048 改成1024
[root@k8s-master01 pod]# cat nginx.conf  | grep 2048
    worker_connections  2048;
[root@k8s-master01 pod]# sed -i 's/2048/1024/' nginx.conf

查看原有configmap 还是2048

# 利用configmap的创建命令指定 dry-run 生成yaml文件 并交给replace替换
kubectl create cm conf --from-file=nginx.conf \
--dry-run -o yaml | kubectl replace -f -
# 直接替换
# 或者
kubectl create cm conf --from-file=nginx.conf \
--dry-run -o yaml > nginx.yaml
kubectl replace -f nginx.yaml

如图这里就是1024 更新后的结果

# 进入容器查看
大概30s - 1min后 容器内会更新
但容器更新的前提是 你是采用目录的方式挂载而不是subpath文件的方式挂载!

Secret

  • secret的类型
    在这里插入图片描述

创建secret

使用kubectl

官网链接:https://kubernetes.io/zh-cn/docs/tasks/configmap-secret/managing-secret-using-kubectl/

1. 使用源文件 
将凭据保存到文件:

echo -n 'admin' > ./username.txt
echo -n 'S!B\*d$zDsb=' > ./password.txt

-n 标志用来确保生成文件的文末没有多余的换行符。
这很重要,因为当 kubectl 读取文件并将内容编码为 base64 字符串时,额外的换行符也会被编码。 你不需要对文件中包含的字符串中的特殊字符进行转义。

2. 在 kubectl 命令中传递文件路径:
kubectl create secret generic db-user-pass \
    --from-file=./username.txt \
    --from-file=./password.txt

3. 默认键名为文件名。你也可以通过 --from-file=[key=]source 设置键名,例如:
kubectl create secret generic db-user-pass \
    --from-file=username=./username.txt \
    --from-file=password=./password.txt

4. 查看
[root@k8s-master01 pod]# kubectl get secret
NAME                  TYPE                                  DATA   AGE
db-user-pass          Opaque                                2      3s
default-token-58576   kubernetes.io/service-account-token   3      6d18h

5. 使用get 或者describe是看不到源数据的,因为经过base64 编译
[root@k8s-master01 pod]# kubectl get secret/db-user-pass -oyaml
apiVersion: v1
data:
  password.txt: UyFCXCpkJHpEc2I9
  username.txt: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2023-11-26T05:01:45Z"
  name: db-user-pass
  namespace: default
  resourceVersion: "439762"
  uid: 55d730a7-1a79-4900-8901-1369c04678c5
type: Opaque

6. 解码
kubectl get secret/db-user-pass -o jsonpath='{.data}'
{"password.txt":"UyFCXCpkJHpEc2I9","username.txt":"YWRtaW4="}

echo UyFCXCpkJHpEc2I9 | base64 --decode
S!B\*d$zDsb=
使用资源文件

官网地址: https://kubernetes.io/zh-cn/docs/tasks/configmap-secret/managing-secret-using-config-file/

将这些字符串转换为 base64:
echo -n 'admin' | base64
echo -n '1f2d1e2e67df' | base64

输出类似于:
YWRtaW4=
MWYyZDFlMmU2N2Rm

创建清单:
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm

kubectl apply -f ./secret.yaml
创建 Secret 时提供未编码的数据
对于某些场景,你可能希望使用 stringData 字段。 这个字段可以将一个非 base64 编码的字符串直接放入 Secret 中, 当创建或更新该 Secret 时,此字段将被编码。
[root@k8s-master01 pod]# cat secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
    apiUrl: "https://my.api.com/api/v1"
    username: <user>
    password: <password>
    
[root@k8s-master01 pod]# kubectl apply -f secret.yaml 
kbectl secret/mysecret created

输出类似于:
[root@k8s-master01 pod]# kubectl get secret/mysecret -o yaml
apiVersion: v1
data:
  apiUrl: aHR0cHM6Ly9teS5hcGkuY29tL2FwaS92MQ==
  password: PHBhc3N3b3JkPg==
  username: PHVzZXI+
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"Secret","metadata":{"annotations":{},"name":"mysecret","namespace":"default"},"stringData":{"apiUrl":"https://my.api.com/api/v1","password":"\u003cpassword\u003e","username":"\u003cuser\u003e"},"type":"Opaque"}
  creationTimestamp: "2023-11-26T05:21:19Z"
  name: mysecret
  namespace: default
  resourceVersion: "442324"
  uid: 45902cf1-d469-45e9-9694-67e18adcd5f5
type: Opaque


Secret使用之以文件的形式挂载

  • 与configmap类似
# 确保有secret
[root@k8s-master01 pod]# kubectl get secret | grep mysecret
mysecret              Opaque                                3      4m58s

[root@k8s-master01 pod]# cat secret.yaml 
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
stringData:
    secret.conf: |
      apiUrl: "https://my.api.com/api/v1"
      username: <user>
      password: <password>


# pod引用
[root@k8s-master01 pod]# cat dp-cm.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dp-cm
  name: dp-cm
spec:
  replicas: 1
  selector:
    matchLabels:
      app: dp-cm
  template:
    metadata:
      labels:
        app: dp-cm
    spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        volumeMounts:
          - name: secret-conf # 挂载哪个卷
            mountPath: /etc/secret/config # 挂载到哪
      volumes:
      - name: secret-conf # 卷的名称
        secret: # 卷的类型
          secretName: mysecret # 后端secret的名称


验证:
kubectl exec -it dp-cm-7dcc68777-7jmsd -- sh
cd /etc/secret/config
cat secret.conf 
apiUrl: "https://my.api.com/api/v1"
username: <user>
password: <password>
# 可以看到已经成功加载进来了

Secret使用之valueFrom

官网地址:https://kubernetes.io/zh-cn/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data

  • 使用来自 Secret 中的数据定义容器变量
定义环境变量为 Secret 中的键值偶对
kubectl create secret generic backend-user --from-literal=backend-username='backend-admin'

或者使用指定文件的方法创建
[root@k8s-master01 pod]# cat user.conf
backend-username='backend-admin'

[root@k8s-master01 pod]# kubectl create secret generic secret-env2 --from-file=backend-username=./user.conf
这样key名就变成 backend-username了,不然key名是文件名 user.conf

[root@k8s-master01 pod]# cat pod-single-secret-env-variable.yaml
apiVersion: v1
kind: Pod
metadata:
  name: env-single-secret
spec:
  containers:
  - name: envars-test-container
    image: nginx
    env:
    - name: SECRET_USERNAME # 容器中key名
      valueFrom:
        secretKeyRef:
          name: backend-user # 指定secret
          key: backend-username # secret的key对应的value赋值给SECRET_USERNAME
创建 Pod:
kubectl create -f pod-single-secret-env-variable.yaml
在 Shell 中,显示容器环境变量 SECRET_USERNAME 的内容:

kubectl exec -i -t env-single-secret -- /bin/sh -c 'echo $SECRET_USERNAME'
输出类似于:

backend-admin

Secret使用之envFrom

  • 使用 envFrom 来将 Secret 中的所有数据定义为环境变量。 Secret 中的键名成为容器中的环境变量名:
  • 官网链接:https://kubernetes.io/zh-cn/docs/tasks/inject-data-application/distribute-credentials-secure/#define-container-environment-variables-using-secret-data
# 创建包含多个键值偶对的 Secret:
kubectl create secret generic test-secret \
--from-literal=username='my-app' \
--from-literal=password='39528$vdg7Jb'

#使用 envFrom 来将 Secret 中的所有数据定义为环境变量。 
# Secret 中的键名成为容器中的环境变量名:

# 创建Pod
apiVersion: v1
kind: Pod
metadata:
  name: envfrom-secret
spec:
  containers:
  - name: envars-test-container
    image: nginx
    envFrom:
    
    - secretRef:
        name: test-secret

kubectl create -f https://k8s.io/examples/pods/inject/pod-secret-envFrom.yaml

在 Shell 中,显示环境变量 username 和 password 的内容
kubectl exec -i -t envfrom-secret -- /bin/sh -c 'echo "username: $username\npassword: $password\n"'

输出类似与:
username: my-app
password: 39528$vdg7Jb

secret案例之拉取私有仓库镜像

  • 假如你使用私有仓库镜像,那拉取的时候是需要先login的
  • 如果不login会拉取失败
  • 创建secret、资源对象引用即可
kubectl create secret docker-registry private-registry-login --docker-username=xxx@qq.com\
--docker-password=xxxx \
--docker-email=xxxx@163.com \
--docker-server=registry.cn-beijing.aliyuncs.com

kubectl get secret | grep registry
private-registry-login   kubernetes.io/dockerconfigjson        1      59s

# deployment使用secret
root@k8s-master01 pod]# cat dp-cm.yaml 
...
    spec:
      imagePullSecrets:
      - name: private-registry-login
      containers:
      - image: registry.cn-beijing.aliyuncs.com/java-demo-test/nginx:needlogin
        name: nginx

secret案例之管理https证书

# 使用openssl模拟创建不受信任的证书
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=test.com"
# 一般自己买的证书也会有这两个文件
[root@k8s-master01 secret]# ll
total 8
-rw-r--r-- 1 root root 1090 Nov 26 22:00 tls.crt
-rw-r--r-- 1 root root 1704 Nov 26 22:00 tls.key

# 创建secret
kubectl create secret tls nginx-test-tls --key=tls.key --cert=tls.crt

kubectl get secret
NAME                     TYPE                                  DATA   AGE
nginx-test-tls           kubernetes.io/tls                     2      4s

# 配置ingress
[root@k8s-master01 pod]# cat ingress.yaml 
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata: 
  name: nginx-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: nginx.test.com
    http:
      paths:
      - backend:
          service:
            name: whdp
            port:
              number: 80
        path: /
        pathType: ImplementationSpecific
  tls:
  - secretName: nginx-test-tls

# 本地更改hosts将nginx.test.com 映射到 某个宿主机上 
# 测试访问

在这里插入图片描述

subPath使用

  • subPath挂载不会覆盖原有路径的内容,但是缺点是不支持更新
# subpath挂载
spec:
      containers:
      - image: registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12-alpine
        name: nginx
        volumeMounts:
          - name: nginx-conf
            mountPath: /etc/nginx/nginx.conf #文件方式挂载
            subPath: nginx.conf # 指定文件名
      volumes:
      - name: nginx-conf # volume的名称
        configMap: # 使用configmap的挂载方式
          name: conf # 指定configmap的名称

总结

configmap 和secret 都需要提前创建
configmap和secret都可以为pod提供挂载和变量的方式
变量的方式有envfrom全部变量和valuefrom单个变量的引用
configmap和secret 需要和引用的pod或者资源对象在同一个ns下

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐