Secret和ConfigMap

1991/6/26 基础

# 1.Secret介绍

应用启动过程中可能需要一些敏感信息,比如访问数据库的用户名、密码或者密钥。将这些信息直接保存在容器镜像中显然不妥,Kubernetes提供的解决方案是Secret

Secret会以密文的方式存储数据,避免了直接在配置文件中保存敏感信息。

# 2. 创建Secret

# 2.1 通过env文件

语法: kubectl create secret generic name --from-env-file=env文件

# a. 编辑env文件

文件:.env

username=admin
password=123456
1
2

# b. 创建secret

# secret 名称为: mysql-secret
$ kubectl create secret generic mysql-secret --from-env-file=./.env
1
2

# 2.2 通过yaml文件

# a. 编辑文件

文件: redis_secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: redis-secret
data:
  ip: MTI3LjAuMC4x
  port: NjM3OQ==
  user: dGVzdA==
  pass: MTEyMjMz
1
2
3
4
5
6
7
8
9

通过配置文件生成Secret时,val(值)必须通过base64编码,否则会报错。

# b. 创建secret

$ kubectl apply -f redis-secret.yaml
secret/redis-secret created
1
2

# 3. 查看Secret

# 3.1 获取Secret列表

使用kubectl get secret可以查看所有的Secret

# Data数量代表有几个键值对
$ kubectl get secret
NAME                               TYPE                 DATA   AGE
mysql-secret                       Opaque               2      86m
redis-secret                       Opaque               4      3m48s
1
2
3
4
5

# 3.2 查看Secret中的Key

使用kubectl describe secret 名称可以查看Secret的详情信息,其中就包括Key

$ kubectl describe secret redis-secret
Name:         redis-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data  # 下面就是所有的key 
====
user:  4 bytes
ip:    9 bytes
pass:  6 bytes
port:  4 bytes
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.3 查看Secret中的Val

通过使用kubectl edit secret 名称可以查看SecretKey对应的Val信息。

apiVersion: v1
data:
  ip: MTI3LjAuMC4x
  pass: MTEyMjMz
  port: NjM3OQ==
  user: dGVzdA==
kind: Secret
metadata:
...
1
2
3
4
5
6
7
8
9

需要注意的是,查看的Val是通过base64编码后的,想看到具体值,需要反编码。

# 反编码查询具体值信息
$  echo -n MTEyMjMz | base64 --decode
112233
1
2
3

# 4. 使用Secret

Pod可以通过Volume或者环境变量的方式使用Secret.

# 4.1 Volume方式

# a. Pod配置文件

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  containers:
    - image: busybox
      name: write-box
      volumeMounts:
        - mountPath: /home/redisconf
          name: secret-volume
      args:
        - /bin/sh
        - -c
        - sleep 10; touch /tmp/health;sleep 30000

  volumes:
    - name: secret-volume
      secret:
        secretName: redis-secret
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# b. 发布验证

# 发布资源
$ kubectl apply -f test-po.yaml
pod/test-pod created
# 进入pod容器中
$  kubectl exec -it  test-pod sh
# 查看volume映射信息
/ $ cd /home/redisconf/
/home/redisconf $ ls
ip    pass  port  user
# 查看具体文件信息
/home/redisconf $ cat ip
127.0.0.1
1
2
3
4
5
6
7
8
9
10
11
12

可以看到,Kubernetes会在指定的路径/home/redisconf下为每条敏感数据创建一个文件,文件名就是数据条目的KeyValue则以明文存放在文件中。

# c. 验证变更同步

redis-secret中的IP改为100.100.100.100,发布后,查看Pod中是否更新

# 1.修改 redis-secret配置文件
$ vim redis-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: redis-secret
data:
  ip: MTAwLjEwMC4xMDAuMTAw # 这里修改了IP为 100.100.100.100
  port: NjM3OQ==
  user: dGVzdA==
  pass: MTEyMjMz
# 2.重新发布
$ kubectl apply -f redis-secret.yaml
secret/redis-secret configured
# 去pod中查看是否更新
/ # cat /home/redisconf/ip
100.100.100.100 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4.2 环境变量方式

通过Volume使用Secret,容器必须从文件读取数据,稍显麻烦,Kubernetes还支持通过环境变量使用Secret

# a. Pod配置文件

文件: test-po2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: test-pod2
spec:
  containers:
    - image: busybox
      name: write-box
      args:
        - /bin/sh
        - -c
        - sleep; touch /tmp/health;sleep 30000
      env: # 通过环境变量
        - name: REDIS_IP # 环境变量名
          valueFrom:
            secretKeyRef:
              name: redis-secret # secret 名称
              key: ip  # secret中的key
        - name: REDIS_PORT
          valueFrom:
            secretKeyRef:
              name: redis-secret
              key: port
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# b. 发布验证

# 发布资源
$ kubectl apply -f test-po2.yaml
pod/test-pod2 created
$ kubectl exec -it test-pod2 bash
/ # echo $REDIS_IP
100.100.100.100
/ # echo $REDIS_PORT
6379
1
2
3
4
5
6
7
8

需要注意的是,环境变量读取Secret很方便,但无法支撑Secret动态更新。

# 5. ConfigMap介绍

Secret可以为Pod提供密码、Token、私钥等敏感数据;对于一些非敏感数据,比如应用的配置信息,则可以用ConfigMap

ConfigMap的创建和使用方式与Secret非常类似,主要的不同是数据以明文的形式存放。

# 5.1 创建ConfigMap

# a. 通过yaml创建

文件: app_conf.yaml

apiVersion: v1
kind: ConfigMap # 注意这里类型是ConfigMap
metadata:
  name: appconfig
data:
  appName: "k8s学习" # 这里只写明文,不需要base64
  appVersion: "v1.0.0"
1
2
3
4
5
6
7

发布:

$ kubectl apply -f app-conf.yaml
configmap/appconfig created
1
2

# 5.2 使用ConfigMap

Secret一样,Pod也可以通过Volume或者环境变量的方式使用Secret,这里只演示Volume方式:

# a. Pod配置文件

apiVersion: v1
kind: Pod
metadata:
  name: config-map-demo
spec:
  containers:
    - image: busybox
      name: write-box
      args:
        - /bin/sh
        - -c
        - sleep; touch /tmp/health;sleep 30000
      volumeMounts:
        - mountPath: "/etc/k8sconf" # 映射到容器的目录位置
          name: "confmapdemo"
  volumes:
    - name: confmapdemo
      configMap: # 这里有别于secret
        name: appconfig # 上面创建的configMap名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# b. 发布验证

# 发布
$ kubectl apply -f config-map-pod.yaml
pod/config-map-demo created
# 进入容器查看
[root@master secret]# kubectl exec -it config-map-demo sh
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
➜ cd /etc/k8sconf/
➜ ls
appName     appVersion
➜ cat appName
k8s学习
➜ cat appVersion
v1.0.0
1
2
3
4
5
6
7
8
9
10
11
12
13

# 5.3 通过配置文件创建Configmap

大多数情况下,配置信息都以文件形式提供,所以在创建ConfigMap时通常采用--from-fileYAML方式,读取ConfigMap时通常采用Volume方式。

比如我们的应用配置文件如下,现需要把它传递到容器中:

文件名: app.toml

app_name = "k8s-learn"
app_version = "v1.0.0"
[database.default]
driver = "mysql"
host = "127.0.0.1"
port = "3306"
username = "test"
password = "test"
[redis.default]
addr = "127.0.0.1:6379"
db = 2
1
2
3
4
5
6
7
8
9
10
11

# a. 创建

# 发布
$ kubectl create configmap appconf --from-file=./app.toml
# 查看
$ kubectl describe cm appconf
Name:         appconf
Namespace:    default
...
Data
====
app.toml:
----
app_name = "k8s-learn"
app_version = "v1.0.0"
[database.default]
driver = "mysql"
host = "127.0.0.1"
port = "3306"
username = "test"
password = "test"
[redis.default]
addr = "127.0.0.1:6379"
db = 2
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# b. 使用

编辑Pod配置文件:conf-map-file.yaml

apiVersion: v1
kind: Pod
metadata:
  name: config-map-file
spec:
  containers:
    - image: busybox
      name: write-box
      args:
        - /bin/sh
        - -c
        - sleep; touch /tmp/health;sleep 30000
      volumeMounts:
        - mountPath: "/etc/appconf" # 容器映射目录
          name: "confmapdemo"
  volumes:
    - name: confmapdemo
      configMap:
        name: appconf # 我们上面创建的configmap名称
        items:
          - key: app.toml # configMap中的key
            path: www/app.toml # 存到容器相对目录: 容器映射目录+www/app.toml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

发布&验证:

# 发布
$ kubectl apply -f conf-map-file.yaml
pod/config-map-file created
# 进入容器查看pwd
/etc/appconf/www
➜ ls
app.toml
➜ cat app.toml
app_name = "k8s-learn"
app_version = "v1.0.0"
[database.default]
driver = "mysql"
host = "127.0.0.1"
port = "3306"
username = "test"
password = "test"
[redis.default]
addr = "127.0.0.1:6379"
db = 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20