• 云原生之Kubernetes:17.详解Apiserver和RBAC


    1、用什么保证Kubernetes系统安全?

    怎样去保证Kubernetes系统安全,我们可以从以下三个方面去做:
    在这里插入图片描述

    1、Apiserver

    首当其冲的就是apiserver,他是第一道关卡,其作用为:

    谁能进入我们的kubernetes集群,这个谁可以是客户端用户、应用程序,也可以是集群中的node节点。

    防范外部的访问我是知道的,但为什么还要防范集群内部的请求呢?

    如果你运维过spring cloud项目,那你应该会碰到这个难题:

    每个环境我们都有注册中心eureka,那我们如何保障应用不会出现乱注册的情况呢?
    比如:生产环境的应用注册到测试环境的eureka?测试环境的应用注册到生产环境的eureka?
    无论哪个情况发生,都是很致命的!

    也许你会考虑,借助一系列配置管理的规范或者一些流程,又或者基于人员角色的分而治之来规避这个情况的发生,但这都是在规范上面的,实际无法去约束!

    重点在于缺少双向认证的功能!谁来我这里注册,我是要有验证的,而不是任何服务都可以来我这里注册服务的。

    这个双向认证的思想,在kubernetes中很是重要,不是所有知道我们集群主节点信息或者join信息的节点都可以肆意加入集群,这是很有风险的。

    kubernetes的bootstrap token引导令牌在这种情况下就此诞生!他会向已知可信任的node节点颁发一个引导令牌,其中会有一个失效期,可能是12小时,也可能是1天,这取决于集群管理员的配置。

    他会告诉node节点,你必须要在这段时间内加入集群,否则我就不信任你了,你也就不能再加入集群了。

    同时apiserver也通过各种https证书,保证了集群内外部的数据交互的安全。

    2、RBAC

    接着就是系统安全的第2道关卡:RBAC!

    基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略,其职责为:

    对于已知的客户端用户,他们需要什么的权限,他们能够操作什么类型的资源,这就是他所负责的事情了。

    RBAC的配置顺序如下所示:

    首先,定义一个服务账号service account,也就是定义角色;
    接着,定义一个role策略,比如:允许查看pod,禁止describepod等;
    最后,将定义好的角色和role策略进行绑定(binding)即可。

    RBAC中配置生效的经验之谈:

    role+rolebinding=作用于对应名称空间的策略
    clusterrole+clusterrolebinding=作用域集群级别的策略
    clusterrole+rolebinding=作用于对应名称空间的策略,作用同第一条。其好处是更灵活更简洁。

    如果你配置过jumpserver的用户组、机器组和授权,想必很好理解。

    3、Admission Controller

    最后,把手整个系统安全的就是Admission Controller准入控制器了。

    对于已知用户,他可以管理(可能是查看、也可能是新建、也可能会删除等等)其命名空间或者对应集群下的所有授权资源。但这里有一个问题!不知道,你想到了没有?

    如何去校验用户的操作是否合规呢?
    例如:是否在yaml中配置了limits和requets字段,又或者研发人员配置的这两个字段是否合理?

    这也是十分重要的一个环节,对于初创公司或者是kubernetes初建设团队,这个环节可能也可容许暂时被忽略,大家基于一定的自觉、团队研发和上线流程的规范,来软限制这点。

    但当你的团队、集群越来越大的时候,Admission Controller准入控制器的上线和把控是缺一不可的!

    2、实战:Apiserver

    1、首先,我们生成一个用户验证的用户私钥ilinux.crt

    openssl genrsa -out ilinux.crt 2048
    
    • 1

    2、接着,生成证书签名请求文件ilinux.csr,用户证书签名

    openssl req -new -key ilinux.key -out ilinux.csr -subj "/CN=ilinux/O=kubeusers"
    
    • 1

    3、然后,使用k8s的ca.crt和ca.key进行签名生成证书ilinux.crt,有效期为365天

    [root@centos-1 pki]# cd /etc/kubernetes/pki/ 
    [root@centos-1 pki]# openssl x509 -req -in ilinux.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ilinux.crt -days 365
    Signature ok
    subject=/CN=ilinux/O=kubeusers
    Getting CA Private Key
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4、设置新集群(mykube),指明apiserver地址、k8s证书路径和隐藏证书,并保存在(/tmp/ilinux.kubeconfig)

    kubectl config set-cluster mykube --server="https://192.168.0.104:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/ilinux.kubeconfig
    
    • 1

    5)此时,通过查看集群,可以发现新集群已经创建成功;名为mykube

    [root@centos-1 ~]# kubectl config get-clusters 
    NAME
    mykube
    kubernetes
    
    • 1
    • 2
    • 3
    • 4

    6、接着,我们需要配置新集群权限,其自定义权限名为ilinux,username需要和ilinux.csr的CN需要保持一致,–embed-certs=true表示需要打包存放

    kubectl config set-credentials ilinux --client-certificate=/etc/kubernetes/pki/ilinux.crt --client-key=/etc/kubernetes/pki/ilinux.key --username=ilinux --embed-certs=true  --kubeconfig=/tmp/ilinux.kubeconfig
    
    • 1

    7、配置context上下文,并绑定上面设置的新集群名、用户名和自定义权限名,并保存在/tmp/ilinux.kubeconfig

    kubectl config set-context ilinux@mykube --cluster=mykube --user=ilinux  --kubeconfig=/tmp/ilinux.kubeconfig
    
    • 1

    8、查询当前集群配置信息,发现新集群已经载入,但没有载入使用。
    当前读取的配置是current-context: kubernetes-admin@kubernetes

    [root@centos-1 ~]# kubectl config view
    apiVersion: v1
    clusters:
    - cluster:
            certificate-authority-data: DATA+OMITTED
            server: https://192.168.0.104:6443
        name: kubernetes
    - cluster:
            certificate-authority-data: DATA+OMITTED
            server: https://192.168.0.104:6443
        name: mykube
    contexts:
    - context:
            cluster: mykube
            user: ilinux
        name: ilinux@mykube
    - context:
            cluster: kubernetes
            user: kubernetes-admin
        name: kubernetes-admin@kubernetes
    current-context: kubernetes-admin@kubernetes
    kind: Config
    preferences: {}
    users:
    - name: ilinux
        user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED
            username: ilinux
    - name: kubernetes-admin
        user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    9、这里,我们使用新配置的use-context ilinux@mykube进行操作,发现已经没有查询pod的权限了

    [root@centos-1 tmp]# kubectl get pods
    NAME                     READY   STATUS    RESTARTS   AGE
    ngx-new-cb79d555-hfc7h   1/1     Running   0          9d
    
    [root@centos-1 tmp]# kubectl config use-context ilinux@mykube
    Switched to context "ilinux@mykube".
    [root@centos-1 tmp]# kubectl get pods
    Error from server (Forbidden): pods is forbidden: User "ilinux" cannot list resource "pods" in API group "" in the namespace "default"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    10、这时候,再切换成管理员账号,发现一切正常

    [root@centos-1 tmp]# kubectl config use-context         kubernetes-admin@kubernetes
    Switched to context "kubernetes-admin@kubernetes".
    [root@centos-1 tmp]# kubectl get pods
    NAME                     READY   STATUS    RESTARTS   AGE
    ngx-new-cb79d555-hfc7h   1/1     Running   0          9d
    
    • 1
    • 2
    • 3
    • 4
    • 5

    11、我们还可以使用位置参数的方式,使用自定义配置文件进行用户权限临时的切换

    [root@centos-1 tmp]# kubectl config view --kubeconfig=/tmp/ilinux.kubeconfig
    apiVersion: v1
    clusters:
    - cluster:
            certificate-authority-data: DATA+OMITTED
            server: https://192.168.0.104:6443
        name: mykube
    contexts:
    - context:
            cluster: mykube
            user: ilinux
        name: ilinux@mykube
    current-context: ""
    kind: Config
    preferences: {}
    users:
    - name: ilinux
        user:
            client-certificate-data: REDACTED
            client-key-data: REDACTED
            username: ilinux
    
    [root@centos-1 tmp]# kubectl config use-context ilinux@mykube --kubeconfig=/tmp/ilinux.kubeconfig
    Switched to context "ilinux@mykube".
    
    [root@centos-1 tmp]# kubectl get pods --kubeconfig=/tmp/ilinux.kubeconfig
    Error from server (Forbidden): pods is forbidden: User "ilinux" cannot list resource "pods" in API group "" in the namespace "default"
    [root@centos-1 tmp]# kubectl get pods 
    NAME                     READY   STATUS    RESTARTS   AGE
    ngx-new-cb79d555-hfc7h   1/1     Running   0          9d
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    3、RBAC介绍

    RBAC的介绍,上面已经聊了不少,如果你还感兴趣,可以参考RBAC官方文档。
    1、授权模型

    基于节点:

    Node:专用的授权插件,根据Pod对象调度的结果为Node进行授权

    基于用户:

    ABAC:1.17之前的策略,新版本已经默认使用RBAC
    RBAC:赋予某个角色对于某个资源进行某种操作,其中角色可以是人也可以是组

    其他:

    Webhook

    2、集群策略查看

    你可以在集群中,使用cat /etc/kubernetes/manifests/kube-apiserver.yaml查看到当前集群生效的策略是什么?

    –authorization-mode=Node,RBAC看到没有?

    [root@centos-1 dingqishi]# cat /etc/kubernetes/manifests/kube-apiserver.yaml 
    apiVersion: v1
    kind: Pod
    metadata:
        creationTimestamp: null
        labels:
            component: kube-apiserver
            tier: control-plane
        name: kube-apiserver
        namespace: kube-system
    spec:
        containers:
        - command:
            - kube-apiserver
            - --advertise-address=192.168.0.104
            - --allow-privileged=true
            - --authorization-mode=Node,RBAC
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3、相关命令

    名称空间级别权限和绑定的配置查看:

    kubectl explain role
    kubectl explain rolebinding
    
    • 1
    • 2

    集群级别权限和绑定的配置查看:

    kubectl explain ClusterRole
    kubectl explain ClusterRoleBinding
    
    • 1
    • 2

    已有策略的详情查看:

    kubectl get role view -o yaml
    kubectl get clusterrole view -o yaml
    
    • 1
    • 2

    4、实战:RBAC

    (以下所有操作都基于上面创建的ilinux用户进行,并且每个操作之前需要删除之前配置过的权限,否则会相互影响)
    1、Role+RoleBinding

    应用场景:某个名称空间级别的权限授权

    我们先编辑role:res-reader.yaml,定义规则为:default名称空间下,只能get、list和watch相关资源

    kind: Role             #名称空间权限
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      namespace: default         #只能读取default名称空间下的对应规则
      name: res-reader
    rules:
    - apiGroups: [""]   # "" 表示核心群组:core API group
      resources: ["pods", "pods/log", "services"]
      verbs: ["get", "list", "watch"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    然后我们来定义授权绑定rolebinding:ilinux-res-reader.yaml,其作用是将ilinux用户,绑定到我们上面定义的名为res-reader的权限上。

    kind: RoleBinding                 #名称空间级别权限绑定;ClusterRoleBinding为集群级别的权限绑定
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: ilinux-res-reader                   #增加可读性,命名规则:<用户>-<权限>
      namespace: default
    subjects:
    - kind: User
      name: ilinux
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: Role
      name: res-reader
      apiGroup: rbac.authorization.k8s.io
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    依次apply配置文件,发现ilinux用户在default名称空间下有对应pods, pods/log, services的对应权限,和预期一样

    [root@centos-1 RBAC]# kubectl get pod --kubeconfig=/tmp/ilinux.kubeconfig 
    NAME                     READY   STATUS    RESTARTS   AGE
    ngx-new-cb79d555-hfc7h   1/1     Running   0          10d
    
    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig
    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11d
    
    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig -n ingress-nginx
    Error from server (Forbidden): services is forbidden: User "ilinux" cannot list resource "services" in API group "" in the namespace "ingress-nginx"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、ClusterRole+ClusterRoleBinding

    应用场景:k8s集群级别的权限授权

    编辑ClusterRole:cluster-res-reader.yaml

    kind: ClusterRole             #集群范围权限
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cluster-res-reader
    rules:
    - apiGroups: [""]   # "" 表示核心群组:core API group
      resources: ["pods", "pods/log", "services"]
      verbs: ["get", "list", "watch"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编辑ClusterRoleBinding:cluster-ilinux-res-reader.yaml

    kind: ClusterRoleBinding                  #ClusterRoleBinding为集群级别的权限绑定
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cluster-ilinux-res-reader                   #增加可读性,命名规则:<用户>-<权限>
    subjects:
    - kind: User
      name: ilinux
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: cluster-res-reader
      apiGroup: rbac.authorization.k8s.io
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    依次apply配置文件,并通过以下命令观察权限生成情况

    [root@centos-1 RBAC]# kubectl get clusterrole
    [root@centos-1 RBAC]# kubectl get clusterrolebinding
    
    • 1
    • 2

    这时,我们发现ilinux用户已经具有集群级别(所有名称空间)的对应权限

    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig -n ingress-nginx
    NAME                       TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
    nginx-ingress-controller   NodePort   10.99.160.254   <none>        80:30080/TCP,443:30443/TCP   26h
    
    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig 
    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11d
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3、ClusterRole+RoleBinding

    应用场景:交叉使用,其中ClusterRole策略会降级成rolebinding名称空间级别的策略,效果和role+rolebinding一样

    好处:在名称空间很多的时候,重复权限的配置文件会少一半,而且更灵活

    使用上面的ClusterRole(cluster-res-reader.yaml),并apply-f
    编辑rolebinding:cluster-default-ilinux-res-reader.yaml

    kind: RoleBinding                 #名称空间级别权限绑定;ClusterRoleBinding为集群级别的权限绑定
    apiVersion: rbac.authorization.k8s.io/v1
    metadata:
      name: cluster-default-ilinux-res-reader                   #增加可读性,命名规则:<用户>-<权限>
      namespace: default
    subjects:
    - kind: User
      name: ilinux
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: cluster-res-reader
      apiGroup: rbac.authorization.k8s.io    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    测试和预期一样,ClusterRole降级成default名称空间的权限了

    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig 
    NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
    kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   11d
    
    [root@centos-1 RBAC]# kubectl get service --kubeconfig=/tmp/ilinux.kubeconfig  -n ingress-nginx
    Error from server (Forbidden): services is forbidden: User "ilinux" cannot list resource "services" in API group "" in the namespace "ingress-nginx"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    hitcontraining_uaf
    轮到国产游戏统治Steam榜单
    【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(9 月 14 日论文合集)
    3D移动 translate3d
    计及新能源出力不确定性的电气设备综合能源系统协同优化(Matlab代码实现)
    vue官方文档(18) :具名插槽示例
    javascript验证表单字段有效性,使用checkValidity()方法和他的属性
    Spring Boot (三)
    map&set的封装
    计算机视觉--通过HSV和YIQ颜色空间处理图像噪声
  • 原文地址:https://blog.csdn.net/flq18210105507/article/details/126645466