KubernetesLXIII · Linux Security Controls in KubernetesLinux security controls
SELinux — kernel-enforced confinement on RHEL-based nodes
What you'll learn
- Explain what SELinux is and how it differs from AppArmor
- Configure SELinux options in a Pod (`seLinuxOptions`)
- Understand the MCS labels and how they isolate containers
- Recognise the production failure modes (permissive mode, missing labels)
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
SELinux is the Linux Security Module on RHEL-based
distributions (RHEL, CentOS, Rocky, Fedora). It is
more configurable and more strict than AppArmor but
also more complex to operate. Kubernetes integrates
SELinux via the securityContext.seLinuxOptions
field, and the default MCS label isolates containers
from each other. This lesson covers SELinux, the
configuration, and the production patterns.
How SELinux differs from AppArmor
| Aspect | AppArmor | SELinux |
|---|---|---|
| Distribution | Ubuntu, Debian | RHEL, CentOS, Rocky |
| Path-based | Yes | No (label-based) |
| Configuration | Plain text profiles | Policies (modules) |
| Default label | None | System default |
| Isolation | Process-based | MCS label per container |
SELinux uses labels (user, role, type, level) instead of file paths. Every file, process, and network socket has a label; SELinux enforces access based on the labels.
The SELinux modes
SELinux has three modes:
- Enforcing — violations are denied.
- Permissive — violations are logged but allowed. Useful for debugging.
- Disabled — SELinux is off. A Critical security finding.
A production cluster must run in enforcing mode.
permissive is for debugging only.
# Check the mode
getenforce
# Enforcing
Multi-Category Security (MCS)
MCS is the SELinux mechanism for isolating containers
from each other. Each container gets a unique MCS
label (a pair of categories, e.g., s0:c1,c2). Two
containers can only communicate if their MCS labels
overlap.
flowchart LR
A[Container A] -->|MCS: s0:c1,c2| B[File]
C[Container B] -->|MCS: s0:c3,c4| D[File]
B -.denied.-> C
D -.denied.-> A
By default, the kubelet assigns each container a unique MCS label; the containers cannot read each other’s files. To allow communication, the labels must be set explicitly.
The seLinuxOptions field
A Pod can specify SELinux options:
apiVersion: v1
kind: Pod
metadata:
name: api
spec:
securityContext:
seLinuxOptions:
level: "s0:c1,c2"
role: "system_r"
type: "container_t"
user: "system_u"
containers:
- name: api
image: myapp:v1.0
The fields:
user— the SELinux user (typicallysystem_u).role— the SELinux role (typicallysystem_r).type— the SELinux type (typicallycontainer_tfor containers).level— the MCS level (a sensitivity + categories, e.g.,s0:c1,c2).
A Pod without seLinuxOptions gets the kubelet’s
default label, which is unique per container.
PSS restricted and SELinux
PSS restricted does not require SELinux options.
It allows the kubelet’s default label. The
baseline profile allows custom SELinux options.
A workload that needs to share files with another workload sets the same MCS level:
spec:
securityContext:
seLinuxOptions:
level: "s0:c1,c2"
Both workloads have the same level and can read each
other’s files. A workload with a different level
(s0:c3,c4) cannot.
Common failure modes
- SELinux is in permissive mode. Violations are
logged but allowed. The fix is to set the mode to
enforcing. - SELinux is disabled. The kernel’s LSM is off. The fix is to re-enable SELinux (requires a reboot).
- MCS mismatch. Two workloads that need to share files have different MCS levels. The fix is to set the same level on both.
- Wrong SELinux type. A workload’s type is not
container_t. The fix is to set the type tocontainer_t.
Production patterns
- SELinux in enforcing mode. The default for RHEL-based clusters.
- Default MCS per container. The kubelet’s default isolation is sufficient for most workloads.
- Custom MCS for shared-file workloads. Two workloads that share a volume have the same MCS level.
- Audit SELinux status.
getenforcereturnsEnforcing;Disabledis a Critical finding.
Cross-course references
- The Linux course covers SELinux in detail, including policy modules.
- The Observability course covers the audit log
entries for SELinux violations (in
permissivemode).
Quiz
Knowledge check · 4 questions
Q1. What does the SELinux MCS label provide?
Q2. SELinux is in `enforcing` mode by default on RHEL-based distributions.
Q3. Your RHEL-based cluster has SELinux in `permissive` mode. The audit log shows `SELinux: denied` for many operations. The team set `permissive` to debug a workload issue and forgot to revert. Walk the response.
SELinux was set to `permissive` six months ago to debug a workload that needed `container_file_t` access. The workload was fixed; the mode was not reverted. The audit log shows thousands of denials.
Q4. Name the four fields in `securityContext.seLinuxOptions` and explain what each one sets.
Passing score: 75%. Answers are checked in this browser.
Production discipline
SELinux is the right primitive for workload
confinement on RHEL-based distributions. A
defensible SELinux programme keeps the mode at
enforcing, uses the kubelet’s default MCS
labels for isolation, and sets custom MCS levels
only when workloads must share files. A cluster whose
nodes are all Enforcing has a kernel-level
confinement programme that is auditable; a cluster
whose nodes are Permissive or Disabled has a
programme that is not.