安全机制

Kubernetes的安全框架(总的来说就是各种形式访问API Server)


访问K8S集群的资源需要过三关:认证、鉴权、准入控制
普通用户若要安全访问集群API Server,往往需要证书、Token或者用户名+密码;Pod访问API Server,需要ServiceAccount

K8S安全控制框架主要由下面3个阶段进行控制,每一个阶段都支持插件方式,通过API Server配置来启用插件。
1.Authentication
2.Authorization
3.Admission Control

[root@master01 yaml_doc]# kubectl get sa
NAME      SECRETS   AGE
default   1         11d
[root@master01 yaml_doc]# 
[root@master01 yaml_doc]# kubectl get secrets
NAME                   TYPE                                  DATA   AGE
default-token-sj2lw    kubernetes.io/service-account-token   3      15d
#token是用secret资源类型存储的 会生成一个跟ServiceAccount:pod-reader同名的secret  (在同一个命名空间下)
[root@master01 yaml_doc]# kubectl describe secret default-token-sj2lw
Name:         default-token-sj2lw
Namespace:    default
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: default
              kubernetes.io/service-account.uid: 1c1e6043-0430-11ea-9860-1866dafb2f54

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1359 bytes
namespace:  7 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImRlZmF1bHQtdG9rZW4tc2oybHciLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoiZGVmYXVsdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjFjMWU2MDQzLTA0MzAtMTFlYS05ODYwLTE4NjZkYWZiMmY1NCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpkZWZhdWx0OmRlZmF1bHQifQ.b1CuohIrZi_ubpkoYQAQKzCELgWeGSbLAEiCTyN7mIZj1CVro4SkftoaTYisyJnhmMKw8PQyvDunKOLa-tkE1C-XeAVh_rcno80NXOD9Uz33CijUPNZlHNwx0CimjGS_AA5yHoUXmLxAsm-cOq-SkWaawtUfxnRAQVv2TKEjfmha9AaLPw6Gj4-DgBPPhV8pWpBNnuuwDR-tKyyWUTAIE8wGDDhIYyIgKgzo_q7MCOupQpYUiUzwu83B5DTmimHXVcbZ3ffkR1X198KIS3lUu_fR997Pn2ZoxK5mjZ1PmzK6I0gUhSfU7wI8_AUy67sKmRUEJ2ORcAVkk-KQ_PaXUw
默认有个ServiceAccount 用于pod访问API Server

1、Authentication #传输安全,认证  相当于进公司大门

传输安全:告别8080,迎接6443
[root@master01 yaml_doc]# netstat -anput | grep 8080 | grep LISTEN    #不对外
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      169560/kube-apiserv 
[root@master01 yaml_doc]# 
[root@master01 yaml_doc]# netstat -anput | grep 6443 | grep LISTEN
tcp        0      0 10.192.27.100:6443      0.0.0.0:*               LISTEN      169560/kube-apiserv 
[root@master01 yaml_doc]# 
认证
三种客户端身份认证:
•HTTPS 证书认证:基于CA证书签名的数字证书认证
[root@master01 yaml_doc]# ls /root/k8s/k8s-cert/  #不同的组件通过证书访问API Server
admin.csr       admin-key.pem  ca-config.json  ca-csr.json  ca.pem       kube-proxy.csr       kube-proxy-key.pem  server.csr       server-key.pem
admin-csr.json  admin.pem      ca.csr          ca-key.pem   k8s-cert.sh  kube-proxy-csr.json  kube-proxy.pem      server-csr.json  server.pem
[root@master01 yaml_doc]# 

•HTTP Token认证:通过一个Token来识别用户
[root@master01 yaml_doc]# cat /opt/kubernetes/cfg/token.csv   #kubelet-bootstrap认证使用
0fb61c46f8991b718eb38d27b605b008,kubelet-bootstrap,10001,"system:kubelet-bootstrap"
[root@master01 yaml_doc]# 

•HTTP Base认证:用户名+密码的方式认证

2、Authorization  #授权  相当于授权进入那个办公区

RBAC(Role-Based Access Control,基于角色的访问控制):负责完成授权(Authorization)工作。

3、Admission Control #准入控制  相当于验证你的权限

AdminssionControl实际上是一个准入控制器插件列表,发送到APIServer的请求都需要经过这个列表中的每个准入控制器插件的检查,检查不通过,则拒绝请求。
1.11版本以上推荐使用的插件:
--enable-admission-plugins= 
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds, ResourceQuota

[root@master01 yaml_doc]# ps -ef | grep apiserver
root      85972  18645  0 10:36 pts/0    00:00:00 grep --color=auto apiserver
root     169560      1  3 11月11 ?      10:17:24 /opt/kubernetes/bin/kube-apiserver --logtostderr=true --v=4 --etcd-servers=https://10.192.27.100:2379,https://10.192.27.115:2379,https://10.192.27.116:2379 --bind-address=10.192.27.100 --secure-port=6443 --advertise-address=10.192.27.100 --allow-privileged=true  --service-cluster-ip-range=10.0.0.0/24 
准入控制字段设置:--enable-admission-plugins=NamespaceLifecycle(命令控制),LimitRanger(限制pod使用的资源CPU 内存), 
ServiceAccount(会在每个pod中导入默认的serviceaccount,使pod有权限访问API server),ResourceQuota(高级的配额管理),NodeRestriction(node加入进来以最小的权限运行) 
 
 --authorization-mode=RBAC,Node --kubelet-https=true --enable-bootstrap-token-auth --token-auth-file=/opt/kubernetes/cfg/token.csv --service-node-port-range=30000-50000 --tls-cert-file=/opt/kubernetes/ssl/server.pem --tls-private-key-file=/opt/kubernetes/ssl/server-key.pem --client-ca-file=/opt/kubernetes/ssl/ca.pem --service-account-key-file=/opt/kubernetes/ssl/ca-key.pem --etcd-cafile=/opt/etcd/ssl/ca.pem --etcd-certfile=/opt/etcd/ssl/server.pem --etcd-keyfile=/opt/etcd/ssl/server-key.pem
[root@master01 yaml_doc]# 

着重介绍第二个授权阶段

•角色
Role:授权特定命名空间的访问权限
ClusterRole:授权所有命名空间的访问权限 #集群层面
•角色绑定
RoleBinding:将角色绑定到主体(即subject)
ClusterRoleBinding:将集群角色绑定到主体
•主体(subject)
User:用户  #给使用人自己用的
Group:用户组
ServiceAccount:服务账号  #给程序用的
k8s实现多租户不同部门不同项目之间的隔离一般通过命名空间
[root@master01 yaml_doc]#  kubectl get ns  #默认命名空间
NAME          STATUS   AGE
default       Active   11d
kube-public   Active   11d
kube-system   Active   11d
[root@master01 yaml_doc]# kubectl create ns ctnrs  #创建命名空间
namespace/ctnrs created
[root@master01 yaml_doc]#  kubectl get ns
NAME          STATUS   AGE
ctnrs         Active   2s
default       Active   11d
kube-public   Active   11d
kube-system   Active   11d
[root@master01 yaml_doc]# 


两个node节点配置一下 --pod-infra-container-image=10.192.27.111/library/pause-amd64:3.0 然后重启服务
[root@node01 cfg]# ps -ef | grep kubelet
root     166978      1  9 11:10 ?        00:00:00 /opt/kubernetes/bin/kubelet --logtostderr=true --v=4 --hostname-override=10.192.27.115 --kubeconfig=/opt/kubernetes/cfg/kubelet.kubeconfig --bootstrap-kubeconfig=/opt/kubernetes/cfg/bootstrap.kubeconfig --config=/opt/kubernetes/cfg/kubelet.config --cert-dir=/opt/kubernetes/ssl --pod-infra-container-image=10.192.27.111/library/pause-amd64:3.0

[root@master01 yaml_doc]# kubectl run nginx --image=10.192.27.111/library/nginx:latest -n ctnrs
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/nginx created


[root@master01 yaml_doc]# kubectl get all -n ctnrs
NAME                        READY   STATUS    RESTARTS   AGE
pod/nginx-644d56598-n4hnv   1/1     Running   0          3m19s

NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx   1/1     1            1           3m19s

NAME                              DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-644d56598   1         1         1       3m19s
[root@master01 yaml_doc]# 


[root@master01 yaml_doc]# kubectl scale deploy/nginx --replicas=3 -n ctnrs  #调整副本数
deployment.extensions/nginx scaled
[root@master01 yaml_doc]# kubectl get pods -n ctnrs
NAME                    READY   STATUS              RESTARTS   AGE
nginx-644d56598-bqkg4   0/1     ContainerCreating   0          2s
nginx-644d56598-dtcn9   0/1     ContainerCreating   0          2s
nginx-644d56598-n4hnv   1/1     Running             0          4m47s
[root@master01 yaml_doc]# 

来一个例子吧

#创建一个role角色
[root@master01 yaml_doc]# vim rbac-role.yaml  
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: ctnrs
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]  #只能操作pod资源
  verbs: ["get", "watch", "list"] #只读

[root@master01 yaml_doc]# kubectl create -f rbac-role.yaml 
role.rbac.authorization.k8s.io/pod-reader created
[root@master01 yaml_doc]# kubectl get role -n ctnrs
NAME         AGE
pod-reader   16s
[root@master01 yaml_doc]#

######################测试方式一 用户测试###########################
[root@master01 yaml_doc]# vim rbac-rolebinding.yaml #绑定角色
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: ctnrs
subjects: #指定用户
- kind: User
  name: jane  #用户名
  apiGroup: rbac.authorization.k8s.io
roleRef:  #绑定哪个角色
  kind: Role
  name: pod-reader #角色名
  apiGroup: rbac.authorization.k8s.io
[root@master01 yaml_doc]# kubectl create -f rbac-rolebinding.yaml 
rolebinding.rbac.authorization.k8s.io/read-pods created


[root@master01 yaml_doc]# kubectl get role,rolebinding -n ctnrs
NAME                                        AGE
role.rbac.authorization.k8s.io/pod-reader   9m1s

NAME                                              AGE
rolebinding.rbac.authorization.k8s.io/read-pods   2m19s
[root@master01 yaml_doc]# 


#生成证书  以上用户如何识别身份
[root@master01 yaml_doc]# mkdir jane
[root@master01 yaml_doc]# cd jane/
[root@master01 jane]# vim rabc-user.sh
cat > jane-csr.json <<EOF
{
  "CN": "jane",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "L": "BeiJing",
      "ST": "BeiJing"
    }
  ]
}
EOF

cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes jane-csr.json | cfssljson -bare jane  
#设置集群IP 、证书、上下文等配置 生成用户jane的访问集群APIserver的配置文件
kubectl config set-cluster kubernetes 
  --certificate-authority=ca.pem 
  --embed-certs=true 
  --server=https://10.192.27.117:6443 
  --kubeconfig=jane-kubeconfig

kubectl config set-credentials jane 
  --client-key=jane-key.pem 
  --client-certificate=jane.pem 
  --embed-certs=true 
  --kubeconfig=jane-kubeconfig

kubectl config set-context default 
  --cluster=kubernetes 
  --user=jane 
  --kubeconfig=jane-kubeconfig

#使用默认上下文
kubectl config use-context default --kubeconfig=jane-kubeconfig  
[root@master01 jane]# cp /root/k8s/k8s-cert/ca* .           #用到根证书(kube-apiserver是的证书) 生成用户客户端证书
[root@master01 jane]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  rabc-user.sh
[root@master01 jane]# bash rabc-user.sh 
2019/09/17 20:54:24 [INFO] generate received request
2019/09/17 20:54:24 [INFO] received CSR
2019/09/17 20:54:24 [INFO] generating key: rsa-2048
2019/09/17 20:54:25 [INFO] encoded CSR
2019/09/17 20:54:25 [INFO] signed certificate with serial number 30365589649039563082592558185944057795826217362
2019/09/17 20:54:25 [WARNING] This certificate lacks a "hosts" field. This makes it unsuitable for
websites. For more information see the Baseline Requirements for the Issuance and Management
of Publicly-Trusted Certificates, v.1.1.6, from the CA/Browser Forum (https://cabforum.org);
specifically, section 10.2.3 ("Information Requirements").
Cluster "kubernetes" set.
User "jane" set.
Context "default" created.
Switched to context "default".
[root@master01 jane]# ls
ca-config.json  ca.csr  ca-csr.json  ca-key.pem  ca.pem  jane.csr  jane-csr.json  jane-key.pem  jane-kubeconfig  jane.pem  rabc-user.sh
[root@master01 jane]# 
[root@master01 jane]# kubectl --kubeconfig=jane-kubeconfig get pods -n ctnrs  #根据上面的权限(只有ctnrs命令空间的pod只读权限) 查看指定的内容
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7cdbd8cdc9-7rc5x   1/1     Running   0          29m
nginx-7cdbd8cdc9-l4zlj   1/1     Running   0          27m
nginx-7cdbd8cdc9-s8ggw   1/1     Running   0          27m
[root@master01 jane]# kubectl --kubeconfig=jane-kubeconfig get svc -n ctnrs 
Error from server (Forbidden): services is forbidden: User "jane" cannot list resource "services" in API group "" in the namespace "ctnrs"
[root@master01 jane]# kubectl --kubeconfig=jane-kubeconfig get svc    #default空间没有权限
Error from server (Forbidden): services is forbidden: User "jane" cannot list resource "services" in API group "" in the namespace "default"
[root@master01 jane]# kubectl --kubeconfig=jane-kubeconfig get pods    #default空间没有权限
Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods" in API group "" in the namespace "default"
[root@master01 jane]# 
#########################测试方式二  ServiceAccount:服务账号测试  #给程序用的 ###########
#使用web UI  https://10.192.27.115:30001/ 或者116
[root@master01 jane]# kubectl get svc -n kube-system
NAME                   TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)         AGE
kube-dns               ClusterIP   10.0.0.2     <none>        53/UDP,53/TCP   4d11h
kubernetes-dashboard   NodePort    10.0.0.141   <none>        443:30001/TCP   13d

[root@master01 jane]# kubectl get secret -n kube-system
NAME                               TYPE                                  DATA   AGE
coredns-token-bkjq9                kubernetes.io/service-account-token   3      4d11h  
dashboard-admin-token-x2fmd        kubernetes.io/service-account-token   3      13d  #超级管理员
default-token-gkwdg                kubernetes.io/service-account-token   3      14d
kubernetes-dashboard-certs         Opaque                                11     13d
kubernetes-dashboard-key-holder    Opaque                                2      13d
kubernetes-dashboard-token-2qxt6   kubernetes.io/service-account-token   3      13d


[root@master01 jane]# vim sa.yaml   
apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader  #创建sa对应下 这个可以改
  namespace: ctnrs

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: sa-read-pods
  namespace: ctnrs
subjects:
- kind: ServiceAccount
  name: pod-reader #对应上SA名字 这个可以改
roleRef:
  kind: Role
  name: pod-reader #上面创建的的角色
  apiGroup: rbac.authorization.k8s.io
[root@master01 jane]# kubectl apply -f sa.yaml 
serviceaccount/pod-reader created
rolebinding.rbac.authorization.k8s.io/sa-read-pods created
[root@master01 jane]# kubectl get sa -n ctnrs
NAME         SECRETS   AGE
default      1         42m
pod-reader   1         23s
[root@master01 jane]# 
[root@master01 jane]# kubectl describe sa pod-reader -n ctnrs
Name:                pod-reader
Namespace:           ctnrs
Labels:              <none>
Annotations:         kubectl.kubernetes.io/last-applied-configuration:
                       {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"pod-reader","namespace":"ctnrs"}}
Image pull secrets:  <none>
Mountable secrets:   pod-reader-token-5vmrr
Tokens:              pod-reader-token-5vmrr
Events:              <none>
[root@master01 jane]# kubectl describe secret pod-reader -n ctnrs  #token是用secret资源类型存储的 会生成一个跟ServiceAccount:pod-reader同名的secret  (在同一个命名空间下)
Name:         pod-reader-token-5vmrr
Namespace:    ctnrs
Labels:       <none>
Annotations:  kubernetes.io/service-account.name: pod-reader
              kubernetes.io/service-account.uid: 7b1a812f-d94c-11e9-8a2e-000c29586be2

Type:  kubernetes.io/service-account-token

Data
====
ca.crt:     1359 bytes
namespace:  5 bytes
token:      eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJjdG5ycyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJwb2QtcmVhZGVyLXRva2VuLTV2bXJyIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6InBvZC1yZWFkZXIiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI3YjFhODEyZi1kOTRjLTExZTktOGEyZS0wMDBjMjk1ODZiZTIiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6Y3RucnM6cG9kLXJlYWRlciJ9.JyiOaiL79AVAs59QRQY7fyPn2Ukc3b52NejeuUZK5JlHJN7rE6mLqZnJtEm2ef5Yp07rVpf0IAqWzEOcPRC6uKzYKT544BxQxoEHOP1GNaWFDh6JHIeMHP1Ak-4FqmI9q7a7YyCYrvR7RtMuTdUr8G0Fo2gyNzlIkp1UlJH1-LpoAR0BG5MBtFzj4trxlGSIzVHtAHoIXXcG5Ke0mEHWEt0zWEFUJ5r-y-X99HDR3n5yER43djywjpncxzJ426Rm-R3azjpHUZ3LP4urkIwSWocIxuVcGAay5EgX9sHcZb5a-1fT3IZPX77ATK9LDcZfG0UoPYgDjbUPw4BqLq9HGg

[root@master01 jane]# 

使用web UI  https://10.192.27.115:30001/ 或者116 

 

原文地址:https://www.cnblogs.com/linux985/p/11940518.html