1. 机制说明 API Server 是集群内部各个组件通讯的中介,也是外部控制的入口。k8s 使用认证(Authentication)、鉴权(Authorization)、准入控制(Admission Control) 三步来确保API Server的安全。
2. 认证 (Authentication)
HTTP Token:HTTP Request Header 的 Token字段
HTTP Base: 客户端通过base64 USERNAME:PASSWORD
, 填充 HTTP Request Header 的 Authorization字段,服务端收到后解码获取用户名和密码
HTTPS: 基于CA根证书签名的客户端身份认证方式。(推荐)
2.1 HTTPS 证书认证
2.2 需要认证的节点
两种类型:
安全性说明:
Controller Manager、Scheduler与API Server在同一台机器,所以直接使用API Server的非安全端口访问--insecure-bind-address=127.0.0.1
kubectl、kubelet、kube-proxy访问API Server都需要证书进行HTTPS双向认证
证书颁发:
手动签发:通过k8s集群的根 ca 进行签发 HTTPS 证书
自动签发:kubelet 首次访问 API Server 时,使用 token 认证,通过后,Controller Manager 会为kubelet生成一个证书,以后的访问均使用该证书
2.3 kubeconfig kubeconfig 文件包含集群参数(CA证书、API Server地址),客户端参数,集群context信息(集群名称、用户名)。k8s 组件通过启动时指定不同的 kubeconfig 文件可以切换到不同的集群
cat ~/.kube/config
2.4 ServiceAccount Pod 中的容器访问API Server。因为Pod的创建和销毁是动态的,所以要为它手动生成证书是不可行的,k8s 使用 Service Account解决Pod访问API Server的认证问题
2.5 Secret 与 SA 的关系 Secret 分两类:
用于ServiceAccount的 service-account-token
用于保存用户自定义的保密信息的 Opaque
SA 中包含三个部分:
token:使用API Server私钥签名的 JWT
ca.crt: 根证书,用于Client端验证API Server发送的证书
namespace: 标识该service-account-token的作用域名空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 $ kubectl get secret --all-namespaces NAMESPACE NAME TYPE DATA AGE default default-token-rhw7k kubernetes.io/service-account-token 3 5d16h ingress-nginx default-token-ftjf6 kubernetes.io/service-account-token 3 2d3h kube-system kube-proxy-token-kcgcp kubernetes.io/service-account-token 3 5d16h $ kubectl describe secret default-token-rhw7k Name: default-token-rhw7k Namespace: default Labels: <none> Annotations: kubernetes.io/service-account.name: default kubernetes.io/service-account.uid: 3fdb2906-e8c4-4bb1-9dc0-ac8aa15167b6 Type: kubernetes.io/service-account-token Data ==== ca.crt: 1025 bytes namespace: 7 bytes token: eyJhbGciOiJSUzI1NiIsImtpZCI6Ikx5ZjJCcWJPandjZzl5czlkRHpZZWp0d2NtT2dSU0w3c2M5dXY2ZUQ0QkUifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tcmh3N2siLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjNmZGIyOTA2LWU4YzQtNGJiMS05ZGMwLWFjOGFhMTUxNjdiNiIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.FkcID8mWCOXDQbZAZPJLWSSWngvt9R-69AEDVV_QQvyvP_BW1MwiANOM2cXkS-qDo4-hcDcRKGOZ-q7BxQC96YUsj41iiLBbsXyVI1_ovEgp58dwROJe-MTxkSlk8sic40QmW2y1CwREf-5EIxwLy1iGekbbMZb4W0m4oXa-BN7qzNzMwu4Bb6ScJbxljHpO33K80oKtWYN-fpow31FjMjZMEebUvf-pGw6O2FPLvzwC7A7_U-WRNrFWd2wZIRQf8GfQgUf5-phAnmyawcJ4gpQooRvHoyGyW366dEY-qAk4D-1xSj598X0Q_pq7PdT1WQkO3nozHL-w4mbSlb3Ytw $ kubectl get pod -n kube-system NAME READY STATUS RESTARTS AGE kube-proxy-c5t62 1/1 Running 13 5d16h kube-proxy-q7m2t 1/1 Running 13 5d16h kube-proxy-t2tgb 1/1 Running 13 5d16h $ kubectl exec kube-proxy-c5t62 -n kube-system -it -- ls -l /run/secrets/kubernetes.io/serviceaccount total 0 lrwxrwxrwx 1 root root 13 Sep 13 06:40 ca.crt -> ..data/ca.crt lrwxrwxrwx 1 root root 16 Sep 13 06:40 namespace -> ..data/namespace lrwxrwxrwx 1 root root 12 Sep 13 06:40 token -> ..data/token
2.6 总结
3. 鉴权 (Authorization) 认证 和鉴权:
认证(authencation): 通过只代表通讯双方是可信的
鉴权(authorization): 确定请求方有哪些资源权限
API Server的授权策略,启动参数--authorization-mode
AlwaysDeny: 拒绝所有请求,一般用于测试
AlwaysAllow: 接收所有请求。如果集群不需要授权流程,采用该策略
ABAC (Attribute-Based Access Control): 基于属性的访问控制,表示使用用户配置的授权规则对用户请求进行匹配和控制
Webbook: 通过调用外部REST服务对用户进行授权
RBAC (Role-Based Access Control): 基于角色的访问控制 ,默认规则
RBAC优势:
对集群中的资源和非资源均拥有完整的覆盖
整个RBAC完全由几个API对象完成,同其他API对象一样,可以用kubectl或API进行操作
可在运行时调整,无需重启API Server
3.1 RBAC 的 API资源对象
Role
ClusterRole
RoleBinding
ClusterRoleBinding
k8s 不会提供用户管理,User, Group, ServiceAccount指定的用户,需要通过证书请求文件指定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "CN" : "admin" , "hosts" : [], "key" : { "algo" : "rsa" , "size" : 2048 }, "names" : [ { "C" : "CN" , "ST" : "HangZhou" , "L" : "XS" , "O" : "system:master" , "OU" : "Sytem" } ] }
3.2 Role & ClusterRole 3.2.1 Role Role 表示一组规则权限,权限只会增加(累加权限),不存在一开始就开通很多权限而通过RBAC对其减少的操作。Role 必须定义在一个namespace中,跨namespace可以使用ClusterRole
1 2 3 4 5 6 7 8 9 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: Role metadata: name: pod-reader namespace: default rules: - apiGroups: ["" ] resources: [ pods ] verbs: [get , watch , list ]
3.2.2 ClusterRole ClusterRole 是集群级别的,可用于:
集群级别资源控制,例如node访问权限
非资源型 endpoints,例如/healthz 访问
所有命名空间资源控制,例如pod
1 2 3 4 5 6 7 8 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: secret-reader rules: - apiGroups: ["" ] resources: [ secrets ] verbs: [get , watch , list ]
3.3 RoleBinding & ClusterRoleBinding 3.3.1 RoleBinding RoleBinding 可以将角色中定义的权限赋予用户或组,它包含了一种权限列表(subjects),权限列表包含不同形式的待授予权限资源类型(users,groups,service accounts),同时它也包含被Bind的Role引用
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: read-pods namespace: default subjects: - kind: User name: jane apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
RoleBinding引用ClusterRole:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding metadata: name: read-secrets namespace: development subjects: - kind: User name: dave apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
3.3.2 ClusterRoleBinding ClusterRoleBinding 可以对整个集群中的所有命名空间资源权限进行授权
1 2 3 4 5 6 7 8 9 10 11 12 13 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: read-secrets-global subjects: - kind: Group name: manager apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: secret-reader apiGroup: rbac.authorization.k8s.io
3.4 Resources 访问子资源:
1 GET /api/v1/namespaces/{namespace}/pods/{name}/log
1 2 3 4 5 6 7 8 apiVersion: rbac.authorization.k8s.io/v1beta1 kind: Role metadata: name: pod-and-pod-logs-reader rules: - apiGroups: ["" ] resources: [ pods , "pods/log" ] verbs: [get , list ]
3.5 to Subjects RoleBinding & ClusterRoleBinding 可以将Role绑定到Subjects, Subjects 可以是groups, users, 或SA
3.6 示例 3.6.1 创建Linux账号 1 2 3 4 5 6 useradd devuser passwd devuser su - devuser $ kubectl get pod The connection to the server localhost:8080 was refused - did you specify the right host or port?
3.6.2 安装证书工具 1 2 3 4 5 6 7 8 $ wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 $ wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 $ wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 $ chmod +x cfssl* $ mv cfssl_linux-amd64 /usr/local /bin/cfssl $ mv cfssljson_linux-amd64 /usr/local /bin/cfssljson $ mv cfssl-certinfo_linux-amd64 /usr/local /bin/cfssl-certinfo
3.6.3 生成证书 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 $ mkdir -p ~/cert/devuser $ cat > ~/cert/devuser/user-csr.json <<EOF { "CN": "devuser", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "JS", "L": "NJ", "O": "k8s", "OU": "Sytem" } ] } EOF $ cd /etc/kubernetes/pki $ cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes ~/cert/devuser/user-csr.json | cfssljson -bare devuser
3.6.4 设置集群参数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 cd ~/cert/devuserexport KUBE_APISERVER="https://192.168.31.40:6443" kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/pki/ca.crt \ --embed-certs=true \ --server=${KUBE_APISERVER} \ --kubeconfig=devuser.kubeconfig kubectl config set-credentials devuser \ --client-certificate=/etc/kubernetes/pki/devuser.pem \ --client-key=/etc/kubernetes/pki/devuser-key.pem \ --embed-certs=true \ --kubeconfig=devuser.kubeconfig kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=devuser \ --namespace=dev \ --kubeconfig=devuser.kubeconfig
3.6.5 角色绑定 1 2 3 kubectl create ns dev kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev
3.6.6 用户管理配置 1 2 3 mkdir -p /home/devuser/.kube cp devuser.kubeconfig /home/devuser/.kube/config chown -R devuser:devuser /home/devuser/.kube
3.6.7 设置默认上下 和 验证 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 su - devuser $ kubectl config use-context kubernetes --kubeconfig=.kube/config Switched to context "kubernetes" . $ kubectl get pod No resources found in dev namespace. $ kubectl run nginx --image=hub.elihe.io/test /nginx:v1 pod/nginx created $ kubectl get pod NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 4s $ kubectl get pod -n default Error from server (Forbidden): pods is forbidden: User "devuser" cannot list resource "pods" in API group "" in the namespace "default"
4. 准入控制 准入控制是 API Server 的插件集合,通过添加不同的插件,实现额外的准入控制规则
常见准入控制插件:
NamespaceLifecycle: 防止在不存在的namespace上创建对象;防止删除系统预置的namespace;删除namespace时,连带删除它下面的所有资源
LimitRanger: 确保请求的资源不会超过资源所在Namespace的LimitRange的限制
ServiceAccount: 实现自动化添加SA
ResourceQuota: 确保请求的资源不会超过资源的ResourceQuota限制