kubernetes/MD/kubernetes资源对象Secret.md

8.8 KiB
Raw Blame History

kubernetes资源对象Secret

著作:行癫 <盗版必究>


Secret

Secret用来保存小片敏感数据的k8s资源例如密码token或者秘钥。这类数据当然也可以存放在Pod或者镜像中但是放在Secret中是为了更方便的控制如何使用数据并减少暴露的风险用户可以创建自己的secret系统也会有自己的secret。Pod需要先引用才能使用某个secret

1.Pod使用secret的方式

作为volume的一个域被一个或多个容器挂载

在拉取镜像的时候被kubelet引用

2.內建的Secrets

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

3.创建自己的Secret

方式1使用kubectl create secret命令

方式2yaml文件创建Secret

命令方式创建secret

假如某个Pod要访问数据库需要用户名密码分别存放在2个文件中username.txtpassword.txt

[root@master ~]# echo -n 'admin' > ./username.txt
[root@master ~]# echo -n '1f2d1e2e67df' > ./password.txt

kubectl create secret指令将用户名密码写到secret中并在apiserver创建Secret

[root@master ~]# kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created

查看创建结果

[root@master ~]# kubectl get secrets
NAME     TYPE           DATA      AGE
db-user-pass    Opaque     2    51s 
[root@master ~]# kubectl describe secret/db-user-pass
Name:            db-user-pass
Namespace:       default
Labels:          <none>
Annotations:     <none>
Type:            Opaque
Data
====
password.txt:    12 bytes
username.txt:    5 bytes

get或describe指令都不会展示secret的实际内容这是出于对数据的保护的考虑如果想查看实际内容使用命令

[root@master ~]# kubectl get secret db-user-pass -o json

yaml方式创建Secret

创建一个secret.yaml文件内容用base64编码

[root@master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm

yaml文件内容

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

创建

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

解析Secret中内容

[root@master ~]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
kind: Secret
metadata:
  creationTimestamp: 2016-01-22T18:41:56Z
  name: mysecret
  namespace: default
  resourceVersion: "164619"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque

base64解码

[root@master ~]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
1f2d1e2e67df

4.使用Secret

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

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

创建一个Secret多个Pod可以引用同一个Secret

修改Pod的定义在spec.volumes[]加一个volume给这个volume起个名字spec.volumes[].secret.secretName记录的是要引用的Secret名字在每个需要使用Secret的容器中添加一项spec.containers[].volumeMounts[]指定spec.containers[].volumeMounts[].readOnly = truespec.containers[].volumeMounts[].mountPath要指向一个未被使用的系统路径

修改镜像或者命令行使系统可以找到上一步指定的路径。此时Secret中data字段的每一个key都是指定路径下面的一个文件名

6.Pod中引用Secret的列子

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"  //这里是pod内部的目录
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret

pod里面查看

[root@master ~]# kubectl  exec -it mypod /bin/bash
root@mypod:/# cd /etc/foo/
root@mypod:/etc/foo# ls
password  username

每一个被引用的Secret都要在spec.volumes中定义

映射secret key到指定的路径

可以控制secret key被映射到容器内的路径利用spec.volumes[].secret.items来修改被映射的具体路径

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

username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username

password没有变

从volume中读取secret的值

值得注意的一点是以文件的形式挂载到容器中的secret他们的值已经是经过base64解码的了可以直接读出来使用

[root@master ~]# ls /etc/foo/
username
password
[root@master ~]# cat /etc/foo/username
admin
[root@master ~]# cat /etc/foo/password
1f2d1e2e67df

被挂载的secret内容自动更新

也就是如果修改一个Secret的内容那么挂载了该Secret的容器中也将会取到更新后的值

7.环境变量的形式使用Secret

创建一个Secret多个Pod可以引用同一个Secret

修改pod的定义定义环境变量并使用env[].valueFrom.secretKeyRef指定secret和相应的key

修改镜像或命令行,让它们可以读到环境变量

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

容器中读取环境变量已经是base64解码后的值了

[root@master ~]# echo $SECRET_USERNAME
admin
[root@master ~]# echo $SECRET_PASSWORD
1f2d1e2e67df

8.案例

Pod中的ssh keys,创建一个包含ssh keys的secret

[root@master ~]# kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/path/to/.ssh/id_rsa --from-file=ssh-publickey=/path/to/.ssh/id_rsa.pub

创建一个Pod其中的容器可以用volume的形式使用ssh keys

kind: Pod
apiVersion: v1
metadata:
  name: secret-test-pod
  labels:
    name: secret-test
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: ssh-key-secret
  containers:
  - name: ssh-test-container
    image: daocloud.io/library/nginx
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"

9.k8s集群连接harbor私有仓库

使用命令创建一个secret

--docker-server 是私有仓库地址

--docker-username 是私有仓库用户名

--docker-password 是私有仓库对用用户名的密码

[root@master ~]# kubectl create secret docker-registry regcred --docker-server=10.11.67.119 --docker-username=diange --docker-password=QianFeng@123

创建pod的yaml文件

[root@master ~]# cat nginx.yaml 
apiVersion: v1
kind: Pod
metadata:
  name: xingdian
  labels:
    app: xingdian
spec:
  containers:
    - name: diandian
      image: 10.11.67.119/xingdian/nginx@sha256:2963fc49cc50883ba9af25f977a9997ff9af06b45c12d968b7985dc1e9254e4b 
      ports:
      - containerPort: 80
  imagePullSecrets:
    - name: regcred

创建pod

[root@master ~]# kubectl create -f nginx.yaml

查看pod

[root@master ~]# kubectl get pods
NAME       READY   STATUS    RESTARTS   AGE
xingdian   1/1     Running   0          10m

注意:

保证docker可以使用http连接下载默认是https

修改docker启动文件
[root@master ~]# vim /etc/systemd/system/multi-user.target.wants/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry 10.0.1.13 --containerd=/run/containerd/containerd.sock
[root@master ~]# systemctl daemon-reload
[root@master ~]# systemctl restart docker