在Kubernetes(k8s)中,应用程序的配置和数据存储是一个重要且敏感的议题。Kubernetes提供了两种主要的资源类型来管理这些敏感信息和配置数据:Secrets和ConfigMaps。本文将深入探讨这两种资源类型,以及如何在Kubernetes集群中有效地使用它们。

一、Secrets资源管理

1.1 Secrets概述

        在Kubernetes(k8s)中,Secrets是一种用于存储敏感信息的对象,如密码、OAuth令牌、SSH密钥等。这些信息在部署应用程序时可能需要,但又不希望直接硬编码在应用程序的代码中或者公开暴露。通过使用Secrets,我们可以将敏感信息与应用程序代码解耦,从而提高安全性。

1.2 Secrets类型(三种类型)

       ① service-account-token:用于访问API的服务账户令牌。由 Kubernetes 自动创建,用来访问 APIServer 的 Secret,Pod 会默认使用这个 Secret 与 APIServer 通信, 并且会自动挂载到 Pod 的 /var/run/secrets/kubernetes.io/serviceaccount 目录中

[root@master01 ~]#kubectl run nginx --image=nginx:1.18.0
pod/nginx created
[root@master01 ~]#kubectl describe pod nginx |sed -n '/Mounts/{p;n;p}'
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-vgx6f (ro)
-------------------------------------------------------------------------------------
#新建立一个pod,它会自动以挂载的方式,使用serviceaccount来访问,并且权限是只读权限

        ② Opaque:Base64 编码格式的Secret,用来存储用户自定义的密码、密钥等/Secrets中的敏感信息在存储之前会先被Base64编码。但是请注意,Base64编码并不提供安全性,它只是用来避免在YAML文件中直接暴露明文信息,是默认的Secret 类型

        ③ Docker Config:用于认证私有Docker仓库的凭据。存储私有 docker registry 的认证信息,搭建私有仓库时,使用该类型,在客户端登录私有仓库时,可以免密登录

        ④ TLS:用于存储TLS证书和私钥

1.3  Secrets使用方式

可挂载为卷:Secrets可以挂载到Pod中的容器,以文件的形式提供敏感信息。

可作为环境变量:Secrets中的信息也可以被设置为Pod中容器的环境变量

1.4 创建Secrets

1.4.1 陈述式命令创建

1.4.1.1 定义用户与密码文件

[root@master01 data]#mkdir -p /data/secret/pass
[root@master01 data]#cd /data/secret
[root@master01 secret]#echo -n 'china' >/data/secret/pass/user.txt
#创建用户名文件
[root@master01 secret]#echo -n '19491001' >/data/secret/pass/passwd.txt
#创建密码文件

1.4.1.2 使用陈述式命令创建

[root@master01 secret]#kubectl create secret generic secret01 --from-file=/data/secret/pass/user.txt --from-file=/data/secret/pass/passwd.txt
secret/secret01 created
[root@master01 secret]#kubectl get secrets secret01
NAME                     TYPE                                  DATA   AGE
secret01                 Opaque                                2      11s
[root@master01 secret]#kubectl describe secrets secret01
Name:         secret01
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Type:  Opaque
 
Data
====
user.txt:    5 bytes
passwd.txt:  8 bytes
---------------------------------------------------------------------------------
#kubectl create secret generic secret01
#这一部分命令告诉Kubernetes创建一个新的泛型(generic)类型的Secret对象,命名为secret01。
#使用generic子命令来标明要创建的是一个Opaque类型的Secret
 
--from-file=/data/secret/pass/user.txt
#此选项指定了一个文件路径/data/secret/pass/user.txt,其内容将被用来创建Secret中的一个键值对。
#键(key)通常是文件名(即user.txt),值(value)是文件的内容。
#这意味着Secret将包含一个条目,其中键为user.txt,值为该文件中的文本内容。
   0
--from-file=/data/secret/pass/passwd.txt
#同理,此选项也指定了另一个文件路径/data/secret/pass/passwd.txt,
#其内容也会被加入到Secret中作为一个独立的条
 
#不论是使用get命令还是describe查看,都不会显示实际的内容,而是以字节长度的信息显示

1.4.2 使用base64创建

        上述创建方式,虽然可以创建Secrets,但是它还是属于一种明文创建的方式,可以使用base方式进行加密

1.4.2.1 获取加密信息

[root@master01 secret]#echo -n china |base64
Y2hpbmE=
[root@master01 secret]#echo -n 19491001 |base64
MTk0OTEwMDE=

1.4.2.2  使用yaml文件创建

[root@master01 secret]#vim secret.yaml
[root@master01 secret]#cat secret.yaml
apiVersion: v1
kind: Secret                   #指定资源的类型为Secret
metadata:
  name: secret-v1              #Secret资源的名称
type: Opaque                   #指定Secret的类型
data:                          #包含实际存储的秘密数据,以base64编码格式给出的键值对
  username: Y2hpbmE=           #base64编码后的“chance”字符串,表示用户名
  password: MTk0OTEwMDE=       #base64编码后的密码
[root@master01 secret]#kubectl apply -f secret.yaml
secret/secret-v1 created
[root@master01 secret]#kubectl get secrets secret-v1 
NAME        TYPE     DATA   AGE
secret-v1   Opaque   2      10s
--------------------------------------------------------------------------------
#使用这个Secret时,Kubernetes会自动处理这些值的base64解码,
#使Pod内的应用程序能够直接使用解码后的原始数据。

1.5 使用Secrets

1.5.1 使用挂载的方式

1.5.1.1 定义文件

在yaml文件中,通过挂载的方式,将指定的Secret资源,挂载到pod的指定目录下

[root@master01 secret]#vim secret-pod01.yaml 
[root@master01 secret]#cat secret-pod01.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod01
spec:
  containers:
  - name: nginx
    image: nginx:1.18.0
    volumeMounts:                 #定义挂载Volume到容器内部的配置
    - name: secrets               #引用了在volumes部分定义的Volume名称
      mountPath: "/etc/secrets"   #容器内挂载点的路径,即Volume将在这个路径下可见
      readOnly: true              #以只读方式挂载,不能修改secret-v1的内容
  volumes:
  - name: secrets                 #secrets Volume的名称,需与volumeMounts中的name相匹配
    secret:
      secretName: secret-v1       #指定此Volume将挂载的Secret的名称

1.5.1.2 创建pod

[root@master01 secret]#kubectl apply -f secret-pod01.yaml 
pod/secret-pod01 created
[root@master01 secret]#kubectl get pod secret-pod01
NAME                          READY   STATUS              RESTARTS   AGE
secret-pod01                  1/1     Running             0          7s
 
[root@master01 secret]#kubectl exec -it secret-pod01 bash                      
root@secret-pod01:/# cat /etc/secrets/username 
china
root@secret-pod01:/# cat /etc/secrets/password 
19491001
root@secret-pod01:/# rm -rf /etc/secrets/password 
rm: cannot remove '/etc/secrets/password': Read-only file system
root@secret-pod01:/# echo 1111 > /etc/secrets/password 
bash: /etc/secrets/password: Read-only file system
root@secret-pod01:/# 
#无法进行删除和重写,它是以只读的方式进行挂载的

1.5.2 使用环境变量的方式

1.5.2.1 定义文件

在yaml文件中定义环境变量的键值信息,其键值可以从Secret中获取

[root@master01 secret]#vim secret-pod02.yaml 
[root@master01 secret]#cat secret-pod02.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: secret-pod02
spec:
  containers:
  - name: nginx
    image: nginx:1.18.0
    env:
    - name: USER_SCT         #环境变量的名称
      valueFrom:
        secretKeyRef:        #指定环境变量的值来自于Secret中的某个键
          name: secret-v1    #使用的Secret名称,需要与之前创建的Secret相匹配
          key: username      #从Secret中提取的键名,对应的值将会被设置为环境变量USER_SCT的值
    - name: PASSWD_SCT       #另一个环境变量的名称
      valueFrom:
        secretKeyRef:
          name: secret-v1
          key: password      #从Secret中提取的另一个键名,其值被设置为环境变量PASSWD_SCT的值

1.5.2.2 创建pod 

[root@master01 secret]#kubectl apply -f secret-pod02.yaml 
pod/secret-pod02 created
[root@master01 secret]#kubectl get pod secret-pod02 
NAME           READY   STATUS    RESTARTS   AGE
secret-pod02   1/1     Running   0          14s
[root@master01 secret]#kubectl exec -it secret-pod02 bash
root@secret-pod02:/# echo "$USER_SCT"     #查看USER_SCT的值
china
root@secret-pod02:/# echo "$PASSWD_SCT"   #查看PASSWD_SCT的值
19491001
root@secret-pod02:/# env |grep SCT   #使用env指令查看系统所有内置变量,并进行过滤
USER_SCT=china
PASSWD_SCT=19491001

1.6 Secret的作用

        安全性提升:避免明文存储敏感信息,减少因不当配置导致的数据泄露风险。

        简化配置管理:集中管理Pod或服务账户所需的敏感信息,便于更新和复用。

        灵活性:支持多种方式使用Secret,包括环境变量、文件挂载或作为命令行参数,满足不同应用的需求。

        权限控制:通过RBAC(Role-Based Access Control)限制对Secret的访问,确保只有授权的用户和服务账户能访问敏感数据。

1.7 注意事项

        保护Secrets:确保你的Secrets在传输和存储过程中都是安全的。避免在不受信任的环境中暴露Secrets。

        定期轮换:对于重要的Secrets,如数据库密码或API密钥,定期轮换是一个好的安全实践。

        最小权限原则:只将必要的Secrets暴露给需要它们的Pod。避免在不需要的地方暴露Secrets。

        不要将Secrets硬编码在代码中:这是非常不安全的做法,因为一旦代码被泄露,Secrets也会被泄露。

        使用RBAC:通过Kubernetes的角色和角色绑定(RBAC)来控制对Secrets的访问权限。

二、 ConfigMap

2.1 ConfigMap概述

        ConfigMap 是 Kubernetes 中的一种资源对象,用于将非敏感的配置数据注入 Pod 或其他 Kubernetes 对象。与 Secret 相似,它提供了一种在不直接硬编码配置信息到容器镜像或 Pod 定义中的方式,从而使得配置易于管理和更新。ConfigMap 允许您将配置数据以键值对的形式存储,并可以在 Pod 运行时将这些配置映射为环境变量、命令行参数或是直接挂载为容器内的文件

2.2 为什么需要ConfigMap

        传统配置管理的问题:在传统架构中,配置文件往往被保存在宿主机上,容器化部署时,由于容器所在的节点不固定,这种方式不再适用。同时,如果配置文件被打包在容器镜像中,那么一旦配置更改,就需要重新构建镜像,这非常不便。

        ConfigMap的作用:ConfigMap将环境配置信息和容器镜像解耦,使得在不重新构建镜像的情况下,可以方便地修改和更新配置。ConfigMap也是按Namespace隔离的,不同的Namespace之间ConfigMap的名称可以相同,但不能跨Namespace进行访问。

2.3 特点与用途

2.3.1 特点

非机密性数据存储:ConfigMap主要用于存储非机密性的配置信息,如数据库连接信息、环境变量等。

键值对形式:ConfigMap的数据可以用key/value键值对的形式保存,也可以通过文件的形式保存。

资源对象:ConfigMap是k8s中的资源对象,可以通过kubectl命令行工具或Kubernetes API进行创建、更新和删除。

与Pod的交互:Pods可以将ConfigMap用作环境变量、命令行参数或存储卷中的配置文件。

动态更新:ConfigMap支持热更新,即在不重启Pods的情况下,可以动态地修改ConfigMap中的数据,Pods会实时地读取新的配置

2.3.2 用途

环境变量:将 ConfigMap 中的配置作为环境变量传递给容器中的应用程序。

命令行参数:使用 ConfigMap 中的值填充容器启动命令的参数。

文件挂载:将ConfigMap 数据作为文件或目录挂载到容器的文件系统中,方便应用程序按文件形式读取配置。

2.4 ConfigMap的创建方式

2.4.1 命令行直接创建

通过kubectl命令行工具,使用--from-literal参数指定键值对来创建ConfigMap。

[root@master01 data]#kubectl create configmap configmap-01 --from-literal=id=001 --from-literal=user=zhangshan
configmap/configmap-01 created
[root@master01 data]#kubectl get configmaps configmap-01
NAME           DATA   AGE
configmap-01   2      19s
[root@master01 data]#kubectl describe configmaps configmap-01
Name:         configmap-01
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
id:         #键名称
----
001         #值
user:       #键名称
----
zhangshan   #值
Events:  <none>

2.4.2 通过文件/目录创建

将配置文件放在指定的目录中,然后通过kubectl命令行工具或YAML文件来创建ConfigMap

2.4.2.1 使用文件创建

[root@master01 data]#mkdir /data/configmap
[root@master01 data]#cd  /data/configmap/
[root@master01 configmap]#echo "this is configmap" >index.html
[root@master01 configmap]#kubectl create configmap configmap-02 --from-file=index.html 
configmap/configmap-02 created
[root@master01 configmap]#kubectl get configmaps configmap-02
NAME           DATA   AGE
configmap-02   1      24s
[root@master01 configmap]#kubectl describe configmaps configmap-02
Name:         configmap-02
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
index.html:
----
this is configmap
 
Events:  <none>

2.4.2.2 使用目录创建

[root@master01 configmap]#mkdir /data/test
[root@master01 configmap]#echo "this is test01" >/data/test/test01.txt
[root@master01 configmap]#echo "this is test02" >/data/test/test02.txt
[root@master01 configmap]#kubectl create configmap configmap-03 --from-file=/data/test/
configmap/configmap-03 created
[root@master01 configmap]#kubectl describe configmaps configmap-03
Name:         configmap-03
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
test01.txt:
----
this is test01
 
test02.txt:
----
this is test02
 
Events:  <none>
[root@master01 configmap]#kubectl get configmaps configmap-03
NAME           DATA   AGE
configmap-03   2      11s

2.4.2.3 YAML创建

编写YAML文件定义ConfigMap,然后使用kubectl apply命令来创建。

[root@master01 configmap]#vim configmap.yaml 
[root@master01 configmap]#cat configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap-04
data:
  APP_SETTING_1: value1              #第一个键:值
  APP_SETTING_2: value2              #第二个键:值
[root@master01 configmap]#kubectl apply -f configmap.yaml 
configmap/configmap-04 created
[root@master01 configmap]#kubectl describe configmaps configmap-04
Name:         configmap-04
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
APP_SETTING_1:
----
value1
APP_SETTING_2:
----
value2
Events:  <none>
[root@master01 configmap]#kubectl get configmaps configmap-04
NAME           DATA   AGE
configmap-04   2      25s

 2.5 使用ConfigMap

删除之前创建的示例

[root@master01 configmap]#kubectl delete configmaps --all
configmap "configmap-01" deleted
configmap "configmap-02" deleted
configmap "configmap-03" deleted
configmap "configmap-04" deleted
configmap "kube-root-ca.crt" deleted

2.5.1 替代环境变量

2.5.1.1 引用值

将configmap中定义的值,设置为自定义变量名称的值

首先使用yaml文件,定义configmaps

[root@master01 configmap]#vim configmap.yaml 
[root@master01 configmap]#cat configmap.yaml 
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap01
data:
  FROM: china        #键名为FROM,值为china
  NAME: ZG           #键名为NAME,值为ZG
[root@master01 configmap]#kubectl apply -f configmap.yaml 
configmap/configmap01 created
[root@master01 configmap]#kubectl describe configmaps configmap01 
Name:         configmap01
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
FROM:
----
china
NAME:
----
ZG
Events:  <none>

定义yaml文件,创建pod,并应用文件configmap对象中的值为自定义变量的值

[root@master01 configmap]#vim pod-cm01.yaml
[root@master01 configmap]#cat pod-cm01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm01
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    command: [ "/bin/sh", "-c", "env" ]  #指令让容器启动时执行env命令,打印所有的环境变量。
    env:
      - name: WHERE_ARE_YOU              #定义变量名称
        valueFrom:                       #指定值的来源
          configMapKeyRef:               #从ConfigMap中引用键的值
            name: configmap01            #指定ConfigMap的名称
            key: FROM                    #指定从configmap01中的FROM键来获取值,即china
      - name: YOU_NAME                   #同上
        valueFrom:
          configMapKeyRef:
            name: configmap01
            key: NAME

创建pod之后,通过查看日志信息,来查看自定的变量

[root@master01 configmap]#kubectl apply -f pod-cm01.yaml 
pod/pod-cm01 created
[root@master01 configmap]#kubectl logs pod-cm01 
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=pod-cm01
SHLVL=1
HOME=/root
WHERE_ARE_YOU=china           #变量值为configmap01对象中FROM的值,即china
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
YOU_NAME=ZG                   #变量值为configmap01对象中NAME的值,即ZG
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/

2.5.1.2 引用键值

可以将configmap中的键值同时引用

[root@master01 configmap]#vim config-pod.yaml
[root@master01 configmap]#cat config-pod.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: configmap02
data:
 PASSWORD_TEST: abc123     #键值
---                        #第一部分为设置configmap对象
apiVersion: v1
kind: Pod
metadata:
  name: pod-cm02
spec:
  containers:
  - name: busybox
    image: busybox:1.28
    command: [ "/bin/sh", "-c", "env" ]
    envFrom:                   #从整个ConfigMap中导入环境变量
    - configMapRef:            #指定ConfigMap的名称。
      name: configmap02
  restartPolicy: Never

使用kubectl apply 命令创建之后查看日志信息

[root@master01 configmap]#kubectl apply -f config-pod.yaml 
configmap/configmap02 created
pod/pod-cm02 created
[root@master01 configmap]#kubectl logs pod-cm02 
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=pod-cm02
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PASSWORD_TEST=abc123               #引用指定configmap中的所有键值
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_HOST=10.96.0.1
PWD=/

2.5.2 文件挂载

        将ConfigMap 数据作为文件或目录挂载到容器的文件系统中,在这个文件中,键就是文件名,键值就是文件内容

2.5.2.1 准备挂载文件

[root@master01 configmap]#echo "this is configmap-pod" >/mnt/index.html
[root@master01 configmap]#cat /mnt/index.html 
this is configmap-pod

2.5.2.2 创建configmap

[root@master01 configmap]#kubectl create configmap config03 --from-file=/mnt/index.html
configmap/config03 created
[root@master01 configmap]#kubectl describe configmaps config03 
Name:         config03
Namespace:    default
Labels:       <none>
Annotations:  <none>
 
Data
====
index.html:
----
this is configmap-pod
 
Events:  <none>

2.5.2.3 数据挂载

[root@master01 configmap]#vim deployment-cm.yaml
[root@master01 configmap]#cat deployment-cm.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-pod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.18.0
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-mount
          mountPath: /usr/share/nginx/html/
      volumes:
        - name: config-mount
          configMap:              #表明这个卷的内容来源于一个ConfigMap
            name: config03        #指定了ConfigMap的名称为config03

创建pod并进行访问

[root@master01 configmap]#kubectl apply -f deployment-cm.yaml 
deployment.apps/nginx-pod created
[root@master01 configmap]#kubectl get pod -owide
NAME                         READY   STATUS      RESTARTS   AGE   IP             NODE     NOMINATED NODE   READINESS GATES
nginx-pod-6f67db4865-ljsx4   1/1     Running     0          12s   10.244.2.246   node02   <none>           <none>
[root@master01 configmap]#vim deployment-cm.yaml 
[root@master01 configmap]#curl 10.244.2.246
this is configmap-pod

2.5.3 热更新

        直接修改configmap的信息,保存退出后,就可等待十秒钟左右,使用该ConfigMap挂载的 Volume 中的数据同步更新

[root@master01 configmap]#kubectl edit configmap config03 
configmap/config03 edited    #修改值的信息

Logo

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

更多推荐