Introduction
DevOps Engineers or Developers who deal with Kubernetes: the concept of container immutability.
What is Container Immutability?
Immutable
(or stateless
) containers do not change during their lifetime. Instead of being changed, they are replaced with new containers. This often means that the container file system remains static, and the container does not depend on non-immutable host resources that require privileged access.Main Concepts
K8S
- Privileged Mode
- To maintain immutability, do not use
securityContext.privileged: true
.
- To maintain immutability, do not use
- Host Namespaces
- Setting like
hostNetwork: true
can make containers mutable.
- Setting like
- Allow Privilege Escalation
securityContext.allowPrivilegeEscalation: true
allows a container to gain more privileges than the parent process. This can make a container mutable.
- Root User
securityContext.runAsUser: root
or0
makes the container process run as root. Use a different user to maintain immutability.
2. Avoid :latest tag for container
Host Namespace:
- hostIPC – If set to true, containers will use the host’s inter-process communication (IPC) namespace.
- hostNetwork – If set to true, containers will use host’s network namespace.
- hostPID – If set to true, containers will use the host’s process id (PID) namespace
Host Level Resources
Privileged mode
allows containers to access host-level resources and capabilities, much like a non-container process running directly on the host.
Container Immutability
FROM alpine:latest
USER root
COPY start.sh .
USER root
CMD ["./start.sh"]
apiVersion: apps/v1
kind: Deployment
metadata:
name: un-secure
spec:
replicas: 3
selector:
matchLabels:
app: un-secure
template:
metadata:
labels:
app: un-secure
spec:
containers:
- name: un-secure
image: alpine:latest
securityContext:
privileged: true
runAsUser: 0
More secure
FROM alpine:3.15.0
USER userone
CMD ["./start.sh"]
- Image version is defined
- User is defined
apiVersion: apps/v1
kind: Deployment
metadata:
name: un-secure
spec:
replicas: 3
selector:
matchLabels:
app: un-secure
template:
metadata:
labels:
app: un-secure
spec:
containers:
- name: un-secure
image: alpine:3.14
securityContext:
privileged: false
runAsUser: 55774
- privileged is false
- user is defined