k8s之ServiceAccount
导读
上一篇说了k8s的RBAC授权模式,今天就来简单看一下其中涉及到的ServiceAccount。
简介
k8s创建两套独立的账号系统,原因如下:
(1)User账号给用户用,Service Account是给Pod里的进程使用的,面向的对象不同
(2)User账号是全局性的,Service Account则属于某个具体的Namespace
(3)User账号是与后端的用户数据库同步的,创建一个新用户通常要走一套复杂的业务流程才能实现,Service Account的创建则需要极轻量级的实现方式,集群管理员可以很容易地为某些特定任务创建一个Service Account
(4)对于一个复杂的系统来说,多个组件通常拥有各种账号的配置信息,Service Account是Namespace隔离的,可以针对组件进行一对一的定义,同时具备很好的“便携性”
Controller Manager创建了ServiceAccount Controller和Token Controller这两个安全相关的控制器。其中ServiceAccount Controller一直监听Service Account和Namespace的事件,如果在一个Namespace中没有default Service Account,那么Service Account会给Namespace创建一个默认(default)的Service Account。
如果Controller manager进程在启动时指定API Service私钥(service-accountprivate-key-file参数),那么Controller manager会创建Token Controller,Token Controller也监听Service Account事件。
当我们在API Server的鉴权过程中启用了Service Account类型的准入控制器,即在kube-apiserver启动参数中包括下面的内容时:
--admission_control=ServiceAccount
则针对Pod新增或修改的请求,Service Account准入控制器会验证Pod里的Service Account是否合法:
(1)如果spec.serviceAccount域没有被设置,则Kubernetes默认为其指定名称为default的Service Account。
(2)如果指定了spec.serviceAccountName并且不是default,如果此Service Account不存在,则该Pod操作失败。
(3)如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中。
(4)给Pod添加一个特殊的Volume,在该Volume中包含ServiceAccount Secret中的Token,并将Volume挂载到Pod中所有容器的指定目录下(/var/run/secrets/kubernetes.io/serviceaccount)。
ServiceAccount
ServiceAccount是一种账号,给运行在Pod里面的进程提供必要的身份证明。
做过业务系统的同学应该都知道系统中会有一种叫做角色的定义,角色是拥有某些权限的集合,而上一篇说到的Role就是这个角色,而这个ServiceAccount就相当于是拥有某个角色的账号,也就拥有了某些权限。
为了确保k8s集群的安全,API Server都会对客户端进行安全认证。在Pod中访问API Server服务时,是以Service方式访问名为Kubernetes这个服务的,是以类似HTTP Token的新认证方式:Service Account Auth,Pod在调用API Server时,在Http Header中传递了一个Token字符串,类似于之前提到的Http Token认证方式,有以下几处不同:
(1)Token内容来自Pod指定路径下的一个文件(文件名为token),由Kubernetes Controller进程用API Server的私钥(--service-account-private-zkey-file指定的私钥)签名指定生成的一个JWT Secret。
(2)通过HTTPS方式与API Server建立连接后,会用Pod里指定路径下的一个CA证书(文件名为ca.crt)验证API Server发来的证书,验证是否为CA证书签名的合法证书。
(3)API Server收到Token后,采用自身私钥(service-accountkey-file指定,如果没有指定,则默认采用tls-private-key-file指定的参数)对Token进行合法性验证。
上面的认证过程中所涉及的Pod中的以下三个文件:token、ca.crt、namespace,三个文件都在/run/secrets/kubernetes.io/serviceaccount目录下
这三个文件由于参与到Pod进程和API Server认证的过程中,起到了类似Secret(私密凭据)的作用,所以被称为Kubernetes Secret对象,Secret从属于Service Account资源对象,一个Service Account对象里面可以包括多个不同的Secret对象,分别用于不同目的的认证活动。
一个Secret也是有这三样东西:
查看Service Account详细信息
kubectl describe serviceaccounts
查看Secret
kubectl get secrets
在每个Namespace下都有一个名为default的默认Service Account对象,在这个ServiceAccount里面有一个名为Tokens的可以当做Volume被挂载到Pod里的Secret,当Pod启动时,这个Secret会自动被挂载到Pod的指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权。
一个ServiceAccount可包含多个Secret
其中
(1)名为Tokens的Secret用于访问API Server的Secret,也被称为Service Account Secret。
(2)名为imagePullSecrets的Secret用于下载容器镜像时的认证过程,通常镜像库运行在Insecure模式下,所以这个为空
(3)用户自定义的其他Secret,用于用户的进程。
如果一个Pod在定义时没有指定spec.serviceAccountName属性,则会默认赋值为default,可进行如下指定:
apiVersion: v1 kind: Pod metadata: name: pod spec: containers: - name: podtest image: nginx serviceAccountName: myServiceAccount
创建ServiceAccount
apiVersion: v1 kind: ServiceAccount metadata: labels: k8s-app: kubernetes-dashboard name: kubernetes-dashboard-admin namespace: kube-system
将这个ServiceAccount跟ClusterRole进行绑定:
apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: kubernetes-dashboard-admin labels: k8s-app: kubernetes-dashboard roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: kubernetes-dashboard-admin namespace: kube-system
这样ServiceAccount就拥有了ClusterRole的权限
在Pod中使用ServiceAccount
apiVersion: v1 kind: Pod metadata: name: pod namespace: kube-system spec: containers: - name: podtest image: nginx serviceAccountName: kubernetes-dashboard-admin
===============================
我是Liusy,一个喜欢健身的程序员。
欢迎关注微信公众号【上古伪神】,一起交流Java技术及健身,获取更多干货,领取Java进阶干货,领取最新大厂面试资料,一起成为Java大神。
来都来了,关注一波再溜呗。