K8s 安全抽象:Secret

欢迎访问博客原文

Secret 是对敏感信息的抽象,例如:密码、token、SSH key,其他对象可引用Secret。

Pod 使用 Secret 有两种场景:

  • 作为 volume 中的文件被挂载到 Pod 中一个或多个容器中
  • 拉取镜像时需要使用 secret 作为安全凭证

Secret 分类

Secret 可分为三类:

  • docker-registry: 创建一个给 Docker Registry 使用的 secret,实际是保存了账户密码。
  • generic:从本地 file, directory 或者 literal value 创建一个 secret。
  • tls:创建一个 TLS secret。

创建 generic secret

通过 literal(字面量)创建

创建一个order数据库的secret,包含账户密码两个字段。

kubectl create secret generic db-order-secret --from-literal=username=admin --from-literal=password=123456

literal 中若包含特殊字符则需要进行转义,如"123456!" 需设置为 “123456​\!”

查看secret,describe secret db-order-secret,查看时隐藏了字段值,仅展示了字节数。

对应的API对象为 Opaque([oʊˈpeɪk]),译为"不透明物",等同于"敏感数据"。

Name:         db-order-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  6 bytes
username:  5 bytes

再看看其yaml形态:

kubectl get secret db-order-secret -o yaml

其中字段是base64编码后的值。

apiVersion: v1
data:
  password: MTIzNDU2
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: "2020-03-14T04:21:29Z"
  name: db-order-secret
  namespace: default
  resourceVersion: "28023453"
  selfLink: /api/v1/namespaces/default/secrets/db-order-secret
  uid: 5c60f906-ec8e-4277-8b96-caa75ef6589a
type: Opaque

解码password字段,值为123456

$ echo MTIzNDU2 | base64 --decode
123456

通过文件创建

在当前目录创建一个RSA 公私钥对作为例子。

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): ./id_rsa
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in ./id_rsa.
Your public key has been saved in ./id_rsa.pub.

将私钥创建为secret,公钥可分发给另一方。

kubectl create secret generic rsa-key-secret --from-file=./id_rsa

通过yaml创建

通过yaml提供元数据以创建secret,字段需用base64先编码,如: echo -n admin | base64

apiVersion: v1
kind: Secret
metadata:
  name: db-user-secret
type: Opaque
data:
  username: YWRtaW4=
  password: MTIzNDU2

然后创建Secret即可。

kubectl apply -f ./secret.yaml

Pod 中应用Secret

下面的例子演示了Secret 的三种应用方式。

  • 作为volume直接挂载,在容器中可直接使用
  • 在环境变量中使用secret
  • 向特定目录映射secret

下面是Pod yaml。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    env:
      - name: SECRET_USERNAME
      # 使用secret 做环境变量
        valueFrom:
          secretKeyRef:
            name: db-user-secret
            key: username
    volumeMounts:
    # 将secret作为volume挂载
    - name: volume1
      mountPath: "/etc/foo1"
      readOnly: true
    # 向特定目录映射secret  
    - name: volume2
      mountPath: "/etc/foo2"
      readOnly: true
  volumes:
  - name: volume1
    secret:
      secretName: db-user-secret
  - name: volume2
    secret:
      secretName: db-user-secret
      items:
      - key: username
        path: usernameFile

创建Pod,然后进入Pod验证效果。

  • 做环境变量
      - name: SECRET_USERNAME
        valueFrom:
          secretKeyRef:
            name: db-user-secret
            key: username

结果如下:

$ env | grep SECRET_USERNAME
SECRET_USERNAME=admin
  • 挂载到容器
    volumeMounts:
    - name: volume1
      mountPath: "/etc/foo1"
      readOnly: true

效果如下:

$ ls -l /etc/foo1
total 0
lrwxrwxrwx 1 root root 15 Mar 14 07:49 password -> ..data/password
lrwxrwxrwx 1 root root 15 Mar 14 07:49 username -> ..data/username
  • 向特定目录映射secret
spec:
    volumeMounts:
    - name: volume2
      mountPath: "/etc/foo2"
      readOnly: true
  volumes:
  - name: volume2
    secret:
      secretName: db-user-secret
      items:
      - key: username
        path: usernameFile

将 username 字段映射到了 /etc/foo2/usernameFile

$ cat /etc/foo2/usernameFile
admin

创建 docker-registry secret 拉取镜像

构建、部署时需要拉取镜像,可以向Pod提供一个secret专门用于拉取镜像。

以腾讯云镜像仓库为例,ccr.ccs.tencentyun.com/easyk8s/nginx 是一个私有的demo镜像。

利用下面yaml跑一个简单Pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: ccr.ccs.tencentyun.com/easyk8s/nginx:1.17

运行后Pod Event如下,出现 Error: ErrImagePull

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aCIiPd6t-1584194450616)(https://imgcdn.chenyongjun.vip/2020/03/14/2.png)]

接下来创建一个secret专门用于拉取镜像。

kubectl create secret docker-registry registry-tecent-secret \
--docker-server=ccr.ccs.tencentyun.com \
--docker-username=name \
--docker-password=password

在 Pod 中使用 secret。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: ccr.ccs.tencentyun.com/easyk8s/nginx:1.17
  imagePullSecrets:
  - name: registry-tecent-secret

应用yaml后Pod成功创建。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-F28N8FX3-1584194450617)(https://imgcdn.chenyongjun.vip/2020/03/14/3.png)]

通过kubectl get secret registry-tecent-secret -o yaml 拿到的 registry-tecent-secret 的yaml结构如下:

apiVersion: v1
data:
  .dockerconfigjson: eyJhdXR...
kind: Secret
metadata:
  creationTimestamp: "2020-03-14T05:01:04Z"
  name: registry-tecent-secret
  namespace: default
  resourceVersion: "28027921"
  selfLink: /api/v1/namespaces/default/secrets/registry-tecent-secret
  uid: a05ae3c0-b504-448b-bc78-8c540b2dda6c
type: kubernetes.io/dockerconfigjson

其中 .dockerconfigjson 通过base64解码后可以拿到docker-registry的账户密码。

创建tls secret

存储用于SSL通讯的私钥文件和证书文件,下面以nginx为例子。

预先准备好nginx ssl 通讯所需的key和crt文件.

kubectl create secret tls nginx-ssl-secret \
--key=nginx.key \
--cert=nginx.crt

下面是 secret 的数据,其类型为:kubernetes.io/tls

$ kubectl describe secret/nginx-ssl-secret
Name:         nginx-ssl-secret
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
tls.crt:  4241 bytes
tls.key:  1679 bytes

在nginx pod 中应用该secret,作为volume映射到容器中。

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: nginx-crt
      mountPath: /etc/nginx/ssl
      readOnly: true
  volumes:
  - name: nginx-crt
    secret:
      secretName: nginx-ssl-secret

运行Pod后进入Pod查看 /etc/nginx/ssl 目录,可看到映射的证书、私钥文件,不过名字从 nginx.crt, nginx.key 变为了 tls.crt, tls.key

$ ls -l /etc/nginx/ssl/
total 0
lrwxrwxrwx 1 root root 14 Mar 14 08:42 tls.crt -> ..data/tls.crt
lrwxrwxrwx 1 root root 14 Mar 14 08:42 tls.key -> ..data/tls.key

接着可以在nginx配置中使用这两个文件完成ssl通讯配置。

常用 Secret 示意图

在这里插入图片描述


欢迎关注公众号 [陈一乐],一起学习,一起成长

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值