1. 理解Secret
Secret对象存储数据的方式是以键值方式存储数据,在Pod资源进行调用Secret的方式是通过环境变量或者存储卷的方式进行访问数据
,解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。
另外,Secret对象的数据存储和打印格式为Base64编码的字符串,因此用户在创建Secret对象时,也需要提供该类型的编码格式的数据。在容器中以环境变量或存储卷的方式访问时,会自动解码为明文格式
。需要注意的是,如果是在Master节点上,Secret对象以非加密的格式存储在etcd中,所以需要对etcd的管理和权限进行严格控制。
要使用 Secret,Pod 需要引用 Secret。 Pod 可以用三种方式之一来使用 Secret:
- 作为挂载到一个或多个容器上的 卷 中的文件。
- 作为容器的环境变量
- 由 kubelet 在为 Pod 拉取镜像时使用
Secret 对象的名称必须是合法的 DNS 子域名。 在为创建 Secret 编写配置文件时,你可以设置 data 与/或 stringData 字段。 data 和 stringData 字段都是可选的。data 字段中所有键值都必须是 base64 编码的字符串。如果不希望执行这种 base64 字符串的转换操作,你可以选择设置 stringData 字段,其中可以使用任何字符串作为其取值。
2. Secret 的类型
在创建 Secret 对象时,你可以使用 Secret 资源的 type 字段,或者与其等价的 kubectl 命令行参数(如果有的话)为其设置类型。 Secret 的类型用来帮助编写程序处理 Secret 数据。
Kubernetes 提供若干种内置的类型,用于一些常见的使用场景。 针对这些类型,Kubernetes 所执行的合法性检查操作以及对其所实施的限制各不相同。
通过为 Secret 对象的 type 字段设置一个非空的字符串值,你也可以定义并使用自己 Secret 类型。如果 type 值为空字符串,则被视为 Opaque 类型。 Kubernetes 并不对类型的名称作任何限制。不过,如果你要使用内置类型之一, 则你必须满足为该类型所定义的所有要求。
3. Service Account
Kubernetes 在创建 Pod 时会自动创建一个服务账号 Secret 并自动修改你的 Pod 以使用该 Secret。该服务账号令牌 Secret 中包含了访问 Kubernetes API 所需要的凭据。
Service Account 用来访问kubernetes API,由Kubernetes自动创建,并且会自动挂载到Pod的/run/secrets/http://kubernetes.io/serviceaccount目录中。
Service Account 不需要我们自己去管理的,此证书是由kubernetes自己来进行维护管理的。
# 创建pod kubectl run my-nginx --image=nginx:1.20.0 # 查看证书 kubctl exec -it podName -- bash # 进入证书目录/run/secrets/kubernetes.io/serviceaccount查看即可 ca.crt namespace token # 查看证书 # root@my-nginx:/run/secrets/kubernetes.io/serviceaccount# cat ca.crt -----BEGIN CERTIFICATE----- MIIC5zCCAc+gAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl cm5ldGVzMB4XDTIxMDUxNzA3MTgyMloXDTMxMDUxNTA3MTgyMlowFTETMBEGA1UE AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALIB eVgGvrAomjLyj4fgasSoJQoZnhpZj75wKDOg7gYFKmGb9oLX5qIj33jqmrK4bUI5 symIPTJTrNZ7FsVmeC66JiE50niMpxuD01pDJARTfc0cMgkFWDq7JsVptA7MNILT 81keKB7eOZY0Cx7c/O+9w6f6UrvpHTMgNvE6wG3StFw2YJFPhDC6ZqwduISzBIsK wbTrwp6jBHPTxsQEmEuHuoe0Hz+sjov5wXFpw7QB5V+P980tVvgK1GGX9wPxMytJ ofv3vwbvHD/DrotA6HNwdYELIEgFULXPGuO/HL4z7C2MJxqVW7UdirCdnBDtI6HB m55toVZJtmHj7kCpkzMCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB /wQFMAMBAf8wHQYDVR0OBBYEFIaXFp8Y2aneT8Wk59gysMNJxmOhMA0GCSqGSIb3 DQEBCwUAA4IBAQCuPXfqD25NJagNOoEPjXyTfWGCHHBJSqSknnz3B/KaJu7hzIwD G5c5zLQwDc/chHNjaRRZWcvOpfQfmqdhRg0EdDIa/B4cVmGa9eUs7f2XwlZuu6aw 5VOoTRZ6h/a9L4RQLxSSWTl2/AR4YeiBiU1tjfrc+gmZTObptmNLyuDfU7A4BG7U 1N8AddG4dojH2a7xbAnIKbTjTXRtLsI5aC0BPWHazwwG5NOreCauD+yVnQlw/dcw C74QaamuFeWr/K2W0pq0qcjH471xuKhOUnY02HkN7P1zOL2uIZQ613yBYNksmPZB 9AQJ9VZlD6szo0XoniWcSD0Z2J90pbFCJCUd -----END CERTIFICATE----- # 查看命名空间 root@my-nginx:/run/secrets/kubernetes.io/serviceaccount# cat namespace default # 查看token # root@my-nginx:/run/secrets/kubernetes.io/serviceaccount# cat token eyJhbGciOiJSUzI1NiIsImtpZCI6ImIyMVg2OTBtZm1jUVNWM2ZGMUI0QkQ2MzJVS0EyOER2N3NuZFpha3pRMDgifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxNjU0MzM0NzE4LCJpYXQiOjE2MjI3OTg3MTgsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJteS1uZ2lueCIsInVpZCI6IjEyNzI5NWFjLWIzN2EtNDc5Zi1hMzYwLWEzNDg4ODA0NDgxZCJ9LCJzZXJ2aWNlYWNjb3VudCI6eyJuYW1lIjoiZGVmYXVsdCIsInVpZCI6IjE5Y2ZkZmM2LThlZGMtNDNjYy05YjUxLTJlNDUzZjMwNTRhZSJ9LCJ3YXJuYWZ0ZXIiOjE2MjI4MDIzMjV9LCJuYmYiOjE2MjI3OTg3MTgsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.i-VcnUBSBGm6FlukqjgcWe50nBQNGgERoKjWhkPod5rTAIswJ9EGyUcADt-vYewT4CYb8R4SVRY53kfk2mPnaH54_b9BbHD5jixA99YxYcDc7N99UE_ySyJj13zHlPNRFgoagBKmwr2b2nXNtw5PEAKqI_lHbDI2oQfUHY_yTqUM9si6HMqGJJ7W2non44OzGnB33RAV--ZzJkr6oZBkgMesPYAwsJa4FMoCOIB8OtczQ3Yvtr7IxvMGoeSRbjcjN5A_v4p8-GpjlkbbXfMME9B04iFeZmhERQpkf6CwtnXgEtNwktYJATQ9jOE9lXLwYd4WpBr7zspmU67yuVtuqQ
4. Opaque Secret
4.1 创建示例
当 Secret 配置文件中未作显式设定时,默认的 Secret 类型是 Opaque。 当你使用 kubectl 来创建一个 Secret 时,你会使用 generic 子命令来标明 要创建的是一个 Opaque 类型 Secret。
Opaque类型的数据一个map类型,要求value是base64编码格式
# base64对用户名,密码加密效果演示 # [root@k8s-master configmap]# echo "superadmin" | base64 c3VwZXJhZG1pbgo= # [root@k8s-master configmap]# echo "passpppp" | base64 cGFzc3BwcHAK
多次加密结果都是一样的,破解很容易
# secre-test.yaml配置文件方式 apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: c3VwZXJhZG1pbgo= # 上面演示用户名加密结果 password: cGFzc3BwcHAK # 密码加密结果 # [root@k8s-master configmap]# kubectl apply -f secret-test.yaml secret/mysecret created # [root@k8s-master configmap]# kubectl get secret NAME TYPE DATA AGE default-token-cgxwv kubernetes.io/service-account-token 3 18d mysecret Opaque 2 13s # 自定义的secret类型为Opaque tls-secret kubernetes.io/tls 2 8d
4.2 使用方式一:作为挂载到一个或多个容器上的 卷 中的文件
# 将secret挂载到volume中 # secret-in-volume.yaml apiVersion: v1 kind: Pod metadata: name: secret-test labels: name: secret-test spec: containers: - name: nginx-secret-volume image: nginx:1.20.0 imagePullPolicy: IfNotPresent volumeMounts: - name: myvolsecrets mountPath: "/etc/secrets" # 容器挂载数据卷,挂载到/etc/secrets目录下 readOnly: true volumes: # 引入一个数据卷 - name: myvolsecrets secret: # 挂载指定的secret secretName: mysecret # [root@k8s-master configmap]# kubectl apply -f secret-in-volume.yaml pod/secret-test created # [root@k8s-master configmap]# kubectl get pods NAME READY STATUS RESTARTS AGE secret-test 1/1 Running 0 3m1s # 进入容器 [root@k8s-master configmap]# kubectl exec -it secret-test -n default -- bash # 切换路径 # root@secret-test:/# cd /etc/secrets/ # 查看挂载文件 # root@secret-test:/etc/secrets# ls password username # 查看文件内容--文件内容已自动解析为明文 # root@secret-test:/etc/secrets# cat password username passpppp superadmin
4.3 使用方式二:作为容器的环境变量
# 将secret导出到环境变量中 # vim secret-to-env.yaml apiVersion: apps/v1 kind: Deployment metadata: name: secret-to-envdeployment spec: replicas: 2 selector: matchLabels: app: pod-secret-to-env template: metadata: labels: app: pod-secret-to-env spec: containers: - name: secret-to-envdeployment image: nginx:1.20.0 imagePullPolicy: IfNotPresent ports: - containerPort: 80 env: # 设置环境变量 - name: TEST_USER valueFrom: secretKeyRef: # 核心在这里 secretKeyRef name: mysecret # secret名称 key: username # key的名称 - name: TEST_PASSWORD valueFrom: secretKeyRef: name: mysecret key: password # [root@k8s-master configmap]# kubectl apply -f secret-to-env.yaml deployment.apps/secret-to-envdeployment created # [root@k8s-master configmap]# kubectl get pods NAME READY STATUS RESTARTS AGE secret-to-envdeployment-67b9584f69-tmlzf 1/1 Running 0 9s # 进入容器 # [root@k8s-master configmap]# kubectl exec -it pod/secret-to-envdeployment-67b9584f69-tmlzf -n default -- bash # 打印环境变量 # root@secret-to-envdeployment-67b9584f69-tmlzf:/# echo ${TEST_USER} superadmin # root@secret-to-envdeployment-67b9584f69-tmlzf:/# echo ${TEST_PASSWORD} passpppp