ServiceAccount
Kubernetes中所有的访问,无论外部内部,都会通过API Server处理,访问Kubernetes资源前需要经过认证与授权。
-
Authentication:用于识别用户身份的认证,Kubernetes分外部服务账号和内部服务账号,采取不同的认证机制,具体请参见认证与ServiceAccount。
-
Authorization:用于控制用户对资源访问的授权,对访问的授权目前主要使用RBAC机制,将在RBAC介绍。
图1 API Server的认证授权
认证与ServiceAccount
Kubernetes的用户分为服务账户(ServiceAccount)和普通账户两种类型。
-
服务账户与Namespace绑定,关联一套凭证,存储在Secret中,Pod创建时挂载Secret,从而允许与API Server之间调用。
-
Kubernetes中没有代表普通账户的对象,这类账户默认由外部服务独立管理,比如在华为云上CCE的用户是由IAM管理的。
普通账号并不是这里要讨论的内容,这里主要关注ServiceAccount。
ServiceAccount同样是Kubernetes中的资源,与Pod、ConfigMap类似,且作用于独立的命名空间,也就是ServiceAccount是属于命名空间级别的,创建命名空间时会自动创建一个名为default的ServiceAccount。
使用下面命令可以查看ServiceAccount。
$ kubectl get sa
NAME SECRETS AGE
default 1 30d
同时Kubernetes还会为ServiceAccount自动创建一个Secret,使用下面命令可以查看到。
$ kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>Mountable secrets: default-token-vssmwTokens: default-token-vssmwEvents: <none>
在Pod的定义文件中,可以用指定账户名称的方式将一个ServiceAccount赋值给一个Pod,如果不指定就会使用默认的ServiceAccount。当API Server接收到一个带有认证Token的请求时,API Server会用这个Token来验证发送请求的客户端所关联的ServiceAccount是否允许执行请求的操作。
创建ServiceAccount
使用如下命令就可以创建ServiceAccount:
$ kubectl create serviceaccount sa-example
serviceaccount/sa-example created
$ kubectl get sa
NAME SECRETS AGE
default 1 30d
sa-example 1 2s
可以看到已经创建了与ServiceAccount相关联的Token。
$ kubectl describe sa sa-example
Name: sa-example
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>Mountable secrets: sa-example-token-c7bqxTokens: sa-example-token-c7bqxEvents: <none>
查看Secret的内容,可以发现ca.crt、namespace和token三个数据。
$ kubectl describe secret sa-example-token-c7bqx
Name: sa-example-token-c7bqx
...
Data
====
ca.crt: 1082 bytes
namespace: 7 bytes
token: <Token的内容>
在Pod中使用ServiceAccount
Pod中使用ServiceAccount非常方便,只需要制定ServiceAccount的名称即可。
apiVersion: v1
kind: Pod
metadata:
name: sa-example
spec:
serviceAccountName: sa-example
containers:
- image: nginx:alpine
name: container-0
resources:
limits:
cpu: 100m
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
imagePullSecrets:
- name: default-secret
创建并查看这个Pod,可以看到Pod挂载了sa-example-token-c7bqx,也就是sa-example这个ServiceAccount对应的Token,即Pod使用这个Token来做认证。
$ kubectl create -f sa-pod.yaml
pod/sa-example created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
sa-example 0/1 running 0 5s
$ kubectl describe pod sa-example
...
Containers:
sa-example:
Mounts: /var/run/secrets/kubernetes.io/serviceaccount from sa-example-token-c7bqx (ro)
进入Pod内部,还可以看到对应的文件,如下所示。
$ kubectl exec -it sa-example -- /bin/sh
/ # cd /run/secrets/kubernetes.io/serviceaccount
/run/secrets/kubernetes.io/serviceaccount # ls
ca.crt namespace token
如上,在容器应用中,就可以使用ca.crt和Token来访问API Server。
下面来验证一下认证是否能生效。在Kubernetes集群中,默认为API Server创建了一个名为kubernetes的Service,通过这个Service可以访问API Server。
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.247.0.1 <none> 443/TCP 34
进入Pod,使用curl命令直接访问会得到如下返回信息,表示并没有权限。
$ kubectl exec -it sa-example -- /bin/sh
/ # curl https://kubernetes
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
使用ca.crt和Token做认证,先将ca.crt放到CURL_CA_BUNDLE这个环境变量中,curl命令使用CURL_CA_BUNDLE指定证书;再将Token的内容放到TOKEN中,然后带上TOKEN访问API Server。
# export CURL_CA_BUNDLE=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
# TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
# curl -H "Authorization: Bearer $TOKEN" https://kubernetes
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "forbidden: User \"system:serviceaccount:default:sa-example\" cannot get path \"/\"",
"reason": "Forbidden",
"details": {
},
"code": 403
}
可以看到,已经能够通过认证了,但是API Server返回的是cannot get path \"/\"",表示没有权限访问,这说明还需要得到授权后才能访问,授权机制将在RBAC中介绍。
了解更多Kubernetes集群相关知识和使用方法请猛击这里。
- 点赞
- 收藏
- 关注作者
评论(0)