Switch language name 'zh' to 'zh-cn'
This is the first step to rename 'zh' to 'zh-cn'. There are several reasons why we rename the language name.
- The upstream docsy theme changed the language name, leading to many warnings during site build;
The side-effect is that the i18n strings are no longer working.
- We believe renaming the language is the right thing to do, because this move can make room for other variants of Chinese language, such as 'zh-tw', 'zh-sg' etc.
There would be several follow-ups to this PR, such as fixing the intra-site links, adding redirects etc.
We will lock up changes to zh/zh-cn pages for the moment, until this one gets in.
This PR is based on commit cdad0a7342.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: "安全"
|
||||
weight: 40
|
||||
---
|
||||
|
||||
@@ -0,0 +1,692 @@
|
||||
---
|
||||
title: 使用 AppArmor 限制容器对资源的访问
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
---
|
||||
<!--
|
||||
title: Restrict a Container's Access to Resources with AppArmor
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.4" state="beta" >}}
|
||||
|
||||
<!--
|
||||
AppArmor is a Linux kernel security module that supplements the standard Linux user and group based
|
||||
permissions to confine programs to a limited set of resources. AppArmor can be configured for any
|
||||
application to reduce its potential attack surface and provide greater in-depth defense. It is
|
||||
configured through profiles tuned to allow the access needed by a specific program or container,
|
||||
such as Linux capabilities, network access, file permissions, etc. Each profile can be run in either
|
||||
*enforcing* mode, which blocks access to disallowed resources, or *complain* mode, which only reports
|
||||
violations.
|
||||
-->
|
||||
AppArmor 是一个 Linux 内核安全模块,
|
||||
它补充了基于标准 Linux 用户和组的权限,将程序限制在一组有限的资源中。
|
||||
AppArmor 可以配置为任何应用程序减少潜在的攻击面,并且提供更加深入的防御。
|
||||
它通过调整配置文件进行配置,以允许特定程序或容器所需的访问,
|
||||
如 Linux 权能字、网络访问、文件权限等。
|
||||
每个配置文件都可以在
|
||||
*强制(enforcing)* 模式(阻止访问不允许的资源)或
|
||||
*投诉(complain)* 模式(仅报告冲突)下运行。
|
||||
|
||||
<!--
|
||||
AppArmor can help you to run a more secure deployment by restricting what containers are allowed to
|
||||
do, and/or provide better auditing through system logs. However, it is important to keep in mind
|
||||
that AppArmor is not a silver bullet and can only do so much to protect against exploits in your
|
||||
application code. It is important to provide good, restrictive profiles, and harden your
|
||||
applications and cluster from other angles as well.
|
||||
-->
|
||||
AppArmor 可以通过限制允许容器执行的操作,
|
||||
和/或通过系统日志提供更好的审计来帮助你运行更安全的部署。
|
||||
但是,重要的是要记住 AppArmor 不是灵丹妙药,
|
||||
只能做部分事情来防止应用程序代码中的漏洞。
|
||||
提供良好的限制性配置文件,并从其他角度强化你的应用程序和集群非常重要。
|
||||
|
||||
## {{% heading "objectives" %}}
|
||||
|
||||
<!--
|
||||
* See an example of how to load a profile on a node
|
||||
* Learn how to enforce the profile on a Pod
|
||||
* Learn how to check that the profile is loaded
|
||||
* See what happens when a profile is violated
|
||||
* See what happens when a profile cannot be loaded
|
||||
-->
|
||||
* 查看如何在节点上加载配置文件示例
|
||||
* 了解如何在 Pod 上强制执行配置文件
|
||||
* 了解如何检查配置文件是否已加载
|
||||
* 查看违反配置文件时会发生什么
|
||||
* 查看无法加载配置文件时会发生什么
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
<!-- Make sure: -->
|
||||
确保:
|
||||
|
||||
<!--
|
||||
1. Kubernetes version is at least v1.4 -- Kubernetes support for AppArmor was added in
|
||||
v1.4. Kubernetes components older than v1.4 are not aware of the new AppArmor annotations, and
|
||||
will **silently ignore** any AppArmor settings that are provided. To ensure that your Pods are
|
||||
receiving the expected protections, it is important to verify the Kubelet version of your nodes:
|
||||
|
||||
```shell
|
||||
kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
|
||||
```
|
||||
```
|
||||
gke-test-default-pool-239f5d02-gyn2: v1.4.0
|
||||
gke-test-default-pool-239f5d02-x1kf: v1.4.0
|
||||
gke-test-default-pool-239f5d02-xwux: v1.4.0
|
||||
```
|
||||
-->
|
||||
1. Kubernetes 版本至少是 v1.4 —— AppArmor 在 Kubernetes v1.4 版本中才添加了对 AppArmor 的支持。
|
||||
早于 v1.4 版本的 Kubernetes 组件不知道新的 AppArmor 注解
|
||||
并且将会 **默认忽略** 提供的任何 AppArmor 设置。
|
||||
为了确保你的 Pod 能够得到预期的保护,必须验证节点的 Kubelet 版本:
|
||||
|
||||
```shell
|
||||
kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {@.status.nodeInfo.kubeletVersion}\n{end}'
|
||||
```
|
||||
```
|
||||
gke-test-default-pool-239f5d02-gyn2: v1.4.0
|
||||
gke-test-default-pool-239f5d02-x1kf: v1.4.0
|
||||
gke-test-default-pool-239f5d02-xwux: v1.4.0
|
||||
```
|
||||
|
||||
<!--
|
||||
2. AppArmor kernel module is enabled -- For the Linux kernel to enforce an AppArmor profile, the
|
||||
AppArmor kernel module must be installed and enabled. Several distributions enable the module by
|
||||
default, such as Ubuntu and SUSE, and many others provide optional support. To check whether the
|
||||
module is enabled, check the `/sys/module/apparmor/parameters/enabled` file:
|
||||
|
||||
```shell
|
||||
cat /sys/module/apparmor/parameters/enabled
|
||||
Y
|
||||
```
|
||||
|
||||
If the Kubelet contains AppArmor support (>= v1.4), it will refuse to run a Pod with AppArmor
|
||||
options if the kernel module is not enabled.
|
||||
|
||||
{{< note >}}
|
||||
Ubuntu carries many AppArmor patches that have not been merged into the upstream Linux
|
||||
kernel, including patches that add additional hooks and features. Kubernetes has only been
|
||||
tested with the upstream version, and does not promise support for other features.
|
||||
{{< /note >}}
|
||||
-->
|
||||
2. AppArmor 内核模块已启用 —— 要使 Linux 内核强制执行 AppArmor 配置文件,
|
||||
必须安装并且启动 AppArmor 内核模块。默认情况下,有几个发行版支持该模块,
|
||||
如 Ubuntu 和 SUSE,还有许多发行版提供可选支持。要检查模块是否已启用,请检查
|
||||
`/sys/module/apparmor/parameters/enabled` 文件:
|
||||
|
||||
```shell
|
||||
cat /sys/module/apparmor/parameters/enabled
|
||||
Y
|
||||
```
|
||||
|
||||
如果 Kubelet 包含 AppArmor 支持(>= v1.4),
|
||||
但是内核模块未启用,它将拒绝运行带有 AppArmor 选项的 Pod。
|
||||
|
||||
{{< note >}}
|
||||
Ubuntu 携带了许多没有合并到上游 Linux 内核中的 AppArmor 补丁,
|
||||
包括添加附加钩子和特性的补丁。Kubernetes 只在上游版本中测试过,不承诺支持其他特性。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
3. Container runtime supports AppArmor -- Currently all common Kubernetes-supported container
|
||||
runtimes should support AppArmor, like {{< glossary_tooltip term_id="docker">}},
|
||||
{{< glossary_tooltip term_id="cri-o" >}} or {{< glossary_tooltip term_id="containerd" >}}.
|
||||
Please refer to the corresponding runtime documentation and verify that the cluster fulfills
|
||||
the requirements to use AppArmor.
|
||||
-->
|
||||
3. 容器运行时支持 AppArmor —— 目前所有常见的 Kubernetes 支持的容器运行时都应该支持 AppArmor,
|
||||
像 {{< glossary_tooltip term_id="docker">}},{{< glossary_tooltip term_id="cri-o" >}}
|
||||
或 {{< glossary_tooltip term_id="containerd" >}}。
|
||||
请参考相应的运行时文档并验证集群是否满足使用 AppArmor 的要求。
|
||||
|
||||
<!--
|
||||
4. Profile is loaded -- AppArmor is applied to a Pod by specifying an AppArmor profile that each
|
||||
container should be run with. If any of the specified profiles is not already loaded in the
|
||||
kernel, the Kubelet (>= v1.4) will reject the Pod. You can view which profiles are loaded on a
|
||||
node by checking the `/sys/kernel/security/apparmor/profiles` file. For example:
|
||||
|
||||
```shell
|
||||
ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort"
|
||||
```
|
||||
```
|
||||
apparmor-test-deny-write (enforce)
|
||||
apparmor-test-audit-write (enforce)
|
||||
docker-default (enforce)
|
||||
k8s-nginx (enforce)
|
||||
```
|
||||
|
||||
For more details on loading profiles on nodes, see
|
||||
[Setting up nodes with profiles](#setting-up-nodes-with-profiles).
|
||||
-->
|
||||
4. 配置文件已加载 —— 通过指定每个容器都应使用的 AppArmor 配置文件,
|
||||
AppArmor 会被应用到 Pod 上。如果指定的任何配置文件尚未加载到内核,
|
||||
Kubelet(>= v1.4) 将拒绝 Pod。
|
||||
通过检查 `/sys/kernel/security/apparmor/profiles` 文件,
|
||||
可以查看节点加载了哪些配置文件。例如:
|
||||
|
||||
```shell
|
||||
ssh gke-test-default-pool-239f5d02-gyn2 "sudo cat /sys/kernel/security/apparmor/profiles | sort"
|
||||
```
|
||||
```
|
||||
apparmor-test-deny-write (enforce)
|
||||
apparmor-test-audit-write (enforce)
|
||||
docker-default (enforce)
|
||||
k8s-nginx (enforce)
|
||||
```
|
||||
|
||||
有关在节点上加载配置文件的详细信息,请参见[使用配置文件设置节点](#setting-up-nodes-with-profiles)。
|
||||
|
||||
<!--
|
||||
As long as the Kubelet version includes AppArmor support (>= v1.4), the Kubelet will reject a Pod
|
||||
with AppArmor options if any of the prerequisites are not met. You can also verify AppArmor support
|
||||
on nodes by checking the node ready condition message (though this is likely to be removed in a
|
||||
later release):
|
||||
-->
|
||||
只要 Kubelet 版本包含 AppArmor 支持(>=v1.4),
|
||||
如果不满足这些先决条件,Kubelet 将拒绝带有 AppArmor 选项的 Pod。
|
||||
你还可以通过检查节点就绪状况消息来验证节点上的 AppArmor 支持(尽管这可能会在以后的版本中删除):
|
||||
|
||||
```shell
|
||||
kubectl get nodes -o=jsonpath=$'{range .items[*]}{@.metadata.name}: {.status.conditions[?(@.reason=="KubeletReady")].message}\n{end}'
|
||||
```
|
||||
```
|
||||
gke-test-default-pool-239f5d02-gyn2: kubelet is posting ready status. AppArmor enabled
|
||||
gke-test-default-pool-239f5d02-x1kf: kubelet is posting ready status. AppArmor enabled
|
||||
gke-test-default-pool-239f5d02-xwux: kubelet is posting ready status. AppArmor enabled
|
||||
```
|
||||
|
||||
<!-- lessoncontent -->
|
||||
|
||||
<!-- ## Securing a Pod -->
|
||||
## 保护 Pod {#securing-a-pod}
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
AppArmor is currently in beta, so options are specified as annotations. Once support graduates to
|
||||
general availability, the annotations will be replaced with first-class fields (more details in
|
||||
[Upgrade path to GA](#upgrade-path-to-general-availability)).
|
||||
-->
|
||||
AppArmor 目前处于 Beta 阶段,因此选项以注解形式设定。
|
||||
一旦 AppArmor 支持进入正式发布阶段,注解将被替换为一阶的资源字段
|
||||
(更多详情参见[升级到 GA 的途径](#upgrade-path-to-general-availability))。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
AppArmor profiles are specified *per-container*. To specify the AppArmor profile to run a Pod
|
||||
container with, add an annotation to the Pod's metadata:
|
||||
-->
|
||||
AppArmor 配置文件是按 *逐个容器* 的形式来设置的。
|
||||
要指定用来运行 Pod 容器的 AppArmor 配置文件,请向 Pod 的 metadata 添加注解:
|
||||
|
||||
```yaml
|
||||
container.apparmor.security.beta.kubernetes.io/<container_name>: <profile_ref>
|
||||
```
|
||||
|
||||
<!--
|
||||
Where `<container_name>` is the name of the container to apply the profile to, and `<profile_ref>`
|
||||
specifies the profile to apply. The `profile_ref` can be one of:
|
||||
-->
|
||||
`<container_name>` 的名称是配置文件所针对的容器的名称,`<profile_def>` 则设置要应用的配置文件。
|
||||
`<profile_ref>` 可以是以下取值之一:
|
||||
|
||||
<!--
|
||||
* `runtime/default` to apply the runtime's default profile
|
||||
* `localhost/<profile_name>` to apply the profile loaded on the host with the name `<profile_name>`
|
||||
* `unconfined` to indicate that no profiles will be loaded
|
||||
-->
|
||||
* `runtime/default` 应用运行时的默认配置
|
||||
* `localhost/<profile_name>` 应用在主机上加载的名为 `<profile_name>` 的配置文件
|
||||
* `unconfined` 表示不加载配置文件
|
||||
|
||||
<!--
|
||||
See the [API Reference](#api-reference) for the full details on the annotation and profile name formats.
|
||||
-->
|
||||
有关注解和配置文件名称格式的详细信息,请参阅[API 参考](#api-reference)。
|
||||
|
||||
<!--
|
||||
Kubernetes AppArmor enforcement works by first checking that all the prerequisites have been
|
||||
met, and then forwarding the profile selection to the container runtime for enforcement. If the
|
||||
prerequisites have not been met, the Pod will be rejected, and will not run.
|
||||
-->
|
||||
Kubernetes AppArmor 强制执行机制首先检查所有先决条件都已满足,
|
||||
然后将所选的配置文件转发到容器运行时进行强制执行。
|
||||
如果未满足先决条件,Pod 将被拒绝,并且不会运行。
|
||||
|
||||
<!--
|
||||
To verify that the profile was applied, you can look for the AppArmor security option listed in the container created event:
|
||||
-->
|
||||
要验证是否应用了配置文件,可以在容器创建事件中查找所列出的 AppArmor 安全选项:
|
||||
|
||||
```shell
|
||||
kubectl get events | grep Created
|
||||
```
|
||||
```
|
||||
22s 22s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet e2e-test-stclair-node-pool-31nt} Created container with docker id 269a53b202d3; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
|
||||
```
|
||||
|
||||
<!--
|
||||
You can also verify directly that the container's root process is running with the correct profile by checking its proc attr:
|
||||
-->
|
||||
你还可以通过检查容器的 proc attr,直接验证容器的根进程是否以正确的配置文件运行:
|
||||
|
||||
```shell
|
||||
kubectl exec <pod_name> cat /proc/1/attr/current
|
||||
```
|
||||
```
|
||||
k8s-apparmor-example-deny-write (enforce)
|
||||
```
|
||||
|
||||
<!-- ## Example -->
|
||||
## 举例 {#example}
|
||||
|
||||
<!-- *This example assumes you have already set up a cluster with AppArmor support.* -->
|
||||
*本例假设你已经设置了一个集群使用 AppArmor 支持。*
|
||||
|
||||
<!--
|
||||
First, we need to load the profile we want to use onto our nodes. This profile denies all file writes:
|
||||
-->
|
||||
首先,我们需要将要使用的配置文件加载到节点上。配置文件拒绝所有文件写入:
|
||||
|
||||
```shell
|
||||
#include <tunables/global>
|
||||
|
||||
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
|
||||
#include <abstractions/base>
|
||||
|
||||
file,
|
||||
|
||||
# Deny all file writes.
|
||||
deny /** w,
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
Since we don't know where the Pod will be scheduled, we'll need to load the profile on all our
|
||||
nodes. For this example we'll use SSH to install the profiles, but other approaches are
|
||||
discussed in [Setting up nodes with profiles](#setting-up-nodes-with-profiles).
|
||||
-->
|
||||
由于我们不知道 Pod 将被调度到哪里,我们需要在所有节点上加载配置文件。
|
||||
在本例中,我们将使用 SSH 来安装概要文件,
|
||||
但是在[使用配置文件设置节点](#setting-up-nodes-with-profiles)中讨论了其他方法。
|
||||
|
||||
```shell
|
||||
NODES=(
|
||||
# The SSH-accessible domain names of your nodes
|
||||
gke-test-default-pool-239f5d02-gyn2.us-central1-a.my-k8s
|
||||
gke-test-default-pool-239f5d02-x1kf.us-central1-a.my-k8s
|
||||
gke-test-default-pool-239f5d02-xwux.us-central1-a.my-k8s)
|
||||
for NODE in ${NODES[*]}; do ssh $NODE 'sudo apparmor_parser -q <<EOF
|
||||
#include <tunables/global>
|
||||
|
||||
profile k8s-apparmor-example-deny-write flags=(attach_disconnected) {
|
||||
#include <abstractions/base>
|
||||
|
||||
file,
|
||||
|
||||
# Deny all file writes.
|
||||
deny /** w,
|
||||
}
|
||||
EOF'
|
||||
done
|
||||
```
|
||||
|
||||
<!-- Next, we'll run a simple "Hello AppArmor" pod with the deny-write profile: -->
|
||||
接下来,我们将运行一个带有拒绝写入配置文件的简单 “Hello AppArmor” Pod:
|
||||
|
||||
{{< codenew file="pods/security/hello-apparmor.yaml" >}}
|
||||
|
||||
```shell
|
||||
kubectl create -f ./hello-apparmor.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
If we look at the pod events, we can see that the Pod container was created with the AppArmor
|
||||
profile "k8s-apparmor-example-deny-write":
|
||||
-->
|
||||
如果我们查看 Pod 事件,我们可以看到 Pod 容器是用 AppArmor
|
||||
配置文件 “k8s-apparmor-example-deny-write” 所创建的:
|
||||
|
||||
```shell
|
||||
kubectl get events | grep hello-apparmor
|
||||
```
|
||||
```
|
||||
14s 14s 1 hello-apparmor Pod Normal Scheduled {default-scheduler } Successfully assigned hello-apparmor to gke-test-default-pool-239f5d02-gyn2
|
||||
14s 14s 1 hello-apparmor Pod spec.containers{hello} Normal Pulling {kubelet gke-test-default-pool-239f5d02-gyn2} pulling image "busybox"
|
||||
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Pulled {kubelet gke-test-default-pool-239f5d02-gyn2} Successfully pulled image "busybox"
|
||||
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Created {kubelet gke-test-default-pool-239f5d02-gyn2} Created container with docker id 06b6cd1c0989; Security:[seccomp=unconfined apparmor=k8s-apparmor-example-deny-write]
|
||||
13s 13s 1 hello-apparmor Pod spec.containers{hello} Normal Started {kubelet gke-test-default-pool-239f5d02-gyn2} Started container with docker id 06b6cd1c0989
|
||||
```
|
||||
|
||||
<!-- We can verify that the container is actually running with that profile by checking its proc attr: -->
|
||||
我们可以通过检查该配置文件的 proc attr 来验证容器是否实际使用该配置文件运行:
|
||||
|
||||
```shell
|
||||
kubectl exec hello-apparmor -- cat /proc/1/attr/current
|
||||
```
|
||||
```
|
||||
k8s-apparmor-example-deny-write (enforce)
|
||||
```
|
||||
|
||||
<!-- Finally, we can see what happens if we try to violate the profile by writing to a file: -->
|
||||
最后,我们可以看到,如果我们尝试通过写入文件来违反配置文件会发生什么:
|
||||
|
||||
```shell
|
||||
kubectl exec hello-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
|
||||
```
|
||||
|
||||
<!-- To wrap up, let's look at what happens if we try to specify a profile that hasn't been loaded: -->
|
||||
最后,让我们看看如果我们试图指定一个尚未加载的配置文件会发生什么:
|
||||
|
||||
```shell
|
||||
kubectl create -f /dev/stdin <<EOF
|
||||
```
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: hello-apparmor-2
|
||||
annotations:
|
||||
container.apparmor.security.beta.kubernetes.io/hello: localhost/k8s-apparmor-example-allow-write
|
||||
spec:
|
||||
containers:
|
||||
- name: hello
|
||||
image: busybox:1.28
|
||||
command: [ "sh", "-c", "echo 'Hello AppArmor!' && sleep 1h" ]
|
||||
EOF
|
||||
pod/hello-apparmor-2 created
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl describe pod hello-apparmor-2
|
||||
```
|
||||
```
|
||||
Name: hello-apparmor-2
|
||||
Namespace: default
|
||||
Node: gke-test-default-pool-239f5d02-x1kf/
|
||||
Start Time: Tue, 30 Aug 2016 17:58:56 -0700
|
||||
Labels: <none>
|
||||
Annotations: container.apparmor.security.beta.kubernetes.io/hello=localhost/k8s-apparmor-example-allow-write
|
||||
Status: Pending
|
||||
Reason: AppArmor
|
||||
Message: Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
|
||||
IP:
|
||||
Controllers: <none>
|
||||
Containers:
|
||||
hello:
|
||||
Container ID:
|
||||
Image: busybox
|
||||
Image ID:
|
||||
Port:
|
||||
Command:
|
||||
sh
|
||||
-c
|
||||
echo 'Hello AppArmor!' && sleep 1h
|
||||
State: Waiting
|
||||
Reason: Blocked
|
||||
Ready: False
|
||||
Restart Count: 0
|
||||
Environment: <none>
|
||||
Mounts:
|
||||
/var/run/secrets/kubernetes.io/serviceaccount from default-token-dnz7v (ro)
|
||||
Conditions:
|
||||
Type Status
|
||||
Initialized True
|
||||
Ready False
|
||||
PodScheduled True
|
||||
Volumes:
|
||||
default-token-dnz7v:
|
||||
Type: Secret (a volume populated by a Secret)
|
||||
SecretName: default-token-dnz7v
|
||||
Optional: false
|
||||
QoS Class: BestEffort
|
||||
Node-Selectors: <none>
|
||||
Tolerations: <none>
|
||||
Events:
|
||||
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
|
||||
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||
23s 23s 1 {default-scheduler } Normal Scheduled Successfully assigned hello-apparmor-2 to e2e-test-stclair-node-pool-t1f5
|
||||
23s 23s 1 {kubelet e2e-test-stclair-node-pool-t1f5} Warning AppArmor Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded
|
||||
```
|
||||
|
||||
<!--
|
||||
Note the pod status is Pending, with a helpful error message: `Pod Cannot enforce AppArmor: profile
|
||||
"k8s-apparmor-example-allow-write" is not loaded`. An event was also recorded with the same message.
|
||||
-->
|
||||
注意 Pod 呈现 Pending 状态,并且显示一条有用的错误信息:
|
||||
`Pod Cannot enforce AppArmor: profile "k8s-apparmor-example-allow-write" is not loaded`。
|
||||
还用相同的消息记录了一个事件。
|
||||
|
||||
<!-- ## Administration -->
|
||||
## 管理 {#administration}
|
||||
|
||||
<!-- ### Setting up nodes with profiles -->
|
||||
### 使用配置文件设置节点 {#setting-up-nodes-with-profiles}
|
||||
|
||||
<!--
|
||||
Kubernetes does not currently provide any native mechanisms for loading AppArmor profiles onto
|
||||
nodes. There are lots of ways to setup the profiles though, such as:
|
||||
-->
|
||||
Kubernetes 目前不提供任何本地机制来将 AppArmor 配置文件加载到节点上。
|
||||
有很多方法可以设置配置文件,例如:
|
||||
|
||||
<!--
|
||||
* Through a [DaemonSet](/docs/concepts/workloads/controllers/daemonset/) that runs a Pod on each node to
|
||||
ensure the correct profiles are loaded. An example implementation can be found
|
||||
[here](https://git.k8s.io/kubernetes/test/images/apparmor-loader).
|
||||
* At node initialization time, using your node initialization scripts (e.g. Salt, Ansible, etc.) or
|
||||
image.
|
||||
* By copying the profiles to each node and loading them through SSH, as demonstrated in the
|
||||
[Example](#example).
|
||||
-->
|
||||
* 通过在每个节点上运行 Pod 的
|
||||
[DaemonSet](/zh/docs/concepts/workloads/controllers/daemonset/)来确保加载了正确的配置文件。
|
||||
可以在[这里](https://git.k8s.io/kubernetes/test/images/apparmor-loader)找到实现示例。
|
||||
* 在节点初始化时,使用节点初始化脚本(例如 Salt、Ansible 等)或镜像。
|
||||
* 通过将配置文件复制到每个节点并通过 SSH 加载它们,如[示例](#example)。
|
||||
|
||||
<!--
|
||||
The scheduler is not aware of which profiles are loaded onto which node, so the full set of profiles
|
||||
must be loaded onto every node. An alternative approach is to add a node label for each profile (or
|
||||
class of profiles) on the node, and use a
|
||||
[node selector](/docs/concepts/configuration/assign-pod-node/) to ensure the Pod is run on a
|
||||
node with the required profile.
|
||||
-->
|
||||
调度程序不知道哪些配置文件加载到哪个节点上,因此必须将全套配置文件加载到每个节点上。
|
||||
另一种方法是为节点上的每个配置文件(或配置文件类)添加节点标签,
|
||||
并使用[节点选择器](/zh/docs/concepts/configuration/assign-pod-node/)确保
|
||||
Pod 在具有所需配置文件的节点上运行。
|
||||
|
||||
<!-- ### Restricting profiles with the PodSecurityPolicy -->
|
||||
### 使用 PodSecurityPolicy 限制配置文件 {#restricting-profiles-with-the-podsecuritypolicy}
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
PodSecurityPolicy is deprecated in Kubernetes v1.21, and will be removed in v1.25.
|
||||
See [PodSecurityPolicy](/docs/concepts/security/pod-security-policy/) documentation for more information.
|
||||
-->
|
||||
PodSecurityPolicy 在 Kubernetes v1.21 版本中已被废弃,将在 v1.25 版本移除。
|
||||
查看 [PodSecurityPolicy](/zh/docs/concepts/security/pod-security-policy/) 文档获取更多信息。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
If the PodSecurityPolicy extension is enabled, cluster-wide AppArmor restrictions can be applied. To
|
||||
enable the PodSecurityPolicy, the following flag must be set on the `apiserver`:
|
||||
-->
|
||||
如果启用了 PodSecurityPolicy 扩展,则可以应用集群范围的 AppArmor 限制。
|
||||
要启用 PodSecurityPolicy,必须在 `apiserver` 上设置以下标志:
|
||||
|
||||
```
|
||||
--enable-admission-plugins=PodSecurityPolicy[,others...]
|
||||
```
|
||||
|
||||
<!-- The AppArmor options can be specified as annotations on the PodSecurityPolicy: -->
|
||||
AppArmor 选项可以指定为 PodSecurityPolicy 上的注解:
|
||||
|
||||
```yaml
|
||||
apparmor.security.beta.kubernetes.io/defaultProfileName: <profile_ref>
|
||||
apparmor.security.beta.kubernetes.io/allowedProfileNames: <profile_ref>[,others...]
|
||||
```
|
||||
|
||||
<!--
|
||||
The default profile name option specifies the profile to apply to containers by default when none is
|
||||
specified. The allowed profile names option specifies a list of profiles that Pod containers are
|
||||
allowed to be run with. If both options are provided, the default must be allowed. The profiles are
|
||||
specified in the same format as on containers. See the [API Reference](#api-reference) for the full
|
||||
specification.
|
||||
-->
|
||||
默认配置文件名选项指定默认情况下在未指定任何配置文件时应用于容器的配置文件。
|
||||
所允许的配置文件名称选项指定允许 Pod 容器运行期间所对应的配置文件列表。
|
||||
如果同时提供了这两个选项,则必须允许默认值。
|
||||
配置文件的指定格式与容器上的相同。有关完整规范,请参阅 [API 参考](#api-reference)。
|
||||
|
||||
<!-- ### Disabling AppArmor -->
|
||||
### 禁用 AppArmor {#disabling-apparmor}
|
||||
|
||||
<!-- If you do not want AppArmor to be available on your cluster, it can be disabled by a command-line flag: -->
|
||||
如果你不希望 AppArmor 在集群上可用,可以通过命令行标志禁用它:
|
||||
|
||||
```
|
||||
--feature-gates=AppArmor=false
|
||||
```
|
||||
|
||||
<!--
|
||||
When disabled, any Pod that includes an AppArmor profile will fail validation with a "Forbidden"
|
||||
error.
|
||||
-->
|
||||
禁用时,任何包含 AppArmor 配置文件的 Pod 都将导致验证失败,且返回 “Forbidden” 错误。
|
||||
|
||||
{{<note>}}
|
||||
<!--
|
||||
Even if the Kubernetes feature is disabled, runtimes may still enforce the default profile. The
|
||||
option to disable the AppArmor feature will be removed when AppArmor graduates to general
|
||||
availability (GA).
|
||||
-->
|
||||
即使此 Kubernetes 特性被禁用,运行时仍可能强制执行默认配置文件。
|
||||
当 AppArmor 升级为正式版 (GA) 时,禁用 AppArmor 功能的选项将被删除。
|
||||
|
||||
{{</note>}}
|
||||
|
||||
|
||||
<!-- ## Authoring Profiles -->
|
||||
## 编写配置文件 {#authoring-profiles}
|
||||
|
||||
<!--
|
||||
Getting AppArmor profiles specified correctly can be a tricky business. Fortunately there are some
|
||||
tools to help with that:
|
||||
-->
|
||||
获得正确指定的 AppArmor 配置文件可能是一件棘手的事情。幸运的是,有一些工具可以帮助你做到这一点:
|
||||
|
||||
<!--
|
||||
* `aa-genprof` and `aa-logprof` generate profile rules by monitoring an application's activity and
|
||||
logs, and admitting the actions it takes. Further instructions are provided by the
|
||||
[AppArmor documentation](https://gitlab.com/apparmor/apparmor/wikis/Profiling_with_tools).
|
||||
* [bane](https://github.com/jfrazelle/bane) is an AppArmor profile generator for Docker that uses a
|
||||
simplified profile language.
|
||||
-->
|
||||
* `aa-genprof` 和 `aa-logprof`
|
||||
通过监视应用程序的活动和日志并准许它所执行的操作来生成配置文件规则。
|
||||
[AppArmor 文档](https://gitlab.com/apparmor/apparmor/wikis/Profiling_with_tools)提供了进一步的指导。
|
||||
* [bane](https://github.com/jfrazelle/bane)
|
||||
是一个用于 Docker的 AppArmor 配置文件生成器,它使用一种简化的画像语言(profile language)
|
||||
|
||||
<!--
|
||||
To debug problems with AppArmor, you can check the system logs to see what, specifically, was
|
||||
denied. AppArmor logs verbose messages to `dmesg`, and errors can usually be found in the system
|
||||
logs or through `journalctl`. More information is provided in
|
||||
[AppArmor failures](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Failures).
|
||||
-->
|
||||
想要调试 AppArmor 的问题,你可以检查系统日志,查看具体拒绝了什么。
|
||||
AppArmor 将详细消息记录到 `dmesg`,
|
||||
错误通常可以在系统日志中或通过 `journalctl` 找到。
|
||||
更多详细信息见 [AppArmor 失败](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Failures)。
|
||||
|
||||
<!-- ## API Reference -->
|
||||
## API 参考 {#api-reference}
|
||||
|
||||
<!-- ### Pod Annotation -->
|
||||
### Pod 注解 {#pod-annotation}
|
||||
|
||||
<!-- Specifying the profile a container will run with: -->
|
||||
指定容器将使用的配置文件:
|
||||
|
||||
<!--
|
||||
- **key**: `container.apparmor.security.beta.kubernetes.io/<container_name>`
|
||||
Where `<container_name>` matches the name of a container in the Pod.
|
||||
A separate profile can be specified for each container in the Pod.
|
||||
- **value**: a profile reference, described below
|
||||
-->
|
||||
- **键名**: `container.apparmor.security.beta.kubernetes.io/<container_name>`
|
||||
,其中 `<container_name>` 与 Pod 中某容器的名称匹配。
|
||||
可以为 Pod 中的每个容器指定单独的配置文件。
|
||||
- **键值**: 对配置文件的引用,如下所述
|
||||
|
||||
<!-- ### Profile Reference -->
|
||||
### 配置文件引用 {#profile-reference}
|
||||
|
||||
<!--
|
||||
- `runtime/default`: Refers to the default runtime profile.
|
||||
- Equivalent to not specifying a profile (without a PodSecurityPolicy default), except it still
|
||||
requires AppArmor to be enabled.
|
||||
- In practice, many container runtimes use the same OCI default profile, defined here:
|
||||
https://github.com/containers/common/blob/main/pkg/apparmor/apparmor_linux_template.go
|
||||
- `localhost/<profile_name>`: Refers to a profile loaded on the node (localhost) by name.
|
||||
- The possible profile names are detailed in the
|
||||
[core policy reference](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Core_Policy_Reference#profile-names-and-attachment-specifications).
|
||||
- `unconfined`: This effectively disables AppArmor on the container.
|
||||
-->
|
||||
- `runtime/default`: 指默认运行时配置文件。
|
||||
- 等同于不指定配置文件(没有 PodSecurityPolicy 默认值),只是它仍然需要启用 AppArmor。
|
||||
- 实际上,许多容器运行时使用相同的 OCI 默认配置文件,在此处定义:
|
||||
https://github.com/containers/common/blob/main/pkg/apparmor/apparmor_linux_template.go
|
||||
- `localhost/<profile_name>`: 按名称引用加载到节点(localhost)上的配置文件。
|
||||
- 可能的配置文件名在[核心策略参考](https://gitlab.com/apparmor/apparmor/wikis/AppArmor_Core_Policy_Reference#profile-names-and-attachment-specifications)。
|
||||
- `unconfined`: 这相当于为容器禁用 AppArmor。
|
||||
|
||||
<!-- Any other profile reference format is invalid. -->
|
||||
任何其他配置文件引用格式无效。
|
||||
|
||||
<!-- ### PodSecurityPolicy Annotations -->
|
||||
### PodSecurityPolicy 注解 {#podsecuritypolicy-annotations}
|
||||
|
||||
<!-- Specifying the default profile to apply to containers when none is provided: -->
|
||||
指定在未提供容器时应用于容器的默认配置文件:
|
||||
|
||||
<!--
|
||||
* **key**: `apparmor.security.beta.kubernetes.io/defaultProfileName`
|
||||
* **value**: a profile reference, described above
|
||||
-->
|
||||
* **键名**: `apparmor.security.beta.kubernetes.io/defaultProfileName`
|
||||
* **键值**: 如上述文件参考所述
|
||||
|
||||
<!-- Specifying the list of profiles Pod containers is allowed to specify: -->
|
||||
上面描述的指定配置文件,Pod 容器列表的配置文件引用允许指定:
|
||||
|
||||
<!--
|
||||
* **key**: `apparmor.security.beta.kubernetes.io/allowedProfileNames`
|
||||
* **value**: a comma-separated list of profile references (described above)
|
||||
- Although an escaped comma is a legal character in a profile name, it cannot be explicitly
|
||||
allowed here.
|
||||
-->
|
||||
* **键名**: `apparmor.security.beta.kubernetes.io/allowedProfileNames`
|
||||
* **键值**: 配置文件引用的逗号分隔列表(如上所述)
|
||||
- 尽管转义逗号是配置文件名中的合法字符,但此处不能显式允许。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!-- Additional resources: -->
|
||||
其他资源:
|
||||
|
||||
<!--
|
||||
* [Quick guide to the AppArmor profile language](https://gitlab.com/apparmor/apparmor/wikis/QuickProfileLanguage)
|
||||
* [AppArmor core policy reference](https://gitlab.com/apparmor/apparmor/wikis/Policy_Layout)
|
||||
-->
|
||||
* [Apparmor 配置文件语言快速指南](https://gitlab.com/apparmor/apparmor/wikis/QuickProfileLanguage)
|
||||
* [Apparmor 核心策略参考](https://gitlab.com/apparmor/apparmor/wikis/Policy_Layout)
|
||||
@@ -0,0 +1,444 @@
|
||||
---
|
||||
title: 在集群级别应用 Pod 安全标准
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
---
|
||||
<!--
|
||||
title: Apply Pod Security Standards at the Cluster Level
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
-->
|
||||
|
||||
{{% alert title="Note" %}}
|
||||
<!-- This tutorial applies only for new clusters. -->
|
||||
本教程仅适用于新集群。
|
||||
{{% /alert %}}
|
||||
|
||||
<!--
|
||||
Pod Security admission (PSA) is enabled by default in v1.23 and later, as it has
|
||||
[graduated to beta](/blog/2021/12/09/pod-security-admission-beta/).
|
||||
Pod Security
|
||||
is an admission controller that carries out checks against the Kubernetes
|
||||
[Pod Security Standards](/docs/concepts/security/pod-security-standards/) when new pods are
|
||||
created. This tutorial shows you how to enforce the `baseline` Pod Security
|
||||
Standard at the cluster level which applies a standard configuration
|
||||
to all namespaces in a cluster.
|
||||
|
||||
To apply Pod Security Standards to specific namespaces, refer to [Apply Pod Security Standards at the namespace level](/docs/tutorials/security/ns-level-pss).
|
||||
-->
|
||||
Pod 安全准入(PSA)在 v1.23 及更高版本默认启用,
|
||||
因为它[升级到测试版(beta)](/blog/2021/12/09/pod-security-admission-beta/)。
|
||||
Pod 安全准入是在创建 Pod 时应用
|
||||
[Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/)的准入控制器。
|
||||
本教程将向你展示如何在集群级别实施 `baseline` Pod 安全标准,
|
||||
该标准将标准配置应用于集群中的所有名称空间。
|
||||
|
||||
要将 Pod 安全标准应用于特定名字空间,
|
||||
请参阅[在名字空间级别应用 Pod 安全标准](/zh/docs/tutorials/security/ns-level-pss)。
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
<!--
|
||||
Install the following on your workstation:
|
||||
|
||||
- [KinD](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
|
||||
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
|
||||
-->
|
||||
在你的工作站中安装以下内容:
|
||||
|
||||
- [KinD](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
|
||||
- [kubectl](https://kubernetes.io/docs/tasks/tools/)
|
||||
|
||||
<!--
|
||||
## Choose the right Pod Security Standard to apply
|
||||
|
||||
[Pod Security Admission](/docs/concepts/security/pod-security-admission/)
|
||||
lets you apply built-in [Pod Security Standards](/docs/concepts/security/pod-security-standards/)
|
||||
with the following modes: `enforce`, `audit`, and `warn`.
|
||||
|
||||
To gather information that helps you to choose the Pod Security Standards
|
||||
that are most appropriate for your configuration, do the following:
|
||||
-->
|
||||
## 正确选择要应用的 Pod 安全标准 {#choose-the-right-pod-security-standard-to-apply}
|
||||
|
||||
[Pod 安全准入](/zh/docs/concepts/security/pod-security-admission/)
|
||||
允许你使用以下模式应用内置的
|
||||
[Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/):
|
||||
`enforce`、`audit` 和 `warn`。
|
||||
|
||||
要收集信息以便选择最适合你的配置的 Pod 安全标准,请执行以下操作:
|
||||
|
||||
<!--
|
||||
1. Create a cluster with no Pod Security Standards applied:
|
||||
-->
|
||||
1. 创建一个没有应用 Pod 安全标准的集群:
|
||||
|
||||
```shell
|
||||
kind create cluster --name psa-wo-cluster-pss --image kindest/node:v1.23.0
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Creating cluster "psa-wo-cluster-pss" ...
|
||||
✓ Ensuring node image (kindest/node:v1.23.0) 🖼
|
||||
✓ Preparing nodes 📦
|
||||
✓ Writing configuration 📜
|
||||
✓ Starting control-plane 🕹️
|
||||
✓ Installing CNI 🔌
|
||||
✓ Installing StorageClass 💾
|
||||
Set kubectl context to "kind-psa-wo-cluster-pss"
|
||||
You can now use your cluster with:
|
||||
|
||||
kubectl cluster-info --context kind-psa-wo-cluster-pss
|
||||
|
||||
Thanks for using kind! 😊
|
||||
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Set the kubectl context to the new cluster:
|
||||
-->
|
||||
2. 将 kubectl 上下文设置为新集群:
|
||||
|
||||
```shell
|
||||
kubectl cluster-info --context kind-psa-wo-cluster-pss
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
|
||||
```
|
||||
Kubernetes control plane is running at https://127.0.0.1:61350
|
||||
CoreDNS is running at https://127.0.0.1:61350/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
|
||||
|
||||
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Get a list of namespaces in the cluster:
|
||||
-->
|
||||
3. 获取集群中的名字空间列表:
|
||||
|
||||
```shell
|
||||
kubectl get ns
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
NAME STATUS AGE
|
||||
default Active 9m30s
|
||||
kube-node-lease Active 9m32s
|
||||
kube-public Active 9m32s
|
||||
kube-system Active 9m32s
|
||||
local-path-storage Active 9m26s
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Use `--dry-run=server` to understand what happens when different Pod Security Standards
|
||||
are applied:
|
||||
-->
|
||||
4. 使用 `--dry-run=server` 来了解应用不同的 Pod 安全标准时会发生什么:
|
||||
|
||||
1. Privileged
|
||||
```shell
|
||||
kubectl label --dry-run=server --overwrite ns --all \
|
||||
pod-security.kubernetes.io/enforce=privileged
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
namespace/default labeled
|
||||
namespace/kube-node-lease labeled
|
||||
namespace/kube-public labeled
|
||||
namespace/kube-system labeled
|
||||
namespace/local-path-storage labeled
|
||||
```
|
||||
2. Baseline
|
||||
```shell
|
||||
kubectl label --dry-run=server --overwrite ns --all \
|
||||
pod-security.kubernetes.io/enforce=baseline
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
namespace/default labeled
|
||||
namespace/kube-node-lease labeled
|
||||
namespace/kube-public labeled
|
||||
Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "baseline:latest"
|
||||
Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes
|
||||
Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes
|
||||
Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged
|
||||
namespace/kube-system labeled
|
||||
namespace/local-path-storage labeled
|
||||
```
|
||||
|
||||
3. Restricted
|
||||
```shell
|
||||
kubectl label --dry-run=server --overwrite ns --all \
|
||||
pod-security.kubernetes.io/enforce=restricted
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
namespace/default labeled
|
||||
namespace/kube-node-lease labeled
|
||||
namespace/kube-public labeled
|
||||
Warning: existing pods in namespace "kube-system" violate the new PodSecurity enforce level "restricted:latest"
|
||||
Warning: coredns-7bb9c7b568-hsptc (and 1 other pod): unrestricted capabilities, runAsNonRoot != true, seccompProfile
|
||||
Warning: etcd-psa-wo-cluster-pss-control-plane (and 3 other pods): host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true
|
||||
Warning: kindnet-vzj42: non-default capabilities, host namespaces, hostPath volumes, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
|
||||
Warning: kube-proxy-m6hwf: host namespaces, hostPath volumes, privileged, allowPrivilegeEscalation != false, unrestricted capabilities, restricted volume types, runAsNonRoot != true, seccompProfile
|
||||
namespace/kube-system labeled
|
||||
Warning: existing pods in namespace "local-path-storage" violate the new PodSecurity enforce level "restricted:latest"
|
||||
Warning: local-path-provisioner-d6d9f7ffc-lw9lh: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile
|
||||
namespace/local-path-storage labeled
|
||||
```
|
||||
|
||||
<!--
|
||||
From the previous output, you'll notice that applying the `privileged` Pod Security Standard shows no warnings
|
||||
for any namespaces. However, `baseline` and `restricted` standards both have
|
||||
warnings, specifically in the `kube-system` namespace.
|
||||
-->
|
||||
从前面的输出中,你会注意到应用 `privileged` Pod 安全标准不会显示任何名字空间的警告。
|
||||
然而,`baseline` 和 `restricted` 标准都有警告,特别是在 `kube-system` 名字空间中。
|
||||
|
||||
<!--
|
||||
## Set modes, versions and standards
|
||||
|
||||
In this section, you apply the following Pod Security Standards to the `latest` version:
|
||||
|
||||
* `baseline` standard in `enforce` mode.
|
||||
* `restricted` standard in `warn` and `audit` mode.
|
||||
-->
|
||||
## 设置模式、版本和标准 {#set-modes-versions-and-standards}
|
||||
|
||||
在本节中,你将以下 Pod 安全标准应用于最新(`latest`)版本:
|
||||
|
||||
* 在 `enforce` 模式下的 `baseline` 标准。
|
||||
* `warn` 和 `audit` 模式下的 `restricted` 标准。
|
||||
|
||||
<!--
|
||||
The `baseline` Pod Security Standard provides a convenient
|
||||
middle ground that allows keeping the exemption list short and prevents known
|
||||
privilege escalations.
|
||||
|
||||
Additionally, to prevent pods from failing in `kube-system`, you'll exempt the namespace
|
||||
from having Pod Security Standards applied.
|
||||
|
||||
When you implement Pod Security Admission in your own environment, consider the
|
||||
following:
|
||||
-->
|
||||
`baseline` Pod 安全标准提供了一个方便的中间立场,能够保持豁免列表简短并防止已知的特权升级。
|
||||
|
||||
此外,为了防止 `kube-system` 中的 Pod 失败,你将免除该名字空间应用 Pod 安全标准。
|
||||
|
||||
在你自己的环境中实施 Pod 安全准入时,请考虑以下事项:
|
||||
|
||||
<!--
|
||||
1. Based on the risk posture applied to a cluster, a stricter Pod Security
|
||||
Standard like `restricted` might be a better choice.
|
||||
1. Exempting the `kube-system` namespace allows pods to run as
|
||||
`privileged` in this namespace. For real world use, the Kubernetes project
|
||||
strongly recommends that you apply strict RBAC
|
||||
policies that limit access to `kube-system`, following the principle of least
|
||||
privilege.
|
||||
To implement the preceding standards, do the following:
|
||||
1. Create a configuration file that can be consumed by the Pod Security
|
||||
Admission Controller to implement these Pod Security Standards:
|
||||
-->
|
||||
1. 根据应用于集群的风险状况,更严格的 Pod 安全标准(如 `restricted`)可能是更好的选择。
|
||||
2. 对 `kube-system` 名字空间进行赦免会允许 Pod 在其中以 `privileged` 模式运行。
|
||||
对于实际使用,Kubernetes 项目强烈建议你应用严格的 RBAC 策略来限制对 `kube-system` 的访问,
|
||||
遵循最小特权原则。
|
||||
3. 创建一个配置文件,Pod 安全准入控制器可以使用该文件来实现这些 Pod 安全标准:
|
||||
|
||||
```
|
||||
mkdir -p /tmp/pss
|
||||
cat <<EOF > /tmp/pss/cluster-level-pss.yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: AdmissionConfiguration
|
||||
plugins:
|
||||
- name: PodSecurity
|
||||
configuration:
|
||||
apiVersion: pod-security.admission.config.k8s.io/v1beta1
|
||||
kind: PodSecurityConfiguration
|
||||
defaults:
|
||||
enforce: "baseline"
|
||||
enforce-version: "latest"
|
||||
audit: "restricted"
|
||||
audit-version: "latest"
|
||||
warn: "restricted"
|
||||
warn-version: "latest"
|
||||
exemptions:
|
||||
usernames: []
|
||||
runtimeClasses: []
|
||||
namespaces: [kube-system]
|
||||
EOF
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Configure the API server to consume this file during cluster creation:
|
||||
-->
|
||||
4. 在创建集群时配置 API 服务器使用此文件:
|
||||
|
||||
```
|
||||
cat <<EOF > /tmp/pss/cluster-config.yaml
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: ClusterConfiguration
|
||||
apiServer:
|
||||
extraArgs:
|
||||
admission-control-config-file: /etc/config/cluster-level-pss.yaml
|
||||
extraVolumes:
|
||||
- name: accf
|
||||
hostPath: /etc/config
|
||||
mountPath: /etc/config
|
||||
readOnly: false
|
||||
pathType: "DirectoryOrCreate"
|
||||
extraMounts:
|
||||
- hostPath: /tmp/pss
|
||||
containerPath: /etc/config
|
||||
# optional: if set, the mount is read-only.
|
||||
# default false
|
||||
readOnly: false
|
||||
# optional: if set, the mount needs SELinux relabeling.
|
||||
# default false
|
||||
selinuxRelabel: false
|
||||
# optional: set propagation mode (None, HostToContainer or Bidirectional)
|
||||
# see https://kubernetes.io/docs/concepts/storage/volumes/#mount-propagation
|
||||
# default None
|
||||
propagation: None
|
||||
EOF
|
||||
```
|
||||
|
||||
{{<note>}}
|
||||
<!--
|
||||
If you use Docker Desktop with KinD on macOS, you can
|
||||
add `/tmp` as a Shared Directory under the menu item
|
||||
**Preferences > Resources > File Sharing**.
|
||||
-->
|
||||
如果你在 macOS 上使用 Docker Desktop 和 KinD,
|
||||
你可以在菜单项 **Preferences > Resources > File Sharing**
|
||||
下添加 `/tmp` 作为共享目录。
|
||||
{{</note>}}
|
||||
|
||||
<!--
|
||||
1. Create a cluster that uses Pod Security Admission to apply
|
||||
these Pod Security Standards:
|
||||
-->
|
||||
5. 创建一个使用 Pod 安全准入的集群来应用这些 Pod 安全标准:
|
||||
|
||||
```shell
|
||||
kind create cluster --name psa-with-cluster-pss --image kindest/node:v1.23.0 --config /tmp/pss/cluster-config.yaml
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Creating cluster "psa-with-cluster-pss" ...
|
||||
✓ Ensuring node image (kindest/node:v1.23.0) 🖼
|
||||
✓ Preparing nodes 📦
|
||||
✓ Writing configuration 📜
|
||||
✓ Starting control-plane 🕹️
|
||||
✓ Installing CNI 🔌
|
||||
✓ Installing StorageClass 💾
|
||||
Set kubectl context to "kind-psa-with-cluster-pss"
|
||||
You can now use your cluster with:
|
||||
|
||||
kubectl cluster-info --context kind-psa-with-cluster-pss
|
||||
|
||||
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community 🙂
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Point kubectl to the cluster
|
||||
-->
|
||||
6. 将 kubectl 指向集群
|
||||
|
||||
```shell
|
||||
kubectl cluster-info --context kind-psa-with-cluster-pss
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Kubernetes control plane is running at https://127.0.0.1:63855
|
||||
CoreDNS is running at https://127.0.0.1:63855/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
|
||||
|
||||
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Create the following Pod specification for a minimal configuration in the default namespace:
|
||||
-->
|
||||
7. 创建以下 Pod 规约作为在 default 名字空间中的一个最小配置:
|
||||
|
||||
```
|
||||
cat <<EOF > /tmp/pss/nginx-pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
EOF
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Create the Pod in the cluster:
|
||||
-->
|
||||
8. 在集群中创建 Pod:
|
||||
|
||||
```shell
|
||||
kubectl apply -f /tmp/pss/nginx-pod.yaml
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext seccompProfile.type to "RuntimeDefault" or "Localhost")
|
||||
pod/nginx created
|
||||
```
|
||||
|
||||
<!--
|
||||
## Clean up
|
||||
|
||||
Run `kind delete cluster --name psa-with-cluster-pss` and
|
||||
`kind delete cluster --name psa-wo-cluster-pss` to delete the clusters you
|
||||
created.
|
||||
-->
|
||||
## 清理 {#clean-up}
|
||||
|
||||
运行 `kind delete cluster --name psa-with-cluster-pss` 和
|
||||
`kind delete cluster --name psa-wo-cluster-pss` 来删除你创建的集群。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
- Run a
|
||||
[shell script](/examples/security/kind-with-cluster-level-baseline-pod-security.sh)
|
||||
to perform all the preceding steps at once:
|
||||
1. Create a Pod Security Standards based cluster level Configuration
|
||||
2. Create a file to let API server consumes this configuration
|
||||
3. Create a cluster that creates an API server with this configuration
|
||||
4. Set kubectl context to this new cluster
|
||||
5. Create a minimal pod yaml file
|
||||
6. Apply this file to create a Pod in the new cluster
|
||||
- [Pod Security Admission](/docs/concepts/security/pod-security-admission/)
|
||||
- [Pod Security Standards](/docs/concepts/security/pod-security-standards/)
|
||||
- [Apply Pod Security Standards at the namespace level](/docs/tutorials/security/ns-level-pss/)
|
||||
-->
|
||||
- 运行一个 [shell 脚本](/zh/examples/security/kind-with-cluster-level-baseline-pod-security.sh)
|
||||
一次执行前面的所有步骤:
|
||||
1. 创建一个基于 Pod 安全标准的集群级别配置
|
||||
2. 创建一个文件让 API 服务器消费这个配置
|
||||
3. 创建一个集群,用这个配置创建一个 API 服务器
|
||||
4. 设置 kubectl 上下文为这个新集群
|
||||
5. 创建一个最小的 Pod yaml 文件
|
||||
6. 应用这个文件,在新集群中创建一个 Pod
|
||||
- [Pod 安全准入](/zh/docs/concepts/security/pod-security-admission/)
|
||||
- [Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/)
|
||||
- [在名字空间级别应用 Pod 安全标准](/zh/docs/tutorials/security/ns-level-pss/)
|
||||
@@ -0,0 +1,252 @@
|
||||
---
|
||||
title: 在名字空间级别应用 Pod 安全标准
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
---
|
||||
|
||||
<!--
|
||||
title: Apply Pod Security Standards at the Namespace Level
|
||||
content_type: tutorial
|
||||
weight: 10
|
||||
-->
|
||||
|
||||
{{% alert title="Note" %}}
|
||||
<!-- This tutorial applies only for new clusters. -->
|
||||
本教程仅适用于新集群。
|
||||
{{% /alert %}}
|
||||
|
||||
<!--
|
||||
Pod Security admission (PSA) is enabled by default in v1.23 and later, as it
|
||||
[graduated to beta](/blog/2021/12/09/pod-security-admission-beta/). Pod Security Admission
|
||||
is an admission controller that applies
|
||||
[Pod Security Standards](/docs/concepts/security/pod-security-standards/)
|
||||
when pods are created. In this tutorial, you will enforce the `baseline` Pod Security Standard,
|
||||
one namespace at a time.
|
||||
|
||||
You can also apply Pod Security Standards to multiple namespaces at once at the cluster
|
||||
level. For instructions, refer to
|
||||
[Apply Pod Security Standards at the cluster level](/docs/tutorials/security/cluster-level-pss).
|
||||
-->
|
||||
Pod 安全准入(PSA)在 v1.23 及更高版本默认启用,
|
||||
因为它[升级到测试版(beta)](/blog/2021/12/09/pod-security-admission-beta/)。
|
||||
Pod 安全准入是在创建 Pod 时应用
|
||||
[Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/)的准入控制器。
|
||||
在本教程中,你将应用 `baseline` Pod 安全标准,每次一个名字空间。
|
||||
|
||||
你还可以在集群级别一次将 Pod 安全标准应用于多个名称空间。
|
||||
有关说明,请参阅[在集群级别应用 Pod 安全标准](/zh/docs/tutorials/security/cluster-level-pss)。
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
<!--
|
||||
Install the following on your workstation:
|
||||
|
||||
- [KinD](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
|
||||
- [kubectl](/docs/tasks/tools/)
|
||||
-->
|
||||
在你的工作站中安装以下内容:
|
||||
|
||||
- [KinD](https://kind.sigs.k8s.io/docs/user/quick-start/#installation)
|
||||
- [kubectl](/zh/docs/tasks/tools/)
|
||||
|
||||
<!--
|
||||
## Create cluster
|
||||
|
||||
1. Create a `KinD` cluster as follows:
|
||||
-->
|
||||
## 创建集群 {#create-cluster}
|
||||
|
||||
2. 按照如下方式创建一个 `KinD` 集群:
|
||||
|
||||
```shell
|
||||
kind create cluster --name psa-ns-level --image kindest/node:v1.23.0
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Creating cluster "psa-ns-level" ...
|
||||
✓ Ensuring node image (kindest/node:v1.23.0) 🖼
|
||||
✓ Preparing nodes 📦
|
||||
✓ Writing configuration 📜
|
||||
✓ Starting control-plane 🕹️
|
||||
✓ Installing CNI 🔌
|
||||
✓ Installing StorageClass 💾
|
||||
Set kubectl context to "kind-psa-ns-level"
|
||||
You can now use your cluster with:
|
||||
|
||||
kubectl cluster-info --context kind-psa-ns-level
|
||||
|
||||
Not sure what to do next? 😅 Check out https://kind.sigs.k8s.io/docs/user/quick-start/
|
||||
```
|
||||
|
||||
<!-- 1. Set the kubectl context to the new cluster: -->
|
||||
1. 将 kubectl 上下文设置为新集群:
|
||||
```shell
|
||||
kubectl cluster-info --context kind-psa-ns-level
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Kubernetes control plane is running at https://127.0.0.1:50996
|
||||
CoreDNS is running at https://127.0.0.1:50996/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
|
||||
|
||||
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create a namespace
|
||||
|
||||
Create a new namespace called `example`:
|
||||
-->
|
||||
## 创建名字空间 {#create-a-namespace}
|
||||
|
||||
创建一个名为 `example` 的新名字空间:
|
||||
|
||||
```shell
|
||||
kubectl create ns example
|
||||
```
|
||||
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
|
||||
```
|
||||
namespace/example created
|
||||
```
|
||||
|
||||
<!--
|
||||
## Apply Pod Security Standards
|
||||
|
||||
1. Enable Pod Security Standards on this namespace using labels supported by
|
||||
built-in Pod Security Admission. In this step we will warn on baseline pod
|
||||
security standard as per the latest version (default value)
|
||||
-->
|
||||
## 应用 Pod 安全标准 {#apply-pod-security-standards}
|
||||
|
||||
1. 使用内置 Pod 安全准入所支持的标签在此名字空间上启用 Pod 安全标准。
|
||||
在这一步中,我们将根据最新版本(默认值)对基线 Pod 安全标准发出警告。
|
||||
|
||||
```shell
|
||||
kubectl label --overwrite ns example \
|
||||
pod-security.kubernetes.io/warn=baseline \
|
||||
pod-security.kubernetes.io/warn-version=latest
|
||||
```
|
||||
|
||||
<!--
|
||||
2. Multiple pod security standards can be enabled on any namespace, using labels.
|
||||
Following command will `enforce` the `baseline` Pod Security Standard, but
|
||||
`warn` and `audit` for `restricted` Pod Security Standards as per the latest
|
||||
version (default value)
|
||||
-->
|
||||
2. 可以使用标签在任何名字空间上启用多个 Pod 安全标准。
|
||||
以下命令将强制(`enforce`) 执行基线(`baseline`)Pod 安全标准,
|
||||
但根据最新版本(默认值)对受限(`restricted`)Pod 安全标准执行警告(`warn`)和审核(`audit`)。
|
||||
|
||||
```
|
||||
kubectl label --overwrite ns example \
|
||||
pod-security.kubernetes.io/enforce=baseline \
|
||||
pod-security.kubernetes.io/enforce-version=latest \
|
||||
pod-security.kubernetes.io/warn=restricted \
|
||||
pod-security.kubernetes.io/warn-version=latest \
|
||||
pod-security.kubernetes.io/audit=restricted \
|
||||
pod-security.kubernetes.io/audit-version=latest
|
||||
```
|
||||
|
||||
<!--
|
||||
## Verify the Pod Security Standards
|
||||
|
||||
1. Create a minimal pod in `example` namespace:
|
||||
-->
|
||||
## 验证 Pod 安全标准 {#verify-the-pod-security-standards}
|
||||
|
||||
1. 在 `example` 名字空间中创建一个最小的 pod:
|
||||
|
||||
```shell
|
||||
cat <<EOF > /tmp/pss/nginx-pod.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: nginx
|
||||
spec:
|
||||
containers:
|
||||
- image: nginx
|
||||
name: nginx
|
||||
ports:
|
||||
- containerPort: 80
|
||||
EOF
|
||||
```
|
||||
|
||||
<!--
|
||||
2. Apply the pod spec to the cluster in `example` namespace:
|
||||
-->
|
||||
1. 将 Pod 规约应用到集群中的 `example` 名字空间中:
|
||||
```shell
|
||||
kubectl apply -n example -f /tmp/pss/nginx-pod.yaml
|
||||
```
|
||||
<!-- The output is similar to this: -->
|
||||
输出类似于:
|
||||
```
|
||||
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "nginx" must set securityContext allowPrivilegeEscalation=false), unrestricted capabilities (container "nginx" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "nginx" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "nginx" must set securityContext seccompProfile.type to "RuntimeDefault" or "Localhost")
|
||||
pod/nginx created
|
||||
```
|
||||
|
||||
<!--
|
||||
1. Apply the pod spec to the cluster in `default` namespace:
|
||||
-->
|
||||
3. 将 Pod 规约应用到集群中的 `default` 名字空间中:
|
||||
|
||||
```shell
|
||||
kubectl apply -n default -f /tmp/pss/nginx-pod.yaml
|
||||
```
|
||||
|
||||
<!-- Output is similar to this: -->
|
||||
输出类似于:
|
||||
|
||||
```
|
||||
pod/nginx created
|
||||
```
|
||||
|
||||
<!--
|
||||
The Pod Security Standards were applied only to the `example`
|
||||
namespace. You could create the same Pod in the `default` namespace
|
||||
with no warnings.
|
||||
-->
|
||||
以上 Pod 安全标准仅被应用到 `example` 名字空间。
|
||||
你可以在没有警告的情况下在 `default` 名字空间中创建相同的 Pod。
|
||||
|
||||
<!--
|
||||
## Clean up
|
||||
|
||||
Run `kind delete cluster -name psa-ns-level` to delete the cluster created.
|
||||
-->
|
||||
## 清理 {#clean-up}
|
||||
|
||||
运行 `kind delete cluster -name psa-ns-level` 删除创建的集群。
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
- Run a
|
||||
[shell script](/examples/security/kind-with-namespace-level-baseline-pod-security.sh)
|
||||
to perform all the preceding steps all at once.
|
||||
|
||||
1. Create KinD cluster
|
||||
2. Create new namespace
|
||||
3. Apply `baseline` Pod Security Standard in `enforce` mode while applying
|
||||
`restricted` Pod Security Standard also in `warn` and `audit` mode.
|
||||
4. Create a new pod with the following pod security standards applied
|
||||
- [Pod Security Admission](/docs/concepts/security/pod-security-admission/)
|
||||
- [Pod Security Standards](/docs/concepts/security/pod-security-standards/)
|
||||
- [Apply Pod Security Standards at the cluster level](/docs/tutorials/security/cluster-level-pss/)
|
||||
-->
|
||||
- 运行一个 [shell 脚本](/examples/security/kind-with-namespace-level-baseline-pod-security.sh)
|
||||
一次执行所有前面的步骤。
|
||||
|
||||
1. 创建 KinD 集群
|
||||
2. 创建新的名字空间
|
||||
3. 在 `enforce` 模式下应用 `baseline` Pod 安全标准,
|
||||
同时在 `warn` 和 `audit` 模式下应用 `restricted` Pod 安全标准。
|
||||
4. 创建一个应用以下 Pod 安全标准的新 Pod
|
||||
|
||||
- [Pod 安全准入](/zh/docs/concepts/security/pod-security-admission/)
|
||||
- [Pod 安全标准](/zh/docs/concepts/security/pod-security-standards/)
|
||||
- [在集群级别应用 Pod 安全标准](/zh/docs/tutorials/security/cluster-level-pss/)
|
||||
@@ -0,0 +1,783 @@
|
||||
---
|
||||
title: 使用 seccomp 限制容器的系统调用
|
||||
content_type: tutorial
|
||||
weight: 20
|
||||
min-kubernetes-server-version: v1.22
|
||||
---
|
||||
<!--
|
||||
reviewers:
|
||||
- hasheddan
|
||||
- pjbgf
|
||||
- saschagrunert
|
||||
title: Restrict a Container's Syscalls with seccomp
|
||||
content_type: tutorial
|
||||
weight: 20
|
||||
min-kubernetes-server-version: v1.22
|
||||
-->
|
||||
|
||||
<!-- overview -->
|
||||
|
||||
{{< feature-state for_k8s_version="v1.19" state="stable" >}}
|
||||
|
||||
<!--
|
||||
Seccomp stands for secure computing mode and has been a feature of the Linux
|
||||
kernel since version 2.6.12. It can be used to sandbox the privileges of a
|
||||
process, restricting the calls it is able to make from userspace into the
|
||||
kernel. Kubernetes lets you automatically apply seccomp profiles loaded onto a
|
||||
{{< glossary_tooltip text="node" term_id="node" >}} to your Pods and containers.
|
||||
|
||||
Identifying the privileges required for your workloads can be difficult. In this
|
||||
tutorial, you will go through how to load seccomp profiles into a local
|
||||
Kubernetes cluster, how to apply them to a Pod, and how you can begin to craft
|
||||
profiles that give only the necessary privileges to your container processes.
|
||||
-->
|
||||
Seccomp 代表安全计算(Secure Computing)模式,自 2.6.12 版本以来,一直是 Linux 内核的一个特性。
|
||||
它可以用来沙箱化进程的权限,限制进程从用户态到内核态的调用。
|
||||
Kubernetes 能使你自动将加载到 {{< glossary_tooltip text="节点" term_id="node" >}}上的
|
||||
seccomp 配置文件应用到你的 Pod 和容器。
|
||||
|
||||
识别你的工作负载所需要的权限是很困难的。在本篇教程中,
|
||||
你将了解如何将 seccomp 配置文件加载到本地的 Kubernetes 集群中,
|
||||
如何将它们应用到 Pod,以及如何开始制作只为容器进程提供必要的权限的配置文件。
|
||||
|
||||
## {{% heading "objectives" %}}
|
||||
|
||||
<!--
|
||||
* Learn how to load seccomp profiles on a node
|
||||
* Learn how to apply a seccomp profile to a container
|
||||
* Observe auditing of syscalls made by a container process
|
||||
* Observe behavior when a missing profile is specified
|
||||
* Observe a violation of a seccomp profile
|
||||
* Learn how to create fine-grained seccomp profiles
|
||||
* Learn how to apply a container runtime default seccomp profile
|
||||
-->
|
||||
* 了解如何在节点上加载 seccomp 配置文件
|
||||
* 了解如何将 seccomp 配置文件应用到容器上
|
||||
* 观察容器进程对系统调用的审计
|
||||
* 观察指定的配置文件缺失时的行为
|
||||
* 观察违反 seccomp 配置文件的行为
|
||||
* 了解如何创建细粒度的 seccomp 配置文件
|
||||
* 了解如何应用容器运行时所默认的 seccomp 配置文件
|
||||
|
||||
## {{% heading "prerequisites" %}}
|
||||
|
||||
<!--
|
||||
In order to complete all steps in this tutorial, you must install
|
||||
[kind](/docs/tasks/tools/#kind) and [kubectl](/docs/tasks/tools/#kubectl).
|
||||
|
||||
This tutorial shows some examples that are still alpha (since v1.22) and
|
||||
others that use only generally available seccomp functionality. You should
|
||||
make sure that your cluster is
|
||||
[configured correctly](https://kind.sigs.k8s.io/docs/user/quick-start/#setting-kubernetes-version)
|
||||
for the version you are using.
|
||||
|
||||
The tutorial also uses the `curl` tool for downloading examples to your computer.
|
||||
You can adapt the steps to use a different tool if you prefer.
|
||||
-->
|
||||
为了完成本篇教程中的所有步骤,你必须安装 [kind](/zh/docs/tasks/tools/#kind)
|
||||
和 [kubectl](/zh/docs/tasks/tools/#kubectl)。
|
||||
|
||||
本篇教程演示的某些示例仍然是 alpha 状态(自 v1.22 起),另一些示例则仅使用 seccomp 正式发布的功能。
|
||||
你应该确保,针对你使用的版本,
|
||||
[正确配置](https://kind.sigs.k8s.io/docs/user/quick-start/#setting-kubernetes-version)了集群。
|
||||
|
||||
本篇教程也使用了 `curl` 工具来下载示例到你的计算机上。
|
||||
你可以使用其他自己偏好的工具来自适应这些步骤。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
It is not possible to apply a seccomp profile to a container running with
|
||||
`privileged: true` set in the container's `securityContext`. Privileged containers always
|
||||
run as `Unconfined`.
|
||||
-->
|
||||
无法将 seccomp 配置文件应用于在容器的 `securityContext` 中设置了 `privileged: true` 的容器。
|
||||
特权容器始终以 `Unconfined` 的方式运行。
|
||||
{{< /note >}}
|
||||
|
||||
<!-- steps -->
|
||||
|
||||
<!--
|
||||
## Download example seccomp profiles {#download-profiles}
|
||||
|
||||
The contents of these profiles will be explored later on, but for now go ahead
|
||||
and download them into a directory named `profiles/` so that they can be loaded
|
||||
into the cluster.
|
||||
-->
|
||||
## 下载示例 seccomp 配置文件 {#download-profiles}
|
||||
|
||||
这些配置文件的内容将在稍后进行分析,
|
||||
现在先将它们下载到名为 `profiles/` 的目录中,以便将它们加载到集群中。
|
||||
|
||||
{{< tabs name="tab_with_code" >}}
|
||||
{{{< tab name="audit.json" >}}
|
||||
{{< codenew file="pods/security/seccomp/profiles/audit.json" >}}
|
||||
{{< /tab >}}
|
||||
{{< tab name="violation.json" >}}
|
||||
{{< codenew file="pods/security/seccomp/profiles/violation.json" >}}
|
||||
{{< /tab >}}}
|
||||
{{< tab name="fine-grained.json" >}}
|
||||
{{< codenew file="pods/security/seccomp/profiles/fine-grained.json" >}}
|
||||
{{< /tab >}}}
|
||||
{{< /tabs >}}
|
||||
|
||||
<!-- Run these commands: -->
|
||||
执行这些命令:
|
||||
|
||||
```shell
|
||||
mkdir ./profiles
|
||||
curl -L -o profiles/audit.json https://k8s.io/examples/pods/security/seccomp/profiles/audit.json
|
||||
curl -L -o profiles/violation.json https://k8s.io/examples/pods/security/seccomp/profiles/violation.json
|
||||
curl -L -o profiles/fine-grained.json https://k8s.io/examples/pods/security/seccomp/profiles/fine-grained.json
|
||||
ls profiles
|
||||
```
|
||||
|
||||
<!-- You should see three profiles listed at the end of the final step: -->
|
||||
你应该看到在最后一步的末尾列出有三个配置文件:
|
||||
```
|
||||
audit.json fine-grained.json violation.json
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create a local Kubernetes cluster with kind
|
||||
|
||||
For simplicity, [kind](https://kind.sigs.k8s.io/) can be used to create a single
|
||||
node cluster with the seccomp profiles loaded. Kind runs Kubernetes in Docker,
|
||||
so each node of the cluster is a container. This allows for files
|
||||
to be mounted in the filesystem of each container similar to loading files
|
||||
onto a node.
|
||||
-->
|
||||
|
||||
## 使用 kind 创建本地 Kubernetes 集群 {#create-a-local-kubernetes-cluster-with-kind}
|
||||
|
||||
为简单起见,[kind](https://kind.sigs.k8s.io/) 可用来创建加载了 seccomp 配置文件的单节点集群。
|
||||
Kind 在 Docker 中运行 Kubernetes,因此集群的每个节点都是一个容器。
|
||||
这允许将文件挂载到每个容器的文件系统中,类似于将文件加载到节点上。
|
||||
|
||||
{{< codenew file="pods/security/seccomp/kind.yaml" >}}
|
||||
|
||||
<!--
|
||||
Download that example kind configuration, and save it to a file named `kind.yaml`:
|
||||
-->
|
||||
下载该示例 kind 配置,并将其保存到名为 `kind.yaml` 的文件中:
|
||||
```shell
|
||||
curl -L -O https://k8s.io/examples/pods/security/seccomp/kind.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
You can set a specific Kubernetes version by setting the node's container image.
|
||||
See [Nodes](https://kind.sigs.k8s.io/docs/user/configuration/#nodes) within the
|
||||
kind documentation about configuration for more details on this.
|
||||
This tutorial assumes you are using Kubernetes {{< param "version" >}}.
|
||||
-->
|
||||
你可以通过设置节点的容器镜像来设置特定的 Kubernetes 版本。
|
||||
有关此类配置的更多信息,
|
||||
参阅 kind 文档中[节点](https://kind.sigs.k8s.io/docs/user/configuration/#nodes)小节。
|
||||
本篇教程假定你正在使用 Kubernetes {{< param "version" >}}。
|
||||
|
||||
<!--
|
||||
As an alpha feature, you can configure Kubernetes to use the profile that the
|
||||
{{< glossary_tooltip text="container runtime" term_id="container-runtime" >}}
|
||||
prefers by default, rather than falling back to `Unconfined`.
|
||||
If you want to try that, see
|
||||
[enable the use of `RuntimeDefault` as the default seccomp profile for all workloads](#enable-the-use-of-runtimedefault-as-the-default-seccomp-profile-for-all-workloads)
|
||||
before you continue.
|
||||
-->
|
||||
作为 alpha 特性,你可以将 Kubernetes 配置为使用
|
||||
{{< glossary_tooltip text="容器运行时" term_id="container-runtime" >}}
|
||||
默认首选的配置文件,而不是回退到 `Unconfined`。
|
||||
如果你想尝试,请在继续之前参阅
|
||||
[启用使用 `RuntimeDefault` 作为所有工作负载的默认 seccomp 配置文件](#enable-runtimedefault-as-default)
|
||||
|
||||
<!--
|
||||
Once you have a kind configuration in place, create the kind cluster with
|
||||
that configuration:
|
||||
-->
|
||||
有了 kind 配置后,使用该配置创建 kind 集群:
|
||||
|
||||
```shell
|
||||
kind create cluster --config=kind.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
After the new Kubernetes cluster is ready, identify the Docker container running
|
||||
as the single node cluster:
|
||||
-->
|
||||
新的 Kubernetes 集群准备就绪后,找出作为单节点集群运行的 Docker 容器:
|
||||
|
||||
```shell
|
||||
docker ps
|
||||
```
|
||||
|
||||
<!--
|
||||
You should see output indicating that a container is running with name
|
||||
`kind-control-plane`. The output is similar to:
|
||||
-->
|
||||
你应该看到输出中名为 `kind-control-plane` 的容器正在运行。
|
||||
输出类似于:
|
||||
```
|
||||
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||
6a96207fed4b kindest/node:v1.18.2 "/usr/local/bin/entr…" 27 seconds ago Up 24 seconds 127.0.0.1:42223->6443/tcp kind-control-plane
|
||||
```
|
||||
|
||||
<!--
|
||||
If observing the filesystem of that container, you should see that the
|
||||
`profiles/` directory has been successfully loaded into the default seccomp path
|
||||
of the kubelet. Use `docker exec` to run a command in the Pod:
|
||||
-->
|
||||
如果观察该容器的文件系统,
|
||||
你应该会看到 `profiles/` 目录已成功加载到 kubelet 的默认 seccomp 路径中。
|
||||
使用 `docker exec` 在 Pod 中运行命令:
|
||||
|
||||
```shell
|
||||
# 将 6a96207fed4b 更改为你从 “docker ps” 看到的容器 ID
|
||||
docker exec -it 6a96207fed4b ls /var/lib/kubelet/seccomp/profiles
|
||||
```
|
||||
|
||||
```
|
||||
audit.json fine-grained.json violation.json
|
||||
```
|
||||
|
||||
<!--
|
||||
You have verified that these seccomp profiles are available to the kubelet
|
||||
running within kind.
|
||||
-->
|
||||
你已验证这些 seccomp 配置文件可用于在 kind 中运行的 kubelet。
|
||||
|
||||
<!--
|
||||
## Enable the use of `RuntimeDefault` as the default seccomp profile for all workloads
|
||||
-->
|
||||
## 启用使用 `RuntimeDefault` 作为所有工作负载的默认 seccomp 配置文件 {#enable-runtimedefault-as-default}
|
||||
|
||||
{{< feature-state state="alpha" for_k8s_version="v1.22" >}}
|
||||
|
||||
<!--
|
||||
`SeccompDefault` is an optional kubelet
|
||||
[feature gate](/docs/reference/command-line-tools-reference/feature-gates) as
|
||||
well as corresponding `--seccomp-default`
|
||||
[command line flag](/docs/reference/command-line-tools-reference/kubelet).
|
||||
Both have to be enabled simultaneously to use the feature.
|
||||
-->
|
||||
`SeccompDefault` 是一个可选的 kubelet [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates)
|
||||
以及相应的 `--seccomp-default` [命令行标志](/zh/docs/reference/command-line-tools-reference/kubelet)。
|
||||
两者必须同时启用才能使用该功能。
|
||||
|
||||
<!--
|
||||
If enabled, the kubelet will use the `RuntimeDefault` seccomp profile by default, which is
|
||||
defined by the container runtime, instead of using the `Unconfined` (seccomp disabled) mode.
|
||||
The default profiles aim to provide a strong set
|
||||
of security defaults while preserving the functionality of the workload. It is
|
||||
possible that the default profiles differ between container runtimes and their
|
||||
release versions, for example when comparing those from CRI-O and containerd.
|
||||
-->
|
||||
如果启用,kubelet 将会默认使用 `RuntimeDefault` seccomp 配置文件,
|
||||
(这一配置文明是由容器运行时定义的),而不是使用 `Unconfined`(禁用 seccomp)模式。
|
||||
默认的配置文件旨在提供一组限制性较强且能保留工作负载功能的安全默认值。
|
||||
不同容器运行时及其不同发布版本之间的默认配置文件可能有所不同,
|
||||
例如在比较来自 CRI-O 和 containerd 的配置文件时。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
Enabling the feature will neither change the Kubernetes
|
||||
`securityContext.seccompProfile` API field nor add the deprecated annotations of
|
||||
the workload. This provides users the possibility to rollback anytime without
|
||||
actually changing the workload configuration. Tools like
|
||||
[`crictl inspect`](https://github.com/kubernetes-sigs/cri-tools) can be used to
|
||||
verify which seccomp profile is being used by a container.
|
||||
-->
|
||||
启用该功能既不会更改 Kubernetes `securityContext.seccompProfile` API 字段,
|
||||
也不会添加已弃用的工作负载注解。
|
||||
这为用户提供了随时回滚的可能性,而且无需实际更改工作负载配置。
|
||||
[`crictl inspect`](https://github.com/kubernetes-sigs/cri-tools)
|
||||
之类的工具可用于验证容器正在使用哪个 seccomp 配置文件。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
Some workloads may require a lower amount of syscall restrictions than others.
|
||||
This means that they can fail during runtime even with the `RuntimeDefault`
|
||||
profile. To mitigate such a failure, you can:
|
||||
|
||||
- Run the workload explicitly as `Unconfined`.
|
||||
- Disable the `SeccompDefault` feature for the nodes. Also making sure that
|
||||
workloads get scheduled on nodes where the feature is disabled.
|
||||
- Create a custom seccomp profile for the workload.
|
||||
-->
|
||||
与其他工作负载相比,某些工作负载可能需要更少的系统调用限制。
|
||||
这意味着即使使用 `RuntimeDefault` 配置文件,它们也可能在运行时失败。
|
||||
要应对此类故障,你可以:
|
||||
|
||||
- 将工作负载显式运行为 `Unconfined`。
|
||||
- 禁用节点的 `SeccompDefault` 功能。还要确保工作负载被调度到禁用该功能的节点上。
|
||||
- 为工作负载创建自定义 seccomp 配置文件。
|
||||
|
||||
<!--
|
||||
If you were introducing this feature into production-like cluster, the Kubernetes project
|
||||
recommends that you enable this feature gate on a subset of your nodes and then
|
||||
test workload execution before rolling the change out cluster-wide.
|
||||
|
||||
More detailed information about a possible upgrade and downgrade strategy can be
|
||||
found in the [related Kubernetes Enhancement Proposal (KEP)](https://github.com/kubernetes/enhancements/tree/a70cc18/keps/sig-node/2413-seccomp-by-default#upgrade--downgrade-strategy).
|
||||
-->
|
||||
如果你将此功能引入到类似生产的集群中,
|
||||
Kubernetes 项目建议你在部分节点上启用此特性门控,
|
||||
然后在整个集群范围内推出更改之前,测试工作负载执行情况。
|
||||
|
||||
有关可能的升级和降级策略的更多详细信息,
|
||||
请参阅[相关的 Kubernetes 增强提案 (KEP)](https://github.com/kubernetes/enhancements/tree/a70cc18/keps/sig-node/2413-seccomp-by-default#upgrade--downgrade-strategy)。
|
||||
|
||||
<!--
|
||||
Since the feature is in alpha state it is disabled per default. To enable it,
|
||||
pass the flags `--feature-gates=SeccompDefault=true --seccomp-default` to the
|
||||
`kubelet` CLI or enable it via the [kubelet configuration
|
||||
file](/docs/tasks/administer-cluster/kubelet-config-file/). To enable the
|
||||
feature gate in [kind](https://kind.sigs.k8s.io), ensure that `kind` provides
|
||||
the minimum required Kubernetes version and enables the `SeccompDefault` feature
|
||||
[in the kind configuration](https://kind.sigs.k8s.io/docs/user/quick-start/#enable-feature-gates-in-your-cluster):
|
||||
-->
|
||||
由于此特性处于 alpha 阶段,默认是被禁用的。
|
||||
要启用它,传递标志 `--feature-gates=SeccompDefault=true --seccomp-default` 到
|
||||
kubelet CLI 或者通过 [kubelet 配置文件](/docs/tasks/administer-cluster/kubelet-config-file/)启用。
|
||||
要在 [kind](https://kind.sigs.k8s.io) 启用特性门控,
|
||||
请确保 `kind` 提供所需的最低 Kubernetes 版本,
|
||||
并[在 kind 配置中](https://kind.sigs.k8s.io/docs/user/quick-start/#enable-feature-gates-in-your-cluster)
|
||||
启用了 `SeccompDefault` 特性:
|
||||
|
||||
```yaml
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
featureGates:
|
||||
SeccompDefault: true
|
||||
nodes:
|
||||
- role: control-plane
|
||||
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: JoinConfiguration
|
||||
nodeRegistration:
|
||||
kubeletExtraArgs:
|
||||
seccomp-default: "true"
|
||||
- role: worker
|
||||
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: JoinConfiguration
|
||||
nodeRegistration:
|
||||
kubeletExtraArgs:
|
||||
feature-gates: SeccompDefault=true
|
||||
seccomp-default: "true"
|
||||
```
|
||||
|
||||
<!-- If the cluster is ready, then running a pod: -->
|
||||
如果集群已就绪,则运行一个 Pod:
|
||||
|
||||
```shell
|
||||
kubectl run --rm -it --restart=Never --image=alpine alpine -- sh
|
||||
```
|
||||
|
||||
<!--
|
||||
Should now have the default seccomp profile attached. This can be verified by
|
||||
using `docker exec` to run `crictl inspect` for the container on the kind
|
||||
worker:
|
||||
-->
|
||||
现在应该附加了默认的 seccomp 配置文件。
|
||||
这可以通过使用 `docker exec` 为 kind 上的容器运行 `crictl inspect` 来验证:
|
||||
|
||||
```shell
|
||||
docker exec -it kind-worker bash -c \
|
||||
'crictl inspect $(crictl ps --name=alpine -q) | jq .info.runtimeSpec.linux.seccomp'
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"defaultAction": "SCMP_ACT_ERRNO",
|
||||
"architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"],
|
||||
"syscalls": [
|
||||
{
|
||||
"names": ["..."]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create a Pod with a seccomp profile for syscall auditing
|
||||
|
||||
To start off, apply the `audit.json` profile, which will log all syscalls of the
|
||||
process, to a new Pod.
|
||||
|
||||
Here's a manifest for that Pod:
|
||||
-->
|
||||
## 使用 seccomp 配置文件创建 Pod 以进行系统调用审计 {#create-a-pod-with-a-seccomp-profile-for-syscall-auditing}
|
||||
|
||||
首先,将 `audit.json` 配置文件应用到新的 Pod 上,该配置文件将记录进程的所有系统调用。
|
||||
|
||||
这是该 Pod 的清单:
|
||||
|
||||
{{< codenew file="pods/security/seccomp/ga/audit-pod.yaml" >}}
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
The functional support for the already deprecated seccomp annotations
|
||||
`seccomp.security.alpha.kubernetes.io/pod` (for the whole pod) and
|
||||
`container.seccomp.security.alpha.kubernetes.io/[name]` (for a single container)
|
||||
is going to be removed with the release of Kubernetes v1.25. Please always use
|
||||
the native API fields in favor of the annotations.
|
||||
-->
|
||||
已弃用的 seccomp 注解 `seccomp.security.alpha.kubernetes.io/pod`(针对整个 Pod)和
|
||||
`container.seccomp.security.alpha.kubernetes.io/[name]`(针对单个容器)
|
||||
将随着 Kubernetes v1.25 的发布而被删除。
|
||||
请在可能的情况下使用原生 API 字段而不是注解。
|
||||
{{< /note >}}
|
||||
|
||||
<!-- Create the Pod in the cluster: -->
|
||||
在集群中创建 Pod:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/pods/security/seccomp/ga/audit-pod.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
This profile does not restrict any syscalls, so the Pod should start
|
||||
successfully.
|
||||
-->
|
||||
此配置文件不限制任何系统调用,因此 Pod 应该成功启动。
|
||||
|
||||
```shell
|
||||
kubectl get pod/audit-pod
|
||||
```
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
audit-pod 1/1 Running 0 30s
|
||||
```
|
||||
|
||||
<!--
|
||||
In order to be able to interact with this endpoint exposed by this
|
||||
container, create a NodePort {{< glossary_tooltip text="Services" term_id="service" >}}
|
||||
that allows access to the endpoint from inside the kind control plane container.
|
||||
-->
|
||||
为了能够与容器暴露的端点交互,
|
||||
创建一个 NodePort 类型的 {{< glossary_tooltip text="Service" term_id="service" >}},
|
||||
允许从 kind 控制平面容器内部访问端点。
|
||||
|
||||
```shell
|
||||
kubectl expose pod audit-pod --type NodePort --port 5678
|
||||
```
|
||||
|
||||
<!-- Check what port the Service has been assigned on the node. -->
|
||||
检查 Service 在节点上分配的端口。
|
||||
|
||||
```shell
|
||||
kubectl get service audit-pod
|
||||
```
|
||||
|
||||
<!-- The output is similar to: -->
|
||||
输出类似于:
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
audit-pod NodePort 10.111.36.142 <none> 5678:32373/TCP 72s
|
||||
```
|
||||
|
||||
<!--
|
||||
Now you can use `curl` to access that endpoint from inside the kind control plane container,
|
||||
at the port exposed by this Service. Use `docker exec` to run the `curl` command within the
|
||||
container belonging to that control plane container:
|
||||
-->
|
||||
现在,你可以使用 `curl` 从 kind 控制平面容器内部访问该端点,位于该服务所公开的端口上。
|
||||
使用 `docker exec` 在属于该控制平面容器的容器中运行 `curl` 命令:
|
||||
|
||||
```shell
|
||||
# 将 6a96207fed4b 更改为你从 “docker ps” 看到的控制平面容器 ID
|
||||
docker exec -it 6a96207fed4b curl localhost:32373
|
||||
```
|
||||
|
||||
```
|
||||
just made some syscalls!
|
||||
```
|
||||
|
||||
<!--
|
||||
You can see that the process is running, but what syscalls did it actually make?
|
||||
Because this Pod is running in a local cluster, you should be able to see those
|
||||
in `/var/log/syslog`. Open up a new terminal window and `tail` the output for
|
||||
calls from `http-echo`:
|
||||
-->
|
||||
你可以看到该进程正在运行,但它实际上进行了哪些系统调用?
|
||||
因为这个 Pod 在本地集群中运行,你应该能够在 `/var/log/syslog` 中看到它们。
|
||||
打开一个新的终端窗口并 `tail` 来自 `http-echo` 的调用的输出:
|
||||
|
||||
```shell
|
||||
tail -f /var/log/syslog | grep 'http-echo'
|
||||
```
|
||||
|
||||
<!--
|
||||
You should already see some logs of syscalls made by `http-echo`, and if you
|
||||
`curl` the endpoint in the control plane container you will see more written.
|
||||
|
||||
For example:
|
||||
-->
|
||||
你应该已经看到了一些由 `http-echo` 进行的系统调用的日志,
|
||||
如果你在控制平面容器中 `curl` 端点,你会看到更多的写入。
|
||||
|
||||
例如:
|
||||
```
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669452] audit: type=1326 audit(1594067860.484:14536): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=51 compat=0 ip=0x46fe1f code=0x7ffc0000
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669453] audit: type=1326 audit(1594067860.484:14537): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=54 compat=0 ip=0x46fdba code=0x7ffc0000
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669455] audit: type=1326 audit(1594067860.484:14538): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=202 compat=0 ip=0x455e53 code=0x7ffc0000
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669456] audit: type=1326 audit(1594067860.484:14539): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=288 compat=0 ip=0x46fdba code=0x7ffc0000
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669517] audit: type=1326 audit(1594067860.484:14540): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=0 compat=0 ip=0x46fd44 code=0x7ffc0000
|
||||
Jul 6 15:37:40 my-machine kernel: [369128.669519] audit: type=1326 audit(1594067860.484:14541): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=270 compat=0 ip=0x4559b1 code=0x7ffc0000
|
||||
Jul 6 15:38:40 my-machine kernel: [369188.671648] audit: type=1326 audit(1594067920.488:14559): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=270 compat=0 ip=0x4559b1 code=0x7ffc0000
|
||||
Jul 6 15:38:40 my-machine kernel: [369188.671726] audit: type=1326 audit(1594067920.488:14560): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=29064 comm="http-echo" exe="/http-echo" sig=0 arch=c000003e syscall=202 compat=0 ip=0x455e53 code=0x7ffc0000
|
||||
```
|
||||
|
||||
<!--
|
||||
You can begin to understand the syscalls required by the `http-echo` process by
|
||||
looking at the `syscall=` entry on each line. While these are unlikely to
|
||||
encompass all syscalls it uses, it can serve as a basis for a seccomp profile
|
||||
for this container.
|
||||
|
||||
Clean up that Pod and Service before moving to the next section:
|
||||
-->
|
||||
通过查看每一行的 `syscall=` 条目,你可以开始了解 `http-echo` 进程所需的系统调用。
|
||||
虽然这些不太可能包含它使用的所有系统调用,但它可以作为此容器的 seccomp 配置文件的基础。
|
||||
|
||||
在转到下一部分之前清理该 Pod 和 Service:
|
||||
|
||||
```shell
|
||||
kubectl delete service audit-pod --wait
|
||||
kubectl delete pod audit-pod --wait --now
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create Pod with seccomp profile that causes violation
|
||||
|
||||
For demonstration, apply a profile to the Pod that does not allow for any
|
||||
syscalls.
|
||||
|
||||
The manifest for this demonstration is:
|
||||
-->
|
||||
## 使用导致违规的 seccomp 配置文件创建 Pod {#create-pod-with-seccomp-profile-that-causes-violation}
|
||||
|
||||
出于演示目的,将配置文件应用于不允许任何系统调用的 Pod 上。
|
||||
|
||||
此演示的清单是:
|
||||
|
||||
{{< codenew file="pods/security/seccomp/ga/violation-pod.yaml" >}}
|
||||
|
||||
<!-- Attempt to create the Pod in the cluster: -->
|
||||
尝试在集群中创建 Pod:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/pods/security/seccomp/ga/violation-pod.yaml
|
||||
```
|
||||
|
||||
<!--
|
||||
The Pod creates, but there is an issue.
|
||||
If you check the status of the Pod, you should see that it failed to start.
|
||||
-->
|
||||
Pod 创建,但存在问题。
|
||||
如果你检查 Pod 状态,你应该看到它没有启动。
|
||||
|
||||
```shell
|
||||
kubectl get pod/violation-pod
|
||||
```
|
||||
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
violation-pod 0/1 CrashLoopBackOff 1 6s
|
||||
```
|
||||
|
||||
<!--
|
||||
As seen in the previous example, the `http-echo` process requires quite a few
|
||||
syscalls. Here seccomp has been instructed to error on any syscall by setting
|
||||
`"defaultAction": "SCMP_ACT_ERRNO"`. This is extremely secure, but removes the
|
||||
ability to do anything meaningful. What you really want is to give workloads
|
||||
only the privileges they need.
|
||||
|
||||
Clean up that Pod before moving to the next section:
|
||||
-->
|
||||
如上例所示,`http-echo` 进程需要相当多的系统调用。
|
||||
这里 seccomp 已通过设置 `"defaultAction": "SCMP_ACT_ERRNO"` 被指示为在发生任何系统调用时报错。
|
||||
这是非常安全的,但消除了做任何有意义的事情的能力。
|
||||
你真正想要的是只给工作负载它们所需要的权限。
|
||||
|
||||
在转到下一部分之前清理该 Pod:
|
||||
|
||||
```shell
|
||||
kubectl delete pod violation-pod --wait --now
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create Pod with seccomp profile that only allows necessary syscalls
|
||||
|
||||
If you take a look at the `fine-grained.json` profile, you will notice some of the syscalls
|
||||
seen in syslog of the first example where the profile set `"defaultAction":
|
||||
"SCMP_ACT_LOG"`. Now the profile is setting `"defaultAction": "SCMP_ACT_ERRNO"`,
|
||||
but explicitly allowing a set of syscalls in the `"action": "SCMP_ACT_ALLOW"`
|
||||
block. Ideally, the container will run successfully and you will see no messages
|
||||
sent to `syslog`.
|
||||
|
||||
The manifest for this example is:
|
||||
-->
|
||||
## 使用只允许必要的系统调用的 seccomp 配置文件创建 Pod {#create-pod-with-seccomp-profile-that-only-allows-necessary-syscalls}
|
||||
|
||||
如果你看一看 `fine-grained.json` 配置文件,
|
||||
你会注意到第一个示例的 syslog 中看到的一些系统调用,
|
||||
其中配置文件设置为 `"defaultAction": "SCMP_ACT_LOG"`。
|
||||
现在的配置文件设置 `"defaultAction": "SCMP_ACT_ERRNO"`,
|
||||
但在 `"action": "SCMP_ACT_ALLOW"` 块中明确允许一组系统调用。
|
||||
理想情况下,容器将成功运行,并且你看到没有消息发送到 `syslog`。
|
||||
|
||||
此示例的清单是:
|
||||
|
||||
{{< codenew file="pods/security/seccomp/ga/fine-pod.yaml" >}}
|
||||
|
||||
<!-- Create the Pod in your cluster: -->
|
||||
在你的集群中创建 Pod:
|
||||
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/pods/security/seccomp/ga/fine-pod.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get pod fine-pod
|
||||
```
|
||||
|
||||
<!-- The Pod should be showing as having started successfully: -->
|
||||
此 Pod 应该显示为已成功启动:
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
fine-pod 1/1 Running 0 30s
|
||||
```
|
||||
|
||||
<!--
|
||||
Open up a new terminal window and use `tail` to monitor for log entries that
|
||||
mention calls from `http-echo`:
|
||||
-->
|
||||
打开一个新的终端窗口并使用 `tail` 来监视提到来自 `http-echo` 的调用的日志条目:
|
||||
|
||||
```shell
|
||||
# 你计算机上的日志路径可能与 “/var/log/syslog” 不同
|
||||
tail -f /var/log/syslog | grep 'http-echo'
|
||||
```
|
||||
|
||||
<!-- Next, expose the Pod with a NodePort Service: -->
|
||||
接着,使用 NodePort Service 公开 Pod:
|
||||
|
||||
```shell
|
||||
kubectl expose pod fine-pod --type NodePort --port 5678
|
||||
```
|
||||
|
||||
<!-- Check what port the Service has been assigned on the node: -->
|
||||
检查节点上的 Service 分配了什么端口:
|
||||
|
||||
```shell
|
||||
kubectl get service fine-pod
|
||||
```
|
||||
|
||||
<!-- The output is similar to: -->
|
||||
输出类似于:
|
||||
```
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
fine-pod NodePort 10.111.36.142 <none> 5678:32373/TCP 72s
|
||||
```
|
||||
|
||||
<!-- Use `curl` to access that endpoint from inside the kind control plane container: -->
|
||||
使用 `curl` 从 kind 控制平面容器内部访问端点:
|
||||
|
||||
```shell
|
||||
# 将 6a96207fed4b 更改为你从 “docker ps” 看到的控制平面容器 ID
|
||||
docker exec -it 6a96207fed4b curl localhost:32373
|
||||
```
|
||||
|
||||
```
|
||||
just made some syscalls!
|
||||
```
|
||||
|
||||
<!--
|
||||
You should see no output in the `syslog`. This is because the profile allowed all
|
||||
necessary syscalls and specified that an error should occur if one outside of
|
||||
the list is invoked. This is an ideal situation from a security perspective, but
|
||||
required some effort in analyzing the program. It would be nice if there was a
|
||||
simple way to get closer to this security without requiring as much effort.
|
||||
|
||||
Clean up that Pod and Service before moving to the next section:
|
||||
-->
|
||||
你应该在 `syslog` 中看不到任何输出。
|
||||
这是因为配置文件允许所有必要的系统调用,并指定如果调用列表之外的系统调用应发生错误。
|
||||
从安全角度来看,这是一种理想的情况,但需要在分析程序时付出一些努力。
|
||||
如果有一种简单的方法可以在不需要太多努力的情况下更接近这种安全性,那就太好了。
|
||||
|
||||
在转到下一部分之前清理该 Pod 和服务:
|
||||
|
||||
```shell
|
||||
kubectl delete service fine-pod --wait
|
||||
kubectl delete pod fine-pod --wait --now
|
||||
```
|
||||
|
||||
<!--
|
||||
## Create Pod that uses the container runtime default seccomp profile
|
||||
|
||||
Most container runtimes provide a sane set of default syscalls that are allowed
|
||||
or not. You can adopt these defaults for your workload by setting the seccomp
|
||||
type in the security context of a pod or container to `RuntimeDefault`.
|
||||
-->
|
||||
## 创建使用容器运行时默认 seccomp 配置文件的 Pod {#create-pod-that-uses-the-container-runtime-default-seccomp-profile}
|
||||
|
||||
大多数容器运行时都提供了一组合理的默认系统调用,以及是否允许执行这些系统调用。
|
||||
你可以通过将 Pod 或容器的安全上下文中的 seccomp 类型设置为 `RuntimeDefault`
|
||||
来为你的工作负载采用这些默认值。
|
||||
|
||||
{{< note >}}
|
||||
<!--
|
||||
If you have the `SeccompDefault` [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) enabled, then Pods use the `RuntimeDefault` seccomp profile whenever
|
||||
no other seccomp profile is specified. Otherwise, the default is `Unconfined`.
|
||||
-->
|
||||
如果你已经启用了 `SeccompDefault` [特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/),
|
||||
只要没有指定其他 seccomp 配置文件,那么 Pod 就会使用 `SeccompDefault` 的 seccomp 配置文件。
|
||||
否则,默认值为 `Unconfined`。
|
||||
{{< /note >}}
|
||||
|
||||
<!--
|
||||
Here's a manifest for a Pod that requests the `RuntimeDefault` seccomp profile
|
||||
for all its containers:
|
||||
-->
|
||||
这是一个 Pod 的清单,它要求其所有容器使用 `RuntimeDefault` seccomp 配置文件:
|
||||
|
||||
{{< codenew file="pods/security/seccomp/ga/default-pod.yaml" >}}
|
||||
|
||||
<!-- Create that Pod: -->
|
||||
创建此 Pod:
|
||||
```shell
|
||||
kubectl apply -f https://k8s.io/examples/pods/security/seccomp/ga/default-pod.yaml
|
||||
```
|
||||
|
||||
```shell
|
||||
kubectl get pod default-pod
|
||||
```
|
||||
|
||||
<!-- The Pod should be showing as having started successfully: -->
|
||||
此 Pod 应该显示为成功启动:
|
||||
```
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
default-pod 1/1 Running 0 20s
|
||||
```
|
||||
|
||||
<!-- Finally, now that you saw that work OK, clean up: -->
|
||||
最后,你看到一切正常之后,请清理:
|
||||
|
||||
```shell
|
||||
kubectl delete pod default-pod --wait --now
|
||||
```
|
||||
|
||||
## {{% heading "whatsnext" %}}
|
||||
|
||||
<!--
|
||||
You can learn more about Linux seccomp:
|
||||
|
||||
* [A seccomp Overview](https://lwn.net/Articles/656307/)
|
||||
* [Seccomp Security Profiles for Docker](https://docs.docker.com/engine/security/seccomp/)
|
||||
-->
|
||||
你可以了解有关 Linux seccomp 的更多信息:
|
||||
|
||||
* [seccomp 概述](https://lwn.net/Articles/656307/)
|
||||
* [Docker 的 Seccomp 安全配置文件](https://docs.docker.com/engine/security/seccomp/)
|
||||
Reference in New Issue
Block a user