首先Kubernetes中帐户区分为:User Accounts(用户帐户) 和 Service Accounts(服务帐户) 两种,它们的设计及用途以下:html
UserAccount是给kubernetes集群外部用户使用的,例如运维或者集群管理人员,使用kubectl命令时用的就是UserAccount帐户;UserAccount是全局性。在集群全部namespaces中,名称具备惟一性,默认状况下用户为admin;node
用户名称能够在kubeconfig中查看linux
[root@Centos8 ~]# cd ~/.kube/ [root@Centos8 .kube]# ls cache config http-cache [root@Centos8 .kube]# cat config users: - name: kubernetes-admin
Kubernetes设计了一种Secret资源,分为两类,一种是用于 ServiceAccount 的 kubernetes.io/ service-account-token,就是上边说的 SA,另外一种就是用户自定义的保密信息Opaque。nginx
ServiceAccount仅局限它所在的namespace,因此在建立namespace时会自动建立一个默认的 SA,而 SA 建立时,也会建立对应的 Secret,下面操做验证下:web
建立名称空间算法
[root@Centos8 .kube]# kubectl create ns vfan
namespace/vfan created
查看SAdocker
[root@Centos8 .kube]# kubectl get sa -n vfan NAME SECRETS AGE default 1 67s
查看 SA 的 Secretjson
[root@Centos8 .kube]# kubectl describe sa default -n vfan Name: default Namespace: vfan Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: default-token-wwbc8 Tokens: default-token-wwbc8 Events: <none> [root@Centos8 ~]# kubectl get secret -n vfan NAME TYPE DATA AGE default-token-wwbc8 kubernetes.io/service-account-token 3 3m15s
能够看到,建立ns时默认建立了SA,SA默认建立了一个 kubernetes.io/service-account-token类型的secretvim
建立一个Podapi
vim pods.yaml
apiVersion: v1 kind: Pod metadata: name: test-sa namespace: vfan spec: containers: - name: test-sa image: nginx:1.2.1 imagePullPolicy: IfNotPresent ports: - containerPort: 80
[root@Centos8 rbac]# kubectl create -f pods.yaml pod/test-sa created [root@Centos8 rbac]# kubectl get pod -n vfan NAME READY STATUS RESTARTS AGE test-sa 1/1 Running 0 12s [root@Centos8 rbac]# kubectl describe pod test-sa -n vfan ... Containers: test-sa: Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-wwbc8 (ro) Volumes: default-token-wwbc8: Type: Secret (a volume populated by a Secret) SecretName: default-token-wwbc8 Optional: false ...
在不指定SA的状况下,当前 ns下面的 Pod 会默认使用 “default” 这个 SA,对应的 Secret 会自动挂载到 Pod 的 /var/run/secrets/kubernetes.io/serviceaccount/ 目录中,咱们能够在 Pod 里面获取到用于身份认证的信息。
进入Pod Container内,查看 SA
[root@Centos8 rbac]# kubectl exec -it test-sa -n vfan -- /bin/bash root@test-sa:/# cd /var/run/secrets/kubernetes.io/serviceaccount/ root@test-sa:/var/run/secrets/kubernetes.io/serviceaccount# ls ca.crt namespace token ### 能够看到有三个文件,做用分别为 ca.crt:根证书,用于Client端验证API Server发送的证书 namespace:标识这个service-account-token的做用域空间 token:使用API Server私钥签名的JWT,用于访问API Server时,Server端的验证
建立一个 SA
[root@Centos8 rbac]# kubectl create sa vfansa -n vfan serviceaccount/vfansa created [root@Centos8 rbac]# kubectl get sa -n vfan NAME SECRETS AGE default 1 19m vfansa 1 7s [root@Centos8 rbac]# kubectl describe sa vfansa -n vfan Name: vfansa Namespace: vfan Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: vfansa-token-9s8f7 Tokens: vfansa-token-9s8f7 Events: <none> [root@Centos8 rbac]# kubectl get secret -n vfan NAME TYPE DATA AGE default-token-wwbc8 kubernetes.io/service-account-token 3 19m vfansa-token-9s8f7 kubernetes.io/service-account-token 3 49s
一样,建立SA后,自动建立了对应的Secret
更新Pod,使用新建立的SA
vim pods.yaml
apiVersion: v1 kind: Pod metadata: name: test-sa namespace: vfan spec: containers: - name: test-sa image: nginx:1.2.1 imagePullPolicy: IfNotPresent ports: - containerPort: 80 serviceAccountName: vfansa
[root@Centos8 rbac]# kubectl create -f pods.yaml pod/test-sa created [root@Centos8 rbac]# kubectl describe pod test-sa -n vfan ... Mounts: /var/run/secrets/kubernetes.io/serviceaccount from vfansa-token-9s8f7 (ro) Volumes: vfansa-token-9s8f7: Type: Secret (a volume populated by a Secret) SecretName: vfansa-token-9s8f7 Optional: false ...
在笔者以前的博客中:Secret介绍及演示( http://www.javashuo.com/article/p-sonksbxt-mx.html )中说起到,可使用Secret来保存镜像仓库的登陆信息,来达到免登陆获取image的效果,一样,能够将建立好的Secret直接与SA进行绑定,绑定完成后,只要使用此 SA 的 Pod,均可达到免登陆获取image的效果
建立 docker-registry 的 Secret
[root@Centos8 rbac]# kubectl create secret docker-registry myregistrykey --docker-server=hub.vfancloud.com --docker-username=admin --docker-password=admin@123 --docker-email=vfan8991@163.com -n vfan secret/myregistrykey created [root@Centos8 rbac]# kubectl get secret -n vfan NAME TYPE DATA AGE default-token-wwbc8 kubernetes.io/service-account-token 3 62m myregistrykey kubernetes.io/dockerconfigjson 1 7s vfansa-token-9s8f7 kubernetes.io/service-account-token 3 43m
将 docker-registry 的 Secret 添加到SA
kubectl edit sa vfansa -n vfan
apiVersion: v1 kind: ServiceAccount metadata: creationTimestamp: "2020-08-30T03:38:47Z" name: vfansa namespace: vfan resourceVersion: "471829" selfLink: /api/v1/namespaces/vfan/serviceaccounts/vfansa uid: 8a44df93-b2d6-4e61-ad2e-25bc5852f66e secrets: - name: vfansa-token-9s8f7 imagePullSecrets: - name: myregistrykey
查看 SA 的 Image pull secrets
[root@Centos8 rbac]# kubectl describe sa vfansa -n vfan
Name: vfansa
Namespace: vfan
Labels: <none> Annotations: <none> Image pull secrets: myregistrykey Mountable secrets: vfansa-token-9s8f7 Tokens: vfansa-token-9s8f7 Events: <none>
这个时候,只要是使用此 SA 的Pod,均可以在docker-registry拉取镜像了,一样,能够把此 Secret 添加到default 的 SA 中,达到相同的效果
在Kubernetes中,全部资源对象都是经过API对象进行操做,他们保存在etcd里。而对etcd的操做咱们须要经过访问 kube-apiserver 来实现,上面的Service Account其实就是APIServer的认证过程,而受权的机制是经过RBAC:基于角色的访问控制实现。
在RBAC API中,Role表示一组规则权限,权限只会增长(累加权限),不存在一个资源开始就有不少权限而经过RBAC对其进行减小的操做:Role 是定义在一个 namespace 中,而 ClusterRole 是集群级别的。
下面咱们定义一个Role:
vim roles.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: test-role namespace: vfan rules: - apiGroups: [""] # 为空表示为默认的core api group resources: ["pods"] # 数据源类型 verbs: ["get","watch","list"] #赋予的权限 - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get","list","create","update","patch","delete","watch"]
以上Role策略表示在名字为 vfan ns中,对Pods有get,watch,list的权限,对Deployment有......权限
ClusterRole 具备与 Role 相同权限角色控制能力,不一样的就是 Cluster Role是集群级别,它能够用于:
vim clusterroles.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: test-clusterrole rules: - apiGroups: [""] resources: ["services"] verbs: ["get","create","list"]
以上Cluster role策略表示,有get,create,list整个集群service的权限
下面开始建立
## role [root@Centos8 rbac]# kubectl create -f roles.yaml role.rbac.authorization.k8s.io/test-rbac created [root@Centos8 rbac]# kubectl get role -n vfan NAME AGE test-rbac 27s ## cluster role [root@Centos8 rbac]# kubectl get clusterrole -n vfan NAME AGE admin 141d cluster-admin 141d edit 141d flannel 141d ingress-nginx 90d ingress-nginx-admission 90d system:aggregate-to-admin 141d system:aggregate-to-edit 141d system:aggregate-to-view 141d
能够看到,role和cluster role都已经建立成功,可是clusterrole除了此次建立的还有许多,其中以system开头的所有是系统所用的,其余的都是在装一些插件时自动添加的,也要注意,咱们本身建立cluster role时不要以system开通,以避免分不清楚
RoleBinding能够将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表(Subjects),权限列表中包含有不一样形式的待授予权限资源类型(users,groups, or Service Account):Rolebinding 一样包含对被 Bind 的 Role 引用;RoleBinding 适用于某个命名空间内受权,ClusterRoleBinding适用于集群范围内的受权。
建立RoleBinding
vim rolebindings.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: test-rolebinding namespace: vfan subjects: - kind: User # 权限资源类型 name: vfan # 名称 apiGroup: rbac.authorization.k8s.io roleRef: kind: Role #要绑定的Role的类型(能够是Role或ClusterRole) name: test-role # Role的名称 apiGroup: rbac.authorization.k8s.io
此策略表示,将名称为test-role的Role的权限资源赋予名为vfan的用户,仅做用于vfan namespace。
RoleBinding一样能够引用ClusterRole来对当前 namespace 内用户、用户组或SA来进行受权,这种操做容许管理员在整个集群中定义一些通用的ClusterRole,而后在不一样的namespace中使用RoleBinding绑定。
vim rolebindings2.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: test-rolebinding2 namespace: vfan subjects: - kind: User name: vfan apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: test-clusterrole apiGroup: rbac.authorization.k8s.io
以上策略表示,将名称为test-clusterrole的ClusterRole的资源权限赋予给了名称为vfan的用户,虽然赋予的是ClusterRole,可是因为Role仅做用于单个namespace,因此此资源策略仅仅对vfan namespace有效
vim clusterrolebindings.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: test-clusterrolebinding subjects: - kind: Group name: vfan apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: test-clusterrole apiGroup: rbac.authorization.k8s.io
以上策略表示,将name为test-clusterrole的ClusterRole的资源权限赋予给groupname为vfan的用户组,此用户组下全部用户拥有对整个集群的 test-clusterrole内的资源权限
[root@Centos8 rbac]# useradd vfan [root@Centos8 rbac]# su - vfan ## 进入vfan用户测试访问k8s集群 [vfan@Centos8 ~]$ kubectl get pod The connection to the server localhost:8080 was refused - did you specify the right host or port?
默认确定是访问不到的,若是想要访问,必需要建立vfan用户的访问证书
## 下载证书生成工具 cfssl [root@Centos8 bin]# wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 [root@Centos8 bin]# wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 [root@Centos8 bin]# wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 ## 更名,给执行权限 [root@Centos8 bin]# mv cfssl_linux-amd64 cfssl [root@Centos8 bin]# mv cfssljson_linux-amd64 cfssljson [root@Centos8 bin]# mv cfssl-certinfo_linux-amd64 cfssl-certinfo [root@Centos8 bin]# chmod +x * [root@Centos8 bin]# ll -h 总用量 19M -rwxr-xr-x 1 root root 9.9M 3月 30 2016 cfssl -rwxr-xr-x 1 root root 6.3M 3月 30 2016 cfssl-certinfo -rwxr-xr-x 1 root root 2.2M 3月 30 2016 cfssljson [root@Centos8 bin]# mkdir /usr/local/vfancert [root@Centos8 bin]# cd /usr/local/vfancert/
建立CA证书签名请求JSON文件
vim vfan-csr.json
{ "CN": "vfan", # 用户名称 "hosts": [], # 主机地址,不填表示全部主机均可使用 "key": { "algo": "rsa", # 加密算法 "size": 2048 }, "names": [ { "C": "CN", "L": "BeiJing", "O": "Ctyun", "ST": "BeiJing", "OU": "System" } ] }
开始建立访问证书
[root@Centos8 vfancert]# cd /etc/kubernetes/pki/ [root@Centos8 pki]# cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /usr/local/vfancert/vfan-csr.json | cfssljson -bare vfanuser 2020/09/02 22:08:51 [INFO] generate received request 2020/09/02 22:08:51 [INFO] received CSR 2020/09/02 22:08:51 [INFO] generating key: rsa-2048 2020/09/02 22:08:51 [INFO] encoded CSR 2020/09/02 22:08:51 [INFO] signed certificate with serial number 191102646650271030964539871811792985454770130197 2020/09/02 22:08:51 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for websites. For more information see the Baseline Requirements for the Issuance and Management of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org); specifically, section 10.2.3 ("Information Requirements"). ## 建立成功,pki目录下多出vfanuser-key.pem、vfanuser.pem和vfanuser.csr文件 [root@Centos8 pki]# ls vfanuser.csr vfanuser-key.pem vfanuser.pem
## 设置api server的环境变量 [root@Centos8 vfancert]# export KUBE_APISERVER="https://192.168.152.53:6443" ## 建立kubeconfig文件,如下详细参数信息可经过kubectl config set-cluster --help查看 [root@Centos8 vfancert]# kubectl config set-cluster kubernetes --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=vfan.kubeconfig Cluster "kubernetes" set. ## 配置文件生成 [root@Centos8 vfancert]# ls vfan-csr.json vfan.kubeconfig ## 设置客户端参数,绑定用户信息至kubeconfig中 [root@Centos8 vfancert]# kubectl config set-credentials vfanuser \ > --client-certificate=/etc/kubernetes/pki/vfanuser.pem \ > --client-key=/etc/kubernetes/pki/vfanuser-key.pem \ > --embed-certs=true \ > --kubeconfig=vfan.kubeconfig User "vfanuser" set. ## 设置上下文参数 [root@Centos8 vfancert]# kubectl config set-context kubernetes \ > --cluster=kubernetes \ > --user=vfan \ > --namespace=vfan \ > --kubeconfig=vfan.kubeconfig Context "kubenetes" created.
vim vfanrolebind.yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: test-rolebinding namespace: vfan subjects: - kind: User name: vfan apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: test-rbac # 绑定上文中建立的名称为 test-rbac 的Role,具体权限,往上翻下哈 apiGroup: rbac.authorization.k8s.io
把kubeconfig文件复制到 vfan 用户的家目录的.kube下
[root@Centos8 vfancert]# mkdir -p /home/vfan/.kube [root@Centos8 vfancert]# cp vfan.kubeconfig /home/vfan/.kube/config [root@Centos8 vfancert]# cd /home/vfan/.kube/ [root@Centos8 .kube]# ls config ## 修改文件全部者 [root@Centos8 vfan]# chown -R vfan:vfan .kube/
切换上下文,使kubectl读取到config的信息
[vfan@Centos8 .kube]$ kubectl config use-context kubernetes --kubeconfig=config Switched to context "kubernetes".
开始测试权限
[vfan@Centos8 .kube]$ kubectl get pod No resources found. [vfan@Centos8 .kube]$ kubectl get svc Error from server (Forbidden): services is forbidden: User "vfan" cannot list resource "services" in API group "" in the namespace "vfan"
能够get pod,可是不能够get service,由于以前的Role中明确的表示了本身的权限
在vfan名称空间下建立测试Deployment
## root用户下建立 [root@Centos8 k8sYaml]# kubectl run deployment test-vfan --replicas=3 --image=nginx:1.2.1 --namespace=vfan [root@Centos8 k8sYaml]# kubectl get pod -n vfan NAME READY STATUS RESTARTS AGE deployment-7b89b946d-5dtvp 1/1 Running 0 17s deployment-7b89b946d-jpr5v 1/1 Running 0 17s deployment-7b89b946d-r8k4l 1/1 Running 0 17s ## 前往vfan用户查看 [vfan@Centos8 .kube]$ kubectl get pod NAME READY STATUS RESTARTS AGE deployment-7b89b946d-5dtvp 1/1 Running 0 67s deployment-7b89b946d-jpr5v 1/1 Running 0 67s deployment-7b89b946d-r8k4l 1/1 Running 0 67s
能够看到,vfan用户也能够查看到相对应的Pod,由于vfan用户在get pod时并无指定名称空间,因此能够证实vfan的默认名称空间便是vfan