Skip to content

Commit 2692867

Browse files
authored
Merge pull request #41962 from mrgiles/31536_seccomp_tutorial_add_prereqs
Add docker prereq, mention podman and rearrange sections
2 parents f0f9b32 + ee171ac commit 2692867

File tree

1 file changed

+127
-119
lines changed

1 file changed

+127
-119
lines changed

content/en/docs/tutorials/security/seccomp.md

Lines changed: 127 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ profiles that give only the necessary privileges to your container processes.
3939
In order to complete all steps in this tutorial, you must install
4040
[kind](/docs/tasks/tools/#kind) and [kubectl](/docs/tasks/tools/#kubectl).
4141

42+
The commands used in the tutorial assume that you are using
43+
[Docker](https://www.docker.com/) as your container runtime. (The cluster that `kind` creates may
44+
use a different container runtime internally). You could also use
45+
[Podman](https://podman.io/) but in that case, you would have to follow specific
46+
[instructions](https://kind.sigs.k8s.io/docs/user/rootless/) in order to complete the tasks
47+
successfully.
48+
4249
This tutorial shows some examples that are still beta (since v1.25) and
4350
others that use only generally available seccomp functionality. You should
4451
make sure that your cluster is
@@ -154,111 +161,7 @@ audit.json fine-grained.json violation.json
154161
You have verified that these seccomp profiles are available to the kubelet
155162
running within kind.
156163

157-
## Enable the use of `RuntimeDefault` as the default seccomp profile for all workloads
158-
159-
{{< feature-state state="stable" for_k8s_version="v1.27" >}}
160-
161-
To use seccomp profile defaulting, you must run the kubelet with the
162-
`--seccomp-default`
163-
[command line flag](/docs/reference/command-line-tools-reference/kubelet)
164-
enabled for each node where you want to use it.
165-
166-
If enabled, the kubelet will use the `RuntimeDefault` seccomp profile by default, which is
167-
defined by the container runtime, instead of using the `Unconfined` (seccomp disabled) mode.
168-
The default profiles aim to provide a strong set
169-
of security defaults while preserving the functionality of the workload. It is
170-
possible that the default profiles differ between container runtimes and their
171-
release versions, for example when comparing those from CRI-O and containerd.
172-
173-
{{< note >}}
174-
Enabling the feature will neither change the Kubernetes
175-
`securityContext.seccompProfile` API field nor add the deprecated annotations of
176-
the workload. This provides users the possibility to rollback anytime without
177-
actually changing the workload configuration. Tools like
178-
[`crictl inspect`](https://github.com/kubernetes-sigs/cri-tools) can be used to
179-
verify which seccomp profile is being used by a container.
180-
{{< /note >}}
181-
182-
Some workloads may require a lower amount of syscall restrictions than others.
183-
This means that they can fail during runtime even with the `RuntimeDefault`
184-
profile. To mitigate such a failure, you can:
185-
186-
- Run the workload explicitly as `Unconfined`.
187-
- Disable the `SeccompDefault` feature for the nodes. Also making sure that
188-
workloads get scheduled on nodes where the feature is disabled.
189-
- Create a custom seccomp profile for the workload.
190-
191-
If you were introducing this feature into production-like cluster, the Kubernetes project
192-
recommends that you enable this feature gate on a subset of your nodes and then
193-
test workload execution before rolling the change out cluster-wide.
194-
195-
You can find more detailed information about a possible upgrade and downgrade strategy
196-
in the related Kubernetes Enhancement Proposal (KEP):
197-
[Enable seccomp by default](https://github.com/kubernetes/enhancements/tree/9a124fd29d1f9ddf2ff455c49a630e3181992c25/keps/sig-node/2413-seccomp-by-default#upgrade--downgrade-strategy).
198-
199-
Kubernetes {{< skew currentVersion >}} lets you configure the seccomp profile
200-
that applies when the spec for a Pod doesn't define a specific seccomp profile.
201-
However, you still need to enable this defaulting for each node where you would
202-
like to use it.
203-
204-
If you are running a Kubernetes {{< skew currentVersion >}} cluster and want to
205-
enable the feature, either run the kubelet with the `--seccomp-default` command
206-
line flag, or enable it through the [kubelet configuration
207-
file](/docs/tasks/administer-cluster/kubelet-config-file/). To enable the
208-
feature gate in [kind](https://kind.sigs.k8s.io), ensure that `kind` provides
209-
the minimum required Kubernetes version and enables the `SeccompDefault` feature
210-
[in the kind configuration](https://kind.sigs.k8s.io/docs/user/quick-start/#enable-feature-gates-in-your-cluster):
211-
212-
```yaml
213-
kind: Cluster
214-
apiVersion: kind.x-k8s.io/v1alpha4
215-
nodes:
216-
- role: control-plane
217-
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
218-
kubeadmConfigPatches:
219-
- |
220-
kind: JoinConfiguration
221-
nodeRegistration:
222-
kubeletExtraArgs:
223-
seccomp-default: "true"
224-
- role: worker
225-
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
226-
kubeadmConfigPatches:
227-
- |
228-
kind: JoinConfiguration
229-
nodeRegistration:
230-
kubeletExtraArgs:
231-
seccomp-default: "true"
232-
```
233-
234-
If the cluster is ready, then running a pod:
235-
236-
```shell
237-
kubectl run --rm -it --restart=Never --image=alpine alpine -- sh
238-
```
239-
240-
Should now have the default seccomp profile attached. This can be verified by
241-
using `docker exec` to run `crictl inspect` for the container on the kind
242-
worker:
243-
244-
```shell
245-
docker exec -it kind-worker bash -c \
246-
'crictl inspect $(crictl ps --name=alpine -q) | jq .info.runtimeSpec.linux.seccomp'
247-
```
248-
249-
```json
250-
{
251-
"defaultAction": "SCMP_ACT_ERRNO",
252-
"architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"],
253-
"syscalls": [
254-
{
255-
"names": ["..."]
256-
}
257-
]
258-
}
259-
```
260-
261-
## Create Pod that uses the container runtime default seccomp profile
164+
## Create a Pod that uses the container runtime default seccomp profile
262165

263166
Most container runtimes provide a sane set of default syscalls that are allowed
264167
or not. You can adopt these defaults for your workload by setting the seccomp
@@ -290,7 +193,7 @@ NAME READY STATUS RESTARTS AGE
290193
default-pod 1/1 Running 0 20s
291194
```
292195

293-
Finally, now that you saw that work OK, clean up:
196+
Delete the Pod before moving to the next section:
294197

295198
```shell
296199
kubectl delete pod default-pod --wait --now
@@ -323,7 +226,7 @@ This profile does not restrict any syscalls, so the Pod should start
323226
successfully.
324227

325228
```shell
326-
kubectl get pod/audit-pod
229+
kubectl get pod audit-pod
327230
```
328231

329232
```
@@ -332,7 +235,7 @@ audit-pod 1/1 Running 0 30s
332235
```
333236

334237
In order to be able to interact with this endpoint exposed by this
335-
container, create a NodePort {{< glossary_tooltip text="Services" term_id="service" >}}
238+
container, create a NodePort {{< glossary_tooltip text="Service" term_id="service" >}}
336239
that allows access to the endpoint from inside the kind control plane container.
337240

338241
```shell
@@ -356,7 +259,7 @@ at the port exposed by this Service. Use `docker exec` to run the `curl` command
356259
container belonging to that control plane container:
357260

358261
```shell
359-
# Change 6a96207fed4b to the control plane container ID you saw from "docker ps"
262+
# Change 6a96207fed4b to the control plane container ID and 32373 to the port number you saw from "docker ps"
360263
docker exec -it 6a96207fed4b curl localhost:32373
361264
```
362265

@@ -366,15 +269,16 @@ just made some syscalls!
366269

367270
You can see that the process is running, but what syscalls did it actually make?
368271
Because this Pod is running in a local cluster, you should be able to see those
369-
in `/var/log/syslog`. Open up a new terminal window and `tail` the output for
272+
in `/var/log/syslog` on your local system. Open up a new terminal window and `tail` the output for
370273
calls from `http-echo`:
371274

372275
```shell
276+
# The log path on your computer might be different from "/var/log/syslog"
373277
tail -f /var/log/syslog | grep 'http-echo'
374278
```
375279

376-
You should already see some logs of syscalls made by `http-echo`, and if you
377-
`curl` the endpoint in the control plane container you will see more written.
280+
You should already see some logs of syscalls made by `http-echo`, and if you run `curl` again inside
281+
the control plane container you will see more output written to the log.
378282

379283
For example:
380284
```
@@ -393,14 +297,14 @@ looking at the `syscall=` entry on each line. While these are unlikely to
393297
encompass all syscalls it uses, it can serve as a basis for a seccomp profile
394298
for this container.
395299

396-
Clean up that Pod and Service before moving to the next section:
300+
Delete the Service and the Pod before moving to the next section:
397301

398302
```shell
399303
kubectl delete service audit-pod --wait
400304
kubectl delete pod audit-pod --wait --now
401305
```
402306

403-
## Create Pod with a seccomp profile that causes violation
307+
## Create a Pod with a seccomp profile that causes violation
404308

405309
For demonstration, apply a profile to the Pod that does not allow for any
406310
syscalls.
@@ -419,7 +323,7 @@ The Pod creates, but there is an issue.
419323
If you check the status of the Pod, you should see that it failed to start.
420324

421325
```shell
422-
kubectl get pod/violation-pod
326+
kubectl get pod violation-pod
423327
```
424328

425329
```
@@ -433,13 +337,13 @@ syscalls. Here seccomp has been instructed to error on any syscall by setting
433337
ability to do anything meaningful. What you really want is to give workloads
434338
only the privileges they need.
435339

436-
Clean up that Pod before moving to the next section:
340+
Delete the Pod before moving to the next section:
437341

438342
```shell
439343
kubectl delete pod violation-pod --wait --now
440344
```
441345

442-
## Create Pod with a seccomp profile that only allows necessary syscalls
346+
## Create a Pod with a seccomp profile that only allows necessary syscalls
443347

444348
If you take a look at the `fine-grained.json` profile, you will notice some of the syscalls
445349
seen in syslog of the first example where the profile set `"defaultAction":
@@ -497,7 +401,7 @@ fine-pod NodePort 10.111.36.142 <none> 5678:32373/TCP 72s
497401
Use `curl` to access that endpoint from inside the kind control plane container:
498402

499403
```shell
500-
# Change 6a96207fed4b to the control plane container ID you saw from "docker ps"
404+
# Change 6a96207fed4b to the control plane container ID and 32373 to the port number you saw from "docker ps"
501405
docker exec -it 6a96207fed4b curl localhost:32373
502406
```
503407

@@ -511,13 +415,117 @@ the list is invoked. This is an ideal situation from a security perspective, but
511415
required some effort in analyzing the program. It would be nice if there was a
512416
simple way to get closer to this security without requiring as much effort.
513417

514-
Clean up that Pod and Service before moving to the next section:
418+
Delete the Service and the Pod before moving to the next section:
515419

516420
```shell
517421
kubectl delete service fine-pod --wait
518422
kubectl delete pod fine-pod --wait --now
519423
```
520424

425+
## Enable the use of `RuntimeDefault` as the default seccomp profile for all workloads
426+
427+
{{< feature-state state="stable" for_k8s_version="v1.27" >}}
428+
429+
To use seccomp profile defaulting, you must run the kubelet with the
430+
`--seccomp-default`
431+
[command line flag](/docs/reference/command-line-tools-reference/kubelet)
432+
enabled for each node where you want to use it.
433+
434+
If enabled, the kubelet will use the `RuntimeDefault` seccomp profile by default, which is
435+
defined by the container runtime, instead of using the `Unconfined` (seccomp disabled) mode.
436+
The default profiles aim to provide a strong set
437+
of security defaults while preserving the functionality of the workload. It is
438+
possible that the default profiles differ between container runtimes and their
439+
release versions, for example when comparing those from CRI-O and containerd.
440+
441+
{{< note >}}
442+
Enabling the feature will neither change the Kubernetes
443+
`securityContext.seccompProfile` API field nor add the deprecated annotations of
444+
the workload. This provides users the possibility to rollback anytime without
445+
actually changing the workload configuration. Tools like
446+
[`crictl inspect`](https://github.com/kubernetes-sigs/cri-tools) can be used to
447+
verify which seccomp profile is being used by a container.
448+
{{< /note >}}
449+
450+
Some workloads may require a lower amount of syscall restrictions than others.
451+
This means that they can fail during runtime even with the `RuntimeDefault`
452+
profile. To mitigate such a failure, you can:
453+
454+
- Run the workload explicitly as `Unconfined`.
455+
- Disable the `SeccompDefault` feature for the nodes. Also making sure that
456+
workloads get scheduled on nodes where the feature is disabled.
457+
- Create a custom seccomp profile for the workload.
458+
459+
If you were introducing this feature into production-like cluster, the Kubernetes project
460+
recommends that you enable this feature gate on a subset of your nodes and then
461+
test workload execution before rolling the change out cluster-wide.
462+
463+
You can find more detailed information about a possible upgrade and downgrade strategy
464+
in the related Kubernetes Enhancement Proposal (KEP):
465+
[Enable seccomp by default](https://github.com/kubernetes/enhancements/tree/9a124fd29d1f9ddf2ff455c49a630e3181992c25/keps/sig-node/2413-seccomp-by-default#upgrade--downgrade-strategy).
466+
467+
Kubernetes {{< skew currentVersion >}} lets you configure the seccomp profile
468+
that applies when the spec for a Pod doesn't define a specific seccomp profile.
469+
However, you still need to enable this defaulting for each node where you would
470+
like to use it.
471+
472+
If you are running a Kubernetes {{< skew currentVersion >}} cluster and want to
473+
enable the feature, either run the kubelet with the `--seccomp-default` command
474+
line flag, or enable it through the [kubelet configuration
475+
file](/docs/tasks/administer-cluster/kubelet-config-file/). To enable the
476+
feature gate in [kind](https://kind.sigs.k8s.io), ensure that `kind` provides
477+
the minimum required Kubernetes version and enables the `SeccompDefault` feature
478+
[in the kind configuration](https://kind.sigs.k8s.io/docs/user/quick-start/#enable-feature-gates-in-your-cluster):
479+
480+
```yaml
481+
kind: Cluster
482+
apiVersion: kind.x-k8s.io/v1alpha4
483+
nodes:
484+
- role: control-plane
485+
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
486+
kubeadmConfigPatches:
487+
- |
488+
kind: JoinConfiguration
489+
nodeRegistration:
490+
kubeletExtraArgs:
491+
seccomp-default: "true"
492+
- role: worker
493+
image: kindest/node:v1.23.0@sha256:49824ab1727c04e56a21a5d8372a402fcd32ea51ac96a2706a12af38934f81ac
494+
kubeadmConfigPatches:
495+
- |
496+
kind: JoinConfiguration
497+
nodeRegistration:
498+
kubeletExtraArgs:
499+
seccomp-default: "true"
500+
```
501+
502+
If the cluster is ready, then running a pod:
503+
504+
```shell
505+
kubectl run --rm -it --restart=Never --image=alpine alpine -- sh
506+
```
507+
508+
Should now have the default seccomp profile attached. This can be verified by
509+
using `docker exec` to run `crictl inspect` for the container on the kind
510+
worker:
511+
512+
```shell
513+
docker exec -it kind-worker bash -c \
514+
'crictl inspect $(crictl ps --name=alpine -q) | jq .info.runtimeSpec.linux.seccomp'
515+
```
516+
517+
```json
518+
{
519+
"defaultAction": "SCMP_ACT_ERRNO",
520+
"architectures": ["SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32"],
521+
"syscalls": [
522+
{
523+
"names": ["..."]
524+
}
525+
]
526+
}
527+
```
528+
521529
## {{% heading "whatsnext" %}}
522530

523531
You can learn more about Linux seccomp:

0 commit comments

Comments
 (0)