写点什么

在 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:11686

评论

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

创业做共享电动车!如何找厂家合作

共享电单车厂家

共享电动车厂家 共享电单车厂商 共享电单车投放 共享电动车创业项目

大模型竞争白热化 这家广州的科技公司却开辟了新战场

科技热闻

跨平台的Markdown编辑器:Typora for Mac中文版

真大的脸盆

阿里巴巴宣布加入Linux Foundation AI&Data基金会,捐赠首个开源项目DeepRec

阿里云大数据AI技术

人工智能 大数据

MySQL百万数据深度分页优化思路分析

做梦都在改BUG

Java MySQL 数据库

阿里内部教材:15W字的SpringCloud微服务实战,我一口气给你打包

做梦都在改BUG

Java 架构 微服务 Spring Cloud

德邦快递:逆境之下,让数字化辅助业务的利润增长

Kyligence

数据分析 数字化管理 指标中台

用Leangoo领歌Scrum敏捷开发工具管理产品路线图?

顿顿顿

Scrum 敏捷开发 敏捷项目管理 scrum敏捷工具

顶礼膜拜!阿里内部出品,全网首发Spring Security项目实战搭建

做梦都在改BUG

Java spring spring security Spring Security OAuth

如何解决注册并发问题并提高QPS

北桥苏

队列 并发 Redis 核心技术与实战

定了!AIRIOT新品发布会,6月6日北京见。

AIRIOT

物联网 发布会 产品发布会 直播预约

ShareSDK 创建应用

MobTech袤博科技

复杂推理:大型语言模型的"北极星"能力

OneFlow

【活动报名】PolarDB开源数据库&PG中文社区技术沙龙温州站

阿里云数据库开源

数据库 postgresql 阿里云 开源 polarDB

从缓存的本质说起,说服技术大佬用Redis

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 5 月 PK 榜

AI会对我们日常生活带来什么影响?这些技术会改变我们学习阅读工作方式吗?| 社区征文

汀丶人工智能

人工智能 ChatGPT 人工智能ChatGPT 吗? 三周年征文

百人研发团队百亿销售规模的技术架构实践分享

车江毅

SpringBoot 结合 Liquibase 实现数据库变更管理

做梦都在改BUG

Java spring Liquibase

如何更好的分析潜在人脉?聊聊华为云图引擎GES的Cypher子查询

华为云开发者联盟

人工智能 华为云 华为云开发者联盟 企业号 5 月 PK 榜

WebSocket与Socket、TCP、HTTP的区别

Apifox

程序员 TCP socket HTTP websocket

NGINX 和 HAProxy:基于公有云标准环境的用户体验测试对比

NGINX开源社区

nginx 公有云 HAProxy

来这公司一年碰到的问题比我过去10年都多

艾小仙

Java kafka spring spring-boot

共识算法之Raft算法模拟数

TiAmo

算法 共识算法 模拟数

2023淘宝天猫金婴奖公布,小度学习机获年度超级新品奖!

科技热闻

小程序的安全架构解析

Onegun

小程序 安全 小程序容器 小程序架构

intellij idea 粘贴字符串如何不带换行符?

源字节1号

微信小程序 开源 软件开发 前端开发 后端开发

利用Appuploader上架IPA步骤

雪奈椰子

重磅来袭!豆瓣评分9.2,万人血书的多线程与高并发v2.0版本

做梦都在改BUG

Java 多线程 高并发

哪些技术有可能坐上智慧城市发展的快车

Onegun

智慧城市 小程序容器 数字城市

给大家推荐一款CRMEB_Java新零售社交电商系统

CRMEB

GPT:低代码的终局性机遇

小博

人工智能 低代码 PaaS GPT

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