k8s 安全机制

一、kubernetes安全机制

api server是k8s集群的入口,默认有两个端口:

本地端口8080: 用于接收HTTP请求, 不对外服务, 非认证或授权的HTTP请求通过该端口访问API Server
安全端口6443: 用于接收认证授权的HTTPS请求,对外服务。

用户通过安全端口访问k8s的api server需要过三关:认证、授权、准入控制

  • Authentication认证: 用于识别用户身份, 方式有: SSL证书,token, 用户名+密码等
  • Authorization授权: 确认是否对资源具有相关的权限
  • Admission Control准入控制: 判断操作是否符合集群的要求

k8s  安全机制

无论kubectl客户端命令或api或ui,在创建或访问资源时,一定要有apiServer所对应的资源版本,只要资源版本与kind能够正确匹配才能进行继续操作,否侧操作会被终止。

Authentication认证

Authentication认证: 用于识别用户身份, 验证方式有:
SSL证书
token
用户名+密码

用户分类

用户有两种:
用户账户(user) : 是在集群外部访问apiserver时使用的用户,如kubectl命令就是作为kubernetes的admin用户来执行的。
服务账户(ServiceAccount): 为了方便Pod里面的进程调用
Kubernetes API或其他外部服务而设计的。
User account是为人设计的,而service account则是为Pod中的进程调用Kubernetes API而设计;
User account是跨namespace的,而service account则是仅局限它所在的namespace;
每个namespace都会自动创建一个default service account
参考: https://www.kubernetes.org.cn/service-account

kubeconfig文件

  • kubeconfig文件用于组织有关群集、用户、命名空间和身份验证机制的信息,用于对k8s集群的访问。
  • 使用kubectl命令时默认使用~/.kube/config这个kubeconfig文件来访问k8s集群,也可以用--kubeconfig指定其它文件

一个kubeconfig文件通常由以下几个配置段组成:

users: 用户账号及其认证信息列表
cluster: 目标集群列表
contexts: 以哪个user接入哪个cluster的连接组合。
current-context:当前使用的context

示例: 查看admin用户的kubeconfig文件

cat /root/.kube/config

k8s  安全机制

Authorization授权

认证环节之后是授权, 确认是否对资源具有相关的权限
一个请求需要在其请求信息中包含用户名,请求的动作以及目标对象; 若存在某授权策略对于此请求给予了授权许可,即授权成功。

授权模块

Node: 根据Pod对象调度的结果为Node进行授权。
ABAC(Attribute-based access control): 基于属性的访问控制(ABAC)定义了一种访问控制模式,通过使用将属性组合在一起的策略,将访问权限授予用户。这些策略可以使用任何类型的属性(用户属性、资源属性、对象、环境属性等)。
RBAC(Role-based access control): 基于角色的访问控制(RBAC)是一种基于企业中各个用户的角色来管理对计算机或网络资源的访问的方法。使用"rbac.authorization.k8s.io" API驱动授权策略,并支持动态配置。
Webhook: WebHook其实就是一个HTTP回调:在发生某些事情时发生的HTTP POST;通过HTTP POST的简单事件通知。实现WebHooks的web应用程序将在发生某些事情时向URL发送消息。

RBAC

k8s  安全机制

  • 角色
    • Role 授权特定命名空间的访问权限
    • ClusterRole 授权所有命名空间的访问权限
  • 角色绑定
    • RoleBinding 将角色绑定到主机(即subject)
    • ClusterRoleBinding 将集群角色绑定到主体
  • 主体 (subject)
    • User 用户
    • Group 用户组
    • ServiceAccount 服务帐号

Admission Control准入控制

通过认证和鉴权之后,客户端并不能得到API Server的真正响应,这个请求还需通过Admission Control所控制的一个准入控制插件列表的层层考验。

准入控制器

Admission Control配备有一个“准入控制器”的插件列表,发送给API Server的任何请求都需要通过列表中每一个准入控制器的检查,检查不通过API Server拒绝此调用请求。
此外,准入控制器还能够修改请求参数以完成一些自动化的任务,比如Service Account这个控制器。


当前可配置的Admission Control准入控制如下:

  • AlwaysAdmit:允许所有请求;
  • AlwaysPullmages:在启动容器之前总去下载镜像,相当于在每个容器的配置项imagePullPolicy=Always
  • AlwaysDeny:禁止所有请求,一般用于测试;
  • DenyExecOnPrivileged:它会拦截所有想在Privileged Container上执行命令的请求,如果你的集群支持Privileged Container,你又希望限制用户在这些Privileged Container上执行命令,强烈推荐你使用它,其功能已经合并到DenyEscalatingExec中。
  • ImagePolicyWebhook:这个插件将允许后端的一个Webhook程序来完成admission controller的功能。ImagePolicyWebhook需要使用一个配置文件(通过kube-apiserver的启动参数--admission-control-config-file设置)定义后端Webhook的参数。目前该插件还处在Alpha版本。
  • Service Account:这个plug-in将ServiceAccount实现了自动化,默认启用,如果你想使用ServiceAccount对象,那么强烈推荐使用它。
  • SecurityContextDeny:这个插件将使用SecurityContext的Pod中的定义全部失效。SecurityContext在Container中定义了操作系统级别的安全设定(uid,gid,capabilityes,SELinux等)。在未启用PodSecurityPolicy的集群中建议启用该插件,以禁用容器设置的非安全访问权限。
  • ResourceQuota:用于资源配额管理目的,作用于namespace上,它会观察所有请求,确保在namespace上的配额不会超标。推荐在Admission Control参数列表中将这个插件安排在最后一个,以免可能被其他插件拒绝的Pod被过早分配资源。
  • LimitRanger:用于资源限制管理,作用于namespace上,确保对Pod进行资源限制。启用该插件还会为未设置资源限制的Pod进行默认设置,例如为namespace "default"中所有的Pod设置0.1CPU的资源请求。
  • InitialResources:是一个实验特性,旨在为未设置资源请求与限制的Pod,根据其镜像的历史资源的使用情况进行初始化的资源请求、限制设置。
  • NamespaceLifecycle:如果尝试在一个不存在的namespace中创建资源对象,则该创建请求将被拒绝。当删除一个namespace时,系统将会删除该namespace中所有对象,保存Pod,Service等。
  • DefaultStorageClass:为了实现共享存储的动态供应,为未指定StorageClass或PV的PVC尝试匹配默认的StorageClass,尽可能减少用户在申请PVC时所需了解的后端存储细节。
  • DefaultTolerationSeconds:这个插件为那些没有设置forgiveness tolerations并具有notready:NoExecute和unreachable:NoExecute两种taints的Pod设置默认的“容忍”时间,为5min。
  • PodSecurityPolicy:这个插件用于在创建或修改Pod时决定是否根据Pod的security context和可用的PodSecurityPolicy对Pod的安全策略进行控制。

LimitRanger示例

kubectl create ns limitrange
kubectl describe ns limitrange

k8s  安全机制

看到无LimitRange

vim limitrange.yml

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-limit-range
  namespace: limitrange
spec:
  limits:
  - default:
      cpu: 1000m
    defaultRequest:
      cpu: 1000m
    min:
      cpu: 500m
    max:
      cpu: 2000m
    maxLimitRequestRatio:
      cpu: 4
    type: Container

kubectl apply -f limitrange.yml
kubectl describe ns limitrange

k8s  安全机制

vim limitrange-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: limitrange
spec:
  containers:
  - name: c1
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent
    resources:
      requests:
        cpu: 200m                       # cpu请求200m,小于namespace的cpu最小限制(500m)

kubectl apply -f limitrange-pod.yml

k8s  安全机制

说明: 可看到namespace的cpu最小限制是500m,创建此pod请求为200m,准入控制拒绝了。 改成限制范围内就可以创建

vim limitrange-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: nginx
  namespace: limitrange
spec:
  containers:
  - name: c1
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent
    resources:
      requests: 
        cpu: 600m                            #  改成大于500m

kubectl apply -f limitrange-pod.yml

k8s  安全机制

kubectl get pods -n limitrange

k8s  安全机制

可以成功创建pod

ResourceQuota示例

vim resourcequota.yml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: quota
  namespace: limitrange
spec:
  hard:                       #  硬限制
    pods: "1"                 #  限制此namespace里就不能超过1个pod

kubectl apply -f resourcequota.yml
kubectl describe ns limitrange

k8s  安全机制

硬限制为1个pod,已经有1个pod了

vim resourcequota-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: nginx2                                # 改一个pod名
  namespace: limitrange                       # 相同的namespace
spec:
  containers:
  - name: c1
    image: nginx:1.15-alpine
    imagePullPolicy: IfNotPresent

kubectl apply -f resourcequota-pod.yml

k8s  安全机制

报错,pod数量超过了

二、User访问案例

参考资料 https://kubernetes.io/docs/reference/access-authn-authz/rbac/

创建k8s用户(User)

1, 准备工作

mkdir rbac
cd rbac/
cp /etc/kubernetes/ssl/ca-key.pem .
cp /etc/kubernetes/ssl/ca.pem .

2, 创建证书

openssl genrsa -out daniel.key 2048 #创建user私钥

k8s  安全机制

3.创建证书签署请求

(subj中的CN为用户名,O为用户组)

openssl req -new -key daniel.key -out daniel.csr -subj "/O=k8s/CN=daniel"

k8s  安全机制

签署证书

openssl x509 -req -in daniel.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out daniel.crt -days 365

k8s  安全机制

[root@master1 rbac]# ls

k8s  安全机制

3,创建用户配置文件

vim create-rbac-user.sh #过程复杂,直接用脚本

#设置集群连接
kubectl config set-cluster kubernetes \
  --certificate-authority=ca.pem \
  --embed-certs=true \
  --server=https://192.168.154.135:6443 \
  --kubeconfig=daniel-kubeconfig

#颁发证书
kubectl config set-credentials daniel \
  --client-key=daniel.key \
  --client-certificate=daniel.crt \
  --embed-certs=true \
  --kubeconfig=daniel-kubeconfig

#设置安全上下文
kubectl config set-context daniel@kubernetes \
  --cluster=kubernetes \
  --user=daniel \
  --kubeconfig=daniel-kubeconfig

#切换安全上下文
kubectl config use-context daniel@kubernetes --kubeconfig=daniel-kubeconfig
#查看安全上下文
kubectl config view --kubeconfig=daniel-kubeconfig

执行脚本

chmod +x create-rbac-user.sh
sh create-rbac-user.sh

k8s  安全机制

查看kubeconfig文件

[root@master1 ~]# cat /root/rbac/daniel-kubeconfig

k8s  安全机制

创建系统用户

useradd daniel
mkdir -p /home/daniel/.kube
cp /root/rbac/daniel-kubeconfig /home/daniel/.kube/config
chown daniel.daniel -R /home/daniel/
su - daniel

说明: 切换登录用户时, 就使用了/home/daniel/.kube/config文件。

验证用户访问k8s资源

可以看到daniel用户对pod,svc,ns等资源都没有权限

[daniel@master1 ~]$ kubectl get pod

k8s  安全机制

[daniel@master1 ~]$ kubectl get svc

k8s  安全机制

[daniel@master1 ~]$ kubectl get ns

k8s  安全机制

创建role

vim role-pods-read.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: role-pods-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

说明: 此role是表示对pods资源有读的相关权限(get,list,watch)

kubectl apply -f role-pods-read.yaml
kubectl get role |grep role-pods-reader

k8s  安全机制

创建rolebinding

vim rolebinding-pods-read.yml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: rolebinding-pods-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: role-pods-reader                   # 对应上一步的role名
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: daniel                              # 与前面创建的k8s用户一致

kubectl apply -f rolebinding-pods-read.yml
kubectl get rolebinding |grep rolebinding-pods-reader

k8s  安全机制

说明: 这样系统用户daniel与k8s用户daniel通过这个rolebindingrole里定义的权限都联系起来了

再验证用户访问k8s资源

[root@master1 rbac]# su - daniel
[daniel@master1 ~]$ kubectl get pods

k8s  安全机制

[daniel@master1 ~]$ kubectl get pods -n kube-system
[daniel@master1 ~]$ kubectl get svc
[daniel@master1 ~]$ kubectl get ns

k8s  安全机制

说明: 由上可知,daniel 用户终于可以访问 default 命名空间里的pods资源了,但其它的还没有权限访问

创建ClusterRole

vim clusterrole-pods-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: clusterrole-pods-reader
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch

kubectl apply -f clusterrole-pods-reader.yaml
kubectl get clusterrole |grep pods-reader

k8s  安全机制

创建ClusterRoleBinding

vim clusterrolebinding-pods-reader.yaml

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: clusterrolebinding-pods-reader
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: clusterrole-pods-reader
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: daniel

kubectl apply -f clusterrolebinding-pods-reader.yaml
kubectl get clusterrolebinding |grep pods-reader

k8s  安全机制

再验证用户访问k8s资源

[root@master1 rbac]# su - daniel
[daniel@master1 ~]$ kubectl get pod --all-namespaces

k8s  安全机制

现在所有命名空间的pods都可以访问了

问题: 访问svc等其它资源如何操作?

参考查看admin这个clusterrole
kubectl get clusterrole admin -o yaml

aggregationRule:
  clusterRoleSelectors:
  - matchLabels:
      rbac.authorization.k8s.io/aggregate-to-admin: "true"
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  annotations:
    rbac.authorization.kubernetes.io/autoupdate: "true"
  creationTimestamp: "2021-05-28T15:17:10Z"
  labels:
    kubernetes.io/bootstrapping: rbac-defaults
  managedFields:
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:aggregationRule:
        .: {}
        f:clusterRoleSelectors: {}
      f:metadata:
        f:annotations:
          .: {}
          f:rbac.authorization.kubernetes.io/autoupdate: {}
        f:labels:
          .: {}
          f:kubernetes.io/bootstrapping: {}
    manager: kube-apiserver
    operation: Update
    time: "2021-05-28T15:17:10Z"
  - apiVersion: rbac.authorization.k8s.io/v1
    fieldsType: FieldsV1
    fieldsV1:
      f:rules: {}
    manager: kube-controller-manager
    operation: Update
    time: "2021-05-28T15:17:24Z"
  name: admin
  resourceVersion: "212"
  selfLink: /apis/rbac.authorization.k8s.io/v1/clusterroles/admin
  uid: 2068aaa4-36d6-4294-959a-63b9c6a8cc3c
rules:
- apiGroups:
  - ""
  resources:
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  - secrets
  - services/proxy
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - serviceaccounts
  verbs:
  - impersonate
- apiGroups:
  - ""
  resources:
  - pods
  - pods/attach
  - pods/exec
  - pods/portforward
  - pods/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - replicationcontrollers
  - replicationcontrollers/scale
  - secrets
  - serviceaccounts
  - services
  - services/proxy
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - apps
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - replicasets
  - replicasets/scale
  - statefulsets
  - statefulsets/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - batch
  resources:
  - cronjobs
  - jobs
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - deployments
  - deployments/rollback
  - deployments/scale
  - ingresses
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicationcontrollers/scale
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - networkpolicies
  verbs:
  - create
  - delete
  - deletecollection
  - patch
  - update
- apiGroups:
  - ""
  resources:
  - configmaps
  - endpoints
  - persistentvolumeclaims
  - persistentvolumeclaims/status
  - pods
  - replicationcontrollers
  - replicationcontrollers/scale
  - serviceaccounts
  - services
  - services/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - bindings
  - events
  - limitranges
  - namespaces/status
  - pods/log
  - pods/status
  - replicationcontrollers/status
  - resourcequotas
  - resourcequotas/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - namespaces
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - apps
  resources:
  - controllerrevisions
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - replicasets
  - replicasets/scale
  - replicasets/status
  - statefulsets
  - statefulsets/scale
  - statefulsets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  - horizontalpodautoscalers/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - batch
  resources:
  - cronjobs
  - cronjobs/status
  - jobs
  - jobs/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - extensions
  resources:
  - daemonsets
  - daemonsets/status
  - deployments
  - deployments/scale
  - deployments/status
  - ingresses
  - ingresses/status
  - networkpolicies
  - replicasets
  - replicasets/scale
  - replicasets/status
  - replicationcontrollers/scale
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - policy
  resources:
  - poddisruptionbudgets
  - poddisruptionbudgets/status
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - networking.k8s.io
  resources:
  - ingresses
  - ingresses/status
  - networkpolicies
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - authorization.k8s.io
  resources:
  - localsubjectacce***eviews
  verbs:
  - create
- apiGroups:
  - rbac.authorization.k8s.io
  resources:
  - rolebindings
  - roles
  verbs:
  - create
  - delete
  - deletecollection
  - get
  - list
  - patch
  - update
  - watch

三、ServiceAccount访问案例

创建namespace

kubectl create namespace sa

验证namespace的sa与secret

创建namespace默认会创建一个serviceaccount和一个secret

kubectl get sa -n sa

k8s  安全机制

kubectl get secret -n sa

k8s  安全机制

kubectl describe sa default -n sa

k8s  安全机制

kubectl describe secret default-token-gcbbc -n sa

k8s  安全机制

创建pod验证其sa与secret

kubectl run nginx --image=nginx:1.15-alpine -n sa
kubectl describe pod nginx -n sa

k8s  安全机制

说明: 创建pod不指定serviceaccount则默认使用default.

创建一个sa

kubectl create sa daniel -n sa
kubectl get sa -n sa
kubectl get secret -n sa

k8s  安全机制

创建pod并自定义sa

vim sa-pod.yml

apiVersion: v1
kind: Pod
metadata:
  name: nginx2
  namespace: sa
spec:
  containers:
  - name: c1
    image: nginx:1.15-alpine
    ports:
    - name: httpd
      containerPort: 80
  serviceAccountName: daniel                # 指定sa为daniel

验证pod使用的sa

kubectl apply -f sa-pod.yml
kubectl describe pod nginx2 -n sa

k8s  安全机制

上一篇:三国志战略版:Daniel_煮酒论赤壁-论水战


下一篇:三国志战略版:Daniel_五一活动-讲解系列二