hello云胜

技术与生活

0%

k8s中的账号

kubernetes集群中账户分为两类,Kubernetes管理的serviceaccount(服务账户)和useraccount(用户账户)。

k8s创建两套独立的账号系统,原因如下:

(1)面向的对象不同。useraccount给用户用,我们使用kubectl时用的就是userAccount。

​ Service Account是给Pod里的进程使用的。Pod容器的进程需要访问API Server时用的就是ServiceAccount账户

(2)useraccount是全局性的,

​ 在集群所有namespaces中,名称具有唯一性。

​ 用户名称可以在kubeconfig中查看。我这里是kubernetes-admin

1
2
3
4
5
6
7
8
[root@paas-m-k8s-master-1 ~]# cat ~/.kube/config
apiVersion: v1
clusters:
...
users:
- name: kubernetes-admin
user:
client-certificate-data: ...

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
2
3
4
5
6
[root@paas-m-k8s-master-1 ~]# kc get sa,secret
NAME SECRETS AGE
serviceaccount/default 1 717d

NAME TYPE DATA AGE
secret/default-token-d6d9z kubernetes.io/service-account-token 3 717d

我们自己创建一个

1
2
3
4
5
6
7
8
9
10
[root@paas-m-k8s-master-1 ~]# kubectl create serviceaccount mytest
serviceaccount/mytest created
[root@paas-m-k8s-master-1 ~]# kc get sa,secret
NAME SECRETS AGE
serviceaccount/default 1 717d
serviceaccount/mytest 1 3s

NAME TYPE DATA AGE
secret/default-token-d6d9z kubernetes.io/service-account-token 3 717d
secret/mytest-token-qs9pj kubernetes.io/service-account-token 3 3s

k8s会自动创建一个关联的secret

1
2
3
4
5
6
7
8
9
10
[root@paas-m-k8s-master-1 ~]# kc describe serviceaccount/mytest
Name: mytest
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: mytest-token-qs9pj
Tokens: mytest-token-qs9pj
Events: <none>

查看下这个token的内容

![image-20230920112303718](D:\github\docs\云原生\k8s\Service Account.assets\image-20230920112303718.png)

这个token其实是个jwt token

可以拿出来解析看看

![image-20230920112934924](D:\github\docs\云原生\k8s\Service Account.assets\image-20230920112934924.png)

使用serviceAccount

要使用serviceAccount,只需要在 pod 的spec.serviceAccountName 字段中将name设置为想要用的 service account 名字即可。

每个pod都与一个ServiceAccount相关联,但是多个pod可以使用同一个ServiceAccount。

并且只能使用自己所在namespace下的serviceAccount

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Pod
metadata:
name: test-sa
spec:
containers:
- name: test-sa
image: nginx:1.2.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
serviceAccountName: mytest

查看一下pod详情

1
2
3
4
5
6
7
8
9
10
11
12
[root@paas-m-k8s-master-1 test]# kc describe pod test-sa
Name: test-sa
Namespace: default
...
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from mytest-token-qs9pj (ro)
...
Volumes:
mytest-token-qs9pj:
Type: Secret (a volume populated by a Secret)
SecretName: mytest-token-qs9pj
Optional: false

有以下几条原则:

(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的用户名密码。

之后有两种选择

  1. 在Deployment的yaml使用imagePullSecrets
  2. 创建一个绑定该secret的serviceAccount,在deployment的yaml中使用这个serviceAccount。或者把这个secret直接patch给default sa。

我们来操作一下第二种方案

  1. 创建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
  1. 创建sa

    1
    2
    3
    4
    5
    6
    7
    8
    apiVersion: v1
    kind: ServiceAccount
    metadata:
    name: harbor-sa
    namespace: ns001
    secrets:
    imagePullSecrets:
    - name: harborpaas
  2. deployment使用sa

    1
    2
    3
    4
    5
    6
    7
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: test-sa
    namespace: ns001
    spec:
    serviceAccountName: harbor-sa

    根据这一条,如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中。

    所以pod是可以拉取到镜像的。