一个计算机技术爱好者与学习者

0%

好好学K8S:K8S中创建用户账户和服务账户

1. K8S中的账户简介

k8s中的账户分为useraccount和serviceaccount,主要差异有四点:

  • useraccount是给人使用的,serviceaccount是给pod中进程调用APIServer使用的
  • useraccount是跨namespace的,serviceaccount是局限在它所在的namespace的
  • useraccount不能通过k8s api添加,但是能够通过证书签名方式进行认证;serviceaccount可以通过k8s api添加
  • 每个namespace都有一个默认的serviceaccount,叫做default

本文中,我们主要研究怎样为K8S创建用户账户和怎样创建服务账户。

参考文档:用户认证

2. 创建用户账户

需求:创建一个名为jane的用户账户。

2.1. 创建用户密钥对

1
2
openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -subj "/CN=jane" -out jane.csr

其中,key文件是私钥;csr文件是证书签名申请(Certificate Signing Request),里面包含证书的公钥和其他信息。

2.2. 使用CA签名

假设可以登录运行kube-controller-manager的master节点,那么可以直接在该节点进行CA签名。

1、查看签名用的CA路径

1
2
cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep ca.crt
cat /etc/kubernetes/manifests/kube-controller-manager.yaml | grep ca.key

查到的路径为/etc/kubernetes/pki/ca.crt/etc/kubernetes/pki/ca.key

2、使用CA签名

1
openssl x509 -req -in /root/jane.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out /root/jane.crt

其中,crt文件是签名后的证书。

以上,有了crt和key,这俩加起来就是jane用户账户。一般的用户账户是用户名和密码,K8S的用户账户就是签名证书和私钥。

2.3. 使用API签名

如果无法直接使用CA证书进行签名,那么可以通过APIServer的方式进行签名。

1、查看证书签名申请,base64加密

1
cat jane.csr | base64 | tr -d '\n'

2、创建jane-csr.yaml文件,把证书签名申请的内容粘贴到spec.request部分

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
name: jane
spec:
groups:
- system:authenticated
usages:
- digital signature
- key encipherment
- server auth
- client auth
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZEQ0NBVHdDQVFBd0R6RU5NQXNHQTFVRUF3d0VhbUZ1WlRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRApnZ0VQQURDQ0FRb0NnZ0VCQUtxbWFIa3BJeE94dDN2UmxJT1FnSUFxSUFsekhQcTRRVTBDTDVhS04xbmY4NXRzCi9LU3o0eml1a1hEQ1NOSVNIT1pWbTY5NzVJa3RXcGFySmhaTXptc1B2eUFSeXFWbWY2L1h0bmwyeE0xblhaUzAKZGc0b0E1dXFuR0w2dHpaQzF3VFY4RVFIZnRlcWYzbUpTN2JtdlppaXFlak12a2UzVkk5RTNFK0xsUUttNnVXRwprS2RDZ2ZHNUszRGJFczR1VzR6M0lMdTdEa1BlamJodWFtYzlxYVZNRVpLSGZ0bnlBYlFITkZVLzhvWVYvR1VzCnRFVWZMRXBBTmlqUFc5U0pPWHJtNUg1NXhOdExXVHMwenU3YlRSZWE0ZjFVaDFCbkZuUkhWYUJqNysydHpITTgKaklJS01KakdWOS9rUVltRmo3UTJZUW1wYzdXWGpPZEFWcHBSc1kwQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQgpDd1VBQTRJQkFRQUZ2ZUxrUmYxd0xDQmN6cWdMVkJIUGZBa0MzeU1CTDA3VXl0QUlCcVhkR3h1QWtyL3NQT1dkClNxTkhIRkNzQVNmU0lNVC96djBrQS9yN3Fnd25BMCtZREZJSjNzUlBKZkJmNm1Ic3FrbjlPd1htR1E3d0orNFQKWXVCc1lJSllnNWtzVWJoQVhiQkVZekk2OUY0Uk52U0d0K1ZLOHBBdUQzcXRvejJsd3liV0cvaUo4V3FESTZNegpuMURBeDBkRDZmRWhIKy9DTWdSREY5OExCL1ZqMWZOUUlqZ2k3Rmc1aTByU1NtZUdUMllOblJldERZYWN4aWlzCjNFN1B4STdYWDd2QjRjY3pITlUrTG92N3JnSkVXM3lRMXZRTXRCNTZlbWJaNGVnL01XZEhkeWliVXo2aDQ1ZW8KUGN5b3QxaW1wdFRyK3kwSkt0SmJ1YllQOGd2RG5FeFYKLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==

3、签名请求并通过

1
2
3
kubectl apply -f jane-csr.yaml
kubectl get csr
kubectl certificate approve jane

4、导出签名证书

1
2
kubectl get csr jane -o yaml
kubectl get csr jane -o jsonpath='{.status.certificate}' | base64 --decode > jane.crt

以上,有了crt和key,这俩加起来就是jane用户账户。

更多内容参考Manage TLS Certificates in a Cluster

3. 证书格式转换

X.509是一种证书标准,定义了证书中应该包含哪些内容,详情参考RFC5280,SSL使用的就是这种证书标准。
同样的X.509证书,可能有不同的编码格式,目前有以下两种编码格式。
PEM:Privacy Enhanced Mail,BASE64编码,以”—–BEGIN—–”开头,”—–END—–”结尾。
查看PEM格式证书的信息:

1
openssl x509 -in cert.pem -text -noout

DER:Distinguished Encoding Rules,二进制格式,不可读。
查看DER格式证书的信息:

1
openssl x509 -in cert.der -inform der -text -noout

问题来了,k8s中的证书,除了使用pem格式,还有就是crt格式,并没有der格式啊?这是因为,crt只是一个文件后缀,编码格式可能是pem也可能是der。

那么,pem和der怎样互相转换呢?

1
2
3
4
# pem to der
openssl x509 -in cert.crt -outform der -out cert.der
# der to pem
openssl x509 -in cert.crt -inform der -outform pem -out cert.pem

4. K8S中的数字证书

我们自己创建的用户账户拥有自己的数字证书,除此之外,K8S的各个组件也拥有自己的数字证书,用于组件之间的安全访问。

HTTPS(SSL/TLS)加密原理,参考文档《浅谈数据加密》

4.1. 查看证书

1、查看证书位置

1
2
3
4
5
ps aux | grep kubelet
# find config file
cat /var/lib/kubelet/config.yaml | grep staticPodPath
cd /etc/kubernetes/manifests
cat kube-apiserver.yaml

2、查看证书详情

1
openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text

4.2. 签名

签名,或者签名过期后重新签名

1
openssl x509 -req -in /etc/kubernetes/pki/apiserver-etcd-client.csr -CA /etc/kubernetes/pki/etcd/ca.crt -CAkey /etc/kubernetes/pki/etcd/ca.key -CAcreateserial -out /etc/kubernetes/pki/apiserver-etcd-client.crt

5. 创建服务账户

5.1. v1.22之前的版本

1、创建ServiceAccount和Secret

1
kubectl create serviceaccount harkin

v1.22 之前的 Kubernetes 版本,当创建ServiceAccount时,会自动创建Secret,Secret中包含Token和CA,用于访问 Kubernetes API。
当Pod中指定使用这个ServiceAccount时,TOKEN和CA会挂载到Pod中,以便程序使用。

  • Token的路径: /var/run/secrets/kubernetes.io/serviceaccount/token
  • CA证书的路径: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt

2、查看ServiceAccount和Secret

1
2
3
kubectl get sa
kubectl get secret
kubectl get secret harkin-token-xxx -oyaml # 获取token部分和ca.crt部分

5.2. v1.22之后的版本

在包括 Kubernetes v1.27 在内最近的几个版本中,使用 TokenRequest API 直接获得 API 凭据,并使用投射卷挂载到 Pod 中。
使用这种方法获得的令牌具有绑定的生命周期,当挂载的 Pod 被删除时这些令牌将自动失效。

简单来说,新版本的K8S创建sa时,已经不会自动生成admin-user-token-xxx这种secret,也就无法从这种secret中获取token。

详情参考文档手动管理 ServiceAccount 的 Secret

1、创建ServiceAccount

1
kubectl create serviceaccount harkin

2、创建ServiceAccount的Secret
(1)创建有期限Token(令牌)

1
kubectl create token harkin --duration=8760h

该令牌只会显示一次,请保存好它。至于ca.crt,从/etc/kubernetes/pki/ca.crt获取即可。

(2)创建长期有效Token(令牌)
我们仍然可以手动创建 Secret 来保存服务账号令牌,例如在我们需要一个永不过期的令牌的时候。
一旦我们手动创建一个 Secret 并将其关联到 ServiceAccount, Kubernetes 控制平面就会自动将令牌填充到该 Secret 中。

1
2
3
4
5
6
7
8
9
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: harkin-secret
annotations:
kubernetes.io/service-account.name: harkin
type: kubernetes.io/service-account-token
EOF

3、查看ServiceAccount和Secret

1
2
3
kubectl get sa
kubectl get secret
kubectl get secrets/harkin-secret -oyaml # 获取token部分和ca.crt部分

6. 授权

创建完用户账户和服务账户,只是有了账户,并没有K8S集群的权限。
账户授权方法参考文档《好好学K8S:K8S中用户账户的RBAC鉴权》《好好学K8S:K8S中服务账户的RBAC鉴权》