虚拟化容器,大数据,DBA,中间件,监控。

Kubernetes容器集群 - Secret(特殊存储卷)

22 11月
作者:admin|分类:容器虚拟化

 

一、Secret介绍
在Kubernetes集群资源中,Secret对象与ConfigMap对象类似,但它主要是用于存储小片敏感的需要加密的数据,例如密码,token和SSH key密钥等等。这类数据当然也可以存放在Pod的定义中或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,更加安全和灵活,并减少信息暴露的风险。在secret中存储的数据都需要通过base64进行转换加密后存放。Secret解决了密码、token、密钥等敏感数据的配置问题,使用Secret可以避免把这些敏感数据以明文的形式暴露到镜像或者Pod Spec中。用户可以创建自己的secret,系统也会有自己的secret。

Secret一旦被创建,则可以通过以下三种方式来使用:
-> 在创建Pod时,通过为pod指定Service Account来自动使用该Secret,主要用于API Server鉴权的过程;
-> 通过挂载Secret到Pod来使用它。即作为volume的一个域被一个或多个容器挂载;
-> Docker镜像下载时使用,通过指定Pod的spc.ImagePullSecret来引用。一般用于私有仓库登录拉取镜像。即在拉取镜像的时候被kubelet引用。

Kubernetes集群中有內建的Secrets:即由ServiceAccount创建的API证书附加的秘钥,Kubernetes会自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信。这是Kubernetes 默认的行为,也可以通过自定义的方式禁用或者创建我们所需要的Secret。

二、Secret 类型和使用
-> Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。
-> kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息。
-> kubernetes.io/service-account-token (即Service Account):用于被 serviceaccount 引用。serviceaccout 创建时,Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。Service Account 是内置secret,使用 API 凭证自动创建和附加secretKubernetes 自动创建包含访问API凭据的secret,并自动修改pod以使用此类型的secret。如果需要,可以禁用或覆盖自动创建和使用API凭据。但是,如果需要的只是安全地访问apiserver,则推荐这样的工作流程。

第一种类型: Opaque Secret
Opaque类型的Secret,其value为base64编码后的值。

1)从文件中创建Secret:分别创建两个名为username.txt和password.txt的文件

[root@k8s-master01 ~]# echo -n "shibo" > ./username.txt     
[root@k8s-master01 ~]# echo -n "shibo@123" > ./password.txt  

使用kubectl create secret命令创建secret,该命令将这些文件打包到一个Secret中并在API server中创建了一个对象。

[root@k8s-master01 ~]# kubectl create secret generic shibo-secret --from-file=./username.txt --from-file=./password.txt     
secret/shibo-secret created

2)使用描述文件创建Secret:  首先使用base64对数据进行编码

[root@k8s-master01 ~]# echo -n 'kevin_bo' | base64
a2V2aW5fYm8=
[root@k8s-master01 ~]# echo -n 'kevin@123' | base64
a2V2aW5AMTIz

创建一个类型为Secret的描述文件

[root@k8s-master01 ~]# cat secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: a2V2aW5fYm8=
  password: a2V2aW5AMTIz

执行创建

[root@k8s-master01 ~]# kubectl create -f secret.yaml 
secret/mysecret created

查看此Secret

[root@k8s-master01 ~]# kubectl get secret|grep "shibo"
shibo-secret                   Opaque                                2      2m27s

[root@k8s-master01 ~]# kubectl get secret shibo-secret -o yaml  
apiVersion: v1
data:
  password.txt: c2hpYm9AMTIz
  username.txt: c2hpYm8=
kind: Secret
metadata:
  creationTimestamp: "2019-06-26T11:20:17Z"
  name: shibo-secret
  namespace: default
  resourceVersion: "1152263"
  selfLink: /api/v1/namespaces/default/secrets/shibo-secret
  uid: 607ea323-9804-11e9-90d4-005056ac7c81
type: Opaque

[root@k8s-master01 ~]# kubectl describe secret/shibo-secret     
Name:         shibo-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
username.txt:  5 bytes
password.txt:  9 bytes

需要注意:默认情况下,get 和 describe 命令都不会显示文件的内容。这是为了防止将secret中的内容被意外暴露给从终端日志记录中刻意寻找它们的人。

3)Secret的使用
创建好Secret之后,可以通过两种方式使用:
-> 以Volume方式
-> 以环境变量方式

Secret 可以作为数据卷被挂载,或作为环境变量暴露出来以供 pod 中的容器使用。它们也可以被系统的其他部分使用,而不直接暴露在 pod 内。例如,它们可以保存凭据,系统的其他部分应该用它来代表您与外部系统进行交互。

在 Pod 中的 volume 里使用 Secret:
-> 创建一个 secret 或者使用已有的 secret。多个 pod 可以引用同一个 secret。
-> 修改您的 pod 的定义在 spec.volumes[] 下增加一个 volume。可以给这个 volume 随意命名,它的 spec.volumes[].secret.secretName 必须等于 secret 对象的名字。
-> 将下面的配置

spec.containers[].volumeMounts[]

加到需要用到该 secret 的容器中。指定下面的配置

spec.containers[].volumeMounts[].readOnly = true

并设置下面内容为想要该 secret 出现的尚未使用的目录。

spec.containers[].volumeMounts[].mountPath

-> 修改镜像并且/或者命令行让程序从该目录下寻找文件。Secret的data映射中的每一个键都成为了mountPath下的一个文件名。

3.1   将Secret挂载到Volume中 (下面是一个在pod中使用volume挂载secret的例子)

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: data
      mountPath: "/etc/data"
      readOnly: true
  volumes:
  - name: data
    secret:
      secretName: shibo-secret

进入Pod查看挂载的Secret:

# ls /etc/data
password.txt  username.txt
# cat  /etc/data/username.txt
kevin
# cat  /etc/data/password.txt
kevin@123

想要用的每个secret都需要在spec.volumes 中指明。如果pod中有多个容器,每个容器都需要自己的volumeMounts配置块,但是每个secret只需要一个spec.volumes。还可以打包多个文件到一个secret中,或者使用的多个secret,怎样方便就怎样来。也可以向特性路径映射secret密钥。

还可以控制Secret key映射在 volume 中的路径,可以使用 spec.volumes[].secret.items字段修改每个key的目标路径。也就是说可以只挂载Secret中特定的key:

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: data
      mountPath: "/etc/data"
      readOnly: true
  volumes:
  - name: data
    secret:
      secretName: shibo-secret
      items:
      - key: username
        path: my-group/my-username

需要注意,在这种情况下:
username 存储在 /etc/data/my-group/my-username中
password 未被挂载

如果使用了 spec.volumes[].secret.items,只有在 items 中指定的 key 被影射。要使用 secret 中所有的 key,所有这些都必须列在 items 字段中。所有列出的密钥必须存在于相应的 secret 中。否则,不会创建卷。

3.2   将Secret设置为环境变量

apiVersion: v1
kind: Pod
metadata:
  name: secret-env-pod
spec:
  containers:
  - name: mycontainer
    image: redis
    env:
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: shibo-secret
            key: username
      - name: SECRET_PASSWORD
        valueFrom:
          secretKeyRef:
            name: shibo-secret
            key: password
  restartPolicy: Never

第二种类型:kubernetes.io/dockerconfigjson
kubernetes.io/dockerconfigjson用于存储docker registry的认证信息,可以直接使用kubectl create secret命令创建

[root@k8s-master01 ~]# kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL
secret/myregistrykey created

查看secret的内容:

[root@k8s-master01 ~]# kubectl get secret|grep myregistrykey
myregistrykey                  kubernetes.io/dockerconfigjson        1      54s

[root@k8s-master01 ~]# kubectl get secret myregistrykey  -o yaml
apiVersion: v1
data:
  .dockerconfigjson: eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0=
kind: Secret
metadata:
  creationTimestamp: "2019-06-26T11:35:22Z"
  name: myregistrykey
  namespace: default
  resourceVersion: "1153734"
  selfLink: /api/v1/namespaces/default/secrets/myregistrykey
  uid: 7b769a8a-9806-11e9-90d4-005056ac7c81
type: kubernetes.io/dockerconfigjson

通过 base64 对 secret 中的内容解码:

[root@k8s-master01 ~]# echo "eyJhdXRocyI6eyJET0NLRVJfUkVHSVNUUllfU0VSVkVSIjp7InVzZXJuYW1lIjoiRE9DS0VSX1VTRVIiLCJwYXNzd29yZCI6IkRPQ0tFUl9QQVNTV09SRCIsImVtYWlsIjoiRE9DS0VSX0VNQUlMIiwiYXV0aCI6IlJFOURTMFZTWDFWVFJWSTZSRTlEUzBWU1gxQkJVMU5YVDFKRSJ9fX0=" | base64 --decode
{"auths":{"DOCKER_REGISTRY_SERVER":{"username":"DOCKER_USER","password":"DOCKER_PASSWORD","email":"DOCKER_EMAIL","auth":"RE9DS0VSX1VTRVI6RE9DS0VSX1BBU1NXT1JE"}}}

在创建 Pod 的时候,通过 imagePullSecrets 来引用刚创建的 myregistrykey:

apiVersion: v1
kind: Pod
metadata:
  name: data
spec:
  containers:
    - name: data
      image: janedoe/awesomeapp:v1
  imagePullSecrets:
    - name: myregistrykey

第三种类型:kubernetes.io/service-account-token
用于被 serviceaccount 引用。serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。Pod 如果使用了 serviceaccount,对应的 secret 会自动挂载到 Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。

[root@k8s-master01 ~]# kubectl run kevin_nginx --image nginx
deployment "nginx" created

[root@k8s-master01 ~]# kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
kevin_nginx-3137573019-md1u2   1/1       Running   0          13s

[root@k8s-master01 ~]# kubectl exec kevin_nginx-3137573019-md1u2 ls /run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token
浏览342 评论0
返回
目录
返回
首页
Kubernetes容器集群管理环境 - 完整部署(上篇) MySQL+MGR 单主模式和多主模式的集群环境 - 部署手册 (Centos7.5)