k8s之ServiceAccount
k8s有两套独立的账号系统,分为User用户和ServiceAccount账户,区别如下:
- User账号给人使用的,ServiceAccount则是给Pod里面的进程使用
- User账号是全局性的,ServiceAccount是基于具体的Namespace
- User账号与后端数据库同步,创建流程复杂,ServiceAccount创建简单
什么是ServiceAccount?
ServiceAccount是Kubernetes API上的一种资源类型,它属于名称空间级别,用于让Pod对象内部的应用程序在与API Server通信时完成身份认证
三个独立组件协助完成ServiceAccount自动化:
ServiceAccount准入控制器- Token 控制器
ServiceAccount控制器
一、启用ServiceAccount准入控制器插件:
正常安装后,已经开启了此插件,本例以二进制安装为例,如图:

二、ServiceAccount准入控制器职责:
对于Pod的新增或者修改,ServiceAccount准入控制器会验证Pod里的ServiceAccount是否合法,包括如下:
1、如果spec.serviceAccount域没有被设置,则Kubernetes默认为其指定名称为default的Service Account,查看默认命名空间(default)下的serviceaccount内容,如图:

查看默认命名空间(default)下的默认token信息,包含ca.crt、token、namespace,如图:


2、如果指定了spec.serviceAccountName并且不是default,如果此Service Account不存在,则该Pod操作失败
3、如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中
4、如果服务账号的 automountServiceAccountToken 或 Pod 的 automountServiceAccountToken 都未显式设置为 false,则为 Pod 创建一个 volume,在其中包含用来访问 API 的令牌
5、如果上一步为ServiceAccount令牌创建了卷,则为Pod对象中的每个容器添加一个volumeMounts,将ServiceAccount的存储卷挂载至/var/run/secrets/kubernetes.io/serviceaccount,如图:

进入容器内部可以看到存在三个文件,ca.crt,namespace,token,如图:

此token的内容与命名空间中生成的默认token内容一样
通过上述三个文件,Pod访问API Server服务流程如下:
- Pod在调用API Server时,在Http Header中传递了一个Token字符串,此Token内容来自Pod指定路径下的一个文件(文件名token),由Kubernetes Controller进程用API Server的私钥(–service-account-private-zkey-file指定的私钥)签名指定生成的一个JWT Secret
- 通过HTTPS方式与API Server建立连接后,会用Pod里指定路径下的一个CA证书(ca.crt)验证API Server发来的证书,验证是否为CA证书签名的合法证书
- API Server收到Token后,采用自身私钥(service-account-key-file指定,如果没有指定,则默认采用tls-private-key-file指定的参数)对Token进行合法性验证
在每个Namespace下都有一个名为default的默认Service Account对象,在这个ServiceAccount里面有一个名为Tokens的可以当做Volume被挂载到Pod里的Secret,当Pod启动时,这个Secret会自动被挂载到Pod的指定目录下,用来协助完成Pod中的进程访问API Server时的身份鉴权
三、Token控制器:
kube-controller-manager创建了Token Controller控制器,其主要职责包括:
- 监测 ServiceAccount 的创建并创建相应的服务账号令牌 Secret 以允许访问 API,创建了ServiceAccount后会立即自动创建一个Secret
- 监测 ServiceAccount 的删除并删除所有相应的服务账号令牌 Secret
- 监测ServiceAccount Token Secret 的添加,保证相应的 ServiceAccount 存在,如有需要, 向 Secret 中添加Token
必须通过 --service-account-private-key-file 标志为 kube-controller-manager 的令牌控制器传入一个服务账号私钥文件。该私钥用于为所生成的服务账号令牌签名。 同样地,你需要通过 --service-account-key-file 标志将对应的公钥通知给 kube-apiserver。公钥用于在身份认证过程中校验令牌。
四、ServiceAccout控制器:
ServiceAccount控制器管理各名字空间下的 ServiceAccount 对象,并且保证每个活跃的 名字空间下存在一个名为 “default” 的ServiceAccount
Secret从属于Service Account资源对象,一个Service Account对象里面可以包括多个不同的Secret对象,分别用于不同目的的认证活动
例如:下面例子表示创建一个名为myserviceaccount的ServiceAccount,如图:

创建一个secret,在其中指定serviceaccount信息,如图:

再次查看myserviceaccount的内容,可以看到多了个Secret对象,如图:



