一,身份认证
1-1,账户分类
所有 Kubernetes 集群有两类用户:
第1类:ServiceAccounts(服务账户,简写sa)
用于对集群内服务设置账户验证。
ServiceAccount是Pod使用的账号。
Pod容器的进程需要访问API Server时,用的就是ServiceAccount账户。
ServiceAccount仅局限它所在的namespace,每个namespace创建时,都会自动创建一个default service account。
创建Pod时,如果没有指定Service Account,Pod则会使用default Service Account。
# 创建一个ServiceAccounts用户new-user
kubectl create sa new-user
第2类: UsersAccounts (普通账户)
用于用户的登录,管理集群。
UserAccount是给kubernetes集群外部用户使用的。
例如:
kubectl访问k8s集群要用useraccount用户。
kubeadm安装的k8s,默认的useraccount用户是kubernetes-admin。
APIServer需要对客户端做认证,使用kubeadm安装的K8s,会在用户家目录下创建一个认证配置文件 .kube/config 这里面保存了客户端访问API Server的密钥相关信息,这样当用kubectl访问k8s时,它就会自动读取该配置文件,向API Server发起认证,然后完成操作请求。
1-2,认证方式
- 客户端认证。也叫双向TLS认证。kubectl和apiserver,两者通过ca根证书来进行验证。
- Bearertoken。通过将一个密码通过了非对称加密的方式,达到互访。
- Serviceaccount。是内部访问pod和apiserver交互时候采用的一种方式。
它包括了namespace、token、ca,且通过目录挂载的方式给予pod,当pod运行起来的时候,就会读取到这些信息,从而使用该方式和apiserver进行通信。
1-3,kubeconfig文件
kubectl config view
显示如下:
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.40.180:6443 # apiserver的地址
name: kubernetes # 集群的名字
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes # 上下文的名字
current-context: kubernetes-admin@kubernetes # 当前上下文的名字
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
二,RBAC授权
RBAC 是基于角色的访问控制(Role-Based Access Control )
2-1,四种角色
一个角色(或集群角色),包含一组权限,没有拒绝规则,只是附加允许。
作用:针对哪些资源,做哪些操作。
(1)角色:Role
它是 Namespace 级别的资源,只能作用于Namespace之内。
# 定义一个角色用来读取Pod的权限
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac
name: pod-read
rules:
- apiGroups: [""]
resources: ["pods"]
resourceNames: []
verbs: ["get","watch","list"]
rules中的参数说明:
1、apiGroups:支持的API组列表,例如:"apiVersion: apps/v1"等
2、resources:支持的资源对象列表,例如pods、deployments、jobs等
3、resourceNames: 指定resource的名称
4、verbs:对资源对象的操作方法列表。
(2)集群角色:ClusterRole
它是集群内资源类型,可以作用于不同Namespace之间
# 定义一个集群角色可让用户访问任意secrets
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secrets-clusterrole
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get","watch","list"]
还可用于以下特殊元素的授权:
1、集群范围的资源,例如Node
2、非资源型的路径,例如:/healthz
3、包含全部命名空间的资源,例如Pods
(3)角色绑定:RoleBinding
用于对服务账户和角色(Role 或 ClusterRole)的绑定。
作用于 Namespace 内。
(4) 集群角色绑定:ClusterRoleBinding
用于对服务账户和角色(仅限于ClusterRole)的绑定。
作用于集群内不同 Namespace之间 。
2-2,绑定对象
可以将User、Group、service Account ,与角色Role或集群角色ClusterRole进行绑定。
总共3中方案:
- 基于rolebinding绑定到role上
- 基于rolebinding绑定到clusterrole上
- 基于clusterrolebinding绑定到clusterrole上
2-3,常用参数取值
Role和ClusterRole 的 rule下
apiGroups
值:
"","apps", "autoscaling", "batch"
resources
值:
"services", "endpoints", "pods","secrets","configmaps","crontabs","deployments","jobs","nodes","rolebindings","clusterroles","daemonsets","replicasets","statefulsets","horizontalpodautoscalers","replicationcontrollers","cronjobs"
verbs
值:
"get", "list", "watch", "create", "update", "patch", "delete", "exec"
三,准入控制
对认证、鉴权后用户的操作,做规范的限制和变更验证。
3-1,常用准入控制器的模块
- LimitRanger
- ResourceQuota
- ServiceAccount
- PodSecurityPolicy (k8s1.25废弃了)
3-2,如何启用
LimitRanger、ResourceQuota、ServiceAccount 默认系统开启。
如何开启其他控件?
# cat /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.40.180
...
- --enable-admission-plugins=NodeRestriction # 加入此配置, “NodeRestriction”
...
--enable-admission-plugins
选项来指定要启用的准入控制插件,该选项可以使用多个值,用逗号隔开。
3-3,ResourceQuota准入控制器的使用
该控制器是k8s上内置的准入控制器,默认是启用状态。
作用:
用来在名称空间级别,限制用户的资源使用。
示例:限制cpu、内存、pod、deployment数量
# 创建命名空间 ns-quota
kubectl create ns ns-quota
# cat ns-quota.yaml
apiVersion: v1
kind: ResourceQuota # 指定资源类型
metadata:
name: rq-quota
namespace: quota # 指定命名空间
spec:
hard: # 定义资源限制规则
pods: "6" # 限制pod的数量
requests.cpu: "2" # 限制所有pod的cpu下限总和
requests.memory: "2Gi" # 限制所有pod的内存下限总和
requests.storage: "5Gi" # 限制所有pod的存储下限总和
requests.ephemeral-storage: "1Gi" # 限制使用本地临时存储的下限总容量
limits.cpu: "4" # 限制所有pod的cpu上限总和
limits.memory: "10Gi" # 限制所有pod的内存上限总和
limits.ephemeral-storage: "2Gi" # 限制使用本地临时存储的上限总容量
count/deployments.apps: "6" # 限制apps群组下的deployments个数不超过6个
persistentvolumeclaims: "6" # 限制pvc个数不能超过6个
3-4,LimitRanger准入控制器的使用
该控制器是k8s上内置的准入控制器,默认是启用状态。是k8s上的一个标准资源。
作用:
定义在某个名称空间下创建pod时使用的cpu和内存的上限和下限以及默认cpu、内存的上下限。
示例:设置默认cpu、内存、pod、deployment资源使用
# 创建命名空间 ns-limit
kubectl create ns ns-limit
# cat limitrange.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-memory
namespace: ns-limit
spec:
limits:
- default: # 指定默认容器资源上限值
cpu: 1000m
memory: 1000Mi
defaultRequest: # 指定默认容器资源下限值
cpu: 500m
memory: 500Mi
min: # 指定限制用户指定的资源下限不能小于对应资源的值
cpu: 500m
memory: 500Mi
max: # max是用来限制用户指定资源上限值不能大于该值
cpu: 2000m
memory: 2000Mi
maxLimitRequestRatio: # 指定资源的上限和下限的比值
cpu: 4
memory: 4
type: Container # 用来描述对应资源限制的级别,取值 pod 或 container。
【说明】:
该资源清单表示在该名称空间下创建pod时,默认不指定其容器的资源限制,就限制对应容器最少要有0.5个核心的cpu和500M的内存;最大为1个核心cpu,1g内存;如果我们手动定义了容器的资源限制,那么对应资源限制最小不能小于cpu为0.5个核心,内存为500M,最大不能超过cpu为2个核心,内存为2000M;
如果我们在创建pod时,只指定了容器的资源上限或下限,那么上限最大是下限的的4倍,如果指定cpu上限为2000m那么下限一定不会小于500m,如果只指定了cpu下限为500m那么上限最大不会超过2000m,对于内存也是同样的逻辑。
四,应用示例
4-1,常见角色(role)授权的示例
(1)允许读取核心API组的Pod资源
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
(2)允许读写apps API组中的deployment资源
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get","list","watch","create","update","patch","delete"]
(3)允许读取Pod以及读写job信息
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
- apiGroups: [""]
resources: ["jobs"]
verbs: ["get","list","watch","create","update","patch","delete"]
(4)允许读取一个名为my-config的ConfigMap
(必须绑定到一个RoleBinding来限制到一个Namespace下的ConfigMap):
rules:
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["my-configmap"]
verbs: ["get"]
(5)读取核心组的Node资源
(Node属于集群级的资源,所以必须存在于ClusterRole中,并使用ClusterRoleBinding进行绑定):
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get","list","watch"]
(6)允许对非资源端点“/healthz”及其所有子路径进行GET和POST操作
(必须使用ClusterRole和ClusterRoleBinding):
rules:
- nonResourceURLs: ["/healthz","/healthz/*"]
verbs: ["get","post"]
4-2,常见的角色绑定示例
(1)用户名alice
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
```
#### (2)组名alice
```yaml
subjects:
- kind: Group # 指定组名
name: alice
apiGroup: rbac.authorization.k8s.io
(3)kube-system命名空间中默认Service Account
subjects:
- kind: ServiceAccount
name: default
namespace: kube-system
4-3,常见的角色绑定(命令行)示例
(1)名称空间namespace中服务账户Service Account(mysa)授予只读权限
kubectl create rolebinding [rolebinding名称] --clusterrole=view --serviceaccount=[namespace名称]:mysa --namespace=[namespace名称]
【注意】:
--clusterrole=view
:view 为系统自带“只读”角色。
k8s 内置集群角色: cluster-admin,admin ,edit ,view
- cluster-admin 超级管理员,对集群所有权限,和linux下面root一样(在部署dashboard的时候,先创建sa,然后将sa绑定到角色cluster-admin,最后获取到token,这就使用了内置的cluster-admin )
- admin 主要用于授权命名空间所有读写权限(针对于某个命名空间)
- edit 允许对命名空间大多数对象读写操作,不允许查看或者修改角色、角色绑定。
- view 允许对命名空间大多数对象只读权限,不允许查看角色、角色绑定和Secret。
(2)为一个命名空间中名为default的Service Account授权
如果一个应用没有指定 serviceAccountName,则会使用名为default的Service Account。
注意:赋予Service Account “default”的权限会让所有没有指定serviceAccountName的Pod都具有这些权限。
例如:在命名空间[namespace名称]中为Service Account“default”授予只读权限:
kubectl create rolebinding [rolebinding名称] --clusterrole=view --serviceaccount=[namespace名称]:default --namespace=[namespace名称]
(3)为命名空间中所有Service Account都授予一个角色
在指定命名空间中,任何Service Account应用都具有一个角色,则可以为这一命名空间的Service Account群组进行授权
kubectl create rolebinding [rolebinding名称] --clusterrole=view --group=system:serviceaccounts:[namespace名称] --namespace=[namespace名称]
(4)为集群范围内所有Service Account都授予“只读”角色
如果不想为每个命名空间管理授权,则可以把一个集群级别的角色赋给所有Service Account。
kubectl create clusterrolebinding [clusterrolebinding名称] --clusterrole=view --group=system:serviceaccounts
【注意】:
--group=system:serviceaccounts
代表集群范围内所有Service Account组
(5)为集群范围内所有Service Account授予“超级用户”权限
kubectl create clusterrolebinding [clusterrolebinding名称] --clusterrole=cluster-admin --group=system:serviceaccounts
4-4,使用kubectl命令行工具创建资源对象
(1)在命名空间[namespace名称]中为用户mdy授权admin ClusterRole:
kubectl create rolebinding [rolebinding名称] --clusterrole=admin --user=mdy --namespace=[namespace名称]
(2)在命名空间rbac中为名为myapp的Service Account授予view ClusterRole:
kubctl create rolebinding [rolebinding名称] --clusterrole=view --serviceaccount=[namespace名称]:myapp --namespace=[namespace名称]
(3)在全集群范围内为用户root授予cluster-admin ClusterRole:
kubectl create clusterrolebinding [clusterrolebinding名称] --clusterrole=cluster-admin --user=root
(4)在全集群范围内为名为myapp的Service Account授予view ClusterRole:
kubectl create clusterrolebinding [clusterrolebinding名称] --clusterrole=view --serviceaccount=myapp
五,案例
5-1,RBAC创建服务账户并绑定角色
本案例将通过服务账号serviceAccount ,角色role,rolebinding,命名空间namespace, 创建用户只能访问指定空间下的pod。
第1步:创建命名空间
创建一个命名空间namespace,命名为ns-read-pod
kubectl create ns ns-read-pod
第2步:创建服务账户
在命名空间(ns-read-pod)下,创建一个服务账户serviceAccount ,命名为sa-read-pod
kubectl create sa sa-read-pod -n ns-read-pod
第3步:创建角色
创建一个角色role,命名为role-read-pod,对该命名空间(ns-read-pod)下的pod,仅设置读权限。
# cat role-read-pod.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: role-read-pod # 角色名称
namespace: ns-read-pod # 指定命名空间
rules:
- apiGroups: [""] # 资源组,为空 代表默认所有
resources: ["pods","pods/log"] # 指定资源类型
resourceNames: [""] # 不设置,代表多有pod
verbs: ["get", "watch", "list"] # 只有读权限
第4步:rolebinding绑定,即授权
创建一个rolebinding,命名为rolebinding-read-pod,将角色(role-read-pod)和服务账号(sa-read-pod)进行绑定。
【命令行】创建:
kubectl create rolebinding rolebinding-read-pod -n ns-read-pod --role=role-read-pod --serviceaccount=ns-read-pod:sa-read-pod
【Ymal】创建:
# cat rolebinding-read-pod.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rolebinding-read-pod2
namespace: ns-read-pod
subjects: # 定义绑定的账号
- kind: ServiceAccount # 定义账号类型:"User","Group","ServiceAccount"
name: sa-read-pod # 具体账号名称
namespace: ns-read-pod # 定义账号所在命名空间
apiGroup: ""
roleRef: # 定义绑定的角色
kind: Role # 定义角色类型:Role,ClusterRole
name: role-read-pod # 具体角色名称
apiGroup: rbac.authorization.k8s.io
第5步:创建pod,绑定sa账号
创建一个pod,命名为pod-read-pod,在命名空间(ns-read-pod)下,绑定serviceAccount服务账户(sa-read-pod)
# cat pod-read-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-read-pod # pod名称
namespace: ns-read-pod # 指定命名空间
labels:
app: read-pod
spec:
serviceAccountName: sa-read-pod # 绑定SA账户
containers:
- name: container-read-pod
image: nginx
imagePullPolicy: IfNotPresent
第6步:进入pod,用证书访问k8s资源
# 进入pod
kubectl exec -it pod-read-pod -n ns-read-pod -- /bin/bash
# 进入指定目录
cd /var/run/secrets/kubernetes.io/serviceaccount/
# 通过证书,访问kubernets资源
curl --cacert ./ca.crt -H "Authorization: Bearer $(cat ./token)" https://kubernetes.default/api/v1/namespaces/ns-read-pod/pods
至此,成功访问集群内的pods!!
如果有以下提示(403错误),代表授权失败:
5-2,限制不同普通用户,操作k8s集群
应用场景:
针对刚入职新的运维员工,开设服务器账号:yunwei,密码:123456
权限:
新员工k8s账号,只能有访问命名空间(k8s-test)内的资源。
第1步:ssl认证
针对普通用户k8s-admin,做ssl认证后,已被APIserver信任,该用户可以访问apiServer,但是还没有任何操作权限。
# 进入pki目录
cd /etc/kubernetes/pki/
# 生成一个私钥
(umask 077; openssl genrsa -out k8s-admin.key 2048)
# 生成一个账号名为 k8s-admin 的证书请求
openssl req -new -key k8s-admin.key -out k8s-admin.csr -subj "/CN=k8s-admin"
# 生成一个证书 k8s-admin.crt
openssl x509 -req -in k8s-admin.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out k8s-admin.crt -days 3650
第2步:在kubeconfig下新增加用户k8s-admin
# 对config文件备份,以免出差恢复
cp /root/.kube/config /root/.kube/config.backup
# 把用户k8s-admin添加到kubernetes集群中(用来认证apiserver的连接)
kubectl config set-credentials k8s-admin --client-certificate=./k8s-admin.crt --client-key=./k8s-admin.key --embed-certs=true
# 把用户k8s-admin添加到kubernetes集群中的“上下文”中
kubectl config set-context k8s-admin@kubernetes --cluster=kubernetes --user=k8s-admin
执行以上命令后,关于k8s-admin的用户,已经加入到kubernetes配置文件(config)的**“用户”和“上下文”**中:
kubectl配置相关命令,可以通过
kubectl config --help
查看具体操作。
第3步:对k8s内,普通用户k8s-admin授权
对用户授权:仅仅对命名空间k8s-test下有管理员cluster-admin权限。
# 创建名称空间k8s-test
kubectl create ns k8s-test
# 将用户k8s-admin通过rolebinding绑定到clusterrole上,限制在命名空间k8s-test里有效。
kubectl create rolebinding k8s-admin-rolebinding --clusterrole=cluster-admin --user=k8s-admin -n k8s-test
# 切换到k8s-admin这个用户
kubectl config use-context k8s-admin@kubernetes
# 测试是否仅仅在命名空间(k8s-test)内,有权限访问pod
kubectl get pods -n k8s-test
第4步:更改config配置,增加linux服务账号
# 将配置文件拷贝到root下(其他位置也可以)进行更改
cp /root/.kube/config /root/
删除’/root/config’ 文件内容:
config文件已经改好,放到linux新账号的“家目录”即可。
# 在contos服务器创建新的登录账号:yunwei 密码:123456
useradd yunwei
passwd yunwei
第5步:更改config配置路径,测试访问kubernetes
mkdir -p /home/yunwei/.kube/
cp -ar /root/config /home/yunwei/.kube/
chown -R yunwei:yunwei /home/yunwei/
至此,整个账号权限开设完毕!!