> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Securing the Kubelet

> This guide covers best practices for securing the kubelet in Kubernetes, including installation, configuration, and hardening techniques.

In Kubernetes, the **kubelet** acts as the “captain” on each worker node. It:

* Registers the node with the control plane.
* Starts and stops containers per Pod specs.
* Monitors Pod and container health, reporting back to the API Server.

Just like a ship’s captain must secure communications with the harbor master, you must lock down the kubelet so it only accepts instructions from your cluster’s API Server. In this guide, you’ll learn how to:

* Install and configure the kubelet securely
* Inspect its running configuration
* Harden authentication, authorization, and network access

***

## 1. Role & Installation of the Kubelet

### Key Responsibilities

1. **Node Registration**
2. **Pod Lifecycle Management**
3. **Health Reporting**

### Manual Installation

Download the kubelet binary and set up a `systemd` unit:

```bash theme={null}
wget https://storage.googleapis.com/kubernetes-release/release/v1.20.0/bin/linux/amd64/kubelet \
  -O /usr/local/bin/kubelet && chmod +x /usr/local/bin/kubelet
```

```ini theme={null}
# /etc/systemd/system/kubelet.service
[Unit]
Description=Kubelet Service
After=network.target

[Service]
ExecStart=/usr/local/bin/kubelet \
  --container-runtime=remote \
  --image-pull-progress-deadline=2m \
  --kubeconfig=/var/lib/kubelet/kubeconfig \
  --network-plugin=cni \
  --register-node=true \
  --cluster-domain=cluster.local \
  --cluster-dns=10.96.0.10 \
  --v=2

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

<Callout icon="lightbulb" color="#1CB2FE">
  With **kubeadm** (v1.10+), most flags migrate into `/var/lib/kubelet/config.yaml` and are maintained automatically during `kubeadm join`.
</Callout>

### Dedicated Config File

```yaml theme={null}
# /var/lib/kubelet/config.yaml
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
clusterDomain: cluster.local
clusterDNS:
  - 10.96.0.10
fileCheckFrequency: 0s
httpCheckFrequency: 0s
syncFrequency: 0s
healthzPort: 10248
```

Add `--config=/var/lib/kubelet/config.yaml` to your service’s `ExecStart`. Command-line flags will always override the YAML settings.

***

## 2. Inspecting the Active Configuration

On any worker node, verify the kubelet invocation and configuration:

```bash theme={null}
ps aux | grep kubelet
# e.g. /usr/bin/kubelet --kubeconfig=/etc/kubernetes/kubelet.conf \
#       --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf \
#       --config=/var/lib/kubelet/config.yaml \
#       --cgroup-driver=systemd \
#       --network-plugin=cni
```

```bash theme={null}
cat /var/lib/kubelet/config.yaml
# apiVersion: kubelet.config.k8s.io/v1beta1
# kind: KubeletConfiguration
# authentication:
#   anonymous:
#     enabled: false
#   x509:
#     clientCAFile: /path/to/ca.crt
# authorization:
#   mode: Webhook
# readOnlyPort: 0
# rotateCertificates: true
# staticPodPath: /etc/kubernetes/manifests
```

***

## 3. Kubelet API Endpoints

| Port  | Endpoint Type     | Access                     | Recommendation               |
| ----- | ----------------- | -------------------------- | ---------------------------- |
| 10250 | Secure API        | TLS + AuthN/AuthZ required | Keep enabled and locked down |
| 10255 | Read-only metrics | Unauthenticated, HTTP only | Disable in production        |

<Frame>
  ![The image shows a table titled "Kubelet" with two ports, 10250 and 10255, and their descriptions regarding API access.](https://kodekloud.com/kk-media/image/upload/v1752880767/notes-assets/images/Kubernetes-and-Cloud-Native-Security-Associate-KCSA-Securing-the-Kubelet/kubelet-ports-api-access-table.jpg)
</Frame>

Anyone with network access to port 10255 can scrape metrics:

```bash theme={null}
curl -s http://localhost:10255/metrics | head -n 5
# HELP process_cpu_seconds_total Total user and system CPU time spent in seconds.
# TYPE process_cpu_seconds_total counter
# process_cpu_seconds_total 0.01
```

<Callout icon="triangle-alert" color="#FF6B6B">
  Port `10255` is unauthenticated and exposes sensitive metrics. It should always be disabled in production.
</Callout>

***

## 4. Authentication Configuration

By default, the kubelet permits anonymous requests (`system:anonymous`). Disable this to force clients to present credentials.

### Disable Anonymous Access

**Via flags** in your `systemd` unit:

```ini theme={null}
--anonymous-auth=false \
--client-ca-file=/path/to/ca.crt
```

**Or** in `/var/lib/kubelet/config.yaml`:

```yaml theme={null}
authentication:
  anonymous:
    enabled: false
  x509:
    clientCAFile: /path/to/ca.crt
```

### Certificate-Based Client Auth

1. Generate a CA and sign a kubelet-serving certificate.

2. Distribute the CA bundle with `--client-ca-file=/path/to/ca.crt`.

3. Test with:

   ```bash theme={null}
   curl -s --key kubelet-key.pem --cert kubelet-cert.pem \
     https://localhost:10250/pods
   ```

4. Ensure the **API Server** has credentials to call the kubelet:

   ```ini theme={null}
   # /etc/systemd/system/kube-apiserver.service
   --kubelet-client-certificate=/path/to/kubelet-client.crt \
   --kubelet-client-key=/path/to/kubelet-client.key
   ```

***

## 5. Authorization Modes

Out of the box, the kubelet uses `AlwaysAllow` (no authorization). Switch to `Webhook` to delegate decisions to the API Server.

```ini theme={null}
# Flags
--authorization-mode=Webhook
```

```yaml theme={null}
# config.yaml
authorization:
  mode: Webhook
```

Each kubelet request is then validated via the API Server’s SubjectAccessReview endpoint.

***

## 6. Disabling the Read-Only Port

To completely turn off port `10255`:

```ini theme={null}
# Flags
--read-only-port=0
```

```yaml theme={null}
# config.yaml
readOnlyPort: 0
```

<Callout icon="triangle-alert" color="#FF6B6B">
  Always set `readOnlyPort: 0` in production to prevent unauthenticated access to metrics.
</Callout>

***

## 7. Summary of Hardening Steps

| Security Aspect      | Recommended Setting             |
| -------------------- | ------------------------------- |
| Anonymous Auth       | `--anonymous-auth=false`        |
| TLS Client AuthN     | `clientCAFile: /path/to/ca.crt` |
| Authorization        | `--authorization-mode=Webhook`  |
| Read-Only Port       | `readOnlyPort: 0`               |
| Certificate Rotation | `rotateCertificates: true`      |

### Example Final `kubelet.service` Snippet

```ini theme={null}
ExecStart=/usr/local/bin/kubelet \
  --config=/var/lib/kubelet/config.yaml \
  --anonymous-auth=false \
  --client-ca-file=/path/to/ca.crt \
  --authorization-mode=Webhook \
  --read-only-port=0
```

### Example Final `config.yaml`

```yaml theme={null}
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
authentication:
  anonymous:
    enabled: false
  x509:
    clientCAFile: /path/to/ca.crt
authorization:
  mode: Webhook
readOnlyPort: 0
rotateCertificates: true
```

You’re now ready to apply these settings and secure the kubelet in your cluster!

***

## Links and References

* [Kubernetes Official Documentation](https://kubernetes.io/docs/)
* [Kubelet Configuration Reference](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/)
* [Kubeadm Configuration](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-init/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kubernetes-and-cloud-native-security-associate-kcsa/module/ca772db3-53aa-44c1-b424-3d32a046b683/lesson/01b01297-c7b8-409c-b37e-10af456416fd" />

  <Card title="Practice Lab" icon="installation" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kubernetes-and-cloud-native-security-associate-kcsa/module/ca772db3-53aa-44c1-b424-3d32a046b683/lesson/3d54f860-f552-48a2-8ac2-886bacd00893" />
</CardGroup>
