最新发布《数智时代的AI人才粮仓模型解读白皮书(2024版)》,立即领取! 了解详情
写点什么

在 Kubeadm 中使用 pod 安全策略

  • 2019-11-20
  • 本文字数:6803 字

    阅读完需:约 22 分钟

在Kubeadm中使用pod安全策略

Pod 安全策略是一种机制,用于限制容器在 k8s 上运行时可执行的操作,例如防止其作为特权容器的运行,和主机网络运行等。


本文内容较多,所以在此做了一个完整的简介说明:


  • 在 master 节点运行 kubeadm init 并启用 PodSecurityPolicy admission controller;

  • 使用 RBAC 配置添加一些 pod 安全策略 - 足够启动 CNI 和 DNS 等;

  • 没有它,CNI daemonsets 将无法启动

  • 应用您的 CNI 插件,该插件可以使用以前创建的一个 pod 安全策略

  • 通过 kubeadm join 完成向集群添加节点的配置

  • 在向集群添加更多工作负载时,请检查是否需要额外的 pod 安全策略和 RBAC 配置

我们将要做什么

以下是在 kubeadm 上安装运行 pod 安全策略所采取的步骤:


  1. 为 master 节点的初始化配置 pod 安全策略 admission controller

  2. 为网络层组件配置一些 pod 安全策略

  3. 配置 CNI 插件 - 这里将使用 flannel

  4. 然后将使用下面的代码演示一些其他的 pod 安全策略方案

  5. 安装一个具有一些特定要求的 nginx-ingress controller - 这只是为了说明添加额外的策略

  6. 安装没有特定 pod 安全策略要求的常规服务 - 基于 httpbin.org

环境

  • 将只在单个节点说明,而不是具有高可用集群的多节点集群

  • Ubuntu:根据 kubeadm 的要求切换,为 UTC 配置时区

  • Docker:假设当前用户在 docker 组中

  • kubernetes 1.11.3 - 使用 RBAC

master 节点配置

按照说明安装 kubeadm


安装 jq,用它来进行一些 json 输出处理


sudo apt-get update  sudo apt-get install -y jq
复制代码


验证 kubeadm 的版本


sudo kubeadm version
复制代码


接着我们将为下面创建的内容创建一个目录,在以下所有说明中我们假设您在此目录中


mkdir ~/psp-inv  cd ~/psp-inv
复制代码

kubeadm 配置文件

将创建这个文件,并将其用于 master 上的 kubeadm init,使用此内容创建一个 kubeadm-config.yaml 文件 - 请注意我们必须为 flannel 指定 pod 子网为 10.244.0.0/16


请注意,此文件对于此演示是最小的,如果您使用更高版本的 kubeadm,则可能需要更改 apiVersion


apiVersion: kubeadm.k8s.io/v1alpha2  kind: MasterConfiguration  apiServerExtraArgs:   enable-admission-plugins: PodSecurityPolicy  controllerManagerExtraArgs:  address: 0.0.0.0  kubernetesVersion: v1.11.3  networking:  podSubnet: 10.244.0.0/16  schedulerExtraArgs:  address: 0.0.0.0
复制代码

Master init

 
复制代码


根据上面命令输出的说明获取您自己的 kubeconfig 文件副本,如果要将工作节点添加到集群,请注意加入以下信息,并检查 master 节点的状态


NAME STATUS ROLES AGE VERSIONpmcgrath-k8s-master NotReady master 1m v1.11.3
复制代码


这说明节点还没有准备好,因为它正在等待 CNI,检查一下 pods


No resources found.
复制代码


所以,如果我们没有启用 pod security policy admission control,通常看不到任何正在运行的 pod,检查 docker


docker container ls --format '{{ .Names }}'k8s\_kube-scheduler\_kube-scheduler-pmcgrath-k8s-master\_kube-system\_a00c35e56ebd0bdfcd77d53674a5d2a1\_0k8s\_kube-controller-manager\_kube-controller-manager-pmcgrath-k8s-master\_kube-system\_fd832ada507cef85e01885d1e1980c37\_0  k8s\_etcd\_etcd-pmcgrath-k8s-master\_kube-system\_16a8af6b4a79e9b0f81092f85eab37cf\_0  k8s\_kube-apiserver\_kube-apiserver-pmcgrath-k8s-master\_kube-system\_db201a8ecaf8e99623b425502a6ba627\_0  k8s\_POD\_kube-controller-manager-pmcgrath-k8s-master\_kube-system\_fd832ada507cef85e01885d1e1980c37\_0  k8s\_POD\_kube-scheduler-pmcgrath-k8s-master\_kube-system\_a00c35e56ebd0bdfcd77d53674a5d2a1\_0  k8s\_POD\_kube-apiserver-pmcgrath-k8s-master\_kube-system\_db201a8ecaf8e99623b425502a6ba627\_0  k8s\_POD\_etcd-pmcgrath-k8s-master\_kube-system\_16a8af6b4a79e9b0f81092f85eab37cf\_0
复制代码


所有容器都在运行,但这不是通过 kubectl 获取的信息,还需检查事件


 
复制代码


会看到类似这样的错误:pods “kube-proxy-“ is forbidden: no providers available to validate pod request

配置 pod 安全策略

当前已经配置了:


  • 任何工作负载都可以使用默认的 pod 安全策略,它没有什么特权,但应该适用于大多数工作负载

  • 将创建一个 RBAC ClusterRole

  • 将为所有经过身份验证的用户创建 RBAC ClusterRoleBinding

  • 我授予 kube-system 命名空间中的节点和所有服务帐户访问权限的特权 pod 安全策略

  • 考虑这个权限应该被限制在这个命名空间内

  • 应该只在此命名空间中运行 k8s 组件

  • 将创建一个 RBAC ClusterRole

  • 将在 kube-system 命名空间中创建 RBAC RoleBinding


使用此内容创建 default-psp-with-rbac.yaml 文件


apiVersion: policy/v1beta1  kind: PodSecurityPolicy  metadata:   annotations:   apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'   apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'   seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'   seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'   name: default  spec: allowedCapabilities: \[\] # default set of capabilities are implicitly allowed   allowPrivilegeEscalation: false   fsGroup:   rule: 'MustRunAs'   ranges:   # Forbid adding the root group.  \- min: 1   max: 65535   hostIPC: false   hostNetwork: false   hostPID: false   privileged: false   readOnlyRootFilesystem: false   runAsUser:   rule: 'MustRunAsNonRoot'   seLinux:   rule: 'RunAsNonRoot'   supplementalGroups:   rule: 'RunAsNonRoot'   ranges:   # Forbid adding the root group.  \- min: 1   max: 65535   volumes:  \- 'configMap'  \- 'downwardAPI'  \- 'emptyDir'  \- 'persistentVolumeClaim'  \- 'projected'  \- 'secret'   hostNetwork: false   runAsUser:   rule: 'RunAsAny'   seLinux:   rule: 'RunAsAny'   supplementalGroups:   rule: 'RunAsAny'   fsGroup:   rule: 'RunAsAny'\---\# Cluster role which grants access to the default pod security policy apiVersion: rbac.authorization.k8s.io/v1  kind: ClusterRole  metadata:   name: default-psp  rules:  \- apiGroups:   - policy   resourceNames:   - default   resources:   - podsecuritypolicies   verbs:   - use\---\# Cluster role binding for default pod security policy granting all authenticated users accessapiVersion: rbac.authorization.k8s.io/v1  kind: ClusterRoleBinding  metadata:   name: default-psp  roleRef:   apiGroup: rbac.authorization.k8s.io   kind: ClusterRole   name: default-psp  subjects:  \- apiGroup: rbac.authorization.k8s.io   kind: Group   name: system:authenticated
复制代码


使用此内容创建 privileged-psp-with-rbac.yaml 文件


# Should grant access to very few pods, i.e. kube-system system pods and possibly CNI pods  apiVersion: policy/v1beta1  kind: PodSecurityPolicy  metadata:   annotations:   # See https://kubernetes.io/docs/concepts/policy/pod-security-policy/#seccomp   seccomp.security.alpha.kubernetes.io/allowedProfileNames: '\*'   name: privileged  spec:   allowedCapabilities:  \- '\*'   allowPrivilegeEscalation: true   fsGroup:   rule: 'RunAsAny'   hostIPC: true   hostNetwork: true   hostPID: true   hostPorts:  \- min: 0   max: 65535   privileged: true   readOnlyRootFilesystem: false   runAsUser:   rule: 'RunAsAny'   seLinux:   rule: 'RunAsAny'   supplementalGroups:   rule: 'RunAsAny'   volumes:  \- '\*'\---\# Cluster role which grants access to the privileged pod security policy apiVersion: rbac.authorization.k8s.io/v1  kind: ClusterRole  metadata:   name: privileged-psp  rules:  \- apiGroups:   - policy   resourceNames:   - privileged   resources:   - podsecuritypolicies   verbs:   - use\---\# Role binding for kube-system - allow nodes and kube-system service accounts - should take care of CNI i.e. flannel running in the kube-system namespace \# Assumes access to the kube-system is restricted  apiVersion: rbac.authorization.k8s.io/v1  kind: RoleBinding  metadata:   name: kube-system-psp   namespace: kube-system  roleRef:   apiGroup: rbac.authorization.k8s.io   kind: ClusterRole   name: privileged-psp  subjects:  \# For the kubeadm kube-system nodes  \- apiGroup: rbac.authorization.k8s.io   kind: Group   name: system:nodes  \# For all service accounts in the kube-system namespace  \- apiGroup: rbac.authorization.k8s.io   kind: Group   name: system:serviceaccounts:kube-system
复制代码

使用 RBAC 配置应用上述 pod 安全策略

kubectl apply -f default-psp-with-rbac.yaml  kubectl apply -f privileged-psp-with-rbac.yaml
复制代码

校验

一段时间后,网络层 pods 将处于运行状态,coredns pods 将挂起-等待 CNI


kubectl get pods --all-namespaces --output wide --watch
复制代码


在配置 CNI 之前,网络层 pods 将再次启动失败,因为节点仍未准备就绪

安装 flannel**

只有当前存在有特权 pod 安全策略才能完成此操作,并且 kube-system 中的 flannel 服务帐户将能够使用,如果使用不同的 CNI 插件,则应使用其安装说明,可能需要修改用于 kubeadm init 的 kubeadm-config.yaml 文件中的 podSubnet。


延伸链接


kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
复制代码

再次校验

kubectl get pods --all-namespaces --output wide --watch

复制代码


所有 pods 最终将进入运行状态,包括 coredns pod(s)


kubectl get nodes
复制代码


节点现已准备就绪。

允许 master 上的工作负载

如果想要启动工作节点,可以正常使用 kubeadm join 命令,利用 kubeadm init 输出,在这里跳过。


这些工作节点上没有特别需要加入集群 pod 安全策略,允许 master 节点上的工作负载,因为我们只是尝试在单个节点集群上进行验证。


kubectl taint nodes --all node-role.kubernetes.io/master-
复制代码

nginx ingress

使用下方链接的清单


创建一个新的命名空间和单个实例 ingress controller,足以说明额外的 pod 安全策略。


由于命名空间尚不存在,因此我们可以创建,以便引用服务帐户


kubectl create namespace ingress-nginx

创建一个 pod 安全策略

本 pod 安全策略基于 deployment 清单,使用此内容创建文件 nginx-ingress-psp-with-rbac.yaml


apiVersion: policy/v1beta1  kind: PodSecurityPolicy  metadata:   annotations:   # Assumes apparmor available   apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'   apparmor.security.beta.kubernetes.io/defaultProfileName: 'runtime/default'   seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'   seccomp.security.alpha.kubernetes.io/defaultProfileName: 'docker/default'   name: ingress-nginx  spec:   # See nginx-ingress-controller deployment at https://github.com/kubernetes/ingress-nginx/blob/master/deploy/mandatory.yaml   # See also https://github.com/kubernetes-incubator/kubespray/blob/master/roles/kubernetes-apps/ingress\_controller/ingress\_nginx/templates/psp-ingress-nginx.yml.j2   allowedCapabilities:  \- NET\_BIND\_SERVICE   allowPrivilegeEscalation: true   fsGroup:   rule: 'MustRunAs'   ranges:  \- min: 1   max: 65535   hostIPC: false   hostNetwork: false   hostPID: false   hostPorts:  \- min: 80   max: 65535   privileged: false   readOnlyRootFilesystem: false   runAsUser:   rule: 'MustRunAsNonRoot'   ranges:  \- min: 33   max: 65535   seLinux:   rule: 'RunAsAny'   supplementalGroups:   rule: 'MustRunAs'   ranges:   # Forbid adding the root group.  \- min: 1   max: 65535   volumes:  \- 'configMap'  \- 'downwardAPI'  \- 'emptyDir'  \- 'projected'  \- 'secret'
\---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role metadata: name: ingress-nginx-psp namespace: ingress-nginx rules: \- apiGroups: - policy resourceNames: - ingress-nginx resources: - podsecuritypolicies verbs: - use\---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding metadata: name: ingress-nginx-psp namespace: ingress-nginx roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: ingress-nginx-psp subjects: \# Lets cover default and nginx-ingress-serviceaccount service accounts \# Could have altered default-http-backend deployment to use the same service acccount to avoid granting the default service account access \- kind: ServiceAccount name: default \- kind: ServiceAccount name: nginx-ingress-serviceaccount
复制代码


即创建


kubectl apply -f nginx-ingress-psp-with-rbac.yaml
复制代码

创建 nginx-ingress 工作负载

删除 controller-publish-service arg,因为在这里不需要


curl -s https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml | sed '/--publish-service/d' | kubectl apply -f -
复制代码


检查 pods


kubectl get pods --namespace ingress-nginx --watch
复制代码


现在可以看到 pod 安全策略附加了注释


kubectl get pods --namespace ingress-nginx --selector app.kubernetes.io/name=ingress-nginx -o json | jq -r '.items\[0\].metadata.annotations."kubernetes.io/psp"'

复制代码

Httpbin.org 工作负载

部署一个工作负载,默认的 pod 安全策略就足够了,使用此内容创建一个 httpbin.yaml 文件


apiVersion: apps/v1  kind: Deployment  metadata:   labels:   app.kubernetes.io/name: httpbin   name: httpbin  spec:   replicas: 1   selector:   matchLabels:   app.kubernetes.io/name: httpbin   template:   metadata:   labels:   app.kubernetes.io/name: httpbin   spec:   containers:  \- args: \["-b", "0.0.0.0:8080", "httpbin:app"\]   command: \["gunicorn"\]   image: docker.io/kennethreitz/httpbin:latest   imagePullPolicy: Always   name: httpbin   ports:  \- containerPort: 8080   name: http   restartPolicy: Always\---
apiVersion: extensions/v1beta1
kind: Ingress metadata: annotations: kubernetes.io/ingress.class: "nginx" labels: app.kubernetes.io/name: httpbin name: httpbin spec: rules: - host: my.httpbin.com http: paths: - path: backend: serviceName: httpbin servicePort: 8080\---
apiVersion: v1
kind: Service metadata: labels: app.kubernetes.io/name: httpbin name: httpbin spec: ports: - name: http port: 8080 selector: app.kubernetes.io/name: httpbin
复制代码


创建命名空间并在工作负载里运行


kubectl create namespace demo  kubectl apply --namespace demo -f httpbin.yaml
复制代码


检查 pod 是否存在以及是否使用了默认策略


kubectl get pods --namespace demo  kubectl get pods --namespace demo --selector app.kubernetes.io/name=httpbin -o json | jq -r '.items\[0\].metadata.annotations."kubernetes.io/psp"'
复制代码

测试工作负载

通过调用 ingress controller pod 实例


\# Get nginx ingress controller pod IP  nginx\_ip=$(kubectl get pods --namespace ingress-nginx --selector app.kubernetes.io/name=ingress-nginx --output json | jq -r .items\[0\].status.podIP)\# Test ingress and out httpbin workloadcurl -H 'Host: my.httpbin.com' http://$nginx\_ip/get
复制代码


如果打乱它,可以重置并重启


\# Note: Will loose PKI also which is fine here as kubeadm master init will re-create  sudo kubeadm reset\# Should flush iptable rules after a kubeadm reset, see https://blog.heptio.com/properly-resetting-your-kubeadm-bootstrapped-cluster-nodes-heptioprotip-473bd0b824aa sudo iptables -F && sudo iptables -t nat -F && sudo iptables -t mangle -F && sudo iptables -X
复制代码


参考文档


安全建议


GCE政策


添加小助手微信,加入【容器魔方】技术社群。



2019-11-20 19:11607

评论

发布
暂无评论
发现更多内容

web服务器

初学者

网络 web服务器 11月月更

C 语言字符串常用库函数

Maybe_fl

【愚公系列】2022年11月 微信小程序-app.json配置属性之pages

愚公搬代码

11月月更

峰会实录 | StarRocks存储引擎近期进展与实时分析实践

StarRocks

数据库·

开发问题记录

青柚1943

我服了!SpringBoot升级后这服务我一个星期都没跑起来!(上)

艾小仙

Java spring 程序员 springboot spring-boot

JavaScript学习(二)

Studying_swz

JavaScript 11月月更

Vue基础学习(一)

Studying_swz

Vue 11月月更

深入理解Metrics(二):Counters

冰心的小屋

Java metrics Counters

对话ACE第六期:数据库上云的趋势和挑战

OceanBase 数据库

低代码选型应该注重哪些方面的能力?

优秀

低代码

【LeetCode】第 k 个数 Java 题解

Albert

算法 LeetCode 11月月更

新能源物流车行业如何服务升级 地上铁联合火山引擎VeDI“破题”

字节跳动数据平台

大数据 数据应用

随想 小城市的程序员该如何生存

百里丶落云

生活状态 生活杂谈 11月月更

OceanBase CTO杨传辉:单机分布式一体化助力企业降本增效

OceanBase 数据库

Linux su命令 – 切换用户、用户提权

A-刘晨阳

Linux 运维 sudo 11月月更 用户提权

python中私有成员和公有成员

乔乔

11月月更

筑牢数字基础设施:华为笔下的中国诗意

脑极体

人工智能「

OceanBase 社区版4.0发版:一个全新的里程碑

OceanBase 数据库

抓包分析 TCP 握手和挥手

C++后台开发

网络协议 TCP/IP 后端开发 C++开发 抓包分析

【C语言】default 关键字

謓泽

11月月更

Flowable 设置流程变量的四种方式

江南一点雨

springboot flowable

CSS学习笔记(二)

lxmoe

CSS 前端 学习笔记 11月月更

易仓科技×OceanBase:打造跨境行业全生态链的新零售SaaS

OceanBase 数据库

安全!稳定!可信!选OceanBase就对了

OceanBase 数据库

Vue基础学习(二)

Studying_swz

Vue 11月月更

GPU 和显卡是什么关系?

Finovy Cloud

人工智能 gpu 云渲染 GPU渲染

Linux中的日志管理

A-刘晨阳

Linux 运维 日志 log 11月月更

客如云×OceanBase:分布式云升级助力客如云降本增效

OceanBase 数据库

Flowable 已经执行完毕的流程去哪找?

江南一点雨

spring springboot workflow flowable

Linux文件系统ln-软连接、硬链接

A-刘晨阳

Linux 运维 11月月更 软硬连接

在Kubeadm中使用pod安全策略_容器_华为云原生团队_InfoQ精选文章