zoukankan      html  css  js  c++  java
  • Kubernetes之ServiceAccount + Secret + RBAC实现访问APIServer

    API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,一个Pod如果要想访问API Server需要经过以下步骤

    第一步:对客户端访问进行认证操作,确认是否具有访问k8s权限  #这步就是Pod引用Service Account,决定是否能访问API Server
        token(共享秘钥)
        SSL(双向SSL认证)
    ....通过任何一个认证即表示认证通过,进入下一步
    第二步:授权检查,确认是否对资源具有相关的权限   #这步就是创建一个ClusterRole或者Role,然后ClusterRoleBinding或者RoleBinding把ClusterRole和Server Account绑定到一起,决定该Service Account有权限访问API Server的哪些资源,比如Deployment、Pod之类的
        ABAC(基于属性的访问控制)
        RBAC(基于角色的访问控制)
        NODE(基于节点的访问控制)
        WEB HOOK(自定义HTTP回调方法的访问控制)
    第三步:准入控制(对操作资源相关联的其他资源是否有权限操作)

    ServiceAccount

    一.ServiceAccount和User Account介绍

    Kubernetes中账号区分为:Service Account(服务账户)和User Account(用户账户),它们的设计及用途如下

    1).User Account介绍

    User Account是给Kubernetes集群外部使用的,例如运维或者集群管理员,使用kubectl 命令时就是用的User Account账户

    User Account是全局性;在集群所有NameSpace中,名称具有唯一性.

    用户名称可以在kubeconfig中查看

    [root@Centos8 ~]# cd ~/.kube/
    [root@Centos8 .kube]# ls
    cache  config  http-cache
    [root@Centos8 .kube]# cat config
    ...
        users:
        - name: kubernetes-admin
    ...

    2)Service Account介绍

    Service Account是给运行在Pod里的程序使用的身份认证,Pod容器的进程需要访问API Server时用的就是Service Account账户

    Service Account仅局限在它所在的NameSpace,只有该NameSpace下的Pod引用这个Service Account才有权限,每个NameSpace创建时都会自动创建一个Secret(访问API Server时用的Token和CA)和一个Service Account,然后Service Account引用Secret;

    如果每个Pod不指定Service Account的话,就会自动引用该NameSpace下默认的Service Account,此时该Pod可以访问API Server了;

    Service Account为服务提供了一种方便的认证机制,但是Service Accoun不关心授权问题,Pod绑定该Service Account之后,仅仅是能访问API Server了,但是能访问API Server的哪些资源(Deployment、Pod、ConfigMap之类的资源),需要配合RBAC来为Service Account授权

    二.默认的Service Account

    Service Account仅局限它所在的NameSpace,所以在创建NameSpace时会自动创建一个默认的SA,而SA创建时,也会创建对应的Secret,下面操作验证

    1)创建命名空间

    [root@Centos8 .kube]# kubectl create ns vfan
    namespace/vfan created

    2)查看SA

    [root@Centos8 .kube]# kubectl get sa -n vfan
    NAME      SECRETS   AGE
    default   1         67s

    3)查看SA引用的默认Secret

    [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类型的secret

    所有引用该SA的Pod都能访问API Server了

    4)创建一个Pod

    文件名:pods.yaml
    apiVersion: v1 kind: Pod metadata: name: test
    namespace: vfan spec: containers: - name: test image: radial/busyboxplus:curl stdin: true
    tty: true

    为什么pod使用镜像: radial/busyboxplus:curl ,是为了方便执行 curl命令来进行验证

    5)查看Pod引用默认的SA

    [root@Centos8 rbac]# kubectl describe pod test -n vfan
    ...
    Containers:
      test:
        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
    ...
    说明:每个Pod在创建后都会引用这个default的Service Account,除非指定了其他的Service Account
    每个Container启动后都会挂载对应的ServiceAccount引用的Secret里的token、namespace、ca.crt到/var/run/secrets/kubernetes.io/serviceaccount下

    6)进入Pod查看挂载的Token、CA、namespace信息

    /test $ ls -l /var/run/secrets/kubernetes.io/serviceaccount/
    total 0
    lrwxrwxrwx    1 root     root            13 Nov 27 09:00 ca.crt -> ..data/ca.crt
    lrwxrwxrwx    1 root     root            16 Nov 27 09:00 namespace -> ..data/namespace
    lrwxrwxrwx    1 root     root            12 Nov 27 09:00 token -> ..data/token
    ##说明:
    可以看到已将ca.crt 、namespace和token放到容器内了,那么这个容器就可以用Token和CA通过https的请求访问apiserver了

    7)进入Pod测试访问API Server的权限

    #kubectl exec -it test -n vfan
    $curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat/var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods
    {
      "kind": "Status",
      "apiVersion": "v1",
      "metadata": {
    
      },
      "status": "Failure",
      "message": "pods is forbidden: User "system:serviceaccount:mynamespace:default" cannot list resource "pods" in API group "" at the cluster scope",
      "reason": "Forbidden",
      "details": {
        "kind": "pods"
      },
      "code": 403   ##表示403无法访问,没权限
    
    ###注意:
    虽然该Pod的能访问API Server了,还得通过RBAC为该Service Account授权,来决定该ServiceAccount有权限访问API Server的哪些资源,比如Deployment、Pod、Node、Configmap等资源

    授权

    接下来就要通过RBAC给default这个service account授权,来让default这个Service Account拥有list pod的权限

    一、添加ClusterRole

    #cat example-clusterrole.yaml
    
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: example-clusterrole
    rules:
    - apiGroups:
      - ""
      resources:
      - nodes
      - nodes/proxy
      - nodes/metrics
      - services
      - endpoints
      - pods
      - ingress
      verbs:
      - get
      - list
      - watch
    - nonResourceURLs:
      - /metrics
      verbs:
      - get

    二、通过ClusterRoleBinding把ClusterRole和ServiceAccount绑定到一起,Service Account就有ClusterRole定义的权限了

    通过ClusterRoleBinding给所有NameSpace下的default Service Account授权

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: example-clusterrolebinding
    subjects:
    - kind: Group
      name: system:serviceaccounts
      apiGroup: rbac.authorization.k8s.io
    roleRef:
      kind: ClusterRole
      name: example-clusterrole
      apiGroup: rbac.authorization.k8s.io

    二、也可以通过ClusterRoleBinding给单独一个NameSpace下的defult Service Account授权 (可以跟上面的二选一,是给所有授权,还是单独一个授权)

    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      annotations:
      name: example-clusterrolebinding
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: exampe-clusterrole
    subjects:
    - kind: ServiceAccount
      name: default
      namespace: vfan

    三、再次进入容器,通过执行curl命令获取所有pod,执行成功

    #kubectl attach -it test -n vfan
    $curl --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt --header "Authorization:Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1/namespaces/$(cat/var/run/secrets/kubernetes.io/serviceaccount/namespace)/pods
    ...
    "imageID": "docker-pullable://radial/busyboxplus@sha256:a68c05ab1112fd90ad7b14985a48520e9d26dbbe00cb9c09aa79fdc0ef46b372",
                "containerID": "docker://d6b1a94caa364392ac7e3c07dd99faa1c80f15fe6f757aa54509ea778b6c93aa",
                "started": true
              }
            ],
            "qosClass": "BestEffort"
          }
        }
      ]
  • 相关阅读:
    springMVC3学习(二)--ModelAndView对象
    springMVC3学习(一)--框架搭建
    JS作用域
    JS阻止事件冒泡
    Oracle常用函数
    Oracle中复制表结构和表数据
    转:JavaBean 、 Serverlet 总结
    form插件ajaxForm和ajaxSubmit方法传递对象参数说明
    http status 汇总
    浅谈HTTP中Get与Post的区别
  • 原文地址:https://www.cnblogs.com/chadiandianwenrou/p/14070120.html
Copyright © 2011-2022 走看看