zoukankan      html  css  js  c++  java
  • ⑤.kubernetes之认证、授权和准入控制

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

    一、ServiceAccount

    Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同

    • User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;
    • User account是跨namespace的,而service account则是仅局限它所在的namespace;
    • 每个namespace都会自动创建一个default service account;
    • Token controller检测service account的创建,并为它们创建secret;
    • 开启ServiceAccount Admission Controller后
      • 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
      • 验证Pod引用的service account已经存在,否则拒绝创建
      • 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中
      • 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/
        当创建 pod 的时候,如果没有指定一个 service account,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account。而pod和apiserver之间进行通信的账号,称为serviceAccountName。如下:
    [root@master magedu]# kubectl get pod 
    NAME                                READY   STATUS    RESTARTS   AGE
    c2p-pod                             1/1     Running   0          9d
    demoapp2-677db795b4-8kx4c           1/1     Running   0          16d
    demoapp2-677db795b4-9vf7x           1/1     Running   0          16d
    [root@master magedu]# kubectl get pods/c2p-pod -o yaml|grep "serviceAccountName"
      serviceAccountName: default
    [root@master magedu]# kubectl describe pods/c2p-pod 
    Name:         c2p-pod
    Namespace:    default
    Priority:     0
    Node:         node2/192.168.1.244
    ..............................................
    Volumes:
      default-token-ckxbt:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  default-token-ckxbt
        Optional:    false
    .............................................
    

    从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。

    [root@master magedu]# kubectl get ns
    NAME                   STATUS   AGE
    default                Active   20d
    dev-namespace          Active   20d
    [root@master magedu]# kubectl get sa -n dev-namespace
    NAME      SECRETS   AGE
    default   1         20d
    [root@master magedu]# kubectl get secret -n dev-namespace 
    NAME                  TYPE                                  DATA   AGE
    default-token-89wp8   kubernetes.io/service-account-token   3      20d
    [root@master magedu]# kubectl describe secrets default-token-89wp8  -n dev-namespace 
    Name:         default-token-89wp8
    Namespace:    dev-namespace
    Type:  kubernetes.io/service-account-token
    
    Data
    ====
    namespace:  13 bytes
    token:      eyJhbGciOiJSUzI1NiIsImtpZCI6ImxvTjBGUXNUNVYzUkVBVTlOdFpjZW9aMkszd3NsVjZYbkJEWE1CazlrSVEifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXYtbmFtZXNwYWNlIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tODl3cDgiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6ImU4YmQwMTEyLWMwNzYtNDFmMS1hMzFkLTM2ZDc0ZjNmY2UzNyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZXYtbmFtZXNwYWNlOmRlZmF1bHQifQ.BM_6tEpc4aIk_cbPY8sw1H5alnSmZXQuro5cpO2rng-rLyNZSVQLNC5enQ0IrqlA6Ei75FAXzm7XjID3uaeEwy4QpPEyFKODvILwb_FfIXhCviS0B-3UQTEjbcvyjRwduhayki6dZlEcvGIaz4EOw0dyNixZ4QcnUVkfAwXPjU--w7Vg-QHntf8xbYEndlWtYAUlmHqeWxf9WzYYJAyLNfisDbTZBq_0_04IBzRATzqYRi1rx-93luXftdetMkpCsV2ditASNatWcIxTiIeruYBv42fVZLHhM27GREEO3RnbdTWYohk0evN-Ua1DMfZs4BLyLrgr1NBQnAR7xFj-aw
    ca.crt:     1066 bytes
    

    而默认的service account 仅仅只能获取当前Pod自身的相关属性,无法观察到其他名称空间Pod的相关属性信息。如果想要扩展Pod,假设有一个Pod需要用于管理其他Pod或者是其他资源对象,是无法通过自身的名称空间的serviceaccount进行获取其他Pod的相关属性信息的,此时就需要进行手动创建一个serviceaccount,并在创建Pod时进行定义。那么serviceaccount该如何进行定义呢???实际上,service accout也属于一个k8s资源,如下查看service account的定义方式:

    [root@master magedu]# kubectl explain serviceaccount
    KIND:     ServiceAccount
    VERSION:  v1
    
    DESCRIPTION:
         ServiceAccount binds together: * a name, understood by users, and perhaps
         by peripheral systems, for an identity * a principal that can be
         authenticated and authorized * a set of secrets
    
    FIELDS:
       apiVersion	<string>
         APIVersion defines the versioned schema of this representation of an
         object. Servers should convert recognized schemas to the latest internal
         value, and may reject unrecognized values. More info:
         https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
    
       automountServiceAccountToken	<boolean>
         AutomountServiceAccountToken indicates whether pods running as this service
         account should have an API token automatically mounted. Can be overridden
         at the pod level.
    
       imagePullSecrets	<[]Object>
         ImagePullSecrets is a list of references to secrets in the same namespace
         to use for pulling any images in pods that reference this ServiceAccount.
         ImagePullSecrets are distinct from Secrets because Secrets can be mounted
         in the pod, but ImagePullSecrets are only accessed by the kubelet. More
         info:
         https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
    
       kind	<string>
         Kind is a string value representing the REST resource this object
         represents. Servers may infer this from the endpoint the client submits
         requests to. Cannot be updated. In CamelCase. More info:
         https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
    
       metadata	<Object>
         Standard object's metadata. More info:
         https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
    
       secrets	<[]Object>
         Secrets is the list of secrets allowed to be used by pods running using
         this ServiceAccount. More info:
         https://kubernetes.io/docs/concepts/configuration/secret
    

    service account的创建

    [root@k8s-master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run #不执行查看定义方式
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      creationTimestamp: null
      name: mysa
    
    [root@k8s-master mainfests]# kubectl create serviceaccount mysa -o yaml --dry-run > serviceaccount.yaml  #直接导出为yaml定义文件,可以节省敲键盘的时间
    [root@k8s-master mainfests]# kubectl apply -f serviceaccount.yaml 
    serviceaccount/mysa created
    [root@k8s-master mainfests]# kubectl get serviceaccount/mysa -o yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"creationTimestamp":null,"name":"mysa","namespace":"default"}}
      creationTimestamp: 2018-10-11T08:12:25Z
      name: mysa
      namespace: default
      resourceVersion: "432865"
      selfLink: /api/v1/namespaces/default/serviceaccounts/mysa
      uid: 62fc7782-cd2d-11e8-801a-000c2972dc1f
    secrets:
    - name: mysa-token-h2mgk
    

    看到有一个 token 已经被自动创建,并被 service account 引用。设置非默认的 service account,只需要在 pod 的 spec.serviceAccountName 字段中将name设置为您想要用的 service account 名字即可。在 pod 创建之初 service account 就必须已经存在,否则创建将被拒绝。需要注意的是不能更新已创建的 pod 的 service account

    serviceaccount的自定义使用

    这里在default名称空间创建了一个sa为admin,可以看到已经自动生成了一个Tokens:admin-token-7k5nr。

    [root@k8s-master mainfests]# kubectl create serviceaccount admin
    serviceaccount/admin created
    [root@k8s-master mainfests]# kubectl get sa
    NAME      SECRETS   AGE
    admin     1         3s
    default   1         50d
    [root@k8s-master mainfests]# kubectl describe sa/admin
    Name:                admin
    Namespace:           default
    Labels:              <none>
    Annotations:         <none>
    Image pull secrets:  <none>
    Mountable secrets:   admin-token-7k5nr
    Tokens:              admin-token-7k5nr
    Events:              <none>
    [root@k8s-master mainfests]# kubectl get secret
    NAME                    TYPE                                  DATA      AGE
    admin-token-7k5nr       kubernetes.io/service-account-token   3         31s
    default-token-j5pf5     kubernetes.io/service-account-token   3         50d
    mysecret                Opaque                                2         1d
    tomcat-ingress-secret   kubernetes.io/tls                     2         10d
    [root@k8s-master mainfests]# vim pod-sa-demo.yaml  #Pod中引用新建的serviceaccount
    apiVersion: v1
    kind: Pod
    metadata:
      name: pod-sa-demo
      namespace: default
      labels:
        app: myapp
        tier: frontend
    spec:
      containers:
      - name: myapp
        image: ikubernetes/myapp:v1
        ports:
        - name: http
          containerPort: 80
      serviceAccountName: admin
    [root@k8s-master mainfests]# kubectl apply -f pod-sa-demo.yaml 
    pod/pod-sa-demo created
    [root@k8s-master mainfests]# kubectl describe pods pod-sa-demo
    ......
    Volumes:
      admin-token-7k5nr:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  admin-token-7k5nr
        Optional:    false
    ......
    

    在K8S集群当中,每一个用户对资源的访问都是需要通过apiserver进行通信认证才能进行访问的,那么在此机制当中,对资源的访问可以是token,也可以是通过配置文件的方式进行保存和使用认证信息,可以通过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集群的访问

    (1)生成证书
    [root@k8s-master pki]# cd /etc/kubernetes/pki/magedu
    [root@k8s-master pki]# (umask 077;openssl genrsa -out magedu.key 2048)
    Generating RSA private key, 2048 bit long modulus
    ............................................................................................+++
    ...................................................................................+++
    e is 65537 (0x10001)
    [root@k8s-master pki]# ll magedu.key 
    -rw------- 1 root root 1675 Oct 12 23:52 magedu.key
    
    (2)使用ca.crt进行签署
    [root@k8s-master pki]# openssl req -new -key magedu.key -out magedu.csr -subj "/CN=magedu"  证书签署请求
    
    [root@k8s-master pki]# openssl x509 -req -in magedu.csr -CA ../ca.crt -CAkey ../ca.key -CAcreateserial -out magedu.crt -days 3650  #证书签署
    Signature ok
    subject=/CN=magedu
    Getting CA Private Key
    [root@k8s-master pki]# openssl x509 -in magedu.crt -text -noout
    
    (3)添加到用户认证
    [root@k8s-master pki]# kubectl config set-cluster kubernetes --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server=https://192.168.1.242:6443  --kubeconfig=/tmp/magedu.conf
    [root@k8s-master pki]# kubectl config set-credentials magedu --client-certificate=./magedu.crt --client-key=./magedu.key --embed-certs=true --kubeconfig=/tmp/magedu.conf
    User "magedu" set.
    
    [root@k8s-master pki]# kubectl config set-context magedu@kubernetes --cluster=kubernetes --user=magedu --kubeconfig=/tmp/magedu.conf
    Context "magedu@kubernetes" created.
    
    [root@k8s-master pki]# kubectl config use-context magedu@kubernetes --kubeconfig=/tmp/magedu.conf
    
    [root@master magedu]# cat /tmp/magedu.conf 
    apiVersion: v1
    clusters:
    - cluster:
        certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJeE1EZ3dNekEyTURBeE9Gb1hEVE14TURnd01UQTJNREF4T0Zvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTkVwCnNZZ0ZIRG5sejdCRFF5d2JnT2FrZk13YnVhZW1QcEZnbmxhd2ZHOVdUZnU2aHJ0bVNlZVkvckxMRkNac2tmd2kKLzIyVkZjODRtTU1TcDN3UDA0ejl5eEM2anoxclg0SUlvczJvYjlEUWErUWZoRXJpWWNzYzMvMGJ1aEgrUGVSMApIRWI4WitockRwTGdLVnF1eE5Wb010TlB4S2tSTTE3ekQ4Y1pXdmpaWlFXR0xBYXZ6YmwySGRFQmltaWQyMi9CCnE4a2szVmpTNmhsL1hqNTBHS3VxREpKcm1WTFlSL1l0WDR4Zm5QcitnaFJwd3FTY0xaN2w0REJXTUREL1RDbnQKcjhqcU9PTGdCc0xVcFRwdmhpVnNHOGtXckExRXBWWCtsZ3BFOTN6NFdCcjlnMGk2bDZ1MUI5MUZHTElRaG9vRgp2czl1UVdFMzJ2Y2dKYzdpMTY4Q0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZLU1k4aUhYQzRtWDZCSzFpM01ZVDNFdHF6MHNNQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFCQ0R4SDNENXlIUHB4b1NJQTNmdHY3cGNDK2Rhd05XZTlsK25kRDhmQ0tSaVJRNkNmNgpPMnpOWXJtYitVa1RqY1JiN3k2bi9GbDdWQmt1L2thS1RETTZEZUlqK2djMVdMTk1wN0FHdEhPdWF1anNPNVRPCkhuVGVEdEIxRzJDOGhlclFJZ0NZSW1UMWVwWmlSU1ZYMVBoc0lqVWV6MWk1WkFrdlZNeGhvQi9FUWpGVmFrRGgKMVN0RWxNNU9IZDBydHFOTnNIU1RRd2lUYmRNRVFrSDgzaEcydmJLejVHZzNPNHFmdWQ5cGQwM24yd1BPL3ZPTgpjeUE0Y2s4eVowVXN1TVY5YkZWZHVPdzY3emtwdUNGYmpGY1RlWVZGb2Z5dVMrZlUxM3lPeG9JYWM5QXQ3b1FLCnU3cjFrUW1mZXhNeC9GbDh3M3dBclV4MEVlZlByTElKaU9tTwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
        server: https://192.168.1.242:6443
      name: kubernetes
    contexts:
    - context:
        cluster: kubernetes
        user: magedu
      name: magedu@kubernetes
    current-context: magedu@kubernetes
    kind: Config
    preferences: {}
    users:
    - name: magedu
      user:
        client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNvakNDQVlvQ0NRREJMOE5XVW9lM2lEQU5CZ2txaGtpRzl3MEJBUXNGQURBVk1STXdFUVlEVlFRREV3cHIKZFdKbGNtNWxkR1Z6TUI0WERUSXhNRGd5TkRBeE5Ea3lORm9YRFRNeE1EZ3lNakF4TkRreU5Gb3dFVEVQTUEwRwpBMVVFQXd3R2JXRm5aV1IxTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUF3cnBiCkJLWlFkNXYzbGtMWWZoa2ZFc00rNGgzcmhIVldGODFJSStuZjZzMEZ1RUViSUJNdHlRN2d6aDhoTGZLOExsd1MKVk5DTXhMNVczbkRuUWF6YUtVbVl6MktvOEMyMVpCcDFNU0l0dWlNY0JBK2F5Z2NzQXhzTHdQMWxha0l4eDNOcgpOV0pkeG9Eci9HN3MzenZkV1hzNXFtM2U0OEJMd29CTkFPM0dpNEplN0FxMjVxVG92aHpxRXpyNnMyaEtiZ1dNCjcxNkovNm1XcENCUndtNlJQQ0NiNDRjb2o4UERHWTE3TzZHanVHMVArdUlkVmRrbmZoUWltSkVteHhUd0U3akMKcFcwS2UwTDQ2M0g1R3BHaURTeXhHWDdqaGVmbklKTElLL0pacDN0UUp5ekxGS1VmOU1yMnV1aTdaUlBjOWo4eApCZDFUcjBEd3B4QUcrdEIwS1FJREFRQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUFGNk5RK1p6TUkrYjd6CmxLMHRsczd3QzlLTkdUQ3RkVkpRR05ycnNZc2g2NmptMEg1eWNwZzBwZHJCZ04xTklzNEJ0OWdBbjQyVFJYSFAKaWpOOVRBeEVBMVVZZTAwSTVoWWRUeFlZUW9uVTlSZ3RsdHJwVUV1ei8rdWZ0eGhwTFc0bjBENGp6eFFWeWw5NwpiNjFNVjg5WWhqT1F5azVjWFpYSmJqdDY3MUM0ZGZuMVJUMkNoeFBWMFZzN3dEQU5LVDFpbDNJZ0pWSU0rSHhoCkw0V0paTGlkY0F5L2dKcWpUa0VJR2dQSU5FRC9zWFFkREpKZ2MyR0JRMnlNMk44VmUxNGkvQ3dreml5UmZsamkKdklMeFJrcUs1eitya1d2RnQ3K01qbGViL1JTRkQ1MFYzMERMeVF0WURzTkFCbG5WVS9hVDlDMkJZVElJdmhBcwpzT2lLQnFFNAotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
        client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBd3JwYkJLWlFkNXYzbGtMWWZoa2ZFc00rNGgzcmhIVldGODFJSStuZjZzMEZ1RUViCklCTXR5UTdnemg4aExmSzhMbHdTVk5DTXhMNVczbkRuUWF6YUtVbVl6MktvOEMyMVpCcDFNU0l0dWlNY0JBK2EKeWdjc0F4c0x3UDFsYWtJeHgzTnJOV0pkeG9Eci9HN3MzenZkV1hzNXFtM2U0OEJMd29CTkFPM0dpNEplN0FxMgo1cVRvdmh6cUV6cjZzMmhLYmdXTTcxNkovNm1XcENCUndtNlJQQ0NiNDRjb2o4UERHWTE3TzZHanVHMVArdUlkClZka25maFFpbUpFbXh4VHdFN2pDcFcwS2UwTDQ2M0g1R3BHaURTeXhHWDdqaGVmbklKTElLL0pacDN0UUp5ekwKRktVZjlNcjJ1dWk3WlJQYzlqOHhCZDFUcjBEd3B4QUcrdEIwS1FJREFRQUJBb0lCQVFDTVZUek81d1RLamk0cApyZGJUV1V0WmZEZlBRUHpBSXNkK3M4UXZqWlovWW0yaTBkaTRqdG5LTWR5MDd4NDhQTmg5R0lGbGVqNVljMHVyClZ2WnlFQjNRNzJjZTNkMGQ2ZkwxUjFQNXFzWUZoTlBsNFZFT0U0a1dXK0ZtbmJiK2t1SEkrVmJqekJZRXZsaFQKUGFXYlkwc3I5M0FoY0xqV3JYaHJuWWJoQ25xeGdtcmtRbjUvbmdRa3B0eXVERytkeFRTRHdQWTZuamYzQWgyTQpnVHpDZzFLWGUvVUtSMzZ6Wmc5LzRyVklWZlBIQm0vUE9aNVhWVDJ4STU4OWdnQVJMK0F2QjZ1VzBVMkRFU0ozCmhZdlhhTC9WaDBoK1Z1OHRxR0hJeHk2RkgzZGhJT3V5NDdwNlpnek1nWmtxWjF4RUJLRUNtSVNubHNUdmFZdVkKaVRraG5YY0JBb0dCQU9iWWU3Y1Y0WE1CQkEySXBhVkZ2ZEd4MzhpUmVEVStFRmFKZ2dzVXFIZTRoTm9JeVVDWApkaEk3ZWM4aE1wM2pWdEhTVUM4TzQzTzlLa2I4NU95T3IwaVY4bWFUNGpiMjlPYUxDNExjVzY5NzhaTlo3UmFQCnVlZjRvQy9qSmgvQjJQY0h0bC8yU2U1M2hCZnAxSEM2K3VGaE9DekJ5Uy9aeFRhbzZwM2hjL3Z4QW9HQkFOZnkKVzNXSVdJSVg0YVNzeWtVZmdENytMaVdiNVA2WmY3cUxlYU9TcnN3YnFvVHQzMTJiWDc4VWEyTklFTmJkb1Fxawpxa1VyaGtuQW4rRTNwcVdXOWF5ellkcDNob2dXRFlwWWR3SVBPWG1OYzgwcFhhQ3A4NEVIMVNmYTdiNFNwSUE4Cm1DTFNlQ25sNEJUM0lIWkV3VTg3YnNQVU9wUHAzeTdyTG5tZGxKTzVBb0dBZk1NcnVmdmRhU1ozWmtrZ0hYN2YKNUdGYUxUQlI0NVN6aDlHeHN3TnJPYWxFUkFMVG9sRTV3d2phQUpSVW92aW5oNmMvSnUvSkJsaUtiT3RwWG1DUApZNCtHL3VHV05WYXJiWjVnamsxQ1VFbVFlcTd6Y0dvbGM3WHYvWEdxdlNjcmQvZDNIYzRpanZ1UkxNdDN3YVdNCnlocWRIYk51WktveDZDVExDS0U4NmtFQ2dZRUExRmhoVHdXdjR0MFE2Umx3SE9DSS8yaDZnRWozdU5QQUlmT2MKdlJnMEFra0NPSXlnSkMvd3lyaU5rS2NBeUFoUG4yT2tlemY5YVBDZFJwMnVwUTM0cnNZRjV3bTVwSC9xK0t0YwordzExZXUxNWZiaTdkSTBxQVN0dWt5NVlzWnNyWDE0MlM2ZWl1YkJ0MUsvZG4rNmtHQUZkUGZ1blRtT2ZMMGZiCi80TFE0eUVDZ1lBSFFRdm9hcklZYTVYZytyQjdUanZkN1V0c3hhaXlzNjYrS3NLZ2dPRkJBdjN6R1NhTHJqK0YKNlVreXZtRDBvMldmZjZhWW9KYzBsaVdyb3pXaGdwK091cDNLVmxTOEtpbnFPZ0pKUVRsckh5ZFBkNlJDamNOMwpOQ1ZKd1RYdHJsWlhPRVAxSXFma2hxSjk5T3JUVmpKZXk2Y0xEV1dkZ2lJVk5zNERTNkgwTUE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
    
    [root@k8s-master pki]# kubectl config use-context magedu@kubernetes
    Switched to context "magedu@kubernetes".
    [root@k8s-master pki]# kubectl get pods
    No resources found.
    Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
    
    

    从上面的演示,当切换成magedu用户进行访问集群时,由于magedu该账户没有管理集群的权限,所以在获取pods资源信息时,会提示Forrbidden。那么下面就再来了解一下怎么对账户进行授权!!!

    二、RBAC----基于角色的访问控制

    Kubernetes的授权是基于插件形式的,其常用的授权插件有以下几种:

    • Node(节点认证)
    • ABAC(基于属性的访问控制)
    • RBAC(基于角色的访问控制)
    • Webhook(基于http回调机制的访问控制)

    让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问控制。如图:

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

    在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是  把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。此种方式仅作用于名称空间当中,这是什么意思呢?当User1绑定到Role角色当中,User1就获取了对该NamespaceA的操作权限,但是对NamespaceB是没有权限进行操作的,如get,list等操作。
    另外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2,User3通过ClusterRoleBinding到ClusterRole,从而使User2、User3拥有集群的操作权限。Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系如下图:

    但是这里有2种绑定ClusterRoleBindingRoleBinding。也可以使用RoleBinding去绑定ClusterRole
    当使用这种方式进行绑定时,用户仅能获取当前名称空间的所有权限。为什么这么绕呢??举例有10个名称空间,每个名称空间都需要一个管理员,而该管理员的权限都是一致的。那么此时需要去定义这样的管理员,使用RoleBinding就需要创建10个Role,这样显得更加繁重。为此当使用RoleBinding去绑定一个ClusterRole时,该User仅仅拥有对当前名称空间的集群操作权限,换句话说,此时只需要创建一个ClusterRole就解决了以上的需求。

    这里要注意的是:RoleBinding仅仅对当前名称空间有对应的权限。

    在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现。

    三、Kubernetes RBAC的演示

    1、User --> Rolebinding --> Role

    (1)角色的创建
    一个`Role`对象只能用于授予对某一单一命名空间中资源的访问权限
    
    [root@k8s-master ~]# kubectl create role -h   #查看角色创建帮助
    Create a role with single rule.
    
    Examples:
      # Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods
      kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
      
      # Create a Role named "pod-reader" with ResourceName specified
      kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
      
      # Create a Role named "foo" with API Group specified
      kubectl create role foo --verb=get,list,watch --resource=rs.extensions
      
      # Create a Role named "foo" with SubResource specified
      kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
    
    Options:
          --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
    the template. Only applies to golang and jsonpath output formats.
          --dry-run=false: If true, only print the object that would be sent, without sending it.
      -o, --output='': Output format. One of:
    json|yaml|name|go-template|go-template-file|templatefile|template|jsonpath|jsonpath-file.
          --resource=[]: Resource that the rule applies to
          --resource-name=[]: Resource in the white list that the rule applies to, repeat this flag for multiple items
          --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
    annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
          --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
    template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
          --validate=true: If true, use a schema to validate the input before sending it
          --verb=[]: Verb that applies to the resources contained in the rule
    
    Usage:
      kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]
    [options]
    使用kubectl create进行创建角色,指定角色名称,--verb指定权限,--resource指定资源或者资源组,--dry-run单跑模式并不会创建
    
    Use "kubectl options" for a list of global command-line options (applies to all commands).
    
    [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 ~]# cd mainfests/
    [root@k8s-master mainfests]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > role-demo.yaml
    
    [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可以引用在同一命名空间内定义的Role对象。
    
    [root@k8s-master ~]# kubectl create rolebinding -h  #角色绑定创建帮助
    Create a RoleBinding for a particular Role or ClusterRole.
    
    Examples:
      # Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole
      kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1
    
    Options:
          --allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
    the template. Only applies to golang and jsonpath output formats.
          --clusterrole='': ClusterRole this RoleBinding should reference
          --dry-run=false: If true, only print the object that would be sent, without sending it.
          --generator='rolebinding.rbac.authorization.k8s.io/v1alpha1': The name of the API generator to use.
          --group=[]: Groups to bind to the role
      -o, --output='': Output format. One of:
    json|yaml|name|templatefile|template|go-template|go-template-file|jsonpath-file|jsonpath.
          --role='': Role this RoleBinding should reference
          --save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
    annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
          --serviceaccount=[]: Service accounts to bind to the role, in the format <namespace>:<name>
          --template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
    template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
          --validate=true: If true, use a schema to validate the input before sending it
    
    Usage:
      kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
    [--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]
    使用kubectl create进行创建角色绑定,指定角色绑定的名称,--role|--clusterrole指定绑定哪个角色,--user指定哪个用户
    
    Use "kubectl options" for a list of global command-line options (applies to all commands).
    
    [root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --role=pods-reader --user=magedu --dry-run -o yaml > rolebinding-demo.yaml
    [root@k8s-master mainfests]# cat 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这个角色上
    Name:         magedu-read-pods
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"creationTimestamp":null,"name":"magedu-read-pods","name...
    Role:
      Kind:  Role
      Name:  pods-reader
    Subjects:
      Kind  Name    Namespace
      ----  ----    ---------
      User  magedu  
    
     [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
    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          3d
    redis-5b5d6fbbbd-q8ppz   1/1       Running   1          4d
    [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"
    
    

    从上面的操作,可以总结出,role的定义和绑定,仅作用于当前名称空间,在获取ingress-nginx名称空间时,一样会出现Forbidden!!!

    2、User --> Clusterrolebinding --> Clusterrole

    
    ####(1)clusterrole定义
    ClusterRole对象可以授予与Role对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:
    
    * 集群范围资源(例如节点,即node)
    * 非资源类型endpoint(例如”/healthz”)
    * 跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods --all-namespaces来查询集群中所有的pod)
    
    [root@k8s-master mainfests]# kubectl config use-context kubernetes-admin@kubernetes  #切换会kubernetes-admin用户
    Switched to context "kubernetes-admin@kubernetes".
    [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
    
    

    这里我们需要切换回kubernetes-admin账户,是由于magedu账户不具备创建的权限,这也说明普通用户是无法进行创建K8S资源的,除非进行授权。如下,我们另开一个终端,将配置到一个普通用户ik8s上,使其使用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
    

    (2)clusterrolebinding定义

    [root@k8s-master mainfests]# kubectl get rolebinding  #获取角色绑定信息
    NAME               AGE
    magedu-read-pods   1h
    [root@k8s-master mainfests]# kubectl delete rolebinding magedu-read-pods #删除前面的绑定
    rolebinding.rbac.authorization.k8s.io "magedu-read-pods" deleted
    
    [ik8s@k8s-master ~]$ kubectl get pods  #删除后,在ik8s普通用户上进行获取pods资源信息,就立马出现forbidden了
    No resources found.
    Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
    
    [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 get clusterrole
    NAME                                                                   AGE
    admin                                                                  52d
    cluster-admin                                                          52d
    cluster-read                                                           13m
    ......
    
    [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
    
    [root@k8s-master mainfests]# kubectl describe clusterrolebinding magedu-read-all-pods
    Name:         magedu-read-all-pods
    Labels:       <none>
    Annotations:  kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"magedu-read-all-pods","namespace":""...
    Role:
      Kind:  ClusterRole
      Name:  cluster-read
    Subjects:
      Kind  Name    Namespace
      ----  ----    ---------
      User  magedu  
    
    [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"
    

    从上面的实验,我们可以知道对用户magedu进行集群角色绑定,用户magedu将会获取对集群内所有资源的对应权限。

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

    [root@k8s-master mainfests]# kubectl delete clusterrolebinding magedu-read-all-pods
    clusterrolebinding.rbac.authorization.k8s.io "magedu-read-all-pods" deleted

    [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"

  • 相关阅读:
    Ubuntu忘记密码后强制修改密码
    搭建Jetbrains家族IDE授权服务器
    C#ComboBox绑定List
    字体包文件过大
    JS通过ActiveX读写ini配置文件
    NodeJS + express访问html、css、JS等静态资源文件
    VueJS搭建简单后台管理系统框架 (二) 模拟Ajax数据请求
    VueJS搭建简单后台管理系统框架(一)环境搭建
    ExtJS4.x Grid 单元格鼠标悬停提示
    IE9下Ajax缓存问题
  • 原文地址:https://www.cnblogs.com/yangtao416/p/15179607.html
Copyright © 2011-2022 走看看