Seccomp & AppArmor
Seccomp and AppArmor are Linux security modules that restrict what system calls and resources containers can access. They provide an additional layer of security by limiting the attack surface even if a container is compromised.
Seccomp (Secure Computing Mode)
Seccomp restricts the system calls a process can make. Think of it as a whitelist of allowed system calls—if a process tries to use a system call that’s not on the list, it’s killed.
How Seccomp Works
Seccomp Profile Types
Kubernetes supports three seccomp profile types:
- RuntimeDefault - Uses the container runtime’s default profile
- Localhost - Uses a custom profile from the node’s filesystem
- Unconfined - No restrictions (not recommended)
Using RuntimeDefault
The simplest and recommended approach:
apiVersion: v1
kind: Pod
metadata:
name: seccomp-pod
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:latest
Creating Custom Seccomp Profiles
Create a profile file on each node:
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures": ["SCMP_ARCH_X86_64"],
"syscalls": [
{
"names": ["read", "write", "open", "close", "stat"],
"action": "SCMP_ACT_ALLOW"
},
{
"names": ["execve"],
"action": "SCMP_ACT_ALLOW",
"args": [
{
"index": 0,
"value": "/usr/bin/nginx",
"op": "SCMP_CMP_EQ"
}
]
}
]
}
Save to /var/lib/kubelet/seccomp/profiles/my-profile.json on each node.
Using Custom Profile
apiVersion: v1
kind: Pod
metadata:
name: custom-seccomp-pod
spec:
securityContext:
seccompProfile:
type: Localhost
localhostProfile: profiles/my-profile.json
containers:
- name: app
image: nginx:latest
AppArmor
AppArmor restricts what files, network ports, and capabilities a process can access. It’s like a firewall for file and network access.
How AppArmor Works
AppArmor Profile Structure
AppArmor profiles define:
- File system access (read, write, execute)
- Network access (bind, connect)
- Capabilities
- Mount operations
Creating AppArmor Profiles
Create a profile on each node:
# /etc/apparmor.d/k8s-nginx
#include <tunables/global>
profile k8s-nginx flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
# Allow read access to application files
/usr/share/nginx/html/** r,
# Deny write access to most files
deny /usr/share/nginx/html/** w,
# Allow network access
network,
# Allow binding to port 80
capability net_bind_service,
}
Load the profile:
apparmor_parser /etc/apparmor.d/k8s-nginx
Using AppArmor in Pods
apiVersion: v1
kind: Pod
metadata:
name: apparmor-pod
annotations:
container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-nginx
spec:
containers:
- name: app
image: nginx:latest
Practical Examples
Seccomp for Web Server
apiVersion: v1
kind: Pod
metadata:
name: nginx-secure
spec:
securityContext:
seccompProfile:
type: RuntimeDefault
containers:
- name: nginx
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
AppArmor for Database
apiVersion: v1
kind: Pod
metadata:
name: postgres-secure
annotations:
container.apparmor.security.beta.kubernetes.io/postgres: localhost/k8s-postgres
spec:
containers:
- name: postgres
image: postgres:latest
With AppArmor profile:
# /etc/apparmor.d/k8s-postgres
#include <tunables/global>
profile k8s-postgres flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
# Allow database files
/var/lib/postgresql/data/** rw,
# Deny access to system files
deny /etc/** rw,
deny /usr/bin/** x,
# Network access
network,
}
Best Practices
- Start with RuntimeDefault - Use the default seccomp profile first
- Test thoroughly - Ensure applications work with restrictions
- Create custom profiles gradually - Add restrictions incrementally
- Document exceptions - If custom profiles are needed, document why
- Use both together - Seccomp and AppArmor complement each other
- Monitor violations - Watch for denied system calls or file access
Troubleshooting
Seccomp Violations
If a container is killed due to seccomp:
# Check dmesg for seccomp violations
dmesg | grep seccomp
# Check container logs
kubectl logs <pod-name>
AppArmor Denials
Check AppArmor denials:
# On the node
sudo aa-status
sudo cat /var/log/kern.log | grep apparmor
Testing Profiles
Test seccomp profiles:
# Create a test pod
kubectl run test-pod --image=nginx --overrides='
{
"spec": {
"securityContext": {
"seccompProfile": {
"type": "RuntimeDefault"
}
}
}
}'
# Test system calls
kubectl exec test-pod -- strace -e trace=openat ls
See Also
- Workload Hardening - Overview of workload security
- SecurityContext - Pod security context
- Capabilities - Linux capabilities
- Runtime Security - Runtime threat detection