《kubernetes-1.8.0》19-examples-secrets

《kubernetes-1.8.0》19-examples-secrets

《kubernetes 1.8.0 测试环境安装部署》

时间:2017-12-15

一、基础知识:

secrets是用来保存类似于密码、token、key等敏感信息的。将这些敏感信息放在secrets里比直接放在pod或者docker镜像中更安全和灵活。

创建:用户能够创建secrets,同时系统也会自动创建一些secrets(内建secrets)

使用:一个secrets能够被两种方式使用: 通过volume 挂载到一个或者多个容器中,或者在kubelet pull docker镜像的时候使用(需要login的docker仓库)

Build-in Secrets(内建secrets):
这个主要是关联Service Account使用,当创建一个SA的时候将自动关联一个secrets,如果想通过某个sa账户访问apiserver可通过该secrets进行验证;

二、创建自定义secrets:

kubectl create secret创建secrets:

要是一些pod需要访问数据库,用户名和密码保存在本机的./username.txt./password.txt文件中

创建所需的文件:

$ mkdir ~/secret-examle
$ cd ~/secret-examle
$ echo -n "admin" > ./username.txt
$ echo -n "1f2d1e2e67df" > ./password.txt

使用kubectl create secret打包这些文件到secrets

$ kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
secret "db-user-pass" created
  • generic :表明从本地文件,目录,或者键值对创建,还可以使用docker-registry以及tls
  • docker-registry:Create a secret for use with a Docker registry
  • tls:Create a TLS secret

查看:

[root@node-131 secret-examle]# kubectl get secrets
NAME                         TYPE                                  DATA      AGE
...
db-user-pass                 Opaque                                2         15s
...

[root@node-131 secret-examle]# kubectl describe  secrets db-user-pass 
Name:         db-user-pass
Namespace:    default
Labels:       
Annotations:  

Type:  Opaque

Data
====
password.txt:  12 bytes
username.txt:  5 bytes
  • 从查看的结果可以发现不管是get还是describe都没显示文件的内容,保护secrets意外暴露或者通过终端日志暴露

手工创建一个secrets

能够通过yaml或者json文件创建secrets

先获取username和password的base64编码:

$ echo -n "admin" | base64
YWRtaW4=
$ echo -n "1f2d1e2e67df" | base64
MWYyZDFlMmU2N2Rm

创建secrets的yaml:

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  username: YWRtaW4=
  password: MWYyZDFlMmU2N2Rm
  • data部分的value为base64加密过的数据
  • Opaque:base64编码格式的Secret,用来存储密码、密钥等;

应用yaml:

$ kubectl create -f ./secret.yaml
secret "mysecret" created

查看:

[root@node-131 secret-examle]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
  password: MWYyZDFlMmU2N2Rm
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: 2017-12-15T06:49:21Z
  name: mysecret
  namespace: default
  resourceVersion: "3418648"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: 14c9804b-e164-11e7-8e94-005056bc80ed
type: Opaque

decode:

$ echo "MWYyZDFlMmU2N2Rm" | base64 --decode
1f2d1e2e67df

secrets能够被以data volume的方式挂载或者以环境变量的方式暴露在pod中的container。也可以用在系统的其他方面,比如可以保存用于系统其他部分的交互证书;

以文件的方式在pod中使用secrets:

  1. 创建secrets或者使用现有的,多个pods可以关联同一个secrets
  2. 修改pod的配置,在spec.volumes[]部分添加,名字任意,配置spec.volumes[].secret.secretName 为 对应secrets对象的名字
  3. 在每个需要secretscontainer添加spec.containers[].volumeMounts[] 部分, 注明spec.containers[].volumeMounts[].readOnly = true以及注明spec.containers[].volumeMounts[].mountPath 到一个想防止secrets以及未使用的目录名.
  4. 修改镜像或者命令行,使得程序能够去挂载点下找对应的文件,在secrets的data下的每个key都被映射成一个挂载点下的一个文件名。

例子1:挂载secrets到一个volume:

mysecret.yaml

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
  • 所有用到的secrets 放在spec.volumes
  • 如果在pod中有多个container,则每个container需要各自的volumeMounts,而每个secrets只需要一个spec.volumes

应用并查看:

[root@node-131 secret-examle]# kubectl create -f mysecret.yaml 
pod "mypod" created

[root@node-131 secret-examle]# kubectl exec  mypod ls /etc/foo/ 
password  username
[root@node-131 secret-examle]# kubectl exec  mypod cat /etc/foo/password 
1f2d1e2e67df
[root@node-131 secret-examle]# kubectl exec  mypod cat /etc/foo/username
admin

将secrets的key映射至指定路径:

mysecret.yaml

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:这个key将被存放在/etc/foo/my-group/my-username目录下
  • password:这个key将不会被映射
  • 一旦声明了spec.volumes[].secret.items部分,所有想要被映射的key都必须列出来,否则将不比被挂载到指定的目录下

应用并查看:

[root@node-131 secret-examle]# kubectl delete pod mypod
pod "mypod" deleted
##terminating后

[root@node-131 secret-examle]# kubectl create -f mysecret.yaml 
pod "mypod" created

[root@node-131 secret-examle]# kubectl exec mypod ls /etc/foo/
my-group

[root@node-131 secret-examle]# kubectl exec mypod cat /etc/foo/my-group/my-username
admin

设置secrets文件的权限

可以单独设置secrets的权限mode bit,如果没有特别设置,缺省权限为0644,json不支持八进制,所以用256 表示 0400.511表示 0777以此类推;

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      defaultMode: 256
  • defaultMode: 256 :表示设置挂载点下所有文件权限为0400

应用并查看:

[root@node-131 secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/ 
total 0
lrwxrwxrwx 1 root root 15 Dec 15 09:06 password -> ..data/password
lrwxrwxrwx 1 root root 15 Dec 15 09:06 username -> ..data/username
[root@node-131 secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/..data/username
-r-------- 1 root root 5 Dec 15 09:06 /etc/foo/..data/username
  • 注意这边挂载点目录下的文件为符号链接,真实文件在挂载点下的..data/

mysecret.yaml

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      items:
      - key: username
        path: my-group/my-username
        mode: 511
  • mode: 511:设置单个secrets文件的权限为 0700

查看:

[root@node-131 secret-examle]# kubectl exec -ti mypod -- ls -l /etc/foo/..data/my-group/my-username         
-rwxrwxrwx 1 root root 5 Dec 15 09:36 /etc/foo/..data/my-group/my-username

以环境变量的方式在pod中使用secrets:

通过修改env[].valueFrom.secretKeyRef将secrets映射至pod中的环境变量

mysecret.yaml

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
  • env.name:变量名
  • env[].valueFrom.secretKeyRef.name:secret名
  • env[].valueFrom.secretKeyRef.name:secret的data中的哪个key

应用并查看:

[root@node-131 secret-examle]# kubectl exec -ti  secret-env-pod bash
root@secret-env-pod:/data# echo $SECRET_USERNAME
admin
root@secret-env-pod:/data# echo $SECRET_PASSWORD
1f2d1e2e67df

创建用来imagepull的 secrets:

  1. 用kubelet命令创建
$ 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.
  1. 用yaml文件创建

首先本地用docker login进行登录,登录成功后,将在当前用户的宿主目录下创建~/.docker/config.json

用base64将~/.docker/config.json加密

[root@node-131 secret-examle]# cat ~/.docker/config.json  | base64 -w 0
ewoJImFJImF1dGgiOiAiWVdSdGFXNDZRV3hoWkdsdV.....S4wLWNlIChsaW51eCkiCgl9Cn0=

编辑yaml文件

myregistrykey.yaml

apiVersion: v1
kind: Secret
metadata:
  name: myregistrykey
  namespace: default
data:
  .dockerconfigjson: ewoJImFJImF1dGgiOiAiWVdSdGFXNDZRV3hoWkdsdV.....S4wLWNlIChsaW51eCkiCgl9Cn0=
type: kubernetes.io/dockerconfigjson
  • .dockerconfigjson :将base64加密后的那串东西填到这里
  • type: kubernetes.io/dockerconfigjson

创建并查看:

[root@node-131 secret-examle]# kubectl create -f   myregistrykey.yaml
secret "myregistrykey" created
[root@node-131 secret-examle]# kubectl describe secret myregistrykey
Name:         myregistrykey
Namespace:    default
Labels:       
Annotations:  

Type:  kubernetes.io/dockerconfigjson

Data
====
.dockerconfigjson:  155 bytes

创建一个pod测试

foo.yaml

apiVersion: v1
kind: Pod
metadata:
  name: foo
  namespace: default
spec:
  containers:
    - name: foo
      image: 172.18.169.134/elk/elasticsearch:v5.6.4
  imagePullSecrets:
    - name: myregistrykey
  • image: 172.18.169.134/elk/elasticsearch:v5.6.4:根据自己的环境修改

前提条件是做了私有仓库,并设置项目为私有,即必须通过登录才能够pull;

应用yaml并查看:

[root@node-131 secret-examle]# kubectl describe pod foo   
Name:         foo
Namespace:    default
Node:         node.131/172.18.169.131
...
Events:
  Type    Reason                 Age   From               Message
  ----    ------                 ----  ----               -------
  Normal  Scheduled              6s    default-scheduler  Successfully assigned foo to node.131
  Normal  SuccessfulMountVolume  6s    kubelet, node.131  MountVolume.SetUp succeeded for volume "default-token-t8j7k"
  Normal  Pulling                5s    kubelet, node.131  pulling image "172.18.169.134/elk/elasticsearch:v5.6.4"
  Normal  Pulled                 5s    kubelet, node.131  Successfully pulled image "172.18.169.134/elk/elasticsearch:v5.6.4"
  Normal  Created                5s    kubelet, node.131  Created container
  Normal  Started                5s    kubelet, node.131  Started container

其他一些细节:
* secrets 必须在所应用的pod之前先创建
* secrets 必须和所应用的pod在同一个namespace
* secrets 大小必须效益1MB


用例:带有ssh key的pod

创建一个secret 包含本机的ssh key:

[root@node-131 secret-examle]# kubectl create secret generic ssh-key-secret --from-file=ssh-privatekey=/root/.ssh/id_rsa --from-file=ssh-publickey=/root/.ssh/id_rsa.pub
secret "ssh-key-secret" created
  • 注意,测试环境满搞搞,正式环境不推荐,将暴露登陆信息至群集中

创建pod

secret-test-pod.yaml

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: redis
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"

应用并测试:

[root@node-131 secret-examle]# kubectl exec  secret-test-pod cat /etc/secret-volume/ssh-publickey
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDOB8IMzTYPcRb9h2pVoMNBI2Fy5EYPjXOEg11FyI1ffeo+C... root@node-131

[root@node-131 secret-examle]# kubectl exec  secret-test-pod cat /etc/secret-volume/ssh-privatekey
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAzgfCDM02D3EW/YdqVaDDQSNhcuRGD41zhINdRciNX33qPglK
Npks8CIresIAbPdBDc4P6FO0MncuVAoXZVOE4xOUYTcmnXkncwHp6amATMtJNFTc
OSzejJIokVQn9e7nmREU2bCTSUtlnR6804XNm78Tmh9P7dyI863OWEVdGdBKZFFz
G...

后续这个container可以用这个建立与宿主机的ssh链接


用例:使用区分正式环境和测试环境认证信息的pod

这个例子说明了其中一个pod使用正式的认证信息,另一个pod使用测试环境的认证信息:

$ kubectl create secret generic prod-db-secret --from-literal=username=produser --from-literal=password=Y4nys7f11
secret "prod-db-secret" created
$ kubectl create secret generic test-db-secret --from-literal=username=testuser --from-literal=password=iluvtests
secret "test-db-secret" created

创建pod:

apiVersion: v1
kind: List
items:
- kind: Pod
  apiVersion: v1
  metadata:
    name: prod-db-client-pod
    labels:
      name: prod-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: prod-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
- kind: Pod
  apiVersion: v1
  metadata:
    name: test-db-client-pod
    labels:
      name: test-db-client
  spec:
    volumes:
    - name: secret-volume
      secret:
        secretName: test-db-secret
    containers:
    - name: db-client-container
      image: myClientImage
      volumeMounts:
      - name: secret-volume
        readOnly: true
        mountPath: "/etc/secret-volume"
  • 有两个pod,用不同的用户名口令访问数据库
  • 太麻烦了这里就不做了 ^ ^

预期的效果是:

两个不同的pod将拥有两个不同的secrets file(内容):

/etc/secret-volume/username
/etc/secret-volume/password

用例:创建隐藏的secret volume(.file)

kind: Secret
apiVersion: v1
metadata:
  name: dotfile-secret
data:
  .secret-file: dmFsdWUtMg0KDQo=
---
kind: Pod
apiVersion: v1
metadata:
  name: secret-dotfiles-pod
spec:
  volumes:
  - name: secret-volume
    secret:
      secretName: dotfile-secret
  containers:
  - name: dotfile-test-container
    image: gcr.io/google_containers/busybox
    command:
    - ls
    - "-l"
    - "/etc/secret-volume"
    volumeMounts:
    - name: secret-volume
      readOnly: true
      mountPath: "/etc/secret-volume"
  • 关键就在.secret-file,用.开头的方式创建secret的keyname,后续被挂载的时候也将被挂载成’.’开头的文件。。
  • 貌似用ls看不了,用ls -a 一样可以看到。。算是隐藏吧
  • 挺无聊的,也不做了 ^ ^

最后再生产环境需要注意apiserver访问权限对secrets的控制,watchlist 将能够看到secret的值,拥有get请求就可以利用secret进行相关的使用了。

至此secrets 部分算是写完了。。

本系列其他内容:

  • 01-环境准备

  • 02-etcd群集搭建

  • 03-kubectl管理工具

  • 04-master搭建

  • 05-node节点搭建

  • 06-addon-calico

  • 07-addon-kubedns

  • 08-addon-dashboard

  • 09-addon-kube-prometheus

  • 10-addon-EFK

  • 11-addon-Harbor

  • 12-addon-ingress-nginx

  • 13-addon-traefik

参考资料:

https://kubernetes.io/docs/concepts/configuration/secret/

你可能感兴趣的:(kubernetes,secret,kubernetes,1.8.0)