18-K8S Basic-Kubernetes系统安全(认证、授权和准入控制)
一、课程回顾及安全重要性
-
课程总结:节点上组件间的关系及作用
-
etcd :
- 在k8s中扮演了状态存储系统,存储了当前集群的每一个节点的用户定义的相关的期望状态及当前集群中资源运行的状态,保存在etcd的spec和status当中,当然有一些资源是没有spec字段比如ConfigMap和Secret资源,但是此类资源中其实也是存在spec的只不过是过于简单没有进行其状态嵌套而已。
- 如果etcd宕机或者数据丢失,则导致整个集群的所有状态则丢失,所以一般来说一定要对etcd做高可用,etcd本身是一个有状态应用,如果etcd自身也运行在k8s之上我们就应该使用一个Operator或者使用StatefulSet来对其进行管理。
- 此前使用kubeadm方式进行部署,仅对etcd仅部署了一个实例,并非三个,所以是很有风险的,所以说kubeadm方式部署k8s集群是不太适用于生产环境的。
-
API Server :
- 在k8s之上部署的一个应用程序或者运行的运行的守护进程称之为Kube-apiserver,确实整个ectd存储服务的存储服务的访问入口,可以说集群中所有的有状态信息都必须保存在etcd中,任何客户端都不能直接写入,可以理解为etcd的唯一客户端就是API Server。
- 用户想要创建比如一个Pod资源,通常用户应该使用像kubectl这样的客户端工具与API Server通讯,将数据线交给API Server,再由API Server存储到etcd中,因此可以理解为API Server是我们接入整个k8s集群的网关。
- 这里拿创建一个Pod实例流程进行概述:
- 1、通常用户应该使用像kubectl这样的客户端工具与API Server通讯,将数据线交给API Server,再由API Server存储到etcd中,因此可以理解为API Server是我们接入整个k8s集群的网关。
- 2、Pod是如果被调度到集群节点的Worker-Node节点之上的,由这个Node节点上的kubectl调用docker将其运行Pod资源
- 调度器如何知道由一个新建的Pod产生?
- kube-scheduler也是API Server的客户端之一,一旦有kebectl提交了一个新的Pod定义交给API Server,API Server自己把etcd的数据变动能够通知给注册、监视相关资源的程序,而kube-scheduler就像API Server中注册了哪个没有被调度结果的Pod信息,需要通过API Server完成Pod的查询、修改,最后通过API Server将调度的结果保存到etcd当中
- 调度器如何知道由一个新建的Pod产生?
-
Controller-manager
- controller-manager当中运行了很多contraller,在运行着很多的Contraller-loop也可以称之为和解循环
- 和解循环的相关操作必要时又可能需要获取到当前集群中对应的每一个资源的真实状态,并将其状态更新并保存至kube-api server中,Contraller-loop也不能直接操作etcd,必须向API Server发起请求,所以Contraller-Manager也是API Server的客户端
-kubectl (每一个Node节点运行)
- kubectl作为k8s集群中运行在每一个节点之上的代理程序,它用与获取API Server加载对Pod的定义,并加载本地node节点的Docker引擎将其运行为容器,但是在kubernetes表现为Pod
- Kubectl 和其他资源一样需要注册监听在于自己节点上的Pod的相关信息,kubectl创建完本机节点的Pod资源之后,也需要将自己节点上的Pod信息比如Pod启动成功与否等信息保存在etcd当中,也需要借助API Server
- 所以API Server 是操作etcd存储的唯一入口,也可以称之为HUB
-
Kube-proxy
- API Server上有所有用户提交的关于Service的定义,都会被Kube-proxy所捕获,并读取到本机,并将其转换为IPVS或者IPTABLES规则,而Service的定义一定是在API Server上,Kube-proxy也是扮演的API Server的客户端将本机的Service当前状态保存到etcd当中
- API Server作为Kubernetes网关,是访问和管理资源对象的唯一入口,其各种集群组件访问资源都需要经过网关才能进行正常访问和管理。每一次的访问请求都需要进行合法性的检验,其中包括身份验证、操作权限验证以及操作规范验证等,需要通过一系列验证通过之后才能访问或者存储数据到etcd当中。如下图:
二、认证
2.1、权限模型介绍及操作逻辑
- 不同的应用程序需要我们组织不同的权限模型,为此k8s在API Server内部通过三类插件分别完成以下功能
- Client → API Server (authentication)→ Auth policies → Admission Contol → Allow access
- authentication 认证插件 : 自上而下,认证逻辑为一票通过可以理解为短路操作(逻辑或)
- Auth policies 授权插件 : 自上而下,授权逻辑为一票通过可以理解为短路操作(逻辑或)
- Admission Contol 准入控制插件 :自上而下,控制逻辑为一票否决(每一个控制都要检查,所有认证都要通过准入控制检查)
2.2、K8s支持的认证方式(authentication)
具体来说, API Server 支持以下几种具体的认证方式,其中所有的令牌认证机制通常被统称为承载令牌认证
- 1、X509客户端证书认证
- 客户端在请求报文 中携带 X509 格式的数字证书用于认证,认证通过后,证书中的主体标识( ubj ect )将被识别为用户标识,其中的 CN (CommonName 宇段是用户名, (Organization )是用户所属的组,如“/CN=iIinux/O=opmasters/ O=admin ”中 ,用户名为 ilinux ,其属于 opmasters admin 两个组
- 2、静态令牌文件
- ( Static Token File )即保存着令牌信息的文件,由 kube apiserver 的命令行选项 token -au th file 加载,且服务器启动后不可更改; HTTP 客户端也能使用承载令牌进行身份验证,将令牌进行编码后,通过请求报文 中的 Authorization 首部承载传递给API Server即可
- 3、引导令牌
- ( Bootstrap Tokens ):一种动态管理承载令牌进行身份认证的方式,常用于 简化新建 ub metes 集群的节点认证过程,需要通过一experimental-bootstrap-token auth 选项启用;有新的工作节点首次加入时, Master 使用引导令牌确认节点身份的合法性之后自动为其签署数字证书以用于后续的安全通信,使用 kubeadm join 令将节点加入 kubeadm初始化的集群时使用的即是这种认证方式;这些令牌作为 Secrets 存储在 kube-syst 命名空间中时,可以动态管理和创建它们,而 Controller Manager 包含 Token Cleaner 控制器,用于删除过期的引导令牌
- 4、静态密码文件
- 用户名和密码等令牌以明文格式存储的 csv 格式文件,由 kube apiserver 使用 bas ic auth-fil 选项进行加载;客户端在 HTTP basic 认证中将认证用户的用户名和密码编码后以承载令牌 的格式进行认证
- 5、服务账户令牌
- 由 kube-apiserver 自动启用,并可使用可选选项加载 --service-account-key-file 验证承载令牌的密钥,省略时将使用 kube-apiserver 自己的证书匹配的私钥文件;Service Account 通常由 API Server 自动创建并通过 ServiceAccount 准入控制器将其注入Pod 对象,包括 Service Account 上的承载令牌,容器中的应用程序请求 API Server 的服务时将以此完成身份认证
- 6、OpenID连接令牌
- OAuth2 的一种认证风格,由 Azure AD Salesforc 巳和 Google 等0Auth2 服务商所支持,协议的主要扩展是返回的附加字段,其中的访问令牌也称为 ID 令牌 ;它属于 JSON Web 令牌( JWT )类型,有着服务器签名过的常用字段,如 email 等;kube-apiserver 启用这种认证功能的相关选项较多
- 7、Webhook令牌
- HTTP 身份验证允许将服务器的 URL 注册为 Webhook ,并接收带有承载令牌的 POST 请求进行身份认证;客户端使用 kubeconfig 格式的配置文件,在文件中,“ users ”指的是 API 服务器 Webhook ,“ clusters ”指的是 API Server。
- 8、认证代理
- API Server 支持从请求首部的值中识别用户,如 Remote User 首部,它旨在与身份验证代理服务相结合,并由该代理设置相应的请求首部
- 9、Keystone密码
- 借助于外部的 Keystone 务器进行身份认证
- 10、匿名请求
- 未被任何验证机制明确拒绝的用户即为匿名用户,其会被自动标识 为用户名 system:anonymous ,并隶属于 system:unauthenticated 用户组;在 API Server 启用了除 AlwaysA!low 以外的认证机制时,匿名用户处于启用状态,不过,管理员可通过--anonymous auth=false 选项将其禁用
2.3、K8s支持的认证功能
- 一个API 请求要么以常规用户的身份进行,要么以某特定服务账号的身份进行,否则统一被视为匿名用户。
- 无论来自于Kubernetes集群内或集群外的任何进程的请求,都必须由API Server实现完成认证;常见的客户端进程包括:
- kube-scheduler
- kube-controller-manager
- kubectl
- kubelet
- kube-proxy
- Dashboard、CoreDNS、Flannel等
- 集群上运行于Pod中的进程认证时使用的账号即Service Account
[root@k8s ~]# ls /etc/kubernetes/
admin.conf controller-manager.conf kubelet.conf manifests pki scheduler.conf
2.4、K8S中用户账户与用户组
- Kubernetes 并不会存储由认证插件从客户端请求中提取出的用户及所属组的信息,它们仅仅用于检验用户是否有权限执行其所请求的操作 客户端访问 AP 务的途径通常有种: kubectl 客户端库或者 接使用 REST 接口进行请求,而可以执行此类请求的主体也被Kubernetes 分为两类:现实中的“人”和 Pod 象,它们的用户身份分别对应于常规用户(User Account )和服务账号 (Service Account)
User Account (用户账号 → 人类用户在系统上不存在即使用加密方式进程认证不关系用户名)
: 一般是指由独立于 kubernete 之外的其他服务管理的用户账号,例如由管理员分发的密钥 Keystone 一类的用户存储(账号库)、甚至是包含有用户名和密码列表的文件等 Kubernetes 不存在表示 类用户账号的对象,因此不能被直接添加进 Kubernetes 系统中。Sevice Account (服务账号 → 程序自身运行所需要的账号,真实存在)
: 是指 kubernetes API 管理的账号,用于为 Pod 之中的服务进程在访问 Kubernetes API 时提供身份标识( identity Service Account 通常要绑定于特定的名称空间,它们由 API Server 建,或者通过 API 用于动创建,附带着一组存储为 cret 的用于访问 API Server 的凭据。
# Service Account 服务账号,k8s会通过一个标准的资源简称为sa
-
User Account 通常用于复杂的业务逻辑管控,它作用于系统全局,故其名称必须 局唯相比较来说, Service Account 隶属于名称空间,仅用于实现某些特定的操作任务,因此要轻量得多 这两类账号都可以隶属于一个或多个用户组 用户组只是用户账号的逻辑集合,它本身并没有操作权限,但附加于组上的权限可由其内部的所有用户继承,以实现高效的授权管理机制 Kubernetes 有着以下几个内建的用于特殊目的的组。
- system:unauthenticated :未能通过任何 个授权插件检验的账号,即未通过认证测试的用户所属的组
- system :authenticated :认证成功后的用户自动加入的 个组,用于快捷引用所有正常通过认证的用户账号
- system seviceaccounts :当前系统上的所有 Service Account 对象
- system :serviceaccounts : <namespace >:特定名称空间内所有的 Service Account 对象
-
API 请求要么与普通用户或服务账户进行绑定,要么被视为匿名请求 这意味着群集内部或外部的每个进程,包括由人类用户使用的 kubectl ,到节点上的 ubelet ,再到控制平面的成员组件,必须在向 API 服务器发出请求时进行身份验证,否则即被视为匿名用户
2.5、Kubeconfig(任何客户端需要连入K8S都需要借助Kubeconfig配置文件)→ 普通用户
2.5.1、Kubeconfig介绍
- 一个Kubeconfig文件是YAML格式的配置文件,它通常由以下几个配置段组成:
- users : 用户账号及其认证信息列表
- cluster : 目标集群列表
- cntexts : 以哪个user接入那个clusterr的连接组合
- curren-context : 当前使用的context
~]# cat /etc/kubernetes/admin.conf
apiVersion: v1
clusters:
# 目标集群列表
- cluster:
# 集群中被API Server所信任的证书
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwcmRXSmwKY201bGRHVnpNQjRYRFRJd01EUXlOREUyTkRrd05Gb1hEVE13TURReU1qRTJORGt3TkZvd0ZURVRNQkVHQTFVRQpBeE1LYTNWaVpYSnVaWFJsY3pDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBTkhKCjE4WTNjcCtUNSsrRnBzWnZuVmNwejhIalpuV0Z4TzNvRXpyRDBYd1gxN01rSkxOQjNySGlSenp3blZvRVppKzMKZE5rOGRPem5XOCtlV0U1UjNQOFhlUDRkUEFab0FlT1Nvc1JIYnpqMGsydlFiSHJuV0dlZDhQZ001R015em82UQorRUFKeTBvd0tZeXBET1VERjViQ1NyYjFxY3NTUWZzZHlFQXFlL2VNY3B6UDhZR3pscCt1bGhsUTlNeTBINWtHCmV0bDBYTG5wNm9SVDlyaVlSZEE3NFhCcjhlRExGZ3RjVVpDdWVSM0c1akQyZjBneDhmTmcxcnZBc1FNOWcxWUsKczdlZDE2bDJHZGpFWUxWQ3N6Q01IZXVCeEE1Z2EwNzNhUG9hZWNtcU5NK0FsemZrTVNnZ29qQnVoMFdzbTQ2MQpZczhLM1RYY1VpaTVObG41L0pjQ0F3RUFBYU1qTUNFd0RnWURWUjBQQVFIL0JBUURBZ0trTUE4R0ExVWRFd0VCCi93UUZNQU1CQWY4d0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFGWXdWS3VTNjRGVHZaTzJFM2ZPTGZvYVBZRWQKUXg3SDdYbnNkZVRRR2ROd2JzMzhFRU91bDJzYVBRY0xCdjZNS1VQWVlNUjNJdTBkZ0hBRFZtRkwrQkdZajhqSQpYSkh0VlovY3VzV3dPY3FkUGRmaUlJektNNnlpdDJ2WnJieDJ0Nm5mdXVPM1lwZUtVUVJ5aXhxbitoTDVsTVJUCldya0dMcUhYSy9oc1kvdkl1dFMzdk9CVlR4ZUhPSk9VVDdESytuL09FNGs2anFmTGNqY3dKTVNOZ0hZOGc1YmcKYnRhcWlRZFpNajBrMkRkdDA0VGZmaWNNdlJpTVVDUHJRQmM5TS9LUGpKcHV3Z0hkZUhrd1pIMXRrcVZWMzgxKwpTem1pUS9xS1ViSWZad3FSYitpclpWMFp3SnRXQWU5Y0dzYTYyeGpTVkF0YmN6cWF5ZDllRWJ2a1RXTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
# 集群的访问地址和端口
server: https://192.168.20.236:6443
# 集群名称
name: kubernetes
# 以哪个user接入那个clusterr的连接组合
contexts:
- context:
# 集群名称
cluster: kubernetes
# 哪个用户可以接入此集群
user: kubernetes-admin
# 接入的集群名称
name: kubernetes-admin@kubernetes
# 当前使用的context
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
# 用户列表
users:
# 用户名称
- name: kubernetes-admin
# 定义用户信息,用户凭证
user:
# 用户证书
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJSUZaWTVkYlo1aW93RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TURBME1qUXhOalE1TURSYUZ3MHlNVEEwTWpReE5qUTVNVE5hTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXUxQVJQSjR6dkw4UmRYRFoKQk1OdjRHUXdOSTgzdEpXWUMyNlgvbTIrZG9FZEJkUi9iTlVuSURwNWg3MlFJUk5KWERVQjl5Rk1DLzBOdHBCTQo3dHJ3ajVHdERmdU9qRmtNdGNpY253RWdTZk93b2VOcjdGS0oyTVJmOElNSW1zS2d0TW04bmorSlltN2hPL3N4CkRVZUdGclMxSXJ6LzBkcTluR3FRSkg1WTFWaTBTMEtCbXV1WngxdEJEdUozTWJaeW1IK0lvMW96bHEzQ3kyZEUKWDZSUG5RTlpNWjRxVlZTUk0yZm5VeGc3dGNyME9TOUsvMEs0TS9DNXZiZ3RGeVJBSEcySEV4d2NTL0tETUJITwp3V0lMMmpXc0tIeDZMeGN2R3BBYXE3ditua3NLanpsU1Z0V1hBVW11K3grK1JFNExFQjBIY3hYNXczUFFCWFBJCjJTcXBPd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFKVlg3Nzd1OXlXU1JybUZ4cmRLSVg5UEREWktYY05odUhoeQphbFpNamp2WHNFUmh3cTM5cGdkT1hBaStobjIvRTZ1eGh3TnhwQVZFbjBkMDgxcytBbTdBbmhQQy85cTU2bi9xCjE3bFVUV2V1c2Vhb0lPSDRlTXdWOXV5T1Q0dzJyN21jOHVnWUFsaXkvamNjaTNDR3dEckpIK3cyOEhuVElkci8KMnJ1YmlUTUttQkdRQlNnNnkrQ0plQ05QNDlnNWFoOHQ2S0QxQnE2MEtHN2NJVW1sNEIwUTdSSXA4RUt6U0JOTwp5Y3BhR3JiU0U4czBPazRZLzM4NmxqZUU4WnoraTJtVTZIY0hKa1dKblhEMmtKclJPczBRcVFSbDJqSlNFNjBLCkNDRWNqYWtuYTNqSFN2RkZEZmY1ek1JSzRZY2ZlQjlsZk8xdGpFdjNBNi9Wd1BEMU5hST0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
# 用户私钥
client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdTFBUlBKNHp2TDhSZFhEWkJNTnY0R1F3Tkk4M3RKV1lDMjZYL20yK2RvRWRCZFIvCmJOVW5JRHA1aDcyUUlSTkpYRFVCOXlGTUMvME50cEJNN3Ryd2o1R3REZnVPakZrTXRjaWNud0VnU2ZPd29lTnIKN0ZLSjJNUmY4SU1JbXNLZ3RNbThuaitKWW03aE8vc3hEVWVHRnJTMUlyei8wZHE5bkdxUUpINVkxVmkwUzBLQgptdXVaeDF0QkR1SjNNYlp5bUgrSW8xb3pscTNDeTJkRVg2UlBuUU5aTVo0cVZWU1JNMmZuVXhnN3RjcjBPUzlLCi8wSzRNL0M1dmJndEZ5UkFIRzJIRXh3Y1MvS0RNQkhPd1dJTDJqV3NLSHg2THhjdkdwQWFxN3YrbmtzS2p6bFMKVnRXWEFVbXUreCsrUkU0TEVCMEhjeFg1dzNQUUJYUEkyU3FwT3dJREFRQUJBb0lCQUh1ZDNMSkhxZGRQdFlMdgpCWm9hTE5SRzZuVlZheXIzYXM5b25sQ2dOb2xZcmtHeHVxS2xqVnU4bTRYVXViREtYS2pJcHRKa25CNXhVOEovCk92YUxjU1VldTdtMW9aN0lDaFpTSGVMbHlGeGx3ZFVsRkkxeTcxd3FSVEtpRjJTak81SDBiVkYybHdGcU1hVDMKSXFrajRiOU1aUnBXNXZHa3pXdlQrK3JKbzNDd0o4citBekx6MHE0MHU1WFVLK3huU2dxeXFPRXFWN05DaTF5NApERHVZUzAybXhPaFhyd1grSmpidlJoMFRhdmxhemZuUFNPY1VYNWx4Y1lXY0llZEV4UVlycFc0aW44UUE4UStCCjdtaThvYXQ5WkpKVzYyRytiUDE5N1BySi8zUkVBSmZSRFA5bW43aUxLTkd2azV2WXBFaENWQ2hhZjh5QmN1blAKWGdFbmpxRUNnWUVBMjh3TnArTlVnY1hkR1VlVkJvOW56MVFLNFB4RVJXalpNTVFDWm9mTXdRQlVFV0wyejQyRgpZZlRxZ2IwbE9MRmhLQVRCSTVEOTZPM2FpM0p4VG1zbDJpUWtkU1ZRV21wUlhyaHBRR3ZNampkK3NNa1k3SkFzCnNOVlIyZHFTL05nV29ieGVIaVlUVkp4eTlDaWF1cUQ0V2xvRkpIc2pvVytYVE1XMURTWXZLS3NDZ1lFQTJpcEkKWFROZDdrdCtyVy9KV1RjZEs2bmEwdjMvZjVlSkJIVkoyOWEyM0lrQ2ZGSEVQS01qOWRSMGdCZzNUZUFhRmRzLwpnN1h6ai9LNVhEbUZwaUc4TmdWWnVPMVhBRDdaT3R5dFR6UnpFZG5jZEZEY1k5WEdHdTF4TUZRY1pHbHFyOTBqCnVzN2hMRm5NK1NUTlpTbHdTZ3EvamtuRnAva0lwMVhTTHhYMG9iRUNnWUFyYWkzVVdLbnJqRHEwOEplMkdRTm4KUjNGeXFVR08rRHZXVHhFdVVXcVhRTXBhT05NSmdpbXpoSjRCakd2YXUrYTE4ZUo0ZFA1Q1VTRVc1RDhQUDBqVgp3c2ZVdjg4VVhPVy9zT3RSUnptN2FhakRvS1VrclFHMjJCdjN6UjIxaGJWS3N4dGdGeU5BVmpxNmtYNm1tSDhWCjBhd3NYWXBYSytTVnpJT0xtbHc4U3dLQmdFeGlkWWU4VG16Nm5kWFh4K1dtdUYzclVLU0RMZ3ZjWUtyZzdnVTgKdmpXayt1dlFMU2NWNzZkSXhhbDcwUkZCSDZEN2JOZU93MEpwTjZFa3VyaWFJeTIrM2RVenREeHZ4TnNwSEwwWQpuaGxuOEJvQm5jaU90cGdDL3Bodk9xbWxoeWNnQkR5SjVxa0NvQk96WVA3RWJYNWZHUWFXcWMvUUQ4bVc4TXB2Cm80RmhBb0dCQUpuMmYxbVVHVEdlOTNNZmNUeXlFTEFtMWF3dDJ2L2ZzODNUYVRzYURHT0ZnQWJ4cytvdXdTZjUKU2xnZkx5YWZnQnZ0YjhMR2lwZFQrL3locUVOcVV0dExVT01PUVZGbnR3OS9pVCtsRWl4RENGWjRQbVE2WmpLcwpuRmFBeHBVVFk1VWgvTVVxU05JRmRhdmUzRWtKNWl4NitqTVdGcm9jVE01UjA3V0pTM1lDCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
- name: ui-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkdlVkVpWXIwU0FEVmVDT2pwbGtraTlhWDY2UmFCd2ZhUHM3emtqY0VqT0UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJ1aS1hZG1pbi10b2tlbi0yMnFoMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ1aS1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjdhOWExNGI3LTI3MGQtNGY0ZS05YmYxLTUxMDBlYzc2YTVjNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTp1aS1hZG1pbiJ9.iXWwtlH2DUKiNTV6TnuVG2nyKtpY4D8jykFuiQRYp4xt-wh-4gN2-KYJ_TpSJs3M6NvbkJ-dfWXThiuznSZEno9Ay7Vnhxv63vAW9QoyDK9tNfUlSMkjGOlnktT0X7nZvucMWfG53R_I7qU-ExjYIGR3J1Ur_Mlgia7ejkxVP3Dd7QhTqy__wK6RBZp2cIH0aGUJbMAHEa8ycI6bkMzeF5V6K6GEVxUM6nadWvVtEMKs4EkEZD-XvTeaNTyNwrLcbwS0d8y-FCMXXIqHMYvuNk3SI7F_MvyuBttQYHTNGnE9GTlyFyAD9TP8NTsgpZ5hIgu3k8UUXv5fQ99HB4XbMA
-----------------------------------------------
# 使用view方式显示
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.20.236:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: ui-admin
user:
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IkdlVkVpWXIwU0FEVmVDT2pwbGtraTlhWDY2UmFCd2ZhUHM3emtqY0VqT0UifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJ1aS1hZG1pbi10b2tlbi0yMnFoMiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJ1aS1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjdhOWExNGI3LTI3MGQtNGY0ZS05YmYxLTUxMDBlYzc2YTVjNCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTp1aS1hZG1pbiJ9.iXWwtlH2DUKiNTV6TnuVG2nyKtpY4D8jykFuiQRYp4xt-wh-4gN2-KYJ_TpSJs3M6NvbkJ-dfWXThiuznSZEno9Ay7Vnhxv63vAW9QoyDK9tNfUlSMkjGOlnktT0X7nZvucMWfG53R_I7qU-ExjYIGR3J1Ur_Mlgia7ejkxVP3Dd7QhTqy__wK6RBZp2cIH0aGUJbMAHEa8ycI6bkMzeF5V6K6GEVxUM6nadWvVtEMKs4EkEZD-XvTeaNTyNwrLcbwS0d8y-FCMXXIqHMYvuNk3SI7F_MvyuBttQYHTNGnE9GTlyFyAD9TP8NTsgpZ5hIgu3k8UUXv5fQ99HB4XbMA
-----------------------------------------------
# 获取集群名称
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config get-clusters
NAME
kubernetes
-----------------------------------------------
# 获取上下文
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
-----------------------------------------------
# 获取当前连入上下文
~]# kubectl --kubeconfig=/etc/kubernetes/admin.conf config current-context
kubernetes-admin@kubernetes
- 我们也可以自己做自己需要的账号:
- 注意 :证书想要能够认证到K8S集群上来可以使用的账号认证方式:
- 1、证书认证
- 最简单可以后期定制
- 使用API Server默认的CA向外签署证书,客户端仅需要请求API Server的CA认证签署证书就可以登陆K8S (/etc/kubernetes/pki/ca.crt),CN代表用户名,用户名无需实现在系统上出现
- 2、令牌认证
- 使用令牌认证方式也需要修改API Server启动时加载的令牌文件
- 3、密码认证 :
- 使用用户名及密码认证一定要修改API Server启动时加载的账号密码文件,默认是没有加载任何账号密码文件的
2.5.2、自建Kubeconfig证书认证连入K8S
- 自建k8s客户端证书,使用自建的用户账户连入k8s并且并以为kubeconfig使用(不再使用默认的admin.conf中的管理员客户端,使用创建的普通用户权限连入客户端)
1、手动创建一个私钥
~]# cd /etc/kubernetes/pki/
pki]# openssl genrsa -out ilinux.key 2048
Generating RSA private key, 2048 bit long modulus
..................+++
......................................................................................+++
e is 65537 (0x10001)
2、为此用户生成一个证书签署请求,并且使用k8s API Server默认的ca.crt进行签署
# CN=用户名
# O=用户组
pki]# openssl req -new -key ilinux.key -out ilinux.csr -subj "/CN=ilinux/O=kubeusers"
3、使用k8s API Server默认的ca.crt进行对用户证书签署
pki]# openssl x509 -req -in ilinux.csr -CA ./ca.crt -CAkey ./ca.key -CAcreateserial -out ilinux.crt -days 3560
Signature ok
subject=/CN=ilinux/O=kubeusers
Getting CA Private Key
4、使用kubeconfig创建新的集群(set-cluster)
# 集群名称 # 指定API Server服务器地址 # 集群所使用的CA的证书文件 # 证书是否需要打包起来存放
# kubectl config set-cluster e2e --server=https://1.2.3.4 --certificate-authority= --embed-certs=false
# API Server 地址 : kube-apiserver-k8s.master1 1/1 Running 2 33d 192.168.20.236
# pki]# kubectl config set-cluster mykube --server="https://192.168.20.236:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true
# Cluster "mykube" set.
# 没有指定创建的配置文件位置,默认保存在当前配置文件中,获取创建的群组
# pki]# kubectl config get-clusters
# NAME
# kubernetes
# mykube
# 如果想要定义在另外的配置文件中(如果使用默认的配置文件如下的--kubeconfig= 都无需指定)
pki]# kubectl config set-cluster mykube --server="https://192.168.20.236:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --kubeconfig=/tmp/ilinux.kebeconfig
Cluster "mykube" set.
5、在创建的集群中添加用户(set-credentials)
pki]# kubectl config set-credentials
#Usage:
kubectl config set-credentials NAME [--client-certificate=path/to/certfile] [--client-key=path/to/keyfile] [--token=bearer_token] [--username=basic_user] [--password=basic_password] [--auth-provider=provider_name] [--auth-provider-arg=key=value] [--exec-command=exec_command] [--exec-api-version=exec_api_version] [--exec-arg=arg] [--exec-env=key=value] [options]
# NAME : 添加用户的标识
# --client-certificate= 客户端证书文件路劲
# --client-key= 客户端私钥文件路径
# --username= 用户的用户名
pki]# kubectl config set-credentials ilinux --client-certificate=/etc/kubernetes/pki/ilinux.crt --client-key=/etc/kubernetes/pki/ilinux.key --username=ilinux --embed-certs=true -- kubeconfig=/tmp/ilinux.kebeconfig
User "ilinux" set.
6、将用户和集群进行组合(cntexts)
# 集群名称 # 用户名称
# kubectl config set-context [NAME | --current] [--cluster=cluster_nickname] [--user=user_nickname][--namespace=namespace] [options]
pki]# kubectl config set-context ilinux@mykube --cluster=mykube --user=ilinux --kubeconfig=/tmp/ilinux.kebeconfig
Context "ilinux@mykube" created.
# 查看自己的配置文件(kubectl config view : 查看默认配置文件)
pki]# kubectl config view --kubeconfig=/tmp/ilinux.kebeconfig
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://192.168.20.236:6443
name: mykube
contexts:
- context:
cluster: mykube
user: ilinux
name: ilinux@mykube
current-context: ""
kind: Config
preferences: {}
users:
- name: ilinux
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
username: ilinux
7、定义自己创建的config的当前上下文
pki]# kubectl config use-context ilinux@mykube --kubeconfig=/tmp/ilinux.kebeconfig
Switched to context "ilinux@mykube".
pki]# kubectl config get-contexts --kubeconfig=/tmp/ilinux.kebeconfig
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* ilinux@mykube mykube ilinux
8、验证访问pods
pki]# kubectl get pods --kubeconfig=/tmp/ilinux.kebeconfig
Error from server (Forbidden): pods is forbidden: User "ilinux" cannot list resource "pods" in API group "" in the namespace "default" # 返回无权限
# 使用默认的
pki]# kubectl get pods
NAME READY STATUS RESTARTS AGE
myapp-5d587c4d45-b24w7 1/1 Running 1 32d
myapp-5d587c4d45-cvj4z 1/1 Running 2 32d
# 换个配置文件则换个用户及权限
# 如果创建集群时不使用--kebeconfig 选项则标识存放至默认的配置文件中,那么以下的操作都无需使用--kubeconfig选项,切换身份时也无需指定此选项。
- 在上面的配置文件当中,定义了集群、上下文以及用户。其中Config也是K8S的标准资源之一,在该配置文件当中定义了一个集群列表,指定的集群可以有多个;用户列表也可以有多个,指明集群中的用户;而在上下文列表当中,是进行定义可以使用哪个用户对哪个集群进行访问,以及当前使用的上下文是什么。如图:定义了用户kubernetes-admin可以对kubernetes该集群的访问,用户kubernetes-user1对Clluster1集群的访问
2.6、Service Account服务账号管理与应用
- 运行过程中, Pod 资源里的容器进程在某些场景中需要调用 Kubemetes API 或者其他类型的服务,而这些服务通常需要认证客户端身份,如调度器、 Pod 控制器或节点控制器,甚至是获取启动容器的镜像访问的私有 Registry 服务等 服务账户就是用于让 Pod 对象内的容器进程访问其他服务时提供身份认证信息的账户 Service Account 资源一般由用户名及相关的 Secret 对象组成
2.6.1、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/
- Service Account也是一种标准的k8s资源并简称为sa
~]# kubectl explain sa
KIND: ServiceAccount
VERSION: v1 # 属于核心群组
DESCRIPTION:
ServiceAccount binds together: * a name, understood by users, and perhaps
by peripheral systems, for an identity * a principal that can be
authenticated and authorized * a set of secrets
FIELDS:
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
automountServiceAccountToken <boolean>
AutomountServiceAccountToken indicates whether pods running as this service
account should have an API token automatically mounted. Can be overridden
at the pod level.
imagePullSecrets <[]Object> # 此secrets认证信息还可以通过imagePullSecrets接入到某一个docker仓储中,实现托取私有仓库镜像
ImagePullSecrets is a list of references to secrets in the same namespace
to use for pulling any images in pods that reference this ServiceAccount.
ImagePullSecrets are distinct from Secrets because Secrets can be mounted
in the pod, but ImagePullSecrets are only accessed by the kubelet. More
info:
https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
secrets <[]Object> # 通过serets资源保存了账号接入api Service的认证信息
Secrets is the list of secrets allowed to be used by pods running using
this ServiceAccount. More info:
https://kubernetes.io/docs/concepts/configuration/secret
- 细心的读者或许已经注意到,此前创建的每个 Pod 资源都自动关联了一个存储卷,并由其容器挂载至/var/run/secrets/kubernetes.io/servic account 目录,例如,下面由“ kubectl describe pod ”命令显示的某 Pod 对象描述信息的片断
~]# kubectl describe pods mypod
Name: mypod
Namespace: default
Priority: 0
Node: k8s.node2/192.168.20.214
Start Time: Thu, 30 Apr 2020 14:13:03 +0800
Labels: <none>
Annotations: Status: Running
IP: 10.244.2.51
IPs:
IP: 10.244.2.51
Containers:
myapp:
Container ID: docker://e529e2d176d022d6189e46fde07b88660d9e859018c29c3efa54a847e2749899
Image: ikubernetes/myapp:v1
Image ID: docker-pullable://ikubernetes/myapp@sha256:9c3dc30b5219788b2b8a4b065f548b922a34479577befb54b03330999d30d513
Port: 80/TCP
Host Port: 8080/TCP
State: Running
Started: Sat, 23 May 2020 16:29:14 +0800
Last State: Terminated
Reason: Completed
Exit Code: 0
Started: Thu, 30 Apr 2020 14:13:04 +0800
Finished: Sat, 23 May 2020 16:28:57 +0800
Ready: True
Restart Count: 1
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-q97bf (ro)
# (令牌的使用方式)令牌放置路径,在容器内部(里面保存的就是当前运行的pod的service账号的用于认证到API Server上的账号的相关令牌,认证挂载之后基本上都能够连入API Server)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-q97bf: # 默认的令牌,用户当前的Pod用于连入api server 更新自己的信息
Type: Secret (a volume populated by a Secret)
SecretName: default-token-q97bf
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events: <none>
-
从上面可以看到每个Pod无论定义与否都会有个存储卷,这个存储卷为default-token-*** token令牌,这就是pod和serviceaccount认证信息。通过secret进行定义,由于认证信息属于敏感信息,所以需要保存在secret资源当中,并以存储卷的方式挂载到Pod当中。从而让Pod内运行的应用通过对应的secret中的信息来连接apiserver,并完成认证。每个 namespace 中都有一个默认的叫做 default 的 service account 资源。进行查看名称空间内的secret,也可以看到对应的default-token。让当前名称空间中所有的pod在连接apiserver时可以使用的预制认证信息,从而保证pod之间的通信。
-
为了方便每创建一个Pod都要添加一个令牌和认证文件,Pod连接API Server更新自己的Pod信息是一个巨大的麻烦,k8s借助一个准入控制器,当创建Pod时可以接入准入控制器可以自动为Pod创建一个Serveraccount-name,并且连入API Server,所以Pod中的守护进程需要连入API Server时,
[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
- 而默认的service account 仅仅只能获取当前Pod自身的相关属性,无法观察到其他名称空间Pod的相关属性信息。如果想要扩展Pod,假设有一个Pod需要用于管理其他Pod或者是其他资源对象,是无法通过自身的名称空间的serviceaccount进行获取其他Pod的相关属性信息的,此时就需要进行手动创建一个serviceaccount,并在创建Pod时进行定义。那么serviceaccount该如何进行定义呢???实际上,service accout也属于一个k8s资源,如下查看service account的定义方式:
2.6.2、Service Account创建
#1、sa创建实例 , secret不用创建会自动引用相对应的名称空间下默认的Token令牌机制赋予一个令牌Token认证的secret
chapter10]# cat serviceaccount-demo.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: sa-demo
namespace: default
2、使用声明式接口创建资源
chapter10]# kubectl apply -f serviceaccount-demo.yaml
serviceaccount/sa-demo created
3、获取创建的sa资源
chapter10]# kubectl get sa -n default
NAME SECRETS AGE
default 1 33d
sa-demo 1 26s
# 如果创建Pod时没有指明所调用的sa是什么则默认使用default的sa
4、获取默认的default 的sa的secret
chapter10]# kubectl describe sa default
Name: default
Namespace: default
Labels: <none>
Annotations: <none>
Image pull secrets: <none>
Mountable secrets: default-token-q97bf
Tokens: default-token-q97bf # 默认的Token令牌机制赋予一个令牌Token认证的secret
Events: <none>
chapter10]# kubectl get secrets
NAME TYPE DATA AGE
default-token-q97bf kubernetes.io/service-account-token 3 33d
sa-demo-token-6q6n7 kubernetes.io/service-account-token 3 3m20s
- 看到有一个 token 已经被自动创建,并被 service account 引用。设置非默认的 service account,只需要在 pod 的spec.serviceAccountName 字段中将name设置为您想要用的 service account 名字即可。在 pod 创建之初 service account 就必须已经存在,否则创建将被拒绝。需要注意的是不能更新已创建的 pod 的 service account。
四、K8s 授权模块
- Node : 专用的授权插件,根据Pod对象调度结果为Node进行授权
- ABAC : 基于属性的访问控制
- RBAC : 基于角色的访问控制
- Webhook :基于http回调机制的访问控制
# 查看当前k8s集群启动的授权方式
# cat /etc/kubernetes/manifests/kube-apiserver.yaml
spec:
containers:
- command:
- kube-apiserver
- --advertise-address=192.168.20.236
- --allow-privileged=true
- --authorization-mode=Node,RBAC
4.1、授权RBAC角色访问控制介绍
-
Kubernetes的授权是基于插件形式的,其常用的授权插件有以下几种:
- Node(节点认证)
- ABAC(基于属性的访问控制)
- RBAC(基于角色的访问控制)
- 用户→ Subjects
- User Account
- Service Account
- 角色 → Objects
- Resources : 资源
- SjResources : 子资源
- URL :非资源性URL
- Role,RoleBinding(所谓的授权仅是能让用户操作角色仅此而已,但是又不能直接产生关联关系,所以一需要借助Role,RoleBinding)
- Role : 名称空间级别的角色 ,比如名称空间级别的资源(pods、service、contaller等)
- ClusterRole : 集群级别的角色 , 比如集群级别的资源(node、pv、ns等)
- 定义对哪个或哪些资源施加何种操作
- 能够对角色施加的操作
- POST → create
- GET ,head → get ,list
- PUT → update
- PATCH → patch
- DELETE → delete,deletecollections
- 能够对角色施加的操作
- 定义对哪个或哪些资源施加何种操作
- RoleBinding : 将用户绑定到Role , 也能将用户绑定至ClusterRole
- ClusterBinding : 用户绑定到ClusterRole
- 从而使得让用户扮演某个角色
- 用户→ Subjects
- Webhook(基于http回调机制的访问控制)
-
让一个用户(Users)扮演一个角色(Role),角色拥有权限,从而让用户拥有这样的权限,随后在授权机制当中,只需要将权限授予某个角色,此时用户将获取对应角色的权限,从而实现角色的访问控制。如图:
- 基于角色的访问控制(Role-Based Access Control, 即”RBAC”)使用”rbac.authorization.k8s.io” API Group实现授权决策,允许管理员通过Kubernetes API动态配置策略。
- 在k8s的授权机制当中,采用RBAC的方式进行授权,其工作逻辑是 把对对象的操作权限定义到一个角色当中,再将用户绑定到该角色,从而使用户得到对应角色的权限。此种方式仅作用于名称空间当中,这是什么意思呢?当User1绑定到Role角色当中,User1就获取了对该NamespaceA的操作权限,但是对NamespaceB是没有权限进行操作的,如get,list等操作。
- 另外,k8s为此还有一种集群级别的授权机制,就是定义一个集群角色(ClusterRole),对集群内的所有资源都有可操作的权限,从而将User2,User3通过ClusterRoleBinding到ClusterRole,从而使User2、User3拥有集群的操作权限。Role、RoleBinding、ClusterRole和ClusterRoleBinding的关系如下图:
- 但是这里有2种绑定ClusterRoleBinding、RoleBinding。也可以使用RoleBinding去绑定ClusterRole。
- 当使用这种方式进行绑定时,用户仅能获取当前名称空间的所有权限。为什么这么绕呢??
- 举例有10个名称空间,每个名称空间都需要一个管理员,而该管理员的权限都是一致的。那么此时需要去定义这样的管理员,使用RoleBinding就需要创建10个Role,这样显得更加繁重。为此当使用RoleBinding去绑定一个ClusterRole时,该User仅仅拥有对当前名称空间的集群操作权限,换句话说,此时只需要创建一个ClusterRole就解决了以上的需求。
- 这里要注意的是:RoleBinding仅仅对当前名称空间有对应的权限。
- 在RBAC API中,一个角色包含了一套表示一组权限的规则。 权限以纯粹的累加形式累积(没有”否定”的规则)。 角色可以由命名空间(namespace)内的Role对象定义,而整个Kubernetes集群范围内有效的角色则通过ClusterRole对象实现。
4.2、Kubernetes RBAC的演示
User --> Rolebinding --> Role
4.2.1、角色创建
一个Role对象只能用于授予对某一单一命名空间中资源的访问权限
[root@k8s-master ~]# kubectl create role -h #查看角色创建帮助
Create a role with single rule.
Examples:
# Create a Role named "pod-reader" that allows user to perform "get", "watch" and "list" on pods
kubectl create role pod-reader --verb=get --verb=list --verb=watch --resource=pods
# Create a Role named "pod-reader" with ResourceName specified
kubectl create role pod-reader --verb=get --resource=pods --resource-name=readablepod --resource-name=anotherpod
# Create a Role named "foo" with API Group specified
kubectl create role foo --verb=get,list,watch --resource=rs.extensions
# Create a Role named "foo" with SubResource specified
kubectl create role foo --verb=get,list,watch --resource=pods,pods/status
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--dry-run=false: If true, only print the object that would be sent, without sending it.
-o, --output='': Output format. One of:
json|yaml|name|go-template|go-template-file|templatefile|template|jsonpath|jsonpath-file.
--resource=[]: Resource that the rule applies to
--resource-name=[]: Resource in the white list that the rule applies to, repeat this flag for multiple items
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
--verb=[]: Verb that applies to the resources contained in the rule
Usage:
kubectl create role NAME --verb=verb --resource=resource.group/subresource [--resource-name=resourcename] [--dry-run]
[options]
使用kubectl create进行创建角色,指定角色名称,--verb指定权限,--resource指定资源或者资源组,--dry-run单跑模式并不会创建
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master ~]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml #干跑模式查看role的定义
apiVersion: rbac.authorization.k8s.io/v1
kind: Role #资源类型
metadata:
creationTimestamp: null
name: pods-reader
rules:
- apiGroups: #对那些api组内的资源进行操作
- ""
resources: #对那些资源定义
- pods
verbs: #操作权限定义
- get
- list
- watch
[root@k8s-master ~]# cd mainfests/
[root@k8s-master mainfests]# kubectl create role pods-reader --verb=get,list,watch --resource=pods --dry-run -o yaml > role-demo.yaml
[root@k8s-master mainfests]# vim role-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pods-reader
namespace: default
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master mainfests]# kubectl apply -f role-demo.yaml #角色创建
role.rbac.authorization.k8s.io/pods-reader created
[root@k8s-master mainfests]# kubectl get role
NAME AGE
pods-reader 3s
[root@k8s-master mainfests]# kubectl describe role pods-reader
Name: pods-reader
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"Role","metadata":{"annotations":{},"name":"pods-reader","namespace":"default"},"rules":[{"apiGroup...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
pods [] [] [get list watch] #此处已经定义了pods-reader这个角色对pods资源拥有get、list、watch的权限
4.2.2、角色的绑定
RoleBinding可以引用在同一命名空间内定义的Role对象
[root@k8s-master ~]# kubectl create rolebinding -h #角色绑定创建帮助
Create a RoleBinding for a particular Role or ClusterRole.
Examples:
# Create a RoleBinding for user1, user2, and group1 using the admin ClusterRole
kubectl create rolebinding admin --clusterrole=admin --user=user1 --user=user2 --group=group1
Options:
--allow-missing-template-keys=true: If true, ignore any errors in templates when a field or map key is missing in
the template. Only applies to golang and jsonpath output formats.
--clusterrole='': ClusterRole this RoleBinding should reference
--dry-run=false: If true, only print the object that would be sent, without sending it.
--generator='rolebinding.rbac.authorization.k8s.io/v1alpha1': The name of the API generator to use.
--group=[]: Groups to bind to the role
-o, --output='': Output format. One of:
json|yaml|name|templatefile|template|go-template|go-template-file|jsonpath-file|jsonpath.
--role='': Role this RoleBinding should reference
--save-config=false: If true, the configuration of current object will be saved in its annotation. Otherwise, the
annotation will be unchanged. This flag is useful when you want to perform kubectl apply on this object in the future.
--serviceaccount=[]: Service accounts to bind to the role, in the format <namespace>:<name>
--template='': Template string or path to template file to use when -o=go-template, -o=go-template-file. The
template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].
--validate=true: If true, use a schema to validate the input before sending it
Usage:
kubectl create rolebinding NAME --clusterrole=NAME|--role=NAME [--user=username] [--group=groupname]
[--serviceaccount=namespace:serviceaccountname] [--dry-run] [options]
使用kubectl create进行创建角色绑定,指定角色绑定的名称,--role|--clusterrole指定绑定哪个角色,--user指定哪个用户
Use "kubectl options" for a list of global command-line options (applies to all commands).
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --role=pods-reader --user=magedu --dry-run -o yaml > rolebinding-demo.yaml
[root@k8s-master mainfests]# cat rolebinding-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
creationTimestamp: null
name: magedu-read-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-demo.yaml #创建角色绑定
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[root@k8s-master mainfests]# kubectl describe rolebinding magedu-read-pods #查看角色绑定的信息,这里可以看到user:magedu绑定到了pods-reader这个角色上
Name: magedu-read-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"annotations":{},"creationTimestamp":null,"name":"magedu-read-pods","name...
Role:
Kind: Role
Name: pods-reader
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[root@k8s-master ~]# kubectl config use-context magedu@kubernetes #切换magedu这个用户,并使用get获取pods资源信息
Switched to context "magedu@kubernetes".
[root@k8s-master ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 3d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[root@k8s-master ~]# kubectl get pods -n ingress-nginx #测试获取ingress-nginx这个名称空间的pods信息
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
- 从上面的操作,可以总结出,role的定义和绑定,仅作用于当前名称空间,在获取ingress-nginx名称空间时,一样会出现Forbidden!!!
User --> Clusterrolebinding --> Clusterrole
4.2.3、clusterrole定义
- ClusterRole对象可以授予与Role对象相同的权限,但由于它们属于集群范围对象, 也可以使用它们授予对以下几种资源的访问权限:
- 集群范围资源(例如节点,即node)
- 非资源类型endpoint(例如”/healthz”)
- 跨所有命名空间的命名空间范围资源(例如pod,需要运行命令kubectl get pods --all-namespaces来查询集群中所有的pod)
[root@k8s-master mainfests]# kubectl config use-context kubernetes-admin@kubernetes #切换会kubernetes-admin用户
Switched to context "kubernetes-admin@kubernetes".
[root@k8s-master mainfests]# kubectl create clusterrole cluster-read --verb=get,list,watch --resource=pods -o yaml > clusterrole-demo.yaml
[root@k8s-master mainfests]# vim clusterrole-demo.yaml #定义clusterrole和权限
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: cluster-read
rules:
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- list
- watch
[root@k8s-master mainfests]# kubectl apply -f clusterrole-demo.yaml #创建clusterrole
clusterrole.rbac.authorization.k8s.io/cluster-read configured
- 这里我们需要切换回kubernetes-admin账户,是由于magedu账户不具备创建的权限,这也说明普通用户是无法进行创建K8S资源的,除非进行授权。如下,我们另开一个终端,将配置到一个普通用户ik8s上,使其使用magedu账户进行通信
[root@k8s-master ~]# useradd ik8s
[root@k8s-master ~]# cp -rp .kube/ /home/ik8s/
[root@k8s-master ~]# chown -R ik8s.ik8s /home/ik8s/
[root@k8s-master ~]# su - ik8s
[ik8s@k8s-master ~]$ kubectl config use-context magedu@kubernetes
Switched to context "magedu@kubernetes".
[ik8s@k8s-master ~]$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: REDACTED
server: https://192.168.56.11:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: magedu
name: magedu@kubernetes
current-context: magedu@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
- name: magedu
user:
client-certificate-data: REDACTED
client-key-data: REDACTED
4.2.4、clusterrolebinding定义
[root@k8s-master mainfests]# kubectl get rolebinding #获取角色绑定信息
NAME AGE
magedu-read-pods 1h
[root@k8s-master mainfests]# kubectl delete rolebinding magedu-read-pods #删除前面的绑定
rolebinding.rbac.authorization.k8s.io "magedu-read-pods" deleted
[ik8s@k8s-master ~]$ kubectl get pods #删除后,在ik8s普通用户上进行获取pods资源信息,就立马出现forbidden了
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "default"
[root@k8s-master mainfests]# kubectl create clusterrolebinding magedu-read-all-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > clusterrolebinding-demo.yaml
[root@k8s-master mainfests]# vim clusterrolebinding-demo.yaml #创建角色绑定,将magedu绑定到clusterrole:magedu-read-all-pods上
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: magedu-read-all-pods
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl get clusterrole
NAME AGE
admin 52d
cluster-admin 52d
cluster-read 13m
......
[root@k8s-master mainfests]# kubectl apply -f clusterrolebinding-demo.yaml
clusterrolebinding.rbac.authorization.k8s.io/magedu-read-all-pods created
[root@k8s-master mainfests]# kubectl get clusterrolebinding
NAME AGE
......
magedu-read-all-pods 10s
[root@k8s-master mainfests]# kubectl describe clusterrolebinding magedu-read-all-pods
Name: magedu-read-all-pods
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"rbac.authorization.k8s.io/v1beta1","kind":"ClusterRoleBinding","metadata":{"annotations":{},"name":"magedu-read-all-pods","namespace":""...
Role:
Kind: ClusterRole
Name: cluster-read
Subjects:
Kind Name Namespace
---- ---- ---------
User magedu
[ik8s@k8s-master ~]$ kubectl get pods #角色绑定后在ik8s终端上进行获取pods信息,已经不会出现forbidden了
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx #更换名称空间进行查看也是可行的
NAME READY STATUS RESTARTS AGE
default-http-backend-7db7c45b69-nqxw9 1/1 Running 1 4d
nginx-ingress-controller-6bd7c597cb-9fzbw 1/1 Running 0 4d
[ik8s@k8s-master ~]$ kubectl delete pods pod-sa-demo #但是进行删除pod就无法进行,因为在授权时是没有delete权限的
Error from server (Forbidden): pods "pod-sa-demo" is forbidden: User "magedu" cannot delete pods in the namespace "default"
- 从上面的实验,我们可以知道对用户magedu进行集群角色绑定,用户magedu将会获取对集群内所有资源的对应权限。
User --> Rolebinding --> Clusterrole
- 将maedu通过rolebinding到集群角色magedu-read-pods当中,此时,magedu仅作用于当前名称空间的所有pods资源的权限
[root@k8s-master mainfests]# kubectl delete clusterrolebinding magedu-read-all-pods
clusterrolebinding.rbac.authorization.k8s.io "magedu-read-all-pods" deleted
[root@k8s-master mainfests]# kubectl create rolebinding magedu-read-pods --clusterrole=cluster-read --user=magedu --dry-run -o yaml > rolebinding-clusterrole-demo.yaml
[root@k8s-master mainfests]# vim rolebinding-clusterrole-demo.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: magedu-read-pods
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-read
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: magedu
[root@k8s-master mainfests]# kubectl apply -f rolebinding-clusterrole-demo.yaml
rolebinding.rbac.authorization.k8s.io/magedu-read-pods created
[ik8s@k8s-master ~]$ kubectl get pods
NAME READY STATUS RESTARTS AGE
filebeat-ds-hxgdx 1/1 Running 1 36d
filebeat-ds-s466l 1/1 Running 2 36d
myapp-0 1/1 Running 0 2d
myapp-1 1/1 Running 0 2d
myapp-2 1/1 Running 0 2d
myapp-3 1/1 Running 0 2d
pod-sa-demo 1/1 Running 0 1d
pod-vol-demo 2/2 Running 0 4d
redis-5b5d6fbbbd-q8ppz 1/1 Running 1 4d
[ik8s@k8s-master ~]$ kubectl get pods -n ingress-nginx
No resources found.
Error from server (Forbidden): pods is forbidden: User "magedu" cannot list pods in the namespace "ingress-nginx"
五、RBAC的三种授权访问
- RBAC不仅仅可以对user进行访问权限的控制,还可以通过group和serviceaccount进行访问权限控制。当我们想对一组用户进行权限分配时,即可将这一组用户归并到一个组内,从而通过对group进行访问权限的分配,达到访问权限控制的效果。
- 从前面serviceaccount我们可以了解到,Pod可以通过 spec.serviceAccountName来定义其是以某个serviceaccount的身份进行运行,当我们通过RBAC对serviceaccount进行访问授权时,即可以实现Pod对其他资源的访问权限进行控制。也就是说,当我们对serviceaccount进行rolebinding或clusterrolebinding,会使创建Pod拥有对应角色的权限和apiserver进行通信。如图: