简介
ConfigMap是用来存储一些非安全的配置信息,如果涉及到一些安全相关的数据的话用ConfigMap就非常不妥了,
因为ConfigMap明文存储的,这个时候j就应该使用Secret
-
Secret 对象类型用来保存敏感信息,例如密码、OAuth 令牌和 ssh key。
-
敏感信息放在 secret 中比放在 Pod 的定义或者容器镜像中来说更加安全和灵活。
-
Pod 可以用两种方式使用 secret:
- 作为 volume 中的文件被挂载到 pod 中的一个或者多个容器里。
- 当 kubelet 为 pod 拉取镜像时使用(仓库认证信息)。
-
Secret的类型:
- Service Account:Kubernetes 自动创建包含访问 API 凭据的 secret,并自动修改pod 以使用此类型的 secret。
- Opaque:使用base64编码存储信息,可以通过base64 --decode解码获得原始数据,因此安全性弱。
- kubernetes.io/dockerconfigjson:用于存储docker registry的认证信息。
Service Account
[root@server2 manifest]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 7h52m
default-token-j7pl7 kubernetes.io/service-account-token 3 12d /其实就是个token
tls-secret kubernetes.io/tls 2 26h
运行在pod里的进程需要调用Kubernetes API
以及非Kubernetes API
的其它服务。Service Account它并不是给kubernetes集群的用户使用的,而是给pod里面的进程使用的,它为pod提供必要的身份认证,让它可以通过apiserver
获取信息。
- 每个namespace下有一个名为
default
的默认的ServiceAccount
对象:
[root@server2 manifest]# kubectl get sa --all-namespaces
NAMESPACE NAME SECRETS AGE
default default 1 12d
ingress-nginx default 1 29h
ingress-nginx ingress-nginx 1 29h
ingress-nginx ingress-nginx-admission 1 29h
kube-node-lease default 1 12d
kube-public default 1 12d
kube-system attachdetach-controller 1 12d
[root@server2 manifest]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-j7pl7 /可以挂载的secret
Tokens: default-token-j7pl7 /token就是一个secret
Events: <none>
- serviceaccout 创建时 Kubernetes 会默认创建对应的 secret。对应的 secret 会自动挂载到Pod 的 /run/secrets/kubernetes.io/serviceaccount 目录中。
# 进入pod中查看secret的挂载信息。
[root@server2 manifest]# kubectl exec my-nginx-7f45d597d5-n7jft -- ls /var/run/secrets/kubernetes.io/serviceaccount
ca.crt
namespace
token /里面有证书,命名空间和token等信息。
- ServiceAccount里有一个名为Tokens的可以作为Volume一样被Mount到Pod里的Secret,当Pod启动时这个Secret会被自动Mount到Pod的指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权过程。
[root@server2 manifest]# kubectl describe pod my-nginx-7f45d597d5-n7jft
Mounts:
/etc/nginx/conf.d from config-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-j7pl7 (ro)
//secret挂载到了这里
default-token-j7pl7: //secret 就是 sa 里面的一个token
Type: Secret (a volume populated by a Secret)
SecretName: default-token-j7pl7
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Opaque Secret
Opaque使用base64编码存储信息,其value为base64编码后的值。我们需要自行创建。
我们在做ingress的 basic-auth 其实就是一个opaque 类型的secret:
[root@server2 manifest]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 7h52m //这个
default-token-j7pl7 kubernetes.io/service-account-token 3 12d
tls-secret kubernetes.io/tls 2 26h
命令行创建secret:
[root@server2 ~]# kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password=S\!B\\*d\$zDsb
secret/dev-db-secret created
[root@server2 ~]# kubectl get secrets
NAME TYPE DATA AGE
dev-db-secret Opaque 2 2s
注意如果密码具有特殊字符,则需要使用 \ 字符对其进行转义
在文件中创建secret:
[root@server2 ~]# echo -n 'admin' > ./username.txt
[root@server2 ~]# echo -n 'westos' > ./password.txt
[root@server2 ~]# kubectl create secret generic db-user-pass --from-file=./username.txt --from-file=./password.txt
kubesecret/db-user-pass created
[root@server2 ~]# kubectl get secrets
NAME TYPE DATA AGE
db-user-pass Opaque 2 4s
默认情况下 kubectl get和kubectl describe 为了安全是不会显示密码的内容,可以通过以下方式查看:
[root@server2 ~]# kubectl get secrets dev-db-secret -o yaml
apiVersion: v1
data:
password: UyFCXCpkJHpEc2I=
username: ZGV2dXNlcg==
kind: Secret
metadata:
creationTimestamp: "2020-07-01T09:12:14Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:password: {}
f:username: {}
f:type: {}
manager: kubectl
operation: Update
time: "2020-07-01T09:12:14Z"
name: dev-db-secret
namespace: default
resourceVersion: "478900"
selfLink: /api/v1/namespaces/default/secrets/dev-db-secret
uid: e08f8d85-c4ac-4e82-a177-ab70a0e55c1e
type: Opaque
[root@server2 ~]# echo UyFCXCpkJHpEc2I= |base64 -d
S!B\*d$zDsb
[root@server2 ~]# echo ZGV2dXNlcg== |base64 -d
devuser //进行转换就出来了
yaml清单secret
[root@server2 ~]# echo admin |base64
YWRtaW4K
[root@server2 ~]# echo caoaoyuan |base64
Y2FvYW95dWFuCg==
[root@server2 ~]# vim mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: Y2FvYW95dWFuCg==
[root@server2 cm]# kubectl apply -f mysecret.yaml
kubec gsecret/mysecret created
[root@server2 cm]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 8h
db-user-pass Opaque 2 10m
default-token-j7pl7 kubernetes.io/service-account-token 3 12d
dev-db-secret Opaque 2 9m10s
mysecret Opaque 2 6s //这个
将Secret挂载到Volume中:
[root@server2 cm]# vim mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: Y2FvYW95dWFuCg==
---
apiVersion: v1
kind: Pod
metadata:
name: mysecret
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: secrets
mountPath: "/secret" /挂接到这个位置,pod会自动创建
readOnly: true
volumes:
- name: secrets
secret:
secretName: mysecret
[root@server2 cm]# kubectl apply -f mysecret.yaml
secret/mysecret unchanged
pod/mysecret created
[root@server2 cm]# kubectl exec mysecret -- ls /secret
password
username
[root@server2 cm]# kubectl exec mysecret -- cat /secret/password
caoaoyuan
[root@server2 cm]# kubectl exec mysecret -- cat /secret/username
admin
就挂接进去了。
向指定路径映射 secret 密钥:
[root@server2 cm]# vim mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: Y2FvYW95dWFuCg==
---
apiVersion: v1
kind: Pod
metadata:
name: mysecret
spec:
containers:
- name: nginx
image: nginx
volumeMounts:
- name: secrets
mountPath: "/secret"
readOnly: true
volumes:
- name: secrets
secret:
secretName: mysecret
items:
- key: username /选择mysecret中的username这个key
path: my-group/my-username /将它挂载道这个位置
[root@server2 cm]# kubectl apply -f mysecret.yaml
secret/mysecret created
pod/mysecret created
[root@server2 cm]# kubectl exec mysecret -- ls /secret/
my-group
[root@server2 cm]# kubectl exec mysecret -- ls /secret/my-group
my-username
[root@server2 cm]# kubectl exec mysecret -- cat /secret/my-group/my-username
admin
可以看出值有指定的数据挂接到了这里。
将Secret设置为环境变量:
[root@server2 cm]# vim mysecret.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: Y2FvYW95dWFuCg==
---
apiVersion: v1
kind: Pod
metadata:
name: secret-env
spec:
containers:
- name: nginx
image: nginx
env:
- name: SECRET_USERNAME /自己定义名称
valueFrom:
secretKeyRef:
name: mysecret /调用secret的值
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
[root@server2 cm]# kubectl apply -f mysecret.yaml
secret/mysecret unchanged
pod/secret-env created
[root@server2 cm]# kubectl exec secret-env -- env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=secret-env
SECRET_PASSWORD=caoaoyuan
SECRET_USERNAME=admin
KUBERNETES_SERVICE_PORT_HTTPS=443
HOME=/root
环境变量读取Secret很方便,但是无法支撑Secret动态更新。
kubernetes.io/dockerconfigjson
kubernetes.io/dockerconfigjson 类型的secret 用于存储 docker registry 的认证信息.
我们目前用的私有仓库是harbor仓库,我们现在有一个未公开的仓库,里面又一个镜像:
现在我们去拉取:
[root@server3 ~]# docker pull reg.caoaoyuan.org/caoaoyuan/game2048
Using default tag: latest
Error response from daemon: pull access denied for reg.caoaoyuan.org/caoaoyuan/game2048, r
是被拒绝的我们值有登陆进去才能拉取:
[root@server3 ~]# docker login reg.caoaoyuan.org
Username: admin
Password:
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
[root@server3 ~]# docker pull reg.caoaoyuan.org/caoaoyuan/game2048
Using default tag: latest
latest: Pulling from caoaoyuan/game2048
534e72e7cedc: Pull complete
f62e2f6dfeef: Pull complete
fe7db6293242: Pull complete
3f120f6a2bf8: Pull complete
4ba4e6930ea5: Pull complete
Digest: sha256:8a34fb9cb168c420604b6e5d32ca6d412cb0d533a826b313b190535c03fe9390
Status: Downloaded newer image for reg.caoaoyuan.org/caoaoyuan/game2048:latest
reg.caoaoyuan.org/caoaoyuan/game2048:latest
而我们登陆的信息保存在用户主目录下的 .docker 下:
[root@server3 ~]# cd .docker/
[root@server3 .docker]# cat config.json
{
"auths": {
"reg.caoaoyuan.org": {
"auth": "YWRtaW46Y2FvYW95dWFu"
}
},
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.11 (linux)"
}
[root@server3 .docker]# docker rmi reg.caoaoyuan.org/caoaoyuan/game2048:latest
// 先删除镜像
[root@server3 .docker]# docker logout //退出
[root@server3 .docker]# cat config.json
{
"auths": {},
"HttpHeaders": {
"User-Agent": "Docker-Client/19.03.11 (linux)"
}
这种方式是一种不安全且不够灵活的方式,我们可以通过kubernetes.io/dockerconfigjson 类型的secret 来实现简化
手动创建:
[root@server2 cm]# kubectl create secret docker-registry myregistrykey \ /secret 名称
--docker-server=reg.caoaoyuan.org \ /仓库地址
--docker-username=admin --docker-password=caoaoyuan \ /仓库的用户密码
[email protected] /用户邮箱
secret/myregistrykey created
[root@server2 cm]# kubectl get secrets
NAME TYPE DATA AGE
basic-auth Opaque 1 9h
db-user-pass Opaque 2 98m
default-token-j7pl7 kubernetes.io/service-account-token 3 13d
dev-db-secret Opaque 2 97m
myregistrykey kubernetes.io/dockerconfigjson 1 94s
使用:
[root@server2 cm]# cat pod.yml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: game2048
image: reg.caoaoyuan.org/caoaoyuan/game2048
imagePullSecrets:
- name: myregistrykey
secret/myregistrykey created
[root@server2 cm]# kubectl apply -f pod.yml
pod/mypod created
[root@server2 cm]# kubectl get pod
NAME READY STATUS RESTARTS AGE
my-nginx-7f45d597d5-n7jft 1/1 Running 0 4h19m
mypod 1/1 Running 0 9s
/注意这时我们并没有docker login。