05-Kubernetes冰山揭秘-第五层
Kubernetes就像一座冰山。你学习了基础知识,却发现还有很多东西要学。你学得越多,你看到的就越多。这篇文章解释了Reddit上“Kubernetes冰山”模因中列出的所有概念。
不久前,u/dshurupov published a picture on Reddit上发布了一张我称之为“Kubernetes冰山”的照片。这张照片是由弗兰特的人制作的。
它代表了一座巨大的冰山,在上面你有一些最简单的Kubernetes概念,当你在下面和水下时,你会深入到更先进的Kubernetes主题。这是图片:
RBAC
RBAC代表基于角色的访问控制。
这是一种通过拥有一组角色来进行授权的方式。每个角色都被分配了一组权限(做某事的能力)。系统中的每个用户都被分配一组角色。最后,用户分配的角色决定了他们在系统中可以做多少事情。
分配给角色的权限包含一个Kubernetes对象和一个谓词。例如,可以允许某些角色列出部署,但不允许创建部署或更新部署。
RBAC是Kubernetes进行授权的主要方式。
Kubernetes中的RBAC可以通过4个API对象动态配置–Role、ClusterRole、RoleBinding和ClusterRoleBinding。
组织中的示例RBAC方案可以如下所示:
Role | Get/List Deployments | Create/Update Deployments | Create RoleBinding |
---|---|---|---|
Developer | ✅ | ❌ | ❌ |
DevOps | ✅ | ✅ | ❌ |
Admin | ✅ | ✅ | ✅ |
具有开发人员角色的用户可以查看集群中的部署,但不能编辑部署或创建新部署。
DevOps角色不仅可以查看部署,还可以创建新部署和更新现有部署。
但是,DevOps和开发人员都不能创建新的角色绑定(这意味着为用户分配新的角色,从而为某些用户赋予更多的权限)。此操作只能由管理组执行。
您可以在here.阅读Kubernetes中的RBAC。
RBAC很好,因为它在分配角色和权限时给了您很大的灵活性。但是,仅有RBAC可能不足以保护您的集群。继续阅读Kubernetes中使用的更先进的安全技术。
PodSecurityPolicy
PodSecurityPolicy是一个(不推荐的)Kubernetes对象,它支持对pod创建和更新的(某种)细粒度授权。
在创建PodSecurityPolicy时,您可以指定一些预定义规则集,这些规则将对您的Pod对象强制执行。
例如,以下PodSecurityPolicy拒绝运行特权容器的Pods:
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: example
spec:
privileged: false # Don't allow privileged pods!
# The rest fills in some required fields.
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- "*"
当我们试图创建一个违抗此规则的Pod时,我们将得到一个类似于此的错误:
Error from server (Forbidden): error when creating "STDIN": pods "privileged" is forbidden: unable to validate against any pod security policy: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]
这些规则由允许控制器强制执行,在我们创建和强制任何PodSecurityPolicies之前,需要激活该控制器。
有关可用规则的完整规范,请查看文档。
Audit logging
审计日志记录是一种特殊的日志记录,旨在显示谁访问了系统中的内容。审计日志被非常谨慎地处理,通常外包给外部系统,这样即使应用程序出现故障,审计日志也会被保存并可以查看。这还可以防止进入我们系统的攻击者破坏我们的审计日志并删除其踪迹。
Kubernetes提供审计日志功能,记录对给定Kubernetes资源的每次访问。可以在不同级别为不同类型的资源配置审计日志记录。例如,当涉及到关键资源时,您可能希望完全记录所有信息,但当涉及到非关键资源时,您可能希望记录更少的信息。
审核日志记录是通过Audit.k8s.io APi组中的策略对象配置的。
例如,此策略对象将api服务器配置为在与POD交互时记录每个请求和响应,而在与“控制器领导者”ConfigMap交互时不记录任何内容:
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
resources:
- group: ""
resources: ["pods"]
- level: None
resources:
- group: ""
resources: ["configmaps"]
resourceNames: ["controller-leader"]
审核日志记录后端
Kube API服务器支持两个审计日志记录后端。
第一种是基于文件的。使用它意味着API服务器将把所有审计日志输出到一个文件中。它是通过–audit-log-path标志配置的。
第二个受支持的后端是基于WebHooks的后端。使用它意味着API服务器将调用外部API来保存审计日志。它是通过–audit-webhook-config-file标志配置的。标志的值应该是kubeconfig文件的名称,该文件指定远程服务器的位置和访问该服务器的凭据。远程服务器应该是Kubernetes API的一种形式。
Image validation and signing
对容器映像进行签名意味着对特定容器映像版本的内容进行加密签名,以后可以对其进行验证。这增加了从internet下载容器映像的信任度,因为您有一种方法来验证所下载的内容是否正是您所期望的内容。
这可以手动完成,但人们通常将其自动化,并在他们的CI管道中实现工作流。
启用此工作流的最流行的项目是Cosign。
seccomp
seccomp(secure computing mode的缩写)是一个Linux内核实用程序,当为进程激活时,它限制进程进行任何系统调用(exit()、sigreturn()、read()和write()以打开文件描述符除外)。
Kubernetes支持对运行在吊舱中的容器启用seccomp配置文件。
这是通过Pod规范中的spec.securitycontext.SecCompProfile完成的。
有不同的seccomp配置文件提供不同级别的限制。您不希望允许容器执行许多系统组件,但也不希望通过限制容器执行必要的系统组件来阻碍容器执行其工作。这就是为什么必须创建您的自定义seccomp配置文件,这些配置文件允许容器只执行它应该执行的系统代码。
AppArmor
AppArmor是一个Linux应用程序安全系统。它作为内核模块部署,大多数Linux发行版都支持AppArmor。
它是通过启用某些配置文件来使用的,这些配置文件保护您的操作系统免受已知的有害和恶意的应用程序行为的影响。
它也被整合到Kubernetes中。您可以使用kubelet标志启用它,并通过注释将AppArmor配置文件分配给容器。
例如,使用此注释创建Pod将为指定容器启用运行时/默认设备配置文件:
container.apparmor.security.beta.kubernetes.io/<container_name>: runtime/default
您还可以注册自定义配置文件。此配置文件将为所有已分配它的容器启用文件写入:
#include <tunables/global>
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
#include <abstractions/base>
file,
# Deny all file writes.
deny /** w,
}
您可以通过以下注释将其分配给容器:
container.apparmor.security.beta.kubernetes.io/<container_name>: k8s-apparmor-example-deny-write
这是与前一个相同的注释。我们只是更改了配置文件名以匹配自定义配置文件的名称。
如果我们用这个AppArmor配置文件创建一个容器,并尝试写到一个文件,我们将得到以下错误:
$ touch /tmp/test
touch: /tmp/test: Permission denied
error: error executing remote command: command terminated with non-zero exit code: Error executing in Docker Container: 1
自1.4版以来,AppArmor一直是Kubernetes的一个功能,但它仍处于测试阶段。这就是为什么它是通过注释而不是第一类规范字段来配置的。
NetworkPolicy
NetworkPolicy是一个Kubernetes资源,用于控制从和到POD的允许进出流量。
NetworkPolicy只是一种配置资源。它定义了允许的目的地,但不强制执行任何内容。为了实施网络策略,您需要安装一个网络插件(也称为CNI插件)。应用NetworkPolicy而不安装网络插件将没有任何效果。
创建NetworkPolicy时,定义所有允许的入口和出口目标。网络插件将阻止所有不在此允许列表中的目的地。NetworkPolicies是附加的。如果同一个Pod有两个网络策略,则此Pod的allowlist是两个策略的allowlist之和。因此,如果您有一个Pod的allow-all NetworkPolicy,那么此Pod的所有其他策略都将毫无用处。
下面是一个应用于所有标签角色为:db的吊舱的示例策略。它指定这些POD只允许从标签角色为:frontend的POD和CIDR IP块172.17.0.0/16进入连接,但172.17.1.0/24除外:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- podSelector:
matchLabels:
role: frontend
Mutating and Admission webhooks
变异和接纳网络钩子是强大的工具。准入网络钩子允许您实现动态准入控制。变异webhooks使您能够实现对正在创建/更新的资源的动态修复。
Admission webhooks
允许webhooks是确定是否应该允许资源的创建/更新/删除操作的webhooks。
它们由ValidatingMiscrionWebHook允许控制器调用。因此,尽管接纳控制器本身是不可扩展的,但这个特定的接纳控制器允许您部署一个由Kubernetes调用的webhook,从而为接纳工作流增加了可扩展性。
一个录取网络钩子只是,一个网络钩子。它期望一个特定的请求,并且应该返回一个正确的响应。在这两者之间,您可以实现任何您想要的逻辑。这样,您就可以完全控制将哪些资源部署到集群中。
Mutating webhooks
变异webhooks是变异应用于API服务器的资源的webhooks。
它们由ValidatingMiscrionWebHook允许控制器调用。
这对于强制执行资源的某个属性很有用。例如,如果您希望确保所有Pod的spec.securitycontext.runasuser字段都等于1000,那么您可以使用一个可变的webhook,它将在每次应用Pod时将该字段更改为1000。
注意:此示例只适用于直接应用于API服务器的POD,它不适用于部署或复制集拥有的POD,因为部署控制器将协调POD,而不是停止,并试图将字段设置为其原始值。如果您想要实现这一点,您将需要为部署、复制集等创建单独的变异webhook。
Dynamic Admission Control
默认情况下,Kubernetes配备了所谓的准入控制器。这些控制器控制与Kubernetes资源的交互(创建/更新/删除等)。
更具体地说,根据控制器,如果给定资源违反了某些规则,它们可能会阻止该资源的创建/更新/删除。
这些控制器在树中。它们的码基与Kubernetes码基一起生活。它们与Kubernetes一起编译,并在本地调用。如果您想添加一个准入控制器,您需要更改Kubernetes源代码,重新构建它并部署您的自定义Kubernetes版本。
允许控制器可以根据您的喜好启用或禁用。有关可用的准入控制器的完整列表,请查看文档。
Open Policy Agent
Open Policy Agent或OPA是一个通用策略引擎。它根据一组Rego策略评估JSON输入并返回一个JSON输出。
一个简单的Rego策略:
package kubernetes
default allow = false
allow = true {
input.author.name = "Anton Sankov"
}
一个简单的JSON输入:
{
"author": {
"name": "Anton Sankov"
}
}
根据此策略计算此JSON输入的输出:
{
"allow": true
}
它是通用的;因此,它可以用于绝对的一切。
在Kubernetes生态系统中,它被广泛用于安全性,是提供可定制验证WebHook的Gatekeeper等项目的支柱。在本例中,准入策略是用Rego编写的,被计算的Kubernetes对象表示为JSON。
Bonus: Gatekeeper
Gatekeeper项目不包括在冰山中,但我认为它是Kubernetes生态系统的一个重要部分,并在这里解释了一些概念,因此我将在本文中包括它。
Gatekeeper是一个可定制的准入网络钩子。它采用OPA底层实现和接纳webhook,可以用来实现动态接纳控制。
因为它使用OPA,所以策略是用REGO编写的。Gatekeeper负责注册当有人与资源交互时Kubernetes将调用的webhook。然后,这些资源将作为参数传递给策略,以便您可以根据资源字段做出决策。
策略存储为CRD(自定义资源定义)。这个CRD也由Gatekeeper注册,以允许用户以Kubernetes本地的方式与策略作为一级资源进行交互。
要注册将由Gatekeeper评估的简单策略,您需要创建以下两个资源:
首先,指定Rego策略和预期参数的ConstraintTemplate:
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
labels:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequiredlabels
violation[{"msg": msg, "details": {"missing_labels": missing}}] {
provided := {label | input.review.object.metadata.labels[label]}
required := {label | label := input.parameters.labels[_]}
missing := required - provided
count(missing) > 0
msg := sprintf("you must provide labels: %v", [missing])
}
然后是ConstraintTemplate的一个实例(在本例中是K8sRequiredLabels),以告诉Gatekeeper何时调用此策略以及使用什么参数:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: deployments-must-have-gk
spec:
match:
kinds:
- apiGroups: ["*"]
kinds: [“Deployments"]
parameters:
labels: ["gatekeeper"]
如果您想了解更多关于使用Gatekeeper和OPA的信息,请参阅我关于使用 Securing Kubernetes with Open Policy Agent.
OpenID Connect
OpenID Connect是OAuth2.0协议之上的一个简单标识层。它允许客户机基于授权服务器执行的身份验证来验证最终用户的身份,以及以可互操作的和类似REST的方式获得关于最终用户的基本配置文件信息。
Dex
Dex是OpenID连接提供程序。它是一个开源项目,目前是一个CNCF沙箱。
它为多个身份验证提供者提供单一接口。
在Kubernetes的上下文中,Dex可以用作身份验证插件。这意味着由其他身份提供者管理的用户可以通过Dex自动获得对Kubernetes集群的某些访问权限。
这对于较大的组织很有用,因为在这些组织中,用户是在像Active Directory这样的集中位置管理的。像Dex这样的适配器可以使添加到公司AD(或其他IDP)的用户自动访问所有相关的Kubernetes集群,他们的其他团队成员也可以访问这些集群
Enterprise-level security
企业级安全性是一个宽泛的术语,可以意味着很多事情。本文中的每个概念都可以是“企业级安全性”的一部分。
使用Kubernetes并希望以“企业”方式保护它的企业至少需要使用本文中描述的一半内容。
至少,他们需要使用RBAC来确保每个人只能访问他们需要的资源。理想情况下,这将与他们的广告提供商集成使用OpenID连接提供商,如Dex。然后,他们需要启用审计日志记录,这样,如果有人设法提升特权,或者如果RBAC配置错误,就有一个可靠的跟踪。
另一个很好的额外安全层是限制Pods可以通过AppArmor和seccomp等工具运行哪些进程,以及它们可以通过podsecuritypolicies进行哪些网络连接。
最后但并非最不重要的是,他们可以通过变异和接纳网络钩子,使用OPA和GateKeeper等工具来实现动态接纳控制。
- 点赞
- 收藏
- 关注作者
评论(0)