API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中。如下图:
9.1 Service Account
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同
User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;
User account是跨namespace的,而service account则是仅局限它所在的namespace;
[root@k8s-master ~]$ kubectl get pods NAME READY STATUS RESTARTS AGE busybox-6f99677459-qhjpd 1/1 Running 0 19h statefulset-nginx-0 1/1 Running 0 18h statefulset-nginx-1 1/1 Running 0 18h statefulset-nginx-2 1/1 Running 0 18h statefulset-nginx-3 1/1 Running 0 18h statefulset-nginx-4 1/1 Running 0 18h [root@k8s-master ~]$ kubectl get pods statefulset-nginx-0 -o yaml | grep -i serviceaccount - mountPath: /var/run/secrets/kubernetes.io/serviceaccount serviceAccount: default serviceAccountName: default [root@k8s-master ~]$ kubectl describe pod statefulset-nginx-1 Name: statefulset-nginx-1 Namespace: default ...... Volumes: ...... default-token-zl497: Type: Secret (a volume populated by a Secret) SecretName: default-token-zl497 Optional: false
从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[root@k8s-master ~]# kubectl get sa NAME SECRETS AGE default 1 8d [root@k8s-master ~]# kubectl describe sa default Name: default Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: default-token-zl497 Tokens: default-token-zl497 Events: <none> [root@k8s-master ~]# kubectl get secret NAME TYPE DATA AGE default-token-zl497 kubernetes.io/service-account-token 3 8d
[root@k8s-master ~]# kubectl explain sa 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/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/api-conventions.md#types-kinds
metadata <Object> Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/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
[root@k8s-master ~]# kubectl get secrets # 查看自动生成的secret NAME TYPE DATA AGE default-token-zl497 kubernetes.io/service-account-token 3 8d mysa-token-7tf64 kubernetes.io/service-account-token 3 24s
看到有一个 token 已经被自动创建,并被 service account 引用。设置非默认的 service account,只需要在 pod 的spec.serviceAccountName 字段中将name设置为您想要用的 service account 名字即可。在 pod 创建之初 service account 就必须已经存在,否则创建将被拒绝。需要注意的是不能更新已创建的 pod 的 service account
# 切换之后获取pod测试显示没有任何权限获取集群中的对象资源 [root@k8s-master pki]# kubectl get pods -o wide Error from server (Forbidden): pods is forbidden: User "putianhui" cannot list resource "pods"in API group ""in the namespace "default"
[root@k8s-master /]$ kubectl get rolebinding NAME AGE putianhui-rolebinding 6s
[root@k8s-master /]$ kubectl describe rolebinding putianhui-rolebinding #可以看到putianhui用户已经绑定到pod-reader这个role上面了 Name: putianhui-rolebinding Labels: <none> Annotations: <none> Role: Kind: Role Name: pod-reader Subjects: Kind Name Namespace ---- ---- --------- User putianhui # 切换用户验证权限信息是否正确(切换集群用户到前面创建的putianhui用户上使用get pods查看信息) [root@k8s-master /]$ kubectl config use-context putianhui@kubernetes Switched to context "putianhui@kubernetes".
[root@k8s-master /]$ kubectl get pods # 使用get pods访问默认namespace没问题 NAME READY STATUS RESTARTS AGE nginx-797f679bcf-jvjnp 1/1 Running 0 33h
[root@k8s-master /]# kubectl get pods -n ingress-nginx # 使用get pods访问ingress名称空间的pod报错。 Error from server (Forbidden): pods is forbidden: User "putianhui" cannot list resource "pods"in API group ""in the namespace "ingress-nginx"
[root@k8s-master /]$ kubectl get svc # 使用get svc提示没有权限(因为前面只授权了putianhui这个用户针对pods资源只有 get watch list这三个权限) Error from server (Forbidden): services is forbidden: User "putianhui" cannot list resource "services"in API group ""in the namespace "default"
[root@k8s-master /]$ kubectl describe clusterrolebinding cluster-rolebind Name: cluster-rolebind Labels: <none> Annotations: <none> Role: Kind: ClusterRole Name: read-all-pod-clusterole Subjects: Kind Name Namespace ---- ---- --------- User putianhui ## 切换到putianhui用户验证(因为clusterrole授予了pods的get wath list权限,因此可以使用get pod任何名称空间的内容,其他svc deploy这些是无法get到的,还有delete pod这些也是没有权限的) [root@k8s-master secret]$ kubectl config use-context putianhui@kubernetes Switched to context "putianhui@kubernetes". [root@k8s-master secret]$ kubectl get pods NAME READY STATUS RESTARTS AGE busybox-6f99677459-qhjpd 1/1 Running 0 2d7h nginx-797f679bcf-jvjnp 1/1 Running 0 35h statefulset-nginx-0 1/1 Running 0 2d6h statefulset-nginx-1 1/1 Running 0 2d6h statefulset-nginx-2 1/1 Running 0 2d6h statefulset-nginx-3 1/1 Running 0 2d6h statefulset-nginx-4 1/1 Running 0 2d6h [root@k8s-master secret]$ kubectl get pods -n ingress-nginx NAME READY STATUS RESTARTS AGE ingress-nginx-controller-58f68f5ccc-5v2qc 1/1 Running 0 9d
[root@k8s-master ~]$ kubectl get svc Error from server (Forbidden): services is forbidden: User "putianhui" cannot list resource "services"in API group ""in the namespace "default" [root@k8s-master ~]$ kubectl delete pod nginx-797f679bcf-jvjnp Error from server (Forbidden): pods "nginx-797f679bcf-jvjnp" is forbidden: User "putianhui" cannot delete resource "pods"in API group ""in the namespace "default"