Skip to main content

Kubelet Security

Updated Mar 11, 2022 ·

The Kubelet

The kubelet is a vital Kubernetes component responsible for managing and monitoring individual nodes in a cluster.

  • Starts, stops, and maintains application containers.
  • Runs readiness and liveness probes to check container health.
  • Registers the node with the control plane.
  • Handles volume mounting/unmounting for Pods.
  • Reports node and pod statuses to the API server.

Viewing Kubelet Options

To inspect kubelet options, find its configuration file:

ps -aux | grep kubelet

Once located, review the options in the file.

Ports used by kubelet

The kubelet listens on two ports, which pose a security risk if exposed. Authentication and authorization mechanisms help secure access.

Disable Anonymous Authentication

Anonymous access allows unauthenticated users to list pod details. Disable it by setting --anonymous-auth=false in the kubelet configuration:

## kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/concepts/overview/components/#kubelet

[Service]
ExecStart=/usr/bin/kubelet \
--config=/etc/kubernetes/kubelet.conf \
--container-runtime=docker \
--kubeconfig=/etc/kubernetes/kubelet.kubeconfig \
--fail-swap-on=false \
--cgroup-driver=cgroupfs \
--network-plugin=cni \
--pod-manifest-path=/etc/kubernetes/manifests \
--allow-privileged=true \
--anonymous-auth=false
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

This parameter can also be set in the kubelet config file.

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false

Authentication Mechanisms

Certificate (x509)

Configure the kubelet to use TLS certificates for secure communication with the API server. Specify the CA file in the kubelet service file and ensure certificates are valid and up-to-date.

## kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/concepts/overview/components/#kubelet

[Service]
ExecStart=/usr/bin/kubelet \
. . .
--anonymous-auth=false \
--client-ca-file=/path/to/ca.crt
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Similary, it can be specified in the kubelet config file.

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
x509:
clientCAFile: /path/to/ca.crt

Once you have the certificates, we can pass this to the curl command:

curl -sk https://localhost:10250/pods/ \
--key kubelet-key.pem \
--cert kubelet-cert.pem

When the kube-apiserver tries to communicate to kubelet, the kube-apiserver also has to authenticate to the kubelet. This means that the kube-apiserver needs to have kubelet client cert and key.

[Unit]
Description=Kubernetes API Server
Documentation=https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/
After=network.target

[Service]
ExecStart=/usr/bin/kube-apiserver \
. . .
--kubelet-client-certificate=/etc/kubernetes/pki/apiserver-kubelet-client.crt \
--kubelet-client-key=/etc/kubernetes/pki/apiserver-kubelet-client.key \
--kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname \

API Bearer Tokens

Bearer tokens authenticate kubelets to the API server via the "Authorization" header in HTTP requests.

  • Tokens are sent in this format: Authorization: Bearer <token>.
  • The API server verifies the token.
  • Valid tokens allow the operation; invalid ones are denied.

Below is a simplified example of how a Bearer Token might be used in a kubelet configuration:

apiVersion: v1
kind: Config
clusters:
- name: my-cluster
cluster:
server: https://api-server-address
users:
- name: kubelet-user
user:
token: <bearer-token-here>
contexts:
- name: my-context
context:
cluster: my-cluster
user: kubelet-user
current-context: my-context

Authorization Mechanisms

Once the user gains access to the system, authorization defines what resources the user can interact with.

AlwaysAllow

This is the default authorization mode and will always allow all requests to the API.

## kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/concepts/overview/components/#kubelet

[Service]
ExecStart=/usr/bin/kubelet \
. . .
--anonymous-auth=false \
--client-ca-file=/path/to/ca.crt
--authorization-mode=AlwaysAllow

kubelet config file:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
x509:
clientCAFile: /path/to/ca.crt
mode: AlwaysAllow

Webhook

When set to Webhook, the kubelet first makes a call to the API server to determine is the request should be granted or not.

## kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/concepts/overview/components/#kubelet

[Service]
ExecStart=/usr/bin/kubelet \
. . .
--anonymous-auth=false \
--client-ca-file=/path/to/ca.crt
--authorization-mode=Webhook

kubelet config file:

apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
anonymous:
enabled: false
x509:
clientCAFile: /path/to/ca.crt
mode: Webhook

Read-only Metrics API

The metrics API allows read-only access which doesn't need any authentication or authorization.

This is enabled when the read-only-port flag is set to non-zero number in the kubelet service file.

## kubelet.service 
[Unit]
Description=Kubernetes Kubelet
Documentation=https://kubernetes.io/docs/concepts/overview/components/#kubelet

[Service]
ExecStart=/usr/bin/kubelet \
. . .
--anonymous-auth=false \
--client-ca-file=/path/to/ca.crt
--authorization-mode=Webhook
--read-only-port=10255 ## If set to zero, metrics is disabled