k8s_day_07_01
一、k8s系统访问控制基础
系统访问控制:
插件化实现了三个功能:
认证 Authn : 用户身份认证 ,以确保仅能被系统所许可的人访问
授权 Authz :虽然都能认证成功 ,但是应该针对不同级别的用户赋予不同权限,实现权限的分配和管理
准入控制 Admission: 审计功能。 执行一些独特的功能 ,体现在以下2方面 检验(Validation) 、变异(?)。检查用户提交数据的规范 是否是apisever 所定义的格式的。 把用户提交的不符合规范的数据范式化(纠正补全)。 只发挥在 用户的“写请求” 上

如图
当我们用户试图 通过apiserver 完成操作的时候 , 要完成3个步骤:
① 对用户身份的验证是否合法 。
②用户请求的动作是否 得到确切的授权(比如读操作: kubectl get po) 如果是请求的动是写操作 要执行第三步
③校验用户写请求的数据是否合符规范 , 确定无误后存入存储系统。不通过就拒绝请求
注意
以上三步骤的功能全部内置在apiserver 中,但是k8s 为了在访问控制授权更加灵活, 这3个功能全部以插件化的方式实现。 图中那个白色部分 表示就是插件, 每个用户的请求 会至上而下 依次顺序的方式 通过插件的检查。 认证和授权检查插件都是以短路的模式工作。只要其中的一块 认证 (或者授权)的插件检查通过,则直接进入下一步步骤,不会再次执行当前步骤 该插件后面的插件。
但是 准入控制 步骤的插件必须 挨个执行 ,即时其中的一个插件检查不通过也要执行剩下的插件, 为的返回完整错误信息。
如果第一步中 认证插件都执行完成了 都不成功 ,那么取决于系统是否支持匿名用户,如果支持进入下一步,不支持到此为止。
关于k8s的客户端
在k8s 上 ,认为用户有2类:
- User Account:人类用户,k8s不负责存储和管理这类用户;需要借助外部的组件实现;
- Service Account:由k8s之上运行的Pod中的应用程序在访问API Server时认证使用;是标准的k8s资源类型之一,隶属于名称空间级别;
第一种: 人类用户, 通过交互式命令访问。 在k8s上没有任何存储,没有像pod、service 之类的内部固定资源格式提供存储。访问时 ,客户端说自己是谁,就是谁,但是k8s会有插件校验。 这样区分的好处的便于把k8s 集成到环境其他的认证系统上去
第二种: 来自k8s内部的pod访问使用。为它提供专门资源格式存储
k8s 用户组
k8s 内建的默认系统组:
- system:unauthenticated:未能通过任何一个授权插件检验的账号的所有未通过认证测试的用户统一隶属的用户组;()
- system:authenticated:认证成功后的用户自动加入的一个专用组,用于快捷引用所有正常通过认证的用户账号;
- system:serviceaccounts:所有名称空间中的所有ServiceAccount对象;
- system:serviceaccounts:<namespace>:特定名称空间内所有的ServiceAccount对象。
k8s 认证方式:
-
X509数字证书认证;
证书中的Subject中的 CommonName, CN 被当作用户名; Orgnization, O:组名; -
引导令牌(Token):
一个令牌 就是代表身份id。==这个身份也背后也隐藏代表了身份权限== 很多时候即代表用户用户名也代表密码。比如kubeam worker 节点加集群时用到的那个
-
静态令牌:
存储于API Server进程可直接加载到的文件中保存的令牌,该文件内容会由API Server缓存于内存中,如果修改了要生效必须重启api;不是位于etcd中 ,而运行apiserver pod/进程的文件系统上, 当用户访问k8s时,如果它的令牌在这个文件内,就认为它通过了认证
-
静态密码:
存储于API Server进程可直接加载到的文件中保存的账户和密码令牌,该文件内容会由API Server缓存于内存中;类似Linux中的/etc/paasswd -
ServiceAccount令牌:
专门给做ServiceAccount类型应用认证。 和其他类型的令牌认证没有什么区别,只是使用场景不一样
-
OpenID Connect令牌:
OIDC令牌,web认证,第三方集中式认证的常用方式。使用 OAuth 2协议。公有云服务支持这种协议 -
Webhook令牌: 了解
-
代理认证: apiserver 支持从http 请求头部的值识别用户
k8s 授权方式/插件:
- Node: 主要对 kubelet 做访问控制的
- ABAC:Attribution,属性。 基于属性的访问控制 ,可以理解为对k8s资源字段做访问控制。 比较复杂,可使用OPA 开放权限控制管理。
- RBAC: Role-Based AC, 基于角色的访问控制
- Webhook: 基于http回调机制实现外部rest服务检查
准入控制器:
k8s 支持数10中, 不同版本支持的不一样。 具体的必须查文档。 以下常用的3种
-
LimitRanger
限制单个具体pod应用 使用的物理资源配额
-
ResourceQuota:
用于为名称空间设置可用资源上限。比如运行多少个pod
-
PSP: PodSecurityPolicy
在集群级别限制用户使用哪些特权。比如共享宿主机网络
二、ServiceAccount认证 详解
ServiceAccount
简称 sa
[root@master01 ~]# kubectl api-resources|grep sa
serviceaccounts sa v1 true ServiceAccount
[root@master01 ~]#
[root@master01 ~]# kubectl get sa
NAME SECRETS AGE
default 1 11d
[root@master01 ~]#
在每一个名称空间当中,都会为每个pod 挂载存储卷,这个存储卷保存的内容 包括 ServiceAccount认证令牌信息。 目的是 pod 可能需要回溯 apiserver 了解自身信息的, 了解自己如何运行的,属于哪个名称空间的等等。 类似downward api 类型的存储卷 查询引用外部环境信息
Containers: demoapp: Mounts: /var/run/secrets/kubernetes.io/serviceaccount from default-token-wnrlv (ro) Volumes: default-token-wnrlv: Type: Secret (a volume populated by a Secret) SecretName: default-token-wnrlv Optional: false
这个 default-token-wnrlv 存储卷保存了认证到k8s的令牌 ,令牌生效的名称空间。 以及apiserver 的证书
总结:
K8S自动为每个Pod注入一个ServiceAccount,用于ServiceAccount令牌 认证
在每个名称空间中,会自动存在(由ServiceAccount准入控制器负责)一个默认的 ServiceAccount对象 default ,将被该空间下的每个Pod共享使用。pod 通过挂载==‘default-token’== secret开头存储卷 ,使用sa 信息。
[root@master01 ~]# kubectl get secrets |grep 'default-token'
default-token-wnrlv kubernetes.io/service-account-token 3 11d
[root@master01 ~]# kubectl describe secrets/default-token-wnrlv
Name: default-token-wnrlv
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 27ee5a19-fc86-4163-868e-56da28b41249
Type: kubernetes.io/service-account-token
Data
====
namespace: 7 bytes
token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjJLZXBTSDdfYThxVkdJNVd1VTVYU3h5VjJvV0V2V3lhU2cyMXZGc3F1OVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjbt BITJPzFIhubNJ5Pne-AIdQ8JaRpp4GohtD4flHaX_ushhu4vZvs5mkvrUlkz3xzdt3v5P4GedP8ghmRRWwmY0gHompl68fCz0psgkfWYnZukzLOvTAopENBfONLtZYWNXoC4Y-MPYvnYt-srE6LAoSdp-7-xkFnK38qtu9OQ
ca.crt: 1066 bytes
认证令牌保存于该空间下的一个Secret对象中,该对象中共有三个信息:
1、namespace
2、ca.crt
3、token
验证
[root@node01 ~]# kubectl exec -it mypod -- /bin/sh
[root@mypod /]# cd /var/run/secrets/kubernetes.io/serviceaccount
[root@mypod /run/secrets/kubernetes.io/serviceaccount]# ls
ca.crt namespace token
[root@mypod /run/secrets/kubernetes.io/serviceaccount]# cat ca.crt
-----BEGIN CERTIFICATE-----
MIIC5zCCAc+gAwIBAgIBADANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwprdWJl
cm5ldGVzMB4XDTIxMTIxMzAzNTIxOFoXDTMxMTIxMTAzNTIxOFowFTETMBEGA1UE
AxMKa3ViZXJuZXRlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALgM
F3tdVVHdsHqTm5ifpW77W+XoBCIjWJBf4Qw3Gcs7q3ksU7YEDZnk9B+DysaDdFir
qz6sECKQd7HJ3TAPKFOvqGHr6CiVhRKHvNgVMzjsoRx2gt5M5Ol+dl/1BjNXZiHm
LDXkIE1EZ9tNoP0a6/L1G+OkBVwDRWIjM0HFFJBrG/uviCPdsoNaRwsLHz2THWBQ
axgQSo8mviU5mjbuO1sGLuuvynMgcKauIx+HZ8gxPjwETkKNdUxzE/ekdKKw2bvQ
/mlQWzoakc5a3MkDosN+4VDyQzbUmBmkfpXU0VURci1ssfuPRbs9gi3bP2sLyg5t
CMrOeNryBAqYqu5P2d0CAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgKkMA8GA1UdEwEB
/wQFMAMBAf8wHQYDVR0OBBYEFEDhztlc7NHyal3QbtwkpI4q7SAMMA0GCSqGSIb3
DQEBCwUAA4IBAQBNVvLrg36ZKVqgoGg+rpAut++1ljDwRe+ALxm72H67eyygmuII
wnPXBvdcUph9iS40/lnn17QOf/7AXoxrr7tRBaN2tkAo9K0ITl1Lz2tTN+XH+8fE
vlxfuFalrmviyvjhCIFVA9EXhGnjyoFlDuY3dlrF3fUd+/AEVV4AdVPmvFPjgUBr
XdEAUKf92/c1Uwxv+goX00enuPE5k79qc7Oz65LWW0RCXYklkxcHZvDx9TpJ8snU
pG4R6xKztyYp+Db+Vei/mZBxfbr0gT1h48hAZi1tCvIplKSv6kBEHgySjVzS3N9O
cjo4RIXr5jPbHdDA20+n2Sq3Apy9DLOCLXGr
-----END CERTIFICATE-----
[root@mypod /run/secrets/kubernetes.io/serviceaccount]# cat namespace
[root@mypod /run/secrets/kubernetes.io/serviceaccount]# cat token
eyJhbGciOiJSUzI1NiIsImtpZCI6IjJLZXBTSDdfYThxVkdJNVd1VTVYU3h5VjJvV0V2V3lhU2cyMXZGc3F1OVUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4td25ybHYiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjI3ZWU1YTE5LWZjODYtNDE2My04NjhlLTU2ZGEyOGI0MTI0OSIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.r52XszRDvPUUNqHd7g9ovhmrBV9C9N7lkCEEpnS-I4pIcVfEY0dS_uEtD71M-SCWaR6AunwqZVpLIvXbkRMrvxZ9CwDYpIzb7J6BmI6JLb2AobkvFcy22x_DCYU66d68pUxPVoWUYVxhrL9MfxhNtMVDh1COlHMcR2ktp7EIU9GocyBITJPzFIhubNJ5Pne-AIdQ8JaRpp4GohtD4flHaX_ushhu4vZvs5mkvrUlkz3xzdt3v5P4GedP8ghmRRWwmY0gHompl68fCz0psgkfWYnZukzLOvTAopENBfONLtZYWNXoC4Y-MPYvnYt-srE6LAoSdp-7-xkFnK38qtu9OQ[root@mypod /run/secrets/kubernetes.io/serviceaccount]#
例子1 :命令自定义sa
创建pod 时 如果不使用默认的sa ,可以自定义,例如下 只要指的名字 和名称空间就行
[root@node01 ~]# kubectl create ns dev
namespace/dev created
[root@node01 ~]# kubectl get sa -n dev
NAME SECRETS AGE
default 1 16s
[root@node01 ~]# kubectl create sa admin -n dev
serviceaccount/admin created
[root@node01 ~]# kubectl get secret -n dev
NAME TYPE DATA AGE
admin-token-tkm7w kubernetes.io/service-account-token 3 14s
default-token-dwmh6 kubernetes.io/service-account-token 3 111s
[root@node01 ~]# kubectl get sa -n dev
NAME SECRETS AGE
admin 1 31s
default 1 2m8s
[root@node01 ~]#
注意: 创建sa 的同时会自动创建对应的 secret
sa 资源格式:
apiVersion: v1 # ServiceAccount所属的API群组及版本
kind: ServiceAccount # 资源类型标识
metadata:
name <string> # 资源名称
namespace <string> # ServiceAccount是名称空间级别的资源
automountServiceAccountToken <boolean> # 是否让Pod自动挂载API令牌
secrets <[]Object> # 以该SA运行的Pod所要使用的Secret对象组成的列表
apiVersion <string> # 引用的Secret对象所属的API群组及版本,可省略
kind <string> # 引用的资源的类型,这里是指Secret,可省略
name <string> # 引用的Secret对象的名称,通常仅给出该字段即可
namespace <string> # 引用的Secret对象所属的名称空间
uid <string> # 引用的Secret对象的标识符;
imagePullSecrets <[]Object> # 引用的用于下载Pod中容器镜像的Secret对象列表
name <string> # docker-registry类型的Secret资源的名称
在sa 中 指定imagePullSecret 好处就是该名称空间下的所有pod 共用,方便统一管理。而不是在单一pod/创建模板中定义
例子2 :手动创建sa 和 secret
通常没必要手动创建
[root@node01 chapter9]# cat serviceaccount-demo.yaml
# serviceaccount/k8sadmin
# Maintainer: MageEdu <mage@magedu.com>
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: namespace-admin
namespace: default
automountServiceAccountToken: true # 这里默认就是true
[root@node01 chapter9]#
[root@node01 chapter9]# cat secret-token.yaml
apiVersion: v1
kind: Secret
metadata:
name: k8sadmin-secret
namespace: default
annotations:
kubernetes.io/service-account.name: k8sadmin # name和上面的sa未保持一致 ,仅仅演示而已
type: kubernetes.io/service-account-token