九、kubernetes之认证、授权和准入控制

    xiaoxiao2022-07-06  207

    API-Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其他各种集群组件访问资源都需要经过此网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能使用api-server,api-server的数据全部存放在etcd当中。如下图:

    认证Authentication api-server有两个工作地址

    一个用于K8S集群外的真实用户访问(宿主机网络) K8S-master上的kube-apiserver服务(K8S-master的IP+6443端口)

    一个用于K8S集群内部pod中应用进行访问(pod网络,由service引入到pod网络中)

    [root@k8s-master ~]# kubectl describe svc kubernetes Name: kubernetes Namespace: default Labels: component=apiserver provider=kubernetes Annotations: <none> Selector: <none> Type: ClusterIP IP: 10.96.0.1 Port: https 443/TCP TargetPort: 6443/TCP Endpoints: 192.168.80.146:6443 Session Affinity: None Events: <none>

    用户认证 user account 用户访问api-server的方式:通常使用kubectl命令,或利用api-server的Request full接口。

    kubectl命令的认证是使用~/.kube/config文件进行。 kubectl-proxy可以作为api-server的Request full接口的反向代理;向kubect-proxy访问无需认证,kubect-proxy向api-server的访问调用kubectl命令的文件进行认证。

    config资源的定义格式

    [root@k8s-master mainfests]# kubectl config view apiVersion: v1 clusters: #集群列表 - cluster: certificate-authority-data: REDACTED server: https://192.168.56.11:6443 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

    config也是K8S的标准资源之一,在该配置文件当中定义了一个集群列表,指定的集群可以有多个;定义一个用户列表,用户也可以有多个,指明集群中的用户;而在上下文列表当中,是进行定义可以使用哪个用户对哪个集群进行访问,以及当前使用的上下文是什么。如图:定义了用户kubernetes-admin可以对kubernetes该集群的访问,用户kubernetes-user1对Clluster1集群的访问 修改config资源 增加新的用户认证

    ##第一步、生成一个新key文件magedu.key [root@k8s-master ~]# cd /etc/kubernetes/pki [root@k8s-master pki]# (umask 077;openssl genrsa -out magedu.key 2048) Generating RSA private key, 2048 bit long modulus ............................................................................................+++ ...................................................................................+++ e is 65537 (0x10001) ##第二步、创建证书生成请求magedu.csr [root@k8s-master pki]# openssl req -new -key magedu.key -out magedu.csr -subj "/CN=magedu" ##第三步、利用私有CA对证书进行签署 [root@k8s-master pki]# openssl x509 -req -in magedu.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out magedu.crt -days 365 #证书签署 Signature ok subject=/CN=magedu Getting CA Private Key ##第四部、往config中注册新用户magedu并制定使用的key文件和证书crt文件 [root@k8s-master pki]# kubectl config set-credentials magedu --client-certificate=./magedu.crt --client-key=./magedu.key --embed-certs=true User "magedu" set. ##第五步、往config中注册新的上下文context [root@k8s-master pki]# kubectl config set-context magedu@kubernetes --cluster=kubernetes --user=magedu Context "magedu@kubernetes" created. ##第六步、修改config现在使用的context [root@k8s-master pki]# kubectl config use-context magedu@kubernetes Switched to context "magedu@kubernetes".

    查看修改后的config,因magedu能通过认证但还未授权,所以不能执行任何操作,如下图: 内部Pod认证service account Service account是为了方便Pod里面的应用调用Kubernetes API或其他外部服务而设计的。service account有以下特性:

    User account是跨namespace的,而service account则是仅局限它所在的namespace

    每个namespace都会自动创建一个default service account

    每创建一个service account,K8S系统会为它们创建相应的secret

    开启ServiceAccount Admission Controller后:

    每个Pod在创建后都会自动设置spec.serviceAccount为所处namespace的default service account(除非指定了其他ServiceAccout) 验证Pod引用的service account已经存在,否则拒绝创建 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/

    而pod和apiserver之间进行通信的账号,称为serviceAccountName。如下:

    ##每个Pod在创建后都会自动设置spec.serviceAccount为所处namespace的default service account(除非指定了其他ServiceAccout) [root@k8s-master ~]# kubectl get pods myapp-0 -o yaml| grep serviceAccountName -A 5 -B 5 priority: 0 restartPolicy: Always schedulerName: default-scheduler securityContext: {} serviceAccount: default serviceAccountName: default subdomain: myapp-svc terminationGracePeriodSeconds: 30 tolerations: - effect: NoExecute key: node.kubernetes.io/not-ready [root@k8s-master ~]# kubectl get -n default sa NAME SECRETS AGE default 1 14d ##验证Token controller检测service account的创建,并为它们创建secret [root@k8s-master ~]# kubectl describe -n default sa default Name: default Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: default-token-cfgsk Tokens: default-token-cfgsk Events: <none> [root@k8s-master ~]# kubectl get -n default secrets NAME TYPE DATA AGE default-token-cfgsk kubernetes.io/service-account-token 3 14d

    service account中的secret最终会以挂载卷的形式被Pod挂载,从而让Pod中的应用能引用secret

    [root@k8s-master ~]# kubectl describe pods myapp-0 | grep "Volumes:" -A 5 Volumes: default-token-cfgsk: Type: Secret (a volume populated by a Secret) SecretName: default-token-cfgsk Optional: false

    默认的service account 的权限都很低,只能获取当前Pod自身的相关属性。如果要创建一个管理型的Pod(dashboard),需要新建一个service account,并为新service account授予更多权限。

    ##新建一个service account并被用于一个新Pod [root@k8s-master ~]# kubectl get secret NAME TYPE DATA AGE default-token-cfgsk kubernetes.io/service-account-token 3 15d [root@k8s-master ~]# kubectl create serviceaccount admin serviceaccount/admin created [root@k8s-master ~]# kubectl get sa NAME SECRETS AGE admin 1 5s default 1 15d [root@k8s-master ~]# kubectl get secret ##自动为新serviceaccount创建secret NAME TYPE DATA AGE `admin-token-trqdn` kubernetes.io/service-account-token 3 8s default-token-cfgsk kubernetes.io/service-account-token 3 15d [root@k8s-master ~]# kubectl describe sa admin Name: admin Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: `admin-token-trqdn` Tokens: admin-token-trqdn Events: <none> ##新建一个Pod并引用名为admin的serviceaccount [root@k8s-master k8s-yaml]# vim ngx-pod1.yaml apiVersion: v1 kind: Pod metadata: name: pod1 labels: tier: frontend spec: containers: - name: hello1 image: 192.168.80.146:5000/my_ngx:v2 serviceAccountName: admin [root@k8s-master k8s-yaml]# kubectl apply -f ngx-pod1.yaml pod/pod1 created [root@k8s-master k8s-yaml]# kubectl describe pods pod1 | grep "Volumes" -A 5 Volumes: admin-token-trqdn: Type: Secret (a volume populated by a Secret) SecretName: admin-token-trqdn Optional: false

    授权authorization

    K8S的常用授权插件 RBAC

    RBAC全称:Role Based Access Control,实现基于角色进行访问控制。

    许可权限:对某些资源对象能进行的某些操作角色:用户(user account 或service account)绑定(扮演)某个角色,而角色绑定许可权限A,那么该用户就有权限A

    角色和角色绑定分为,分为名称空间级别集群级别

    名称空间级别:角色称Role 角色绑定称RoleBinding集群级别:角色称ClusterRole 角色绑定称ClusterRoleBinding

    一般情况使用Rolebinding绑定Role、使用ClusterRoleBinding绑定ClusterRole。也有特殊情况使用RoleBinding绑定ClusterRole。 当用户使用Rolebinding绑定ClusterRole,那么用户能获取clusterRole的权限,但权限范围被限制在当前所处名称空间内 此类特殊的Rolebinding绑定ClusterRole的使用场景: 用户对自己所处的名称空间拥有相同的权限,则使用使用Rolebinding绑定clusterRole可以更便捷的授权。不用每个名称空间都创建Role,然后再绑定。

    Kubernetes RBAC的演示 user --> RoleBinding --> Role 一个Role对象只能对某一个名称空间中资源的有访问权限 1、创建Role

    [root@k8s-master ~]# kubectl create role -h #查看角色创建帮助 [root@k8s-master ~]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml #干跑模式查看role的定义 apiVersion: rbac.authorization.k8s.io/v1 kind: Role #资源类型 metadata: creationTimestamp: null name: pods-reader rules: - apiGroups: #对那些api组内的资源进行操作 - "" resources: #对那些资源定义 - pods verbs: #操作权限定义 - get - list - watch [root@k8s-master mainfests]# vim role-demo.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pods-reader namespace: default rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch [root@k8s-master mainfests]# kubectl apply -f role-demo.yaml #角色创建 role.rbac.authorization.k8s.io/pods-reader created [root@k8s-master mainfests]# kubectl get role NAME AGE pods-reader 3s [root@k8s-master mainfests]# kubectl describe role pods-reader Name: pods-reader Labels: <none> Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pods-reader","namespace":"default"},"rules":[{"apiGroup... PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- pods [] [] [get list watch] #此处已经定义了pods-reader这个角色对pods资源拥有get、list、watch的权限

    2、进行角色绑定RoleBinding RoleBinding可以把用户绑定在同一命名空间内定义的Role对象

    [root@k8s-master ~]# kubectl create rolebinding -h #角色绑定创建帮助 [root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --role=pods-reader --user=magedu --dry-run -o yaml #干跑获得yaml定义格式 [root@k8s-master mainfests]# vim rolebinding-demo.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: creationTimestamp: null name: magedu-read-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: pods-reader subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: magedu [root@k8s-master mainfests]# kubectl apply -f rolebinding-demo.yaml #创建角色绑定 rolebinding.rbac.authorization.k8s.io/magedu-read-pods created [root@k8s-master mainfests]# kubectl describe rolebinding magedu-read-pods #查看角色绑定的信息,这里可以看到user:magedu绑定到了pods-reader这个角色上 [root@k8s-master ~]# kubectl config use-context magedu@kubernetes #切换magedu这个用户,并使用get获取pods资源信息 Switched to context "magedu@kubernetes". [root@k8s-master ~]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 1 36d filebeat-ds-s466l 1/1 Running 2 36d [root@k8s-master ~]# kubectl get pods -n ingress-nginx #测试获取ingress-nginx这个名称空间的pods信息 No resources found. Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"

    user --> ClusterRoleBinding --> ClusterRole 创建一个linux的新用户ik8s,并为他配置kubectl config(使用k8s的用户magedu)

    [root@k8s-master ~]# useradd ik8s [root@k8s-master ~]# cp -rp .kube/ /home/ik8s/ [root@k8s-master ~]# chown -R ik8s.ik8s /home/ik8s/ [root@k8s-master ~]# su - ik8s [ik8s@k8s-master ~]$ kubectl config use-context magedu@kubernetes Switched to context "magedu@kubernetes". [ik8s@k8s-master ~]$ kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: REDACTED server: https://192.168.56.11:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes - context: cluster: kubernetes user: magedu name: magedu@kubernetes current-context: magedu@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED - name: magedu user: client-certificate-data: REDACTED client-key-data: REDACTED

    1、创建ClusterRole 一个ClusterRole对象能整个K8S任何资源都有访问权限

    [root@k8s-master mainfests]# kubectl create clusterrole cluster-read --verb=get,list,watch --resource=pods -o yaml > clusterrole-demo.yaml [root@k8s-master mainfests]# vim clusterrole-demo.yaml #定义clusterrole和权限 apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-read rules: - apiGroups: - "" resources: - pods verbs: - get - list - watch [root@k8s-master mainfests]# kubectl apply -f clusterrole-demo.yaml #创建clusterrole clusterrole.rbac.authorization.k8s.io/cluster-read configured

    2、进行角色绑定ClusterRoleBinding ClusterRoleBinding可以把用户绑定在一个ClusterRole对象

    [root@k8s-master mainfests]# kubectl create clusterrolebinding magedu-read-all-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > clusterrolebinding-demo.yaml [root@k8s-master mainfests]# vim clusterrolebinding-demo.yaml #创建角色绑定,将magedu绑定到clusterrole:magedu-read-all-pods上 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: magedu-read-all-pods roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-read subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: magedu [root@k8s-master mainfests]# kubectl apply -f clusterrolebinding-demo.yaml clusterrolebinding.rbac.authorization.k8s.io/magedu-read-all-pods created [root@k8s-master mainfests]# kubectl get clusterrolebinding NAME AGE ...... magedu-read-all-pods 10s ##切换到ik8s进行验证 [ik8s@k8s-master ~]$ kubectl get pods #角色绑定后在ik8s终端上进行获取pods信息,已经不会出现forbidden了 NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 1 36d filebeat-ds-s466l 1/1 Running 2 36d myapp-0 1/1 Running 0 2d myapp-1 1/1 Running 0 2d myapp-2 1/1 Running 0 2d myapp-3 1/1 Running 0 2d pod-sa-demo 1/1 Running 0 1d pod-vol-demo 2/2 Running 0 4d redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d [ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx #更换名称空间进行查看也是可行的 NAME READY STATUS RESTARTS AGE default-http-backend-7db7c45b69-nqxw9 1/1 Running 1 4d nginx-ingress-controller-6bd7c597cb-9fzbw 1/1 Running 0 4d [ik8s@k8s-master ~]$ kubectl delete pods pod-sa-demo #但是进行删除pod就无法进行,因为在授权时是没有delete权限的 Error from server (Forbidden): pods "pod-sa-demo" is forbidden: User "magedu" cannot delete pods in the namespace "default"

    User --> Rolebinding --> Clusterrole 将maedu通过rolebinding到集群角色magedu-read-pods当中,此时,magedu仅作用于当前名称空间的所有pods资源的权限

    [root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > rolebinding-clusterrole-demo.yaml [root@k8s-master mainfests]# vim rolebinding-clusterrole-demo.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: magedu-read-pods namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-read subjects: - apiGroup: rbac.authorization.k8s.io kind: User name: magedu [root@k8s-master mainfests]# kubectl apply -f rolebinding-clusterrole-demo.yaml rolebinding.rbac.authorization.k8s.io/magedu-read-pods created [ik8s@k8s-master ~]$ kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 1 36d filebeat-ds-s466l 1/1 Running 2 36d myapp-0 1/1 Running 0 2d myapp-1 1/1 Running 0 2d myapp-2 1/1 Running 0 2d myapp-3 1/1 Running 0 2d pod-sa-demo 1/1 Running 0 1d pod-vol-demo 2/2 Running 0 4d redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d [ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx No resources found. Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
    最新回复(0)