Kubernetes之ServiceAccount+Secret相关概念
https://blog.csdn.net/BigData_Mining/article/details/88529157
API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中。如下图:
每一个用户对API资源进行操作都需要通经过以下三个步骤:
第一步:对客户端访问进行认证操作,确认是否具有访问k8s权限 token(共享秘钥) SSL(双向SSL认证) ....通过任何一个认证即表示认证通过,进入下一步 第二步:授权检查,确认是否对资源具有相关的权限 ABAC(基于属性的访问控制) RBAC(基于角色的访问控制) NODE(基于节点的访问控制) WEB HOOK(自定义HTTP回调方法的访问控制) 第三步:准入控制(对操作资源相关联的其他资源是否有权限操作)
Kubernetes只对以下的API请求属性进行检查
user - username,uid group - user group "extra"- 额外信息 API - API资源的对象 Request path - 请求资源的路径(k8s使用resultful风格接口的API) http://Node_IPaddr:6443/apis/apps/v1/namespaces/namespaces_name/resource_name/ HTTP 请求动作 - HTTP verbs get,post,put,和delete用于非资源请求 HTTP 请求动作映射到 API资源操作- get,list,create,update,patch,watch,proxy,redirect,delete,和deletecollection用于请求resource Resource -被访问(仅用于resource 请求)的resource 的ID或名字- *对于使用resource 的请求get,update,patch,和delete,必须提供resource 名称。 Subresource - 正在访问的subresource (仅用于请求resource ) Namespace - 正在访问对象的命名空间(仅针对命名空间的请求资源) API group - 正在访问的API组(仅用于请求资源)。空字符串指定核心API组。
Secret解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用。
一、Secret
1、Secret类型
Secret有三种类型: Opaque:base64编码格式的Secret,用来存储密码、密钥等;但数据也通过base64 –decode解码得到原始数据,所以加密性很弱。 kubernetes.io/dockerconfigjson:用来存储私有docker registry的认证信息。 kubernetes.io/service-account-token: 用于被serviceaccount引用。serviceaccout创建时Kubernetes会默认创建对应的secret。Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod目录/run/secrets/ kubernetes.io/serviceaccount中。
2、Opaque Secret
Opaque类型的数据是一个map类型,要求value是base64编码格式
$ echo -n "admin" | base64 YWRtaW4= $ echo -n "1f2d1e2e67df" | base64 MWYyZDFlMmU2N2Rm
secrets.yml apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: password: MWYyZDFlMmU2N2Rm username: YWRtaW4=
创建secret:kubectl create -f secrets.yml。
# kubectl get secret NAME TYPE DATA AGE default-token-cty7p kubernetes.io/service-account-token 3 45d mysecret Opaque
注意:其中default-token-cty7p为创建集群时默认创建的secret,被serviceacount/default引用。
如果是从文件创建secret,则可以用更简单的kubectl命令,比如创建tls的secret
kubectl create secret generic helloworld-tls --from-file=key.pem --from-file=cert.pem
kubernetes.io/service-account-token: 用于被serviceaccount引用。serviceaccout创建时Kubernetes会默认创建对应的secret。Pod如果使用了serviceaccount,对应的secret会自动挂载到Pod的/run/secrets/kubernetes.io/serviceaccount目录中。
二、ServiceAccount
User Accounts 与 Service Accounts
Kubernetes区分普通帐户(user accounts)和服务帐户(service accounts)的原因
-普通帐户是针对(人)用户的,服务账户针对Pod进程。 -普通帐户是全局性。在集群所有namespaces中,名称具有惟一性。 -通常,群集的普通帐户可以与企业数据库同步,新的普通帐户创建需要特殊权限。服务账户创建目的是更轻量化,允许集群用户为特定任务创建服务账户。 -普通帐户和服务账户的审核注意事项不同。 -对于复杂系统的配置包,可以包括对该系统的各种组件的服务账户的定义。
Token controller
TokenController作为controller-manager的一部分运行。异步行为
-观察serviceAccount的创建,并创建一个相应的Secret 来允许API访问。 -观察serviceAccount的删除,并删除所有相应的ServiceAccountToken Secret -观察secret 添加,并确保关联的ServiceAccount存在,并在需要时向secret 中添加一个Token。 -观察secret 删除,并在需要时对应 ServiceAccount 的关联
需要使用–service-account-private-key-file 参数选项将Service Account 密匙(key)文件传递给controller-manager中的Token controller。key用于 Service Account Token签名。同样,也需要使用–service-account-key-file 参数选项将相应的(public key)公匙传递给kube-apiserver ,公钥用于在认证期间验证Token。
Service Account Controller
Service Account Controller在namespaces里管理ServiceAccount,并确保每个有效的namespaces中都存在一个名为“default”的ServiceAccount。
什么是serviceaccount
Service Account 用来访问 kubernetes API,通过 kubernetes API 创建和管理,每个 account 只能在一个 namespace 上生效,存储在 kubernetes API 中的 Secrets 资源。kubernetes 会默认创建,并且会自动挂载到 Pod 中的 /run/secrets/kubernetes.io/serviceaccount 目录下。
Service account是为了方便Pod里面的进程调用Kubernetes API或其他外部服务而设计的。它与User account不同
1.User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计; 2.User account是跨namespace的,而service account则是仅局限它所在的namespace; 3.每个namespace都会自动创建一个default service account 4.Token controller检测service account的创建,并为它们创建secret 5.开启ServiceAccount Admission Controller后 1.每个Pod在创建后都会自动设置spec.serviceAccount为default(除非指定了其他ServiceAccout) 2.验证Pod引用的service account已经存在,否则拒绝创建 3.如果Pod没有指定ImagePullSecrets,则把service account的ImagePullSecrets加到Pod中 4.每个container启动后都会挂载该service account的token和ca.crt到/var/run/secrets/kubernetes.io/serviceaccount/
当创建 pod 的时候,如果没有指定一个 service account,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account。而pod和apiserver之间进行通信的账号,称为serviceAccountName。如下:
[ ~]# kubectl get pods NAME READY STATUS RESTARTS AGE filebeat-ds-hxgdx 1/1 Running 1 34d filebeat-ds-s466l 1/1 Running 2 34d myapp-0 1/1 Running 0 3h myapp-1 1/1 Running 0 3h myapp-2 1/1 Running 0 4h myapp-3 1/1 Running 0 4h pod-vol-demo 2/2 Running 0 2d redis-5b5d6fbbbd-q8ppz 1/1 Running 1 2d [-master ~]# kubectl get pods/myapp-0 -o yaml |grep "serviceAccountName" serviceAccountName: default [-master ~]# kubectl describe pods myapp-0 Name: myapp-0 Namespace: default ...... Volumes: ...... default-token-j5pf5: Type: Secret (a volume populated by a Secret) SecretName: default-token-j5pf5 Optional: false
从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。
验证