kubernetes(18):k8s安全认证-service account
k8s安全认证-service account
https://www.cnblogs.com/Smbands/p/10900593.html
https://www.cnblogs.com/panwenbin-logs/p/10029834.html
https://www.cnblogs.com/linuxk/p/9772117.html
1 k8s的认证:
API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中
与API server通信的客户端大致有两类:
1.集群客户端工具(kubectl、kubeadm、kubelet等)
2.集群内pod.
1.1 客户端访问k8sAPI时的过程:
第一步:对客户端访问进行认证操作,确认是否具有访问k8s权限
token(共享秘钥)
SSL(双向SSL认证)
....通过任何一个认证即表示认证通过,进入下一步
第二步:授权检查,确认是否对资源具有相关的权限
ABAC(基于属性的访问控制)
RBAC(基于角色的访问控制)
NODE(基于节点的访问控制)
WEB HOOK(自定义HTTP回调方法的访问控制)
第三步:准入控制(对操作资源相关联的其他资源是否有权限操作)
1.2 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组。
1.3 什么是service account
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/
1.4 验证service account
当创建 pod 的时候,如果没有指定一个 service account,系统会自动在与该pod 相同的 namespace 下为其指派一个default service account。而pod和apiserver之间进行通信的账号,称为serviceAccountName。如下:
[root@k8s-master ~]# kubectl get pod NAME READY STATUS RESTARTS AGE myapp-demo-b9997455b-5mxjm 1/1 Running 0 2d17h [root@k8s-master ~]# kubectl get pod -o yaml| grep serviceAccount serviceAccount: default serviceAccountName: default [root@k8s-master ~]# kubectl describe pods myapp-demo-b9997455b-5mxjm …… Volumes: mysql: Type: Secret (a volume populated by a Secret) SecretName: test Optional: false default-token-wldf4: Type: Secret (a volume populated by a Secret) SecretName: default-token-wldf4 Optional: false ……..
从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。
[root@k8s-master ~]# kubectl get secrets | grep service-account-token default-token-wldf4 kubernetes.io/service-account-token 3 11d nfs-client-provisioner-token-mz6dc kubernetes.io/service-account-token 3 3d20h [root@k8s-master ~]# [root@k8s-master ~]# kubectl get sa NAME SECRETS AGE default 1 50d [root@k8s-master ~]# kubectl get sa -n ingress-nginx #前期创建的ingress-nginx名称空间也存在这样的serviceaccount NAME SECRETS AGE default 1 11d nginx-ingress-serviceaccount 1 11d [root@k8s-master ~]# kubectl get secret NAME TYPE DATA AGE default-token-j5pf5 kubernetes.io/service-account-token 3 50d mysecret Opaque 2 1d tomcat-ingress-secret kubernetes.io/tls 2 10d [root@k8s-master ~]# kubectl get secret -n ingress-nginx NAME TYPE DATA AGE default-token-zl49j kubernetes.io/service-account-token 3 11d nginx-ingress-serviceaccount-token-mcsf4 kubernetes.io/service-account-token 3 11d
2 service account实例
2.1 创建service account
[root@k8s-master ~]# kubectl create serviceaccount admin serviceaccount/admin created [root@k8s-master ~]# kubectl get sa NAME SECRETS AGE admin 1 5s default 1 11d nfs-client-provisioner 1 3d20h [root@k8s-master ~]# kubectl describe sa admin #查看名称为admin的sa的信息,系统会自动创建一个token信息 Name: admin Namespace: default Labels: <none> Annotations: <none> Image pull secrets: <none> Mountable secrets: admin-token-bt2n9 Tokens: admin-token-bt2n9 Events: <none> [root@k8s-master ~]# kubectl get secret #会自动创建一个secret(admin-token-rxtrc),用于当前sa连接至当前API server时使用的认证信息 NAME TYPE DATA AGE admin-token-bt2n9 kubernetes.io/service-account-token 3 27s db-user-pass Opaque 2 2d19h default-token-wldf4 kubernetes.io/service-account-token 3 11d myapp-ingress-secret kubernetes.io/tls 2 6d19h myregistrykey kubernetes.io/dockerconfigjson 1 2d19h mysecret Opaque 2 2d19h nfs-client-provisioner-token-mz6dc kubernetes.io/service-account-token 3 3d20h nginx-ingress-secret kubernetes.io/tls 2 6d19h test Opaque 1 2d18h tomcat-ingress-secret kubernetes.io/tls 2 6d20h
2.2 创建一个pod应用刚刚创建的sa
# cat myapp-deploy.yaml apiVersion: v1 kind: Pod metadata: name: sa-demo labels: app: myapp release: wx spec: containers: - name: myapp image: ikubernetes/myapp:v2 ports: - name: httpd containerPort: 80 serviceAccountName: admin #此处指令为指定sa的名称
[root@k8s-master myapp]# kubectl create -f myapp-deploy.yaml pod/sa-demo created [root@k8s-master myapp]# kubectl get pod NAME READY STATUS RESTARTS AGE sa-demo 1/1 Running 0 8s [root@k8s-master myapp]# kubectl describe pod sa-demo …. Mounts: /var/run/secrets/kubernetes.io/serviceaccount from admin-token-bt2n9 (ro) Volumes: admin-token-bt2n9: Type: Secret (a volume populated by a Secret) SecretName: admin-token-bt2n9 Optional: false
3 Kubeconfig证书认证
集群交互的时候少不了的是身份认证,使用 kubeconfig(即证书) 和 token 两种认证方式是最简单也最通用的认证方式,下面我使用kubeconfing来进行认证
使用kubeconfig文件来组织关于集群,用户,名称空间和身份验证机制的信息。使用 kubectl命令行工具对kubeconfig文件来查找选择群集并与群集的API服务器进行通信所需的信息。
默认情况下 kubectl使用的配置文件名称是在$HOME/.kube目录下 config文件,可以通过设置环境变量KUBECONFIG或者--kubeconfig指定其他的配置文件
3.1 系统的kubeconfig
# kubectl config view apiVersion: v1 clusters: #集群列表 - cluster: certificate-authority-data: REDACTED #认证集群的方式 server: https://172.16.150.212:6443 #访问服务的APIserver的路径 name: kubernetes #集群的名称 contexts: #上下文列表 - context: cluster: kubernetes #访问kubernetes这个集群 user: kubernetes-admin #使用 kubernetes-admin账号 name: kubernetes-admin@kubernetes #给定一个名称 current-context: kubernetes-admin@kubernetes #当前上下文,表示使用哪个账号访问哪个集群 kind: Config preferences: {} users: #用户列表 - name: kubernetes-admin #用户名称 user: client-certificate-data: REDACTED #客户端证书,用于与apiserver进行认证 client-key-data: REDACTED #客户端私钥
在上面的配置文件当中,定义了集群、上下文以及用户。其中Config也是K8S的标准资源之一,在该配置文件当中定义了一个集群列表,指定的集群可以有多个;用户列表也可以有多个,指明集群中的用户;而在上下文列表当中,是进行定义可以使用哪个用户对哪个集群进行访问,以及当前使用的上下文是什么。如图:定义了用户kubernetes-admin可以对kubernetes该集群的访问,用户kubernetes-user1对Clluster1集群的访问
3.2 自建证书和账号进行访问apiserver
#生成证书
[root@k8s-master pki]# (umask 077;openssl genrsa -out wx.key 2048) Generating RSA private key, 2048 bit long modulus ..............................................................................................................................+++ .......................+++ e is 65537 (0x10001) [root@k8s-master pki]#
#使用ca.crt进行签署
[root@k8s-master pki]# openssl req -new -key wx.key -out wx.csr -subj "/CN=wx" #是后面我们创建的用户名称,需要保持一致 [root@k8s-master pki]# ls wx.* wx.csr wx.key [root@k8s-master pki]# openssl x509 -req -in wx.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out wx.crt -days 365 Signature ok subject=/CN=wx Getting CA Private Key [root@k8s-master pki]#
#创建一个当前集群用户
[root@k8s-master pki]# kubectl config set-credentials wx --client-certificate=./wx.crt --client-key=./wx.key --embed-certs=true User "wx" set.
#为wx用户用户创建一个context
[root@k8s-master pki]# kubectl config set-context wx@kubernetes --cluster=kubernetes --user=wx Context "wx@kubernetes" created. [root@k8s-master pki]# [root@k8s-master pki]# kubectl config view apiVersion: v1 clusters: - cluster: certificate-authority-data: DATA+OMITTED server: https://10.6.76.25:6443 name: kubernetes contexts: - context: cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes - context: cluster: kubernetes user: wx name: wx@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: client-certificate-data: REDACTED client-key-data: REDACTED - name: wx user: client-certificate-data: REDACTED client-key-data: REDACTED
#切换serviceaccount
root@k8s-master pki]# kubectl config use-context wx@kubernetes Switched to context "wx@kubernetes". [root@k8s-master pki]# [root@k8s-master pki]# kubectl get pod Error from server (Forbidden): pods is forbidden: User "wx" cannot list resource "pods" in API group "" in the namespace "default" [root@k8s-master pki]#
从上面的演示,当切换成wx用户进行访问集群时,由于该账户没有管理集群的权限,所以在获取pods资源信息时,会提示Forrbidde这就需要授权了,例如RBAC授权