欢迎访问我的博客,你的支持,是我最大的动力!

马哥_K8s进阶实战(8)认证、授权与准入控制

Docker 马从东 260℃ 评论
目录:
[显示]

认证用于身份鉴别,授权实现权限分派,准入控制用于补充授权机制以实现更精细的访问控制功能
认证、授权以插件化方式实现,有多种可用插件

访问控制

API Server是集群网关,是访问及管理资源对象的唯一入口
客户端认证由API Server配置的一到多个认证插件完成(依次调用认证插件,直到其中一个插件可以识别请求者身份为止)

客户端 -> API Server -> 认证插件 -> 授权插件 -> 准入控制插件 -> 写入成功
# 客户端 -> API Server -> Authentication -> Authorization -> AdmissionControl -> 写入成功  即3A认证

用户帐户与用户组

访问API服务途径:kubectl、客户端库、REST接口
请求主体:UserAccount、ServiceAccount

UserAccount常用于复杂业务逻辑管控,作用于系统全局,独立于K8s之外
ServiceAccount仅用于实现某些特定操作任务,隶属于名称空间,由API Server管理

K8s内建用户组:
system:unauthenticated,未通过认证测试的用户所属的组
system:authenticated,认证成功的用户自动加入的组,用于快捷引用所有正常通过认证的用户帐号
system:serviceaccounts,当前系统上所有Service Account对象
system:serviceaccounts:<namespace>,特定名称空间内所有Service Account对象

认证、授权与准入控制基础

身份证认插件,支持的认证方式包括客户端证书、承载令牌 bearer tokens、身份验证代理 authenticating proxy、HTTP basic认证
API Server支持同时启用多种认证机制,但至少包括ServiceAccount和UserAccount各一种
启用多种认证插件时,认证过程会以串行方式进行,直到一种成功即结束,认证失败会返回 401

认证方式:
1、X509客户端证书认证:客户端请求报文中携带X509格式证书,通过后,CN字段是用户名,O字段是所属的组,O可以有多个,即属于多个组
2、静态令牌文件:由kube-apiserver 选项--token-auth-file加载,启动后不可更改;HTTP客户端也能使用承载令牌进行身份验证,将令牌编码后,请求报文中Authorization承载传递
3、引导令牌:kubeadm join将节点加入集群时,就是这种方式
4、静态密码文件:用户名密码等以明文存储的CSV格式文件,由kube-apiserver通过--basic-auth-file加载
5、服务帐户令牌:由kube-apiserver自动启用。ServiceAccount通常由API Server自动创建,并通过ServiceAccount准入控制器将其注入Pod对象,容器中应用请求API Server的服务时将以此完成身份证证
6、OpenID连接令牌:OAuth2认证
7、Webhook令牌:客户端使用kubeconfig格式的配置文件
8、认证代理:X-Remote-User
9、Keystone密码:借助Keystone服务器进行身份认证
10、匿名请求:未被任何验证机制明确拒绝的用户即匿名用户,system:anonymous 属于 system:unauthenticated组;匿名用户可通过 --anonymous-auth=false禁用

内建的授权插件:
Node,基于Pod资源的目标调度节点来实现对kubelet的访问控制
ABAC,基于属性的访问控制,attribute-based access control
RBAC,基于角色的访问控制,role-based access control
Webhook,基于HTTP回调机制通过外部REST服务检查确认用户授权的访问控制
AlwaysDeny,总是拒绝,仅用于测试
AlwaysAllow,总是允许
启用API Server时 --authorization-mode定义要启用的授权机制,多个选项以逗号分隔

准入控制器
在对象持久化存储etcd前,强制执行对象的语义验证等功能
读取资源信息的请求不会经过准入控制器检查
AlwaysAdmit,允许所有请求
AlwaysDeny,拒绝所有请求,仅用于测试
AlwaysPullImages,总是下载镜像
NamespaceLifecycle,拒绝在不存在的名称空间创建资源,删除名称空间会级联删除其下所有资源
LimitRanger,可用资源范围界定,确保资源请求不会超限
ServiceAccount,实现ServiceAccount管理机制自动化,创建Pod对象时自动为其附加相关ServiceAccount对象
PersistnetVolumeLabel,为由云计算服务商提供的PV自动附加region或zone标签
DefaultStorageClass,监控所有创建PVC对象的请求,保证没有附加专用StorageClass的请求会自动设定一个默认值
ResourceQuota,对名称空间设置可用资源上限,确保在其中创建的设置了资源限额的对象不会超出名称空间的资源配额
DefaultTolerationSeconds,如果Pod对象上不存在污点宽容期限,则为它们设置默认宽容期,以宽容 notready:NoExecute 和 unreachable:NoExctute 类污点5min
ValidatingAdmissionWebhook,并行调用匹配当前请求的所有验证类Webhook,任何一个校验失败,请求即失败
MutatingAdmissionWebhook,串行调用匹配当前请求的所有变异类Webhook,每个调用都可能会更改对象

服务帐户管理与应用

Service Account 资源一般由用户名和相关的Secret对象组成
用于让Pod对象内的容器进程访问其他服务时提供身份认证信息,这些其他服务包括:API 调度器 Pod控制器 节点控制器 私有Registry服务等

Service Account 自动化

每个Pod都会自动关联一个存储卷,挂载至 /var/run/secrets/kubernetes.io/serviceaccount

kubectl exec filebeat-ds-tlrf2 -- ls /var/run/secrets/kubernetes.io/serviceaccount
# 挂载点目录中包括三个文件 ca.crt namespace token
# token保存了Service Account的认证token 容器中进程使用它向API Server发起连接请求

每个Pod对象都只有一个服务帐户,若创建时未明确指定,会自动附加当前名称空间中默认服务帐户default
kubectl describe serviceaccounts default

服务帐户自动化依赖三个组件:
Service Account 准入控制器、令牌控制器(token controller)、Service Account帐户控制器
kube-controller-manager要使用 --service-account-private-key-file 指定私钥文件(pem格式),用于对生成的服务帐户令牌进行签名
kube-apiserver要使用 --service-account-key-file 指定与前面私钥配对的公钥,用于在认证期间对认证令牌进行校验

创建服务帐户

每个名称空间都有一个default资源对象
service account隶属于名称空间,用于让Pod内部应用程序与API Server通信时完成身份认证

kubectl get serviceaccounts --all-namespaces

创建Pod资源时,可使用 spec.serviceAccountName 指定要使用的服务帐户对象;省略则自动附加default服务帐户

注,会自动创建对应的secret对象

调用 imagePullSecret资源对象

服务帐户可附带 spec.imagePullSecret字段,用于提供镜像仓库的帐号信息

X.509 数字证书认证

SSL/TLS 双向认证

K8s中的SSL/TLS认证

etcd集群内对等节点通信:默认2380端口,基于SSL/TLS通信
etcd服务器与客户端通信:Restful API 默认2379端口,基于SSL/TLS通信

客户端配置文件kubeconfig

包括kubectl、kubelet、kube-controller-manager等在内的API Server的各类客户端都可以使用kubeconfig配置文件提供接入多个集群的相关配置信息
包括API Server的URL及认证信息,且可设置不同的上下文,并在各环境之间快速切换

/etc/kubernetes/admin.conf即为kubeconfig格式的配置文件

# 查看当前正在使用的配置文件
kubectl config view  #显示群集列表、用户列表、上下文列表、当前使用的上下文
# 上下文是集群和用户的配对

kubeconfig配置文件可通过kubectl config命令进行设定
kubectl config view,打印文件内容
kubectl config set-cluster,设置clusters段
kubectl config set-credentials,设置users段
kubectl config set-context,设置contexts段
kubectl config set-use-context,设置current-context段

添加用户:

1、为帐号kube-user1创建私钥及证书文件,保存于/etc/kubernetes/pki目录中 #需要在master节点以root用户执行
cd /etc/kubernetes/pki
(umask 077; openssl genrsa -out kube-user1.key 2048)
openssl req -new -key kube-user1.key -out kube-user1.csr -subj "/CN=kube-user1/O=kubeusers"
## 其中 CN是用户名,O是用户组
openssl x509 -req -in kube-user1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kube-user1.crt -days 3650
# 验证证书(可选)
openssl x509 -in kube-user1.crt -text -noout
2、以默认管理员 kubernetes-admin@kubernetes为新用户kube-user1设定配置文件,默认保存于 .kube/config 也可使用 --kubeconfig指定自定义路径
i.配置集群信息,存在可省略此步骤
kubectl config set-cluster kubernetes-new --embed-certs=true --certificate-authority=/etc/kubernetes/pki/ca.crt --server="https://192.168.1.110:6443"
ii.配置客户端证书及密钥,用户名组名会自动提取
kubectl config set-credentials kube-user1 --embed-certs=true --client-certificate=/etc/kubernetes/pki/kube-user1.crt --client-key=/etc/kubernetes/pki/kube-user1.key
iii.配置context,组合cluster和credentials
kubectl config set-context kube-user1@kubernetes-new --cluster=kubernetes-new --user=kube-user1
iv.指定当前上下文
kubectl config use-context kube-user1@kubernetes-new
v.测试
kubectl get pods  #因集群启用了RBAC,访问会返回forbidden
临时使用某context
kubectl --context=kube-user1@kubernetes-new get pods

TLS bootstrapping机制

新节点加入集群时,由kubelet自行生成私钥和证书签署请求,发送给集群上的证书签署里程(CA),由管理员验证请求后予以签署或自动统一签署。
请求证书时,kubelet要使用含有bootstrap token的kubeconfig文件向kube-apiserver发送请求
证书请求审批后,接收到的证书和私钥相关信息会存储于--kubeconfig选项指定的文件中,证书和私钥文件存储于 --cert-dir指定的目录下

基于角色的访问控制 RBAC

Role-Based Access Control
为由帐号赋予一到多个角色,从而让其具有角色之上的权限。帐号可以是用户帐号、用户组、服务帐号、相关的组等
同时关联到多个角色的帐号拥有的权限是多个角色之上的权限集合

RBAC 授权插件

支持权限的运行时调整,无需重启API Server
两类角色:Role和ClusterRole  前者作用于名称空间,后者作用于整个集群
对这两类角色赋权时,使用RoleBinding和ClusterRoleBinding两种资源类型
一个帐户可由RoleBinding或ClusterRoleBinding关联到多个角色,从而具有多重许可授权

Role 和 RoleBinding

Role是一组许可权限的集合,描述对哪些资源可执行何种操作

# 读取、列出、监视Pod和Service资源

kubectl explain roles.rules
选项:
apiGroups,资源的API组名称,空串表示核心组
resourceNames,目标资源名称列表,缺省时表示资源类型下的所有资源;此时支持的操作仅有get/delete/update/patch
resources,目标资源类型列表,ResourceAll表示所有资源
verbs,操作列表,get/list/create/update/patch/watch/proxy/redirect/delete/deletecollection,必须
nonResourceURLs,定义有权限访问的网址列表,非名称空间级别的资源,只能应用于ClusterRole

有些资源类型支持子资源,如Pod/log Node/status等
GET /api/v1/namespaces/{namespace}/pods/{name}/log

# kubectl create role 命令
kubectl create role services-admin --verb="*" --resource="services,services/*" -n testing  # verbs 为*表示所有操作

RoleBinding 用于将Role中定义的权限赋予一个或一组用户,RoleBinding仅能引用相同名称空间中的Role

# 将用户 kube-user1 与 pods-reader 绑定

# 测试
kubectl config use-context kube-user1@kubernetes-new
kubectl get pods -n testing
kubectl get services -n testing
kubectl config use-context kubernetes-admin@kubernetes
kubectl create rolebinding -n testing admin-services --role=services-admin --user=kube-user1   # 使用命令创建RoleBinding资源

管理员可为一个帐号通过不同的RoleBinding资源绑定多个名称空间中的角色

kubectl explain rolebinding.subjects  要绑定的主体列表
参数:
apiGroup,主体所属的API群组,ServiceAccount类主体为"";User和Group类主体为 rbac.authorization.k8s.io
kind,必须,主体类别,User、Group、ServiceAccount
name,必须,主体名称
namespace,主体所属名称空间,对User和Group,必须为空

kubectl explain rolebinding.roleRef 要绑定的一个Role
参数:
apiGroup,必须,Role所属的API群组
kind,必须,Role类别,Role或ClusterRole
name,必须,Role的名称

ClusterRole 和 ClusterRoleBinding

集群级别的角色资源除能管理与Role一样的资源外,还可用于集群组件的授权

RoleBinding也能将主体绑定至ClusterRole资源上,但仅能赋予用户访问RoleBinding本身所有名称空间内可由ClusterRole赋予的权限。可用于快速授权
若通过ClusterRoleBinding引用ClusterRole,则相应用户拥有所有名称空间上的权限

非资源型URL,其读取权限默认由 system:discovery的ClusterRole和ClusterRoleBinding自动设定
kubectl describe clusterrole system:discovery
kubectl describe clusterrolebindings.rbac.authorization.k8s.io system:discovery  #授予了所有帐号权限

聚合型 ClusterRole

aggregationRule字段可整合其他ClusterRole对象的规则,使用标签选择器匹配用于聚合的ClusterRole规则再进行合并
聚合型ClusterRole的规则会随着标签选择器的匹配结果动态变化
内建的 admin 和 edit 也是聚合型ClusterRole

kubectl explain clusterrole.aggregationRule

kubectl describe clusterrole monitoring

面向用户的内建 ClusterRole

API Server内建一组默认的ClusterRole和ClusterRoleBinding以预留系统使用,大多以 system: 为前缀
还有面向用户的内建,如超级用户角色 cluster-admin、授予特定名称空间级别权限的 admin edit view

内建的ClusterRole资源 cluster-admin 拥有管理集群所有资源的权限,它通过同名的ClusterRoleBinding绑定到组 system:masters 上,所有在该组中的所有用户都具有超级管理员权限
/etc/kubernetes/admin.conf中定义的用户名为 kubernetes-admin ,使用的证书中Subject信息为 subject= /O=system:masters/CN=kube-apiserver-kubelet-client ,其中O为组名,因此kubernetes-admin具有集群管理权限
# openssl x509 -in a.crt -noout -text
# openssl x509 -in a.crt -noout -subject

定义超级管理员的方法:
1、创建用户证书,其中O值为 system:master
2、创建ClusterRoleBinding将用户绑定至cluster-admin上

多租户环境中,快速授权,在该名称空间中创建RoleBinding资源,引用内建ClusterRole的admin/view/edit即可
kubectl create rolebinding dev-admin --clusterrole=admin --user=kube-user1 -n testing

其他的内建 ClusterRole 和 ClusterRoleBinding

所有默认的ClusterRole和ClusterRoleBinding都打了标签 kubernetes.io/bootstrapping=rbac-defaults
每次启动时,API Server都会自动为默认的ClusterRole重新赋予缺失的权限,为默认的ClusterRoleBindign绑定缺失的Subject
# 要禁此自动恢复功能 可设置 rbac.authorization.kubernetes.io/autoupdate=false

Kubernetes Dashboard

Dashboard依赖Heapster或Metrics Server完成指标数据的采集和可视化
Dashboard本身仅是一个代理,所有相关操作都发给API Server进行

部署HTTPS通信的Dashboard

默认部署时仅定义了运行Dashboard的最小权限,仅能在master主机上通过kubectl proxy创建代理于本机访问,默认禁止来自其他任何主机的访问请求

# 创建证书
(umask 077; openssl genrsa -out dashboard.key 2048)
openssl req -new -key dashboard.key -out dashboard.csr -subj "/O=iLinux/CN=dashboard"
openssl x509 -req -in dashboard.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out dashboard.crt -days 3650
# 基于证书创建Secret对象
kubectl create secret generic kubernetes-dashboard-certs -n kube-system --from-file=dashboard.crt=./dashboard.crt --from-file=dashboard.key=./dashboard.key
# 部署Dashboard
# 资源清单中也创建了Secrets对象,可能会发出警告,默认创建的Service对象类型为ClusterIP,仅能在Pod中访问
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml
kubectl patch svc kubernetes-dashboard -p '{"spec":{"type":"NodePort"}}' -n kube-system
kubectl get svc kubernetes-dashboard -n kube-system
访问 https://192.168.1.110:30100/#!/login

Dashboard是运行于Pod中的应用,其连接API Server的帐户应为ServiceAccount类型,所以用户在登录界面提供的帐号应为服务帐户

配置 token 认证

# 创建名为 dashboard-admin 的 ServiceAccount 并完成集群角色绑定
kubectl create serviceaccount dashboard-admin -n kube-system
kubectl create clusterrolebinding dashboard-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
创建 ServiceAccount 对象时,会自动生成用于认证的 token
kubectl describe -n kube-system serviceaccounts dashboard-admin
kubectl describe secrets dashboard-admin-token-qh2bg -n kube-system
# ADMIN_SECRET=$(kubectl -n kube-system get secret | awk '/^dashboard-admin/{print $1}')
# kubectl describe secrets $ADMIN_SECRET -n kube-system
获取到的token是base64编码的,登录时贴入文本框即可,但不够方便,可将其存入kubeconfig配置文件中,通过kubeconfig认证

配置 kubeconfig 认证

kubeconfig是认证信息承载工具,能存入私钥和证书,或认证令牌

# 创建一个ServiceAccount 用于管理default名称空间,并绑定admin集群角色
kubectl create serviceaccount def-ns-admin -n default
kubectl create rolebinding def-ns-admin --clusterrole=admin --serviceaccount=default:def-ns-admin

创建kubeconfig文件:
第一步 初始化集群信息 提供URL和验证API证书的CA证书
kubectl config set-cluster kubernetes --embed-certs=true --server="https://192.168.1.110:6443" --certificate-authority=/etc/kubernetes/pki/ca.crt --kubeconfig=def-ns-admin.kubeconfig
第二步 获取def-ns-admin的token,并将其做为认证信息 注意要把base64解码
DEFNS_ADMIN_SECRET=$(kubectl -n default get secret | awk '/^def-ns-admin/{print $1}')
DEFNS_ADMIN_TOKEN=$(kubectl -n default get secret ${DEFNS_ADMIN_SECRET} -o jsonpath={.data.token}|base64 -d)
kubectl config set-credentials def-ns-admin --token=${DEFNS_ADMIN_TOKEN} --kubeconfig=def-ns-admin.kubeconfig
第三步 设置context列表
kubectl config set-context def-ns-admin --cluster=kubernetes --user=def-ns-admin --kubeconfig=def-ns-admin.kubeconfig
第四步 设置当前下下文
kubectl config use-context def-ns-admin --kubeconfig=def-ns-admin.kubeconfig

准入控制器

准入控制器会拦截创建、更新、删除类操作请求,执行对象语义验证、设置缺失字段默认值、限制Registry、检查Pod对象的资源限额等

准入控制器可以是验证型、变异型或两者兼具;变异控制器可以修改他许可的对象,验证控制器一般不会
准入控制器分两阶段运行:串行运行各变异型控制器,串行运行各验证型控制器    任何控制器拒绝,则拒绝整个请求并返回错误

LimitRange资源与LimitRanger准入控制器

LimitRange 资源在名称空间中为每个容器指定最小及最大计算资源用量,甚至设置默认的计算资源需求和计算资源限制
LimitRange 支持限制容器、Pod、PVC的资源用量,其中PVC是限制容量

kubectl explain limitrange.spec.limits

新创建的容器,会默认应用限制
若新Pod的资源需求量小于或大于LimitRange中的最小用量,会触发准入控制器,拒绝请求
# kubectl run limit-pod2 --image=ikubernetes/myapp:v1 --restart=Never --requests='cpu=400m'

ResourceQuota 资源与准入控制器

资源配额,限制名称空间的对象数量或资源配额
可限制指定名称空间中非终止状态的所有Pod对象的计算资源需求及计算资源限制问题
注意:资源配额仅对在ResourceQuota对象创建之后生成的对象有效,对已存在的对象不产生任何限制
一但启用资源需求和限制配额,创建任何Pod对象都必须设置这两类属性,可以使用LimitRange为其设置默认值

在名称空间上启用了CPU和内存等系统资源的配额后,若创建的Pod对象没有指定资源需求或限制,会触发准入控制器被拒绝

kubectl explain quota.spec

cpu 或 requests.cpu,CPU资源需求的总量
memory 或 requests.memory,内存资源需求的总量
limits.cpu,CPU资源限制的总量
limits.memory,内存资源的限制总量
requests.storage,PVC存储需求的总量
persistentvolumeclaims,可创建的PVC总数
<storage-class-name>.storageclass.storage.k8s.io/requests.starage,存储类上可使用的所有PVC的总量
<storage-class-name>.storageclass.storage.k8s.io/persistentvolumeclaims,存储类上可使用的PVC总数
requests.ephemeral-storage,所有Pod可用的本地临时存储的总量
limits.ephemeral-storage,所有Pod可用的本地临时存储限制
count/<resource>.<group>,所有资源类型对象计数配额

kubectl describe quota quota-example   # 会显示当前已使用的量和限制的量

kubectl run myapp-deploy --image=ikubernetes/myapp:v1 --replicas=3 --requests='cpu=200m,memory=256Mi' --limits='cpu=500m,memory=256Mi'

每个ResourceQuota对象还支持定义适用范围 scope ,用于定义其配额仅生效于这组适用范围交集内的对象
可用的适用范围:
Terminating,匹配 spec.activeDeadlineSeconds属性值>=0的所有Pod对象
NotTerminating,匹配 spec.activeDeadlineSeconds属性值为空的所有Pod对象
BestEffort,匹配所有位于BestEffort QoS类别的Pod对象
NotBestEffort,匹配所有非BestEffort Qos类别的Pod对象

scopeSelector字段可根据Pod对象的优先级控制Pod资源对系统资源的消耗。 优先级类别 PriorityClass

PodSecurityPolicy

PSP是集群级别的资源类型,默认未启用
用于控制创建Pod时要使用的特权类属性,如使用特权容器、根命名空间、主机文件系统、主机网络和端口、卷类型、Linux Capabilities等
需经过PodSecurityPolicy准入控制器检查并强制生效

未创建PSP对象的情况下启用PSP准入控制器会限止集群中创建任何Pod对象
部署任何Pod对象,则相关UserAccount及ServiceAccount必须全部获得恰当的Pod安全策略授权
定义好Pod安全策略 -> 设置kube-apiserver启用PSP准入控制器

设定重要Pod安全策略并启用PSP准入控制器的方法:
1、设置特权及受限的PSP对象
# system:master组内管理员、system:node组内kubelet,kube-system名称空间中ServiceAccount需有拥有创建各类Pod对象的授权,包括特权Pod对象
kubectl explain psp.spec

# 创建特权PSP

# 创建非特权PSP

2、创建ClusterRole并完成帐户绑定
# 创建ClusterRole 前者为特权,后者为非特权的绑定

# 创建ClusterRoleBinding对象 分别绑定权限

3、启用PSP准入控制器
设置kube-apiserver的 --enable-admission-plugins选项 在其列表中添加 PodSecurityPolicy 然后重启kube-apiserver
对于使用kubeadm部署的集群:
编辑 /etc/kubernetes/manifests/kube-apiserver.yaml 编辑完成后,会自动构建,不需要任何操作
ps -ef|grep kube-apiserver|grep admission  # 查看是否生效

4、验证
使用 securityContext 选项
注意:策略冲突会导致意料不到的结果  因此要务必做到充分测试

 

转载请注明:轻风博客 » 马哥_K8s进阶实战(8)认证、授权与准入控制

喜欢 (0)or分享 (0)