k8s中的账号
kubernetes集群中账户分为两类,Kubernetes管理的serviceaccount(服务账户)和useraccount(用户账户)。
k8s创建两套独立的账号系统,原因如下:
(1)面向的对象不同。useraccount给用户用,我们使用kubectl时用的就是userAccount。
Service Account是给Pod里的进程使用的。Pod容器的进程需要访问API Server时用的就是ServiceAccount账户
(2)useraccount是全局性的,
在集群所有namespaces中,名称具有唯一性。
用户名称可以在kubeconfig中查看。我这里是kubernetes-admin
1 | [root@paas-m-k8s-master-1 ~]# cat ~/.kube/config |
Service Account则属于某个具体的Namespace
(3)useraccount是与后端的用户数据库同步的,创建一个新用户通常要走一套复杂的业务流程才能实现,Service Account的创建则需要极轻量级的实现方式,集群管理员可以很容易地为某些特定任务创建一个Service Account
(4)对于一个复杂的系统来说,多个组件通常拥有各种账号的配置信息,Service Account是Namespace隔离的,可以针对组件进行一对一的定义,同时具备很好的“便携性”
Service Account
Controller Manager创建了ServiceAccount Controller和Token Controller这两个安全相关的控制器。其中ServiceAccount Controller一直监听Service Account和Namespace的事件,
每个Namespace下都有一个名为default的默认的 Service Account对象
如果在一个Namespace中没有default Service Account,那么Service Account会给Namespace创建一个默认(default)的Service Account。
每创建一个ServiceAccount ,就会对应创建一个secret。
这个secret,会和Service Account里面有一个名为Tokens的字段关联,当Pod启动时候,这个Secret会自动Mount到Pod的指定目录下,用来完成Pod中的进程访问API server时的身份认证过程。
应用程序使用这个token连接API-Server时,API-Server的身份认证插件会对ServiceAccount进行身份认证
1 | [root@paas-m-k8s-master-1 ~]# kc get sa,secret |
我们自己创建一个
1 | [root@paas-m-k8s-master-1 ~]# kubectl create serviceaccount mytest |
k8s会自动创建一个关联的secret
1 | [root@paas-m-k8s-master-1 ~]# kc describe serviceaccount/mytest |
查看下这个token的内容

这个token其实是个jwt token
可以拿出来解析看看

使用serviceAccount
要使用serviceAccount,只需要在 pod 的spec.serviceAccountName 字段中将name设置为想要用的 service account 名字即可。
每个pod都与一个ServiceAccount相关联,但是多个pod可以使用同一个ServiceAccount。
并且只能使用自己所在namespace下的serviceAccount
1 | apiVersion: v1 |
查看一下pod详情
1 | [root@paas-m-k8s-master-1 test]# kc describe pod test-sa |
有以下几条原则:
(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)。
一个使用场景
我们从公司的harbor仓库拉取镜像时,应该每个项目组配置自己的私有项目,不应该使用公开的项目。
此时就需要配置imagePullSecrets。否则会拉取失败。
此时我们需要创建一个secret,存储harbor的用户名密码。
之后有两种选择
- 在Deployment的yaml使用imagePullSecrets
- 创建一个绑定该secret的serviceAccount,在deployment的yaml中使用这个serviceAccount。或者把这个secret直接patch给default sa。
我们来操作一下第二种方案
- 创建secret
1 | kubectl create secret docker-registry harborpaas -n ns001 --docker-server=harbor-test.xxx.net --docker-username=paas --docker-password=XXXXX --docker-email=xxx@xxx.com |
创建sa
1
2
3
4
5
6
7
8apiVersion: v1
kind: ServiceAccount
metadata:
name: harbor-sa
namespace: ns001
secrets:
imagePullSecrets:
- name: harborpaasdeployment使用sa
1
2
3
4
5
6
7apiVersion: apps/v1
kind: Deployment
metadata:
name: test-sa
namespace: ns001
spec:
serviceAccountName: harbor-sa根据这一条,如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中。
所以pod是可以拉取到镜像的。