How to harden your Canonical Kubernetes cluster¶
The Canonical Kubernetes hardening guide provides actionable steps to enhance the security posture of your deployment. These steps are designed to help you align with industry-standard frameworks such as CIS and DISA STIG.
Canonical Kubernetes aligns with many security recommendations by default. However, since implementing all security recommendations would come at the expense of compatibility and/or performance we expect cluster administrators to follow post deployment hardening steps based on their needs.
This how-to has both the recommended minimum hardening steps and also a more comprehensive list of manual tests.
Please evaluate the implications of each configuration before applying it.
Post-deployment hardening steps¶
These steps are common to the hardening process for both CIS and DISA STIG compliance.
Control plane nodes¶
Configure log auditing¶
Note
Configuring log auditing requires the cluster administrator’s input and may incurr performance penalties in the form of disk I/O.
Create an audit-policy.yaml file under /var/snap/k8s/common/etc/
and specify
the level of auditing you desire based on the upstream instructions.
Here is a minimal example of such a policy file.
sudo mkdir -p /var/snap/k8s/common/etc/
sudo sh -c 'cat >/var/snap/k8s/common/etc/audit-policy.yaml <<EOL
# Log all requests at the Metadata level.
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: Metadata
EOL'
Enable auditing at the API server level by adding the following arguments.
sudo sh -c 'cat >>/var/snap/k8s/common/args/kube-apiserver <<EOL
--audit-log-path=/var/log/apiserver/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100
--audit-policy-file=/var/snap/k8s/common/etc/audit-policy.yaml
EOL'
Restart the API server:
sudo systemctl restart snap.k8s.kube-apiserver
Set event rate limits¶
Note
Configuring event rate limits requires the cluster administrator’s input in assessing the hardware and workload specifications/requirements.
Create a configuration file with the rate limits and place it under
/var/snap/k8s/common/etc/
.
For example:
sudo mkdir -p /var/snap/k8s/common/etc/
sudo sh -c 'cat >/var/snap/k8s/common/etc/eventconfig.yaml <<EOL
apiVersion: eventratelimit.admission.k8s.io/v1alpha1
kind: Configuration
limits:
- type: Server
qps: 5000
burst: 20000
EOL'
Create an admissions control config file under /var/k8s/snap/common/etc/
.
sudo mkdir -p /var/snap/k8s/common/etc/
sudo sh -c 'cat >/var/snap/k8s/common/etc/admission-control-config-file.yaml <<EOL
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: EventRateLimit
path: eventconfig.yaml
EOL'
Make sure the EventRateLimit admission plugin is loaded in the
/var/snap/k8s/common/args/kube-apiserver
.
--enable-admission-plugins=...,EventRateLimit,...
Load the admission control config file.
sudo sh -c 'cat >>/var/snap/k8s/common/args/kube-apiserver <<EOL
--admission-control-config-file=/var/snap/k8s/common/etc/admission-control-config-file.yaml
EOL'
Restart the API server.
sudo systemctl restart snap.k8s.kube-apiserver
Enable AlwaysPullImages admission control plugin¶
Note
Configuring the AlwaysPullImages admission control plugin may have performance impact in the form of increased network traffic and may hamper offline deployments that use image sideloading.
Make sure the AlwaysPullImages admission plugin is loaded in the
/var/snap/k8s/common/args/kube-apiserver
--enable-admission-plugins=...,AlwaysPullImages,...
Restart the API server.
sudo systemctl restart snap.k8s.kube-apiserver
Set the Kubernetes scheduler and controller manager bind address¶
Note
This configuration may affect compatibility with workloads and metrics collection.
Edit the Kubernetes scheduler arguments file
/var/snap/k8s/common/args/kube-scheduler
and set the --bind-address
to be 127.0.0.1
.
sudo sh -c 'cat >>/var/snap/k8s/common/args/kube-scheduler <<EOL
--bind-address=127.0.0.1
EOL'
Do the same for the Kubernetes controller manager
(/var/snap/k8s/common/args/kube-controller-manager
):
sudo sh -c 'cat >>/var/snap/k8s/common/args/kube-controller-manager <<EOL
--bind-address=127.0.0.1
EOL'
Restart both services.
sudo systemctl restart snap.k8s.kube-scheduler
sudo systemctl restart snap.k8s.kube-controller-manager
Worker nodes¶
Run the following commands on nodes that host workloads. In the default deployment the control plane nodes functions as workers and they may need to be hardened.
Protect kernel defaults¶
Note
This configuration may affect compatibility of workloads.
Kubelet will not start if it finds kernel configurations incompatible with its defaults.
sudo sh -c 'cat >>/var/snap/k8s/common/args/kubelet <<EOL
--protect-kernel-defaults=true
EOL'
Restart kubelet
.
sudo systemctl restart snap.k8s.kubelet
Reload the system daemons:
sudo systemctl daemon-reload
Edit kubelet service file permissions¶
Note
Fully complying with the spirit of this hardening recommendation calls for systemd configuration that is out of the scope of this documentation page.
Ensure that only the owner of /etc/systemd/system/snap.k8s.kubelet.service
has full read and write access to it. Setting the kubelet service file
permission needs to be performed every time the k8s snap refreshes.
chmod 600 /etc/systemd/system/snap.k8s.kubelet.service
Restart kubelet
.
sudo systemctl restart snap.k8s.kubelet
Set the maximum time an idle session is permitted prior to disconnect¶
Idle connections from the Kubelet can be used by unauthorized users to perform malicious activity to the nodes, pods, containers, and cluster within the Kubernetes Control Plane.
Edit /var/snap/k8s/common/args/kubelet
and set the argument --streaming-connection-idle-timeout
to 5m
.
sudo sh -c 'cat >>/var/snap/k8s/common/args/kubelet <<EOL
--streaming-connection-idle-timeout=5m
EOL'
Restart kubelet
.
sudo systemctl restart snap.k8s.kubelet
CIS and DISA STIG hardening¶
To assess compliance to DISA STIG recommendations, please see DISA STIG assessment page.
To assess compliance to the CIS hardening guidelines, please see the CIS assessment page.