简介:
Service Account为Pod中的进程和外部用户提供身份信息,所有的kubernetes集群中账户分为两类,Kubernetes管理的serviceaccount(服务账户)和useraccount(用户账户)
大家都知道api server的集群的入口,对于kunbernetes的api server 是肯定不能随便访问,所以我们必须需要一些认证信息,例如:
当用户访问集群(例如使用kubectl命令)时,apiserver 会将您认证为一个特定的 User Account(目前通常是admin,除非您的系统管理员自定义了集群配置),Pod 容器中的进程也可以与 apiserver 联系,当它们在联系 apiserver 的时候,它们会被认证为一个特定的 Service Account
API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理
每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中
因为kubernetes是高度模块化,所有认证方式和授权方式都可以通过插件的方式让客户自定义的,可以支持很多种,客户端请求的时候首先需要进行认证,认证通过后再进行授权检查,因有些操作需要级联到其他资源或者环境,但是级联环境是否有授权权限,这时候需要准入控制
认证插件:
bearer token:当使用来自 http 客户端的 bearer token 时,API server 期望 Authorization header 中包含 Bearer token 的值,Bearer token 必须是一个字符串序列,只需使用 HTTP 的编码和引用功能就可以将其放入到 HTTP header 中
客户端证书:客户端请求前需要,需要发送api server颁发的证书,由api server来确认是否他来签署的,引用的文件必须包含一个或多个证书颁发机构,用于验证提交给 API server 的客户端证书,如果客户端证书已提交并验证,则使用 subject 的 Common Name(CN)作为请求的用户名,反过来,api server也要验证客户端的证书,所有对于客户端也应该有一个证书,提供api server 验证,此过程是双向验证
HTTP BASE 认证:通过用户名+密码方式认证
当启用了多个认证模块时,第一个认证模块成功认证后将短路请求,不会进行第二个模块的认证,API server 不会保证认证的顺序
用户账户:
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的,它与User account不同:
- User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计
- User account是跨namespace的,而service account则是仅局限它所在的namespace
- 每个namespace都会自动创建一个default service account
- Token controller检测service account的创建,并为它们创建secret
- 开启ServiceAccount Admission Controller后 :
- 每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout)
- 验证Pod引用的service account已经存在,否则拒绝创建
- 如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中
- 每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/
user:保护UserName和UID,UserName是标识最终用户的字符串,UID是标识最终用户的字符串,比用户名更加一致切唯一
group:一组将用户和常规用户组相关联的字符串
extra:包含其他有用认证信息的字符串列表
上述是来自集群外部的访问,我们可以理解成是User Account,是给kubernetes集群外部用户,例如(系统管理员、用户/租户等),Service Account而是给运行在Pod的容器、或者Pod使用的身份认证
正常情况下,为了确保kubernetes集群的安全性,Api Server 都会给客户端进行身份认证,但是Pod访问Kubernetes Api Server服务时,也是需要身份认证的
演示:
当创建 pod 的时候,如果没有指定一个 service account,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account,而pod和apiserver之间进行通信的账号,称为serviceAccountName
[root@master manifests]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-0 1/1 Running 0 16h
myapp-1 1/1 Running 0 16h
myapp-2 1/1 Running 0 16h
myapp-3 1/1 Running 0 16h
[root@master manifests]# kubectl get pods myapp-0 -o yaml|grep serviceAccountName
serviceAccountName: default
[root@master manifests]# kubectl describe pods myapp-0
……
default-token-dqd2f:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-dqd2f
……
每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-* token令牌,这就是pod和serviceaccount认证信息
通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中,从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证
每个 namespace 中都有一个默认的叫做 default 的 service account 资源,进行查看名称空间内的secret,也可以看到对应的default-token,让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信
[root@master manifests]# kubectl get sa
NAME SECRETS AGE
default 1 7d21h
[root@master manifests]# kubectl get sa -n ingress-nginx #所有的名称空间都存在name是default的serviceAccount
NAME SECRETS AGE
default 1 2d20h
nginx-ingress-serviceaccount 1 2d5h
[root@master manifests]# kubectl get secret
NAME TYPE DATA AGE
default-token-dqd2f kubernetes.io/service-account-token 3 7d21h
mysql-root-password Opaque 1 23h
tomcat-ingress-secret kubernetes.io/tls 2 2d3h
[root@master manifests]# kubectl get secret -n ingress-nginx
NAME TYPE DATA AGE
default-token-fkw6s kubernetes.io/service-account-token 3 2d20h
nginx-ingress-serviceaccount-token-jvlq9 kubernetes.io/service-account-token 3 2d5h