secret用来保存小片敏感数据的k8s资源,例如密码,token,或者秘钥。这类数据当然也可以存放在Pod或者镜像中,但是放在Secret中是为了更方便的控制如何使用数据,并减少暴露的风险。
?
?用户可以创建自己的secret,系统也会有自己的secret。
?Pod需要先引用才能使用某个secret
Pod使用secret方式:
作为volume的一个域被一个或多个容器挂载?
內建的Secrets:
由ServiceAccount创建的API证书附加的秘钥k8s自动生成的用来访问apiserver的Secret,所有Pod会默认使用这个Secret与apiserver通信?
创建自己的Secret:
方式1:使用kubectl create secret命令
方式2:yaml文件创建Secret?
创建Secret
假如某个Pod要访问数据库,需要用户名密码,现在我们分别设置这个用户名和密码 Secret 对象要求这些数据必须是经过 Base64 转码的,以免出现明文密码显示的安全隐患。
# 创建一个secret.yaml文件,内容用base64编码:明文显示容易被别人发现,这里先转码。
[root@kub-k8s-master ~]# echo -n 'admin' | base64
YWRtaW4=
[root@kub-k8s-master ~]# echo -n '1f2d1e2e67df' | base64
MWYyZDFlMmU2N2Rm
创建一个secret.yaml文件,内容用base64编码
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque #模糊
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
?创建:
[root@kub-k8s-master prome]# kubectl apply -f secret.yml
secret/mysecret created
?解析Secret中内容,还是经过编码的---需要解码
# 查看secret
[root@kub-k8s-master ~]# kubectl get secrets
NAME TYPE DATA AGE
default-token-7vc82 kubernetes.io/service-account-token 3 30h
mysecret Opaque 2 6s
# 查看secret详细信息
[root@kub-k8s-master prome]# kubectl get secret mysecret -o yaml
apiVersion: v1
data:
password: MWYyZDFlMmU2N2Rm
username: YWRtaW4=
kind: Secret
metadata:
creationTimestamp: "2023-10-21T03:07:56Z"
name: mysecret
namespace: default
resourceVersion: "162855"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: 36bcd07d-92eb-4755-ac0a-a5843ed986dd
type: Opaque
手动base64解码方式:
[root@kub-k8s-master ~]# echo 'MWYyZDFlMmU2N2Rm' | base64 --decode
secret可以作为数据卷挂载或者作为环境变量暴露给Pod中的容器使用,也可以被系统中的其他资源使用。?
一个Pod中引用Secret的列子:
创建一个Secret,多个Pod可以引用同一个Secret
修改Pod的定义,在spec.volumes[]加一个volume,给这个volume起个名字,spec.volumes[].secret.secretName记录的是要引用的Secret名字
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: testredis
image: daocloud.io/library/redis
volumeMounts: #挂载一个卷
- name: foo #这个名字需要与定义的卷的名字一致
mountPath: "/etc/foo" #挂载到容器里哪个目录下,随便写
readOnly: true
volumes: #数据卷的定义
- name: foo #卷的名字这个名字自定义
secret: #卷是直接使用的secret。
secretName: mysecret #调用刚才定义的secret
创建:
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml
pod/mypod created
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/
root@mypod:/etc/foo# ls
password username
root@mypod:/etc/foo# cat password
1f2d1e2e67df
结果中看到,保存在 Etcd 里的用户名和密码信息,已经以文件的形式出现在了容器的 Volume 目录里。
而这个文件的名字,就是 kubectl create secret 指定的 Key,或者说是 Secret 对象的 data 字段指定的 Key。每一个被引用的Secret都要在spec.volumes中定义
?如果Pod中的多个容器都要引用这个Secret那么每一个容器定义中都要指定自己的volumeMounts,但是Pod定义中声明一次spec.volumes就好了。?
映射secret key到指定的路径
可以控制secret key被映射到容器内的路径,利用spec.volumes[].secret.items来修改被映射的具体路径
[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: testredis
image: daocloud.io/library/redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
items: #定义一个items
- key: username #将那个key重新定义到那个目录下
path: my-group/my-username #相对路径,相对于/etc/foo的路径
2.创建
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml
pod/mypod created
3.从volume中读取secret的值
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username
admin
root@mypod:/etc/foo/my-group#
username被映射到了文件/etc/foo/my-group/my-username而不是/etc/foo/username,而password没有被使用,这种方式每个key的调用需要单独用key像username一样调用
被挂载的secret内容自动更新
也就是如果修改一个Secret的内容,那么挂载了该Secret的容器中也将会取到更新后的值,但是这个时间间隔是由kubelet的同步时间决定的。
1.设置base64加密
[root@kub-k8s-master prome]# echo mahong | base64
bWFob25n
2.将admin替换成mahong
[root@kub-k8s-master prome]# vim secret.yml
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: bWFob25n #修改为mahong的base64加密后的
password: MWYyZDFlMmU2N2Rm
1.创建
[root@kub-k8s-master prome]# kubectl apply -f secret.yml
Warning: kubectl apply should be used on resource created by either kubectl create --save-config or kubectl apply
secret/mysecret configured
2.连接pod容器
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# cd /etc/foo/my-group
root@mypod:/etc/foo/my-group# ls
my-username
root@mypod:/etc/foo/my-group# cat my-username
mahong
?以环境变量的形式使用Secret
[root@kub-k8s-master prome]# kubectl delete -f pod_use_secret.yaml
pod "mypod" deleted
[root@kub-k8s-master prome]# vim pod_use_secret.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: testredis
image: daocloud.io/library/redis
env: #定义环境变量
- name: SECRET_USERNAME #创建新的环境变量名称
valueFrom:
secretKeyRef: #调用的key是什么
name: mysecret #变量的值来自于mysecret
key: username #username里面的值
2.创建使用secret的pod容器
[root@kub-k8s-master prome]# kubectl apply -f pod_use_secret.yaml
pod/mypod created
3.连接
[root@kub-k8s-master prome]# kubectl exec -it mypod /bin/bash
root@mypod:/data# echo $SECRET_USERNAME #打印一下定义的变量
mahong
1.创建数据库用户的密码secret
[root@kub-k8s-master test]# echo -n 'Mawenbao@123' | base64
TWF3ZW5iYW9AMTIz
[root@kub-k8s-master test]# cat secret.yml
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
type: Opaque
data:
password: TWF3ZW5iYW9AMTIz
[root@kub-k8s-master test]# kubectl apply -f secret.yml
2.创建数据库并使用secret
[root@kub-k8s-master test]# cat mysql.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-mysql
spec:
containers:
- name: mysql
image: daocloud.io/library/mysql:5.7
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
[root@kub-k8s-master test]# kubectl apply -f myslq.yaml
[root@kub-k8s-master test]# kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
my-mysql 1/1 Running 0 2m47s 10.244.2.13 node2 <none> <none>
测试:
[root@kub-k8s-master test]# mysql -uroot -p'Mawenbao@123' -h 10.244.2.13 -P3306
?ConfigMap与 Secret 类似,用来存储配置文件的kubernetes资源对象,所有的配置内容都存储在etcd中。
与 Secret 的区别:
ConfigMap 保存的是不需要加密的、应用所需的配置信息。
ConfigMap 的用法几乎与 Secret 完全相同:可以使用 kubectl create configmap 从文件或者目录创建 ConfigMap,也可以直接编写 ConfigMap 对象的 YAML 文件。
创建ConfigMap的方式有4种:
命令行方式
方式1:通过直接在命令行中指定configmap参数创建,即--from-literal
方式2:通过指定文件创建,即将一个配置文件创建为一个ConfigMap,--from-file=<文件>
方式3:通过指定目录创建,即将一个目录下的所有配置文件创建为一个ConfigMap,--from-file=<目录>
配置文件方式
方式4:事先写好标准的configmap的yaml文件,然后kubectl create -f 创建
创建命令:
[root@kub-k8s-master prome]# kubectl create configmap test-configmap --from-literal=user=admin --from-literal=pass=1122334
configmap/test-configmap created
结果如下面的data内容所示:
[root@kub-k8s-master prome]# kubectl get configmap test-configmap -o yaml
apiVersion: v1
data:
pass: "1122334"
user: admin
kind: ConfigMap
metadata:
creationTimestamp: "2019-10-21T07:48:15Z"
name: test-configmap
namespace: default
resourceVersion: "187590"
selfLink: /api/v1/namespaces/default/configmaps/test-configmap
uid: 62a8a0d0-fab9-4159-86f4-a06aa213f4b1
编辑文件server.conf内容如下:
[root@kub-k8s-master prome]# vim server.conf
server {
listen 80;
server_name localhost;
location / {
root /var/www/html;
index index.html index.htm;
}
}
?创建(可以有多个--from-file):
[root@kub-k8s-master prome]# kubectl create configmap test-config2 --from-file=server.conf
configmap/test-config2 created
结果如下面data内容所示:
[root@kub-k8s-master prome]# kubectl get configmap test-config2 -o yaml
apiVersion: v1
data:
server.conf: |
server {
listen 80;
server_name localhost;
localtion / {
root /var/www/html;
index index.html index.htm;
}
}
kind: ConfigMap
metadata:
creationTimestamp: "2023-10-21T08:01:43Z"
name: test-config2
namespace: default
resourceVersion: "188765"
selfLink: /api/v1/namespaces/default/configmaps/test-config2
uid: 790fca12-3900-4bf3-a017-5af1070792e5
通过指定文件创建时,configmap会创建一个key/value对,key是文件名,value是文件内容。
configs 目录下的config-1和config-2内容如下所示:
[root@kub-k8s-master prome]# mkdir config
[root@kub-k8s-master prome]# cd config/
[root@kub-k8s-master config]# vim config1
aaa
bbb
c=d
[root@kub-k8s-master config]# vim config2
eee
fff
h=k
?创建:
[root@kub-k8s-master config]# cd ..
[root@kub-k8s-master prome]# kubectl create configmap test-config3 --from-file=./config
configmap/test-config3 created
结果下面data内容所示:
[root@kub-k8s-master prome]# kubectl get configmap test-config3 -o yaml
apiVersion: v1
data:
config1: |
aaa
bbb
c=d
config2: |
eee
fff
h=k
kind: ConfigMap
metadata:
creationTimestamp: "2023-10-21T08:20:42Z"
name: test-config3
namespace: default
resourceVersion: "190420"
selfLink: /api/v1/namespaces/default/configmaps/test-config3
uid: 6e00fded-80a8-4297-aeb3-4c48795e6eb9
指定目录创建时,configmap内容中的各个文件会创建一个key/value对,key是文件名,value是文件内容。
yaml文件内容如下: 注意其中一个key的value有多行内容时的写法
[root@kub-k8s-master prome]# vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test-config4
namespace: default
data:
cache_host: memcached-gcxt
cache_port: "11211"
cache_prefix: gcxt
my.cnf: |
[mysqld]
log-bin = mysql-bin
haha = hehe
?创建:
[root@kub-k8s-master prome]# kubectl apply -f configmap.yaml
configmap/test-config4 created
结果如下面data内容所示:
[root@kub-k8s-master prome]# kubectl get configmap test-config4 -o yaml
apiVersion: v1
data:
cache_host: memcached-gcxt
cache_port: "11211"
cache_prefix: gcxt
my.cnf: |
[mysqld]
log-bin = mysql-bin
haha = hehe
kind: ConfigMap
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","data":{"cache_host":"memcached-gcxt","cache_port":"11211","cache_prefix":"gcxt","my.cnf":"[mysqld]\nlog-bin = mysql-bin\nhaha = hehe\n"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"test-config4","namespace":"default"}}
creationTimestamp: "2023-10-21T08:30:24Z"
name: test-config4
namespace: default
resourceVersion: "191270"
selfLink: /api/v1/namespaces/default/configmaps/test-config4
uid: 2a8cd6e7-db2c-4781-b005-e0b76d26394b
查看configmap的详细信息:
# kubectl describe configmap
使用ConfigMap的方式,一种是通过环境变量的方式,直接传递pod,另一种是使用volume的方式挂载入到pod内
示例ConfigMap文件:
[root@kub-k8s-master prome]# vim config-map.yml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: config-map
namespace: default
data:
special.how: very
special.type: charm
创建
[root@kub-k8s-master prome]# kubectl apply -f config-map.yml
configmap/config-map created
(1) 使用valueFrom、configMapKeyRef、name、key指定要用的key:
1.设置指定变量的方式
[root@kub-k8s-master prome]# vim testpod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: daocloud.io/library/nginx
env: #专门在容器里面设置变量的关键字
- name: SPECIAL_LEVEL_KEY #这里的-name,是容器里设置的新变量的名字
valueFrom:
configMapKeyRef:
name: config-map #这里是来源于哪个configMap
key: special.how #configMap里的key
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: config-map
key: special.type
restartPolicy: Never
创建pod
[root@kub-k8s-master prome]# kubectl apply -f testpod.yml
pod/dapi-test-pod created
测试:
[root@kub-k8s-master prome]# kubectl exec -it dapi-test-pod /bin/bash
root@dapi-test-pod:/# echo $SPECIAL_TYPE_KEY
charm
(2) 通过envFrom、configMapRef、name使得configmap中的所有key/value对儿 ?都自动变成环境变量:
[root@kub-k8s-master prome]# kubectl delete -f testpod.yml
pod "dapi-test-pod" deleted
[root@kub-k8s-master prome]# cp testpod.yml testpod.yml.bak
[root@kub-k8s-master prome]# vim testpod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: daocloud.io/library/nginx
envFrom:
- configMapRef:
name: config-map
restartPolicy: Never
?这样容器里的变量名称直接使用configMap里的key名:
[root@kub-k8s-master prome]# kubectl apply -f testpod.yml
pod/dapi-test-pod created.
[root@kub-k8s-master prome]# kubectl exec -it dapi-test-pod /bin/bash
root@dapi-test-pod:/# env
HOSTNAME=dapi-test-pod
NJS_VERSION=0.3.3
NGINX_VERSION=1.17.1
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
PKG_RELEASE=1~stretch
KUBERNETES_PORT=tcp://10.96.0.1:443
PWD=/
special.how=very
HOME=/root
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
TERM=xterm
SHLVL=1
KUBERNETES_SERVICE_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
special.type=charm
KUBERNETES_SERVICE_HOST=10.96.0.1
_=/usr/bin/env
(1) 把1.4中test-config4所有key/value挂载进来:
[root@kub-k8s-master prome]# kubectl delete -f testpod.yml
pod "dapi-test-pod" deleted
[root@kub-k8s-master prome]# vim volupod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-configmap
spec:
containers:
- name: nginx-configmap
image: daocloud.io/library/nginx
volumeMounts:
- name: config-volume4
mountPath: "/tmp/config4"
volumes:
- name: config-volume4
configMap:
name: test-config4
创建pod
[root@kub-k8s-master prome]# kubectl apply -f volupod.yml
pod/nginx-configmap created
进入容器中/tmp/config4查看:
[root@kub-k8s-master prome]# kubectl exec -it nginx-configmap /bin/bash
root@nginx-configmap:/# ls /tmp/config4/
cache_host cache_port cache_prefix my.cnf
root@nginx-configmap:/# cat /tmp/config4/cache_host
memcached-gcxt
root@nginx-configmap:/#
可以看到,在config4文件夹下以每一个key为文件名,value为内容,创建了多个文件。
创建configmap
[root@kub-k8s-master configmap]# vim configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-server-conf
namespace: default
data:
index.html: |
Hello, cloud computing
Hello, Mr. Wang
[root@kub-k8s-master configmap]# kubectl apply -f configmap.yaml
[root@kub-k8s-master configmap]# kubectl get configmap
NAME DATA AGE
nginx-server-conf 2 7s
[root@kub-k8s-master configmap]# kubectl get configmap nginx-server-conf -o yaml
使用configmap
[root@kub-k8s-master configmap]# vim pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: test-webapp
spec:
containers:
- name: nginx-app
image: daocloud.io/library/nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-volume
mountPath: "/usr/share/nginx/html"
volumes:
- name: nginx-volume
configMap:
name: nginx-server-conf
[root@kub-k8s-master configmap]# kubectl apply -f pod.yaml
[root@kub-k8s-master configmap]# kubectl get pod
NAME READY STATUS RESTARTS AGE
test-webapp 1/1 Running 0 6s
[root@kub-k8s-master configmap]# kubectl exec -it test-webapp /bin/bash
root@test-webapp:/# cd /usr/share/nginx/html/
root@test-webapp:/usr/share/nginx/html# ls
index.html
root@test-webapp:/usr/share/nginx/html# cat index.html
Hello, cloud computing
Hello, Mr. Wang
[root@kub-k8s-master configmap]# curl 10.244.2.25
Hello, cloud computing
Hello, Mr. Wang
Downward API
用于在容器中获取 POD 的基本信息,kubernetes原生支持Downward API提供了两种方式用于将 POD 的信息注入到容器内部:
1.环境变量:用于单个变量,可以将 POD 信息直接注入容器内部。
2.Volume挂载:将 POD 信息生成为文件,直接挂载到容器内部中去。
1. 使用 fieldRef 可以声明使用:
spec.nodeName - 宿主机名字
status.hostIP - 宿主机 IP
metadata.name - Pod 的名字
metadata.namespace - Pod 的 Namespace
status.podIP - Pod 的 IP
spec.serviceAccountName - Pod 的 Service Account 的名字
metadata.uid - Pod 的 UID
metadata.labels['<KEY>'] - 指定 <KEY> 的 Label 值
metadata.annotations['<KEY>'] - 指定 <KEY> 的 Annotation 值
metadata.labels - Pod 的所有 Label
metadata.annotations - Pod 的所有 Annotation上面这个列表的内容,随着 Kubernetes 项目的发展肯定还会不断增加。所以这里列出来的信息仅供参考,在使用 Downward API 时,还是要记得去查阅一下官方文档。
# 所有基本信息可以使用下面的方式去查看(describe方式看不出来):
[root@kub-k8s-master configmap]# kubectl get pod test-webapp -o yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"Pod","metadata":{"annotations":{},"name":"test-webapp","namespace":"default"},"spec":{"containers":[{"image":"daocloud.io/library/nginx","name":"nginx-app","volumeMounts":[{"mountPath":"/usr/share/nginx/html","name":"nginx-volume"}]}],"volumes":[{"configMap":{"name":"nginx-server-conf"},"name":"nginx-volume"}]}}
creationTimestamp: "2021-02-21T09:44:51Z"
name: test-webapp
namespace: default
resourceVersion: "270687"
selfLink: /api/v1/namespaces/default/pods/test-webapp
uid: ed92d685-f800-464f-95dc-d6aa5f92fc9c
......
使用fieldRef获取 POD 的基本信息,以环境变量的方式实现
[root@kub-k8s-master prome]# vim test-env-pod.yml
---
apiVersion: v1
kind: Pod
metadata:
name: test-env-pod
namespace: kube-system
spec:
containers:
- name: test-env-pod
image: daocloud.io/library/nginx
env:
- name: POD_NAME #第一个环境变量的名字
valueFrom: #使用valueFrom方式设置
fieldRef: #关联一个字段metadata.name
fieldPath: metadata.name #这个字段从当前运行的pod详细信息查看
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
注意: POD 的 name 和 namespace 属于元数据,是在 POD 创建之前就已经定下来了的,所以使用 metadata 获取就可以了,但是对于 POD 的 IP 则不一样,因为POD IP 是不固定的,POD 重建了就变了,它属于状态数据,所以使用 status 去获取。?
?创建上面的 POD:
[root@kub-k8s-master prome]# kubectl apply -f test-env-pod.yml
pod/test-env-pod created
?POD 创建成功后,查看:
[root@kub-k8s-master prome]# kubectl exec -it test-env-pod /bin/bash -n kube-system
root@test-env-pod:/# env | grep POD
POD_NAME=test-env-pod
POD_NAMESPACE=kube-system
POD_IP=10.244.1.35
root@test-env-pod:/#
Volume挂载
通过Downward API将 POD 的 Label、等信息通过 Volume 以文件的形式挂载到容器的某个文件中去,然后在容器中打印出该文件的值来验证。
[root@kub-k8s-master prome]# vim test-volume-pod.yaml
---
apiVersion: v1
kind: Pod
metadata:
name: test-volume-pod
namespace: kube-system
labels:
k8s-app: test-volume
node-env: test
spec:
containers:
- name: test-volume-pod-container
image: daocloud.io/library/nginx
volumeMounts:
- name: podinfo
mountPath: /etc/podinfo
volumes:
- name: podinfo
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
创建上面的 POD :
[root@kub-k8s-master prome]# kubectl apply -f test-volume-pod.yaml pod/test-volume-pod created
[root@kub-k8s-master prome]# kubectl get pod -n kube-system
[root@k8s-master prome]# kubectl exec -it test-volume-pod /bin/bash -n kube-system
Secret、ConfigMap,以及 Downward API 这三种 Projected Volume 定义的信息,大多还可以通过环境变量的方式出现在容器里。但是,通过环境变量获取这些信息的方式,不具备自动更新的能力。一般情况下,建议使用 Volume 文件的方式获取这些信息。?
官方文档地址:Configure Service Accounts for Pods | Kubernetes
k8s中提供了良好的多租户认证管理机制,如RBAC、ServiceAccount还有各种Policy等。?
什么是 Service Account ?
Pod里的进程也可以与 apiserver 联系。 当它们在联系 apiserver 的时候,它们就会被认证为一个特定的 Service Account。
使用场景:
? Service Account它并不是给kubernetes集群的用户使用的,而是给pod里面的进程使用的,它为pod提供必要的身份认证。----专门为pod里面的进程和apiserver通信提供认证的。
Service account与User account区别:
1. User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API或其他外部服务而设计的
2. User account是跨namespace的,而service account则是仅局限它所在的namespace; ? 3. 每个namespace都会自动创建一个default service account ? ? ?
4. Token controller检测service account的创建,并为它们创建secret
Service Account(服务账号)示例
因为平时系统会使用默认service account,我们不需要自己创建,感觉不到service account的存在,本实验是使用自己手动创建的service account
1、创建serviceaccount
[root@kub-k8s-master ~]# kubectl create serviceaccount mysa
serviceaccount/mysa created
# yaml 方法创建
[root@kub-k8s-master ~]# vim mysa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
name: mysa
namespace: default
2、查看mysa
[root@kub-k8s-master ~]# kubectl describe sa mysa
Name: mysa
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: mysa-token-cknwf
Tokens: mysa-token-cknwf
Events: <none>
3、查看mysa自动创建的secret
[root@kub-k8s-master ~]# kubectl get secret
NAME TYPE DATA AGE
db-user-pass Opaque 2 11h
default-token-6svwp kubernetes.io/service-account-token 3 4d23h
mysa-token-cknwf kubernetes.io/service-account-token 3 76s
mysecret Opaque 2 11h
mysecret-01 Opaque 2 6h58m
pass Opaque 1 7h6m
user Opaque 1 7h7m
4、创建角色和绑定
[root@kub-k8s-master ~]# vim role.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: mysa-role
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: mysa-binding
namespace: default
subjects:
- kind: ServiceAccount
name: mysa
namespace: default
roleRef:
kind: Role
name: mysa-role
apiGroup: rbac.authorization.k8s.io
5、使用mysa的sa资源配置pod
[root@kub-k8s-master ~]# cd prome/
[root@kub-k8s-master prome]# vim mysa-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: mysa-pod
spec:
serviceAccountName: mysa
containers:
- name: app
image: 10.36.192.206:8088/newrain857/kubectl
command: ["tail","-f","/dev/null"]
6、导入
[root@kub-k8s-master prome]# kubectl apply -f .
pod/mysa-pod created
role.rbac.authorization.k8s.io/mysa-role created
rolebinding.rbac.authorization.k8s.io/mysa-binding created
serviceaccount/mysa created
7、查看
[root@kub-k8s-master prome]# kubectl get pod mysa-pod -o yaml
8、测试
[root@kube-master sa]# kubectl exec -it mysa-pod /bin/sh
/ # kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 1 (50m ago) 17h
mysa-pod 1/1 Running 0 9m5s
/ # kubectl delete pod nginx
Error from server (Forbidden): pods "nginx" is forbidden: User "system:serviceaccount:default:pod-reader" cannot delete resource "pods" in API group "" in the namespace "default"
# 可以看到,我们已经成功限制了pod对资源的访问
在Kubernetes中,授权有ABAC(基于属性的访问控制)、RBAC(基于角色的访问控制)、Webhook、Node、AlwaysDeny(一直拒绝)和AlwaysAllow(一直允许)这6种模式。
RBAC基于角色的访问控制--全拼Role-Based Access Control----做权限控制的,顾名思义就是通过给角色赋予相应的权限,从而使得该角色具有访问相关资源的权限。
k8s里面有两种用户,一种是User,一种就是service account(服务使用的账号)。
User account是为人设计的属于用户账户(个人使用的账号),此外User Account是跨Namespace的,而ServiceAccount则是仅局限它所在的Namespace。在RABC API中,通过如下的步骤进行授权:
1)定义角色:在定义角色时会指定此角色对于资源的访问控制的规则;
2)绑定角色:将主体与角色进行绑定,对用户进行访问授权。
在K8s中这些资源分属于两个级别,名称空间(role/rolebinding)和集群级别(clusterrole/clusterrolebinding)这两个都是标准的K8s资源,可以直接定义。
Role与ClusterRole
?Role普通角色:一个Role对象只能用于授予对某一单一命名空间中资源的访问权限,普通角色只是在当前的名称空间生效。
?ClusterRole集群角色:整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现,可以访问整个集群资源。
?简介
role/ClusterRole:
? ? 1、允许的操作,如get,list,update,create,delete等权限
? ? 2、允许操作的对象,如pod,svc等资源
rolebinding:将哪个用户绑定到哪个role上
clusterrolebinding:绑定到集群角色上
? ?如果使用clusterrolebinding绑定到clusterrole上,表示绑定的用户拥有所有namespace的权限
? ?
?#这里面有哪些重要的东西:role,clusterrole,binding,账号。?
创建账号
1、创建私钥
[root@kub-k8s-master ~]# (umask 077; openssl genrsa -out soso.key 2048)
Generating RSA private key, 2048 bit long modulus
...............................+++
..........................+++
e is 65537 (0x10001)
用此私钥创建一个csr(证书签名请求)文件
[root@kub-k8s-master ~]# openssl req -new -key soso.key -out soso.csr -subj "/CN=soso" # 这个地方是用户名
拿着私钥和请求文件生成证书
[root@kub-k8s-master ~]# openssl x509 -req -in soso.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out soso.crt -days 365
Signature ok
subject=/CN=soso
Getting CA Private Key
生成账号
[root@kub-k8s-master ~]# kubectl config set-credentials soso --client-certificate=soso.crt --client-key=soso.key --embed-certs=true
User "soso" set.
3、设置上下文环境--指的是创建这个账号的环境在当前名称空间中
[root@kub-k8s-master ~]# kubectl config set-context soso@kubernetes --cluster=kubernetes --user=soso
Context "soso@kubernetes" created.
查看当前的工作上下文
[root@kub-k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.96.10:6443
....
4、切换用户(切换上下文)
[root@kub-k8s-master ~]# kubectl config use-context soso@kubernetes
Switched to context "soso@kubernetes".
验证是否已经切换到了新的上下文
[root@kub-k8s-master ~]# kubectl config current-context
soso@kubernetes
5.测试(还未赋予权限)
[root@kub-k8s-master ~]# kubectl get pod
Error from server (Forbidden): pods is forbidden: User "soso" cannot list resource "pods" in API group "" in the namespace "default"
创建一个角色(role)---设置权限
1.切回管理帐号先
[root@kub-k8s-master ~]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
创建角色(命令):
[root@kub-k8s-master ~]# kubectl create role role-reader --verb=get,list,watch --resource=pod,svc
role.rbac.authorization.k8s.io/role-reader created
--verb: 相当于是权限
--resource:给什么资源使用
yaml文件方式:
[root@kub-k8s-master ~]# vim role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-reader
rules: #定义规则
- apiGroups: [""] #表示当前pod使用核心的APIserver组,默认用""表示就可以
resources: ["pods","svc"]
verbs: ["get", "list", "watch", "create", "update", "delete"] #["*"]表示所有权限
[root@kub-k8s-master ~]# kubectl apply -f role.yaml
role.rbac.authorization.k8s.io/role-reader created
[root@kub-k8s-master ~]# kubectl get roles
NAME AGE
role-reader 30s
[root@kub-k8s-master ~]# kubectl describe role role-reader
Name: role-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"Role","metadata":{"annotations":{},"name":"role-reader","namespace":"default"},"...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch create update delete]
svc [] [] [get list watch create update delete]
2.绑定用户soso(上面创建的用户),绑定用户到role-reader
[root@kub-k8s-master ~]# kubectl create rolebinding myrole-binding --role=role-reader --user=soso
rolebinding.rbac.authorization.k8s.io/myrole-binding created
yaml文件方式:
[root@k8s-master ~]# vim role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: myrolebind
subjects: #定义对那个主体进行操作,有三种Subjects:Service Account、User Account、Groups
- kind: User
name: soso
apiGroup: rbac.authorization.k8s.io
roleRef: #定义使用哪个角色
kind: Role
name: role-reader
apiGroup: rbac.authorization.k8s.io
[root@k8s-master ~]# kubectl apply -f role-binding.yaml
rolebinding.rbac.authorization.k8s.io/myrolebind created
[root@k8s-master ~]# kubectl get rolebinding
NAME AGE
myrolebind 25s
3.切换用户
[root@kub-k8s-master ~]# kubectl config use-context soso@kubernetes
Switched to context "soso@kubernetes".
4.查看权限(只授权了default名称空间pod和svc的get,list,watch权限)
[root@kub-k8s-master ~]# kubectl get pod
NAME READY STATUS RESTARTS AGE
lifecycle-demo 1/1 Running 1 22h
mypod 1/1 Running 0 8h
nginx-configmap 1/1 Running 0 4h29m
nginx-pod 1/1 Running 0 39m
[root@kub-k8s-master ~]# kubectl get pod -n kube-system #无权访问kube-system
Error from server (Forbidden): pods is forbidden: User "soso" cannot list resource "pods" in API group "" in the namespace "kube-system"
[root@kub-k8s-master ~]# kubectl delete pod nginx-pod #无权限删除
Error from server (Forbidden): pods "nginx-pod" is forbidden: User "soso" cannot delete resource "pods" in API group "" in the namespace "default"
5.切换用户
[root@kub-k8s-master ~]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
实验二,绑定用户到集群角色
6.删除soso账号之前绑定的rolebinding
[root@kub-k8s-master ~]# kubectl delete rolebinding myrolebind
rolebinding.rbac.authorization.k8s.io "myrolebind" deleted
7.创建clusterrole #可以访问全部的namespace
[root@kub-k8s-master ~]# kubectl create clusterrole myclusterrole --verb=get,list,watch --resource=pod,svc
clusterrole.rbac.authorization.k8s.io/myclusterrole created
yaml文件方式:
[root@kub-k8s-master ~]# vim clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: myclusterrole
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@kub-k8s-master ~]# kubectl apply -f clusterrole.yaml
[root@kub-k8s-master ~]# kubectl get clusterrole
8.绑定集群角色到用户soso
[root@kub-k8s-master ~]# kubectl create clusterrolebinding my-cluster-rolebinding --clusterrole=myclusterrole --user=soso
clusterrolebinding.rbac.authorization.k8s.io/my-cluster-rolebinding created
yaml文件方式:
[root@kub-k8s-master ~]# vim clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: my-cluster-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: myclusterrole
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: soso
[root@kub-k8s-master ~]# kubectl apply -f clusterrolebinding.yaml
[root@kub-k8s-master ~]# kubectl get clusterrolebinding
9.切换账号
[root@kub-k8s-master ~]# kubectl config use-context soso@kubernetes
Switched to context "soso@kubernetes".
10.查看权限 查看kube-system空间的pod
[root@kub-k8s-master ~]# kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-5644d7b6d9-sm8hs 1/1 Running 0 5d
coredns-5644d7b6d9-vddll 1/1 Running 0 5d
etcd-kub-k8s-master 1/1 Running 0 5d
...
注意:11.切换为管理员用户
[root@kub-k8s-master ~]# kubectl config use-context kubernetes-admin@kubernetes
设置工作上下文(前提得有用户)
[root@kub-k8s-master ~]# kubectl config set-context soso@kubernetes --cluster=kubernetes --user=soso
Context "soso@kubernetes" created.
查看当前的工作上下文
[root@kub-k8s-master ~]# kubectl config view
apiVersion: v1
clusters:
- cluster:
....
切换上下文(切换用户)
[root@kub-k8s-master ~]# kubectl config use-context soso@kubernetes
Switched to context "soso@kubernetes".
切换为管理员用户
[root@kub-k8s-master prome]# kubectl config use-context kubernetes-admin@kubernetes
Switched to context "kubernetes-admin@kubernetes".
查看某个资源类型是由哪个apiserver版本提供
[root@kub-k8s-master ~]# kubectl explain ClusterRole