一、Secret

Secret :用来保存一些敏感信息,比如数据库的用户名密码或者秘钥。

概览

Secret是用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
用户可以创建自己的secret,系统也会有自己的secret。
Pod需要先引用才能使用某个secret,Pod有2种方式来使用secret:作为volume的一个域被一个或多个容器挂载;在拉取镜像的时候被kubelet引用。

內建的Secrets

由ServiceAccount创建的API证书附加的秘钥
k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信

1. Secret类型

Secret有三种类型:

  • Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。
  • kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息。
  • kubernetes.io/service-account-token:用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中

举例:保存数据库的用户名和密码

用户名: root
密码: 123.com

1、通过--from-literal(文字的)

[root@master secret]# kubectl create secret generic mysecret1 --from-literal=username=root --from-literal=pasword=123.com

generic:通用的,一般的加密方式

查看一下

[root@master secret]# kubectl get secrets 

k8s的Secret(密文)和configmap(明文)的使用教程_第1张图片

类型是Opaque(不透明的)

2、通过from-file(文件)

新建两个文件并分别写入用户名和密码

[root@master secret]# echo root > username
[root@master secret]# echo 123.com  > password

创建一个secret

[root@master secret]#  kubectl create secret generic mysecret2 --from-file=username --from-file=password 

查看一下

[root@master secret]# kubectl get secrets

k8s的Secret(密文)和configmap(明文)的使用教程_第2张图片

3、通过-- from- env-file:

创建一个文件写入用户名和密码

[root@master secret]#vim env.txt 
username=root
password=123.com

创建一个secret

[root@master secret]# kubectl create secret generic mysecret3 --from-env-file=env.txt 

查看一下

[root@master secret]# kubectl get secrets 

k8s的Secret(密文)和configmap(明文)的使用教程_第3张图片

4、通过yaml配置文件

(1)把需要保存的数据加密(”base64“的方式)

[root@master secret]# echo root | base64
cm9vdAo=
[root@master secret]# echo 123.com | base64
MTIzLmNvbQo=

解码:

[root@master secret]# echo -n cm9vdAo | base64 --decode 
root
[root@master secret]# echo -n MTIzLmNvbQo | base64 --decode 
123.com

(2)编写secre4的yaml文件

[root@master secret]# vim secret4.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret4
data:
  username: cm9vdAo=
  password: MTIzLmNvbQo=
执行一下
[root@master secret]# kubectl apply -f secret4.yaml 

(3)查看一下

[root@master secret]# kubectl get secrets 

k8s的Secret(密文)和configmap(明文)的使用教程_第4张图片

如果来使用Secret资源

1. 以Volume挂载的方式

使用Secret

secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用,也可以被系统中的其他资源使用。比如可以用secret导入与外部系统交互需要的证书文件等。

在Pod中以文件的形式使用secret

  1. 创建一个Secret,多个Pod可以引用同一个Secret
  2. 修改Pod的定义,在spec.volumes[]加一个volume,给这个volume起个名字,spec.volumes[].secret.secretName记录的是要引用的Secret名字
  3. 在每个需要使用Secret的容器中添加一项spec.containers[].volumeMounts[],指定spec.containers[].volumeMounts[].readOnly = true,spec.containers[].volumeMounts[].mountPath要指向一个未被使用的系统路径。
  4. 修改镜像或者命令行使系统可以找到上一步指定的路径。此时Secret中data字段的每一个key都是指定路径下面的一个文件名

编写pod的yaml文件

[root@master secret]# vim pod.yaml 

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    volumeMounts:
    - name: secret-test
      mountPath: "/etc/secret-test"  #pod中的路径
      readOnly: true                 #是否只读
  volumes:
  - name: secret-test
    secret:
      secretName: mysecret1

每一个被引用的Secret都要在spec.volumes中定义
如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts,但是Pod定义中声明一次spec.volumes就好了。
映射secret key到指定的路径
可以控制secret key被映射到容器内的路径,利用spec.volumes[].secret.items来修改被映射的具体路径

执行一下

[root@master secret]# kubectl apply -f pod.yaml 

Secret文件权限

可以指定secret文件的权限,类似linux系统文件权限,如果不指定默认权限是0644,等同于linux文件的-rw-r--r--权限

进入容器查看保存的数据

[root@master secret]# kubectl exec -it mypod /bin/sh
/ # cd /etc/secret-test/
/etc/secret-test # ls
pasword   username
/etc/secret-test # cat username 
root
/etc/secret-test # cat pasword 
123.com

测试是否有只读权限

123.com/etc/secret-test # echo admin > username
/bin/sh: can't create username: Read-only file system

1.1 自定义存放数据的文件名的yaml文件

[root@master yaml]#  vim pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    volumeMounts:
    - name: secret-test
      mountPath: "/etc/secret-test"  #pod中的路径
      readOnly: true                 #是否只读
  volumes:
  - name: secret-test
    secret:
      secretName: mysecret1
      items:
      - key: username
        path: my-group/my-username   #自定义的容器中的目录
      - key: password
        path: my-group/my-password   #自定义的容器中的目录

执行一下

[root@master yaml]# kubectl apply -f pod.yaml

查看一下

[root@master secret]# kubectl exec -it mypod /bin/sh
//进入容器查看
 cat /etc/secret-test/my-group/my-password 
123.com 
 cat /etc/secret-test/my-group/my-username 
root

1.2 如果,现在将secret资源内保存的数据进行更新,请问,使用此数据的应用内,数据是是否也会更新?

会实时更新(这里引用数据,是以volumes挂 载使用数据的方式)。

更新mysecret1的数据: password ---> admin YWRtaW4K (base64)

可以通过edit 命令,直接修改。

[root@master secret]# kubectl edit secrets mysecret1

k8s的Secret(密文)和configmap(明文)的使用教程_第5张图片

查看一下

[root@master secret]# kubectl exec -it mypod /bin/sh
//进入容器查看
  cat /etc/secret-test/my-group/my-password 
admin
  cat /etc/secret-test/my-group/my-username 
root

数据已经成功更新了

2、以环境变量的方式

创建一个Secret,多个Pod可以引用同一个Secret
修改pod的定义,定义环境变量并使用env[].valueFrom.secretKeyRef指定secret和相应的key
修改镜像或命令行,让它们可以读到环境变量

编写pod的yaml文件

[root@master secret]# vim pod-env.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: mypod2
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: mysecret2
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: mysecret2
            key: password

执行一下

[root@master secret]# kubectl apply -f pod-env.yaml 

查看一下

[root@master secret]# kubectl get pod

k8s的Secret(密文)和configmap(明文)的使用教程_第6张图片

进入容器查看保存的数据

[root@master secret]# kubectl exec -it mypod2 /bin/sh
/ # echo $SECRET_USERNAME
root
/ # echo $SECRET_PASSWORD
123.com

2.1 更新sevret文件的内容

 [root@master yaml]# kubectl edit secrets mysecret2
 //修改保存文件的内容

k8s的Secret(密文)和configmap(明文)的使用教程_第7张图片

查看一下

[root@master secret]# kubectl exec -it mypod2 /bin/sh
/ # echo $SECRET_USERNAME
root
/ # echo $SECRET_PASSWORD
123.com

等待了一定时间后,可以看到这个数据并没有没有改变

总结

如果引用secret数据的应用, 要求会随着secret资源对象内保存的数据的更新,而实时更新,那么应该使用volumes挂载的方式引用资源因为用环境变量的方式引用不会实时更新数据。

二、ConfigMap

  上面提到的Secret可以为Pod提供机密数据的存储,而对于一些非机密敏感的数据,像一些应用的配置信息啊神马的,则可以使用Configmap。

  Configmap的创建与使用方式与Secret非常类似,不同点只在于数据以明文形式存放(不过,我觉得Secret的密文形式也并不密文,只能算得上是简单编码)。

和Secret资源类似,不同之处在于,secret 资源保存的是敏感信息,而Configmap保存的是以明文方式存放的数据。
k8s的Secret(密文)和configmap(明文)的使用教程_第8张图片

username:adam

age:18

创建的四种方式

1、通过-- from- literal(文字的):

[root@master yaml]# kubectl create configmap myconfigmap1 --from-literal=username=adam --from-literal=age=18

查看一下

[root@master yaml]# kubectl get cm

k8s的Secret(密文)和configmap(明文)的使用教程

[root@master yaml]# kubectl describe cm

k8s的Secret(密文)和configmap(明文)的使用教程_第9张图片

2、通过--from-file (文件) :

[root@master yaml]# echo adam > username
[root@master yaml]# echo 18 > age

创建

[root@master yaml]# kubectl create configmap myconfigmap2 --from-file=username --from-file=age 

查看一下

[root@master yaml]# kubectl describe cm

k8s的Secret(密文)和configmap(明文)的使用教程_第10张图片

3、通过--from- env-file:

[root@master yaml]# vim env.txt 
username=adam
age=18

创建

[root@master yaml]# kubectl create configmap  myconfigmap3 --from-env-file=env.txt

查看一下

[root@master configmap]# kubectl describe cm

k8s的Secret(密文)和configmap(明文)的使用教程_第11张图片

4、通过yaml配置文件:

[root@master yaml]# vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: myconfigmap4
data:
  username: 'adam'
  age: '18'

创建

[root@master yaml]# kubectl apply -f configmap.yaml 

查看一下

[root@master yaml]# kubectl describe cm

k8s的Secret(密文)和configmap(明文)的使用教程_第12张图片

如何来使用configmap资源

1. 以Volume挂载的方式

[root@master yaml]# vim v-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod1
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    volumeMounts:
    - name: cmp-test
      mountPath: "/etc/cmp-test"
      readOnly: true
  volumes:
  - name: cmp-test
    configMap:
      name: myconfigmap1

执行一下

[root@master configmap]# kubectl apply -f v-pod.yaml 

查看一下

[root@master configmap]# kubectl exec -it pod1 /bin/sh
//进入容器查看一下
 > cat /etc/cmp-test/age 
18/ 
 > cat /etc/cmp-test/username 
adam/ 

1.1 自定义存放数据的文件名的yaml文件

[root@master configmap]# vim v-pod2.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod3
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    volumeMounts:
    - name: cmp-test
      mountPath: "/etc/cmp-test"
      readOnly: true
  volumes:
  - name: cmp-test
    configMap:
      name: myconfigmap1
      items:
      - key: username
        path: my-group/my-username   #自定义的容器中的目录
      - key: age
        path: my-group/my-age   #自定义的容器中的目录 

执行一下

[root@master configmap]# kubectl apply -f v-pod2.yaml

查看一下

[root@master configmap]# kubectl exec -it pod3 /bin/sh
//进入容器查看
> cat /etc/cmp-test/my-group/my-username 
adam/ 
> cat /etc/cmp-test/my-group/my-age 
18/ 

1.2 如果,现在将secret资源内保存的数据进行更新,请问,使用此数据的应用内,数据是是否也会更新?

[root@master configmap]# kubectl edit cm myconfigmap1

k8s的Secret(密文)和configmap(明文)的使用教程_第13张图片

查看一下

[root@master configmap]# kubectl exec -it pod3 /bin/sh
//进入容器查看
> cat /etc/cmp-test/my-group/my-username 
adam/ 
> cat /etc/cmp-test/my-group/my-age 
10

可以看到更新成功

2.以环境变量的方式

[root@master configmap]# vim e-pod.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: pod2
spec:
  containers:
  - name: mypod
    image: busybox
    args:
      - /bin/sh
      - -c
      - sleep 300000
    env:
      - name: CONFIGMAP_NAME
        valueFrom:
          configMapKeyRef:
            name: myconfigmap2
            key: username
      - name: CONFIGMAP_AGE
        valueFrom:
          configMapKeyRef:
            name: myconfigmap2
            key: age

执行一下

[root@master configmap]# kubectl apply -f e-pod.yaml 

查看一下

[root@master configmap]# kubectl exec -it pod2 /bin/sh
//进入容器查看一下
 > echo $CONFIGMAP_NAME
adam
 > echo $CONFIGMAP_AGE
18

2.1 更新sevret文件的内容

[root@master configmap]# kubectl edit cm myconfigmap2
 //修改保存文件的内容

k8s的Secret(密文)和configmap(明文)的使用教程_第14张图片

查看一下

[root@master configmap]# kubectl exec -it pod2 /bin/sh
//进入容器查看一下
 > echo $CONFIGMAP_NAME
adam
  > echo $CONFIGMAP_AGE
18

等待了一定时间后,可以看到这个数据并没有没有改变

可以看出这个configmap和secret的更新效果基本没有区别。

总结configmap、与secret资源有什么相同和不同之处。

Secret 与 ConfigMap 对比

相同点:

key/value的形式

属于某个特定的namespace

可以导出到环境变量

可以通过目录/文件形式挂载

通过 volume 挂载的配置信息均可热更新

不同点:

Secret 可以被 ServerAccount 关联

Secret 可以存储 docker register 的鉴权信息,用在 ImagePullSecret 参数中,用于拉取私有仓库的镜像

Secret 支持 Base64 加密

Secret 分为 kubernetes.io/service-account-token、kubernetes.io/dockerconfigjson、Opaque 三种类型,而 Configmap 不区分类型

总结以volumes挂载、和环境变量方式引用资源的相同和不同之处。

volumes挂载(可根据更改数据更新):引用自己创建的secret(密文)或configmap(明文),挂载到容器中指定的目录下。查看保存的文件时,根据自己所填路径和secret或configmap创建的文件,进行查看。

环境变量(不因更改数据更新):引用自己创建的secret(密文)或configmap(明文),挂载到容器中指定的目录下。查看保存的文件时,根据自己环境变量,进行查看。