K8S 安全机制 node
1、K8S的安全框架linux
• 访问K8S集群的资源须要过三关:认证、鉴权、准入控制
• 普通用户若要安全访问集群API Server,每每须要证书、Token或者用户名+密码;Pod访问,好比ingress控制器Ui的Dashboard都须要ServiceAccount,主要是让这个容器可以访问这个API,也就是全部的交互都是经过API的,这可能经过一我的去经过kubectl去交互,也有可能你的程序去调用API,但这些都是须要受权的nginx
• K8S安全控制框架主要由下面3个阶段进行控制,每个阶段都支持插件方式,经过API Server配置来启用插件。 web
说在前面的话,也就是每一个阶段都是插件化的设计,能够本身开发插件,把这些集成到步骤里面,来实现相关的访问控制,这样的话你就不须要去修改原有的代码去增长了,因此k8s设计原则有不少都是以扩展性去设计的,都尽量的让用户自定义一些东西,集成到里面。
json
接下来看一张图,这是访问API经历的一些阶段
从上面kubectl、API、UI,访问的是k8sAPI,k8s的API提供了不少的接口vim
这些都是Apiserver去提供的,也支持不一样的功能,来完成相关的处理的,相关的认证,再往下就是API内置有三层的受权,第一层就是认证,第二层就是鉴权,第三层就是准入控制,而后经过以后就能够访问相关的资源了,这些资源都是从ETCD中去调用的,一些存储状态的信息api
传输安全:
如今k8s都已经改为https进行访问,也就是无论你是kubeadm部署仍是二进制部署,他都是建议你使用https进行全栈的通讯,告别8080,使用6443安全
认证:
API收到用户发送的请求以后,他会先认证,认证它这边有三个能够作到
三种客户端身份认证: bash
• HTTPS 证书认证:基于CA证书签名的数字证书认证,也就是k8s,CA签出来的证书能够做为你客户端访问携带的证书,它会帮你认证,这是一种方式,从这个证书里面去提取你有没有权限去访问。
• HTTP Token认证:经过一个Token来识别用户。
• HTTP Base认证:用户名+密码的方式认证,这是基于http自身的一个认证,不过这个不多人去用,由于安全系数比较低。框架
第一关就是标识你是用哪一个证书进来的,仍是token标识进来的,看看我这里是否是可信任的,看看我这个token我这里有没有相关的受权,也就是我这里有没有这个token,若是没有就不容许经过,而后下面就不会再进行了,若是经过的话,就好比本地已经建立这个token了,有的话就给你放行,进行下一个判断,也就是第二关受权。
受权:
RBAC(Role-Based Access Control,基于角色的访问控制):负责完成受权(Authorization)工做。也就是会查看你的访问符不符合权限,因此它会在这个地方去给你判断,若是你来的这个身份,虽然有这个身份,可是没有这个权限访问这个资源,也会不容许你经过。
受权的资源有不少类型的支持
准入控制:
简单讲就是开发将一些高级的功能,直接插件化的去设计,也就是准入控制器就是一个插件的集合,集合里面就有一些高级的特性,都是以插件去实现的,若是不启用这些插件的话,那你就使用不了这个功能,这也就是第三关,也就是你的请求会通过你的插件准入控制,准入控制呢会给你效验请求的实现的这个方法,到底这个插件有没有启用这一块,不过大多数的方式默认的插件都是启用的,启动以后来请求相关的资源,才会被容许,由于它启用插件了,若是没启动的话也会不经过
Adminssion Control其实是一个准入控制器插件列表,发送到API Server的请求都须要通过这个列表中的每一个准入控制器,插件的检查,检查不经过,则拒绝请求。
1.11版本以上推荐使用的插件:
--enable-admission-plugins= \
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,ResourceQuota
使用RBAC受权
RBAC(Role-Based Access Control,基于角色的访问控制),容许经过Kubernetes API动态配置策略。也就是即便配置,即时生效,不须要重启服务
角色
• Role:受权特定命名空间的访问权限
• ClusterRole:受权全部命名空间的访问权限
角色绑定
• RoleBinding:将角色绑定到主体(即subject)
• ClusterRoleBinding:将集群角色绑定到主体
主体(subject)
• User:用户
• Group:用户组
• ServiceAccout: 服务帐号
要作一个权限的管理系统,有两块,第一块就是对象是谁,建立的用户,第二就是权限组,好比建立一个开发组,开发组有哪些权限,能够访问这个系统,这也是为了方便去管理这些权限,来划分这个权限组,每一个用户都给他建立一个权限很麻烦,有这个组的话,直接将用户加入这个组里面就能够了,好比来一个开放,并给他设置权限,他是一个来宾用户的组,这个组里面只能查看一些东西,可是他是一个开发组的,对一些项目有一些开发权限,管理员进去呢,在这个管理页面去再去加一个开发组,这样的话他就有开发组的权限了
K8s和刚才说的其实都是同样的,用户就是这个主体,就是谁来访问,而后权限组呢就是角色,定义了一组权限的集合,用户要想将用户与权限集合作一个附加,将开发附加一个权限组,就称为角色绑定,角色里面又分为了,角色及集群角色,集群角色是受权集群命名空间的,
也就是k8s有命名空间这一说,因此有分为了单个命名空间和全部命名空间,这个权限集合的设置,ClusterRole也就是受权全部命名空间,也就是说将某个用户加入这个权限角色里,那就意味着它能够访问全部命名空间,相关的一些权限。
示例:为zhaocheng用户受权default命名空间Pod读取权限
好比就是只能查看pod默认的空间的运行的一些资源,像svc,日志是没有权限查看的,当你试用期过了以后,再给你加一些权限,再作一些相关的操做
实现这个目标须要完成如下三步
建立RBAC权限策略
Ca.crt 和 Ca.key就是这两个须要签发的证书
[root@k8s-master ~]# ls /etc/kubernetes/pki/ apiserver.crt apiserver.key ca.crt front-proxy-ca.crt front-proxy-client.key apiserver-etcd-client.crt apiserver-kubelet-client.crt ca.key front-proxy-ca.key sa.key apiserver-etcd-client.key apiserver-kubelet-client.key etcd front-proxy-client.crt sa.pub
[root@k8s-master ~]# cd demo/ [root@k8s-master demo]# mkdir rbac [root@k8s-master demo]# cd rbac/ [root@k8s-master rbac]# rz -E rz waiting to receive. [root@k8s-master rbac]# ls cert.sh cfssl.sh config.sh rbac.yaml [root@k8s-master rbac]# cat cfssl.sh 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/bin/cfssl mv cfssljson_linux-amd64 /usr/bin/cfssljson mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo [root@k8s-master rbac]# sh cfssl.sh
而后这里咱们把咱们证书签发的脚本拿过来,这里注意的是签发用户的CN这里是指签发用户的用户名,就是说k8s拿这个CA来认证,它不单效验是否是我颁发的证书,还要效验里面的用户名,就是CN这个字段是否是受权过的,至关于鉴权那一块,O是用户组,也能够基于这个用户组去作这个权限限制
[root@k8s-master rbac]# chmod +x cert.sh [root@k8s-master rbac]# vim cert.sh cat > ca-config.json <<EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "usages": [ "signing", "client auth" ], "expiry": "87600h" } } } } EOF cat > zhaocheng-csr.json <<EOF { "CN": "zhaocheng", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "k8s", "OU": "System" } ] } EOF cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes zhaocheng-csr.json | cfssljson -bare zhaocheng [root@k8s-master rbac]# bash cert.sh
主要生成的就是zhaocheng-key.pem zhaocheng.pem
[root@k8s-master rbac]# ls ca-config.json cert.sh cfssl.sh config.sh rbac.yaml zhaocheng.csr zhaocheng-csr.json zhaocheng-key.pem zhaocheng.pem
须要用这两个证书来对客户端作请求认证,写到客户端受权文件里,用这个受权文件就能请求这个k8s集群了
好比公司有多个集群,那么这个开发须要登陆这个集群,须要这个config证书,到时候能够拿这个来回切换登陆不一样的集群
--kubeconfig=zhaocheng.kubeconfig
[root@k8s-master rbac]# vim config.sh kubectl config set-cluster kubernetes \ --certificate-authority=/etc/kubernetes/pki/ca.crt \ --embed-certs=true \ --server=https://192.168.30.21:6443 \ --kubeconfig=zhaocheng.kubeconfig 设置客户端认证 kubectl config set-credentials zhaocheng \ --client-key=zhaocheng-key.pem \ --client-certificate=zhaocheng.pem \ --embed-certs=true \ --kubeconfig=zhaocheng.kubeconfig 设置默认上下文 kubectl config set-context kubernetes \ --cluster=kubernetes \ --user=zhaocheng \ --kubeconfig=zhaocheng.kubeconfig 设置当前使用配置 kubectl config use-context kubernetes --kubeconfig=zhaocheng.kubeconfig [root@k8s-master rbac]# bash config.sh [root@k8s-master rbac]# cat zhaocheng.kubeconfig
如今就能够拿这个kubeconfig去访问集群了
到这呢实际上是到认证这个地方给打回去了,node节点是没有访问权限的,已经识别出来是zhaocheng用户了,可是鉴权这块没有相关的受权,因此如今要为这个用户受权
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig node Error from server (Forbidden): nodes is forbidden: User "zhaocheng" cannot list resource "nodes" in API group "" at the cluster scope
若是有一个组的命名空间,权限比较大,就是能够访问全部命名空间,好比运维来说,有不少的运维,能够建立集群的角色,这样它是管控全部命名空间的角色,这个角色就是针对于特定的命名空间的,好比开发,测试,它只能访问命名空间的项目,它负责的项目,而后可使用这个指定命名空间,而后就是集群的绑定,而后绑定到zhaocheng这个用户身上,这里我定义的是user,也能够是group组。
pod也是不能访问的
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod Error from server (Forbidden): pods is forbidden: User "zhaocheng" cannot list resource "pods" in API group "" in the namespace "default"
[root@k8s-master rbac]# vim rbac.yaml kind: Role apiVersion: rbac.authorization.k8s.io/v1 metadata: namespace: default name: pod-reader rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"] --- kind: RoleBinding apiVersion: rbac.authorization.k8s.io/v1 metadata: name: read-pods namespace: default subjects: - kind: User name: zhaocheng apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io [root@k8s-master rbac]# kubectl create -f rbac.yaml
而后如今就能够进行访问了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig pod NAME READY STATUS RESTARTS AGE my-pod 1/1 Running 0 10h nfs-744d977b46-dh9xj 1/1 Running 0 29h nfs-744d977b46-kcx6h 1/1 Running 0 29h nfs-744d977b46-wqhc6 1/1 Running 0 29h nfs-client-provisioner-fbc77b9d4-kkkll 1/1 Running 0 11h nginx-797db8dc57-tdd5s 1/1 Running 0 8h nginx-a1-6d5fd7b8dd-w647x 1/1 Running 0 4h55m nginx-statefulset-0 1/1 Running 0 7h7m nginx-statefulset-1 1/1 Running 0 7h6m nginx-statefulset-2 1/1 Running 0 7h6m web-0 1/1 Running 0 4h55m web-1 1/1 Running 0 4h53m web-2 1/1 Running 0 4h52m
可是svc是没有定义的因此还不能访问
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig svc Error from server (Forbidden): services is forbidden: User "zhaocheng" cannot list resource "services" in API group "" in the namespace "default"
好比咱们加一个别的访问权限,好比service,deployment
在刚才咱们的rbac的策略里面加上这些权限
- apiGroups: [""] resources: ["pods","services"] verbs: ["get", "watch", "list"]
再来测试一下,已经能够正常去访问svc了
[root@k8s-master rbac]# kubectl get --kubeconfig=./zhaocheng.kubeconfig service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 30h my-service ClusterIP None <none> 80/TCP 7h22m nginx ClusterIP None <none> 80/TCP 4h59m service NodePort 10.1.207.32 <none> 80:30963/TCP 8h zhao ClusterIP 10.1.75.232 <none> 80/TCP 7h31m zhaocheng ClusterIP 10.1.27.206 <none> 80/TCP 7h33m
像其余的受权能够查看官方提供
https://kubernetes.io/docs/reference/access-authn-authz/rbac/