|
| 1 | +# Getting Started with Kubernetes MCP Server |
| 2 | + |
| 3 | +This guide walks you through the foundational setup for using the Kubernetes MCP Server with your Kubernetes cluster. You'll create a dedicated, read-only ServiceAccount and generate a secure kubeconfig file that can be used with various MCP clients. |
| 4 | + |
| 5 | +> **Note:** This setup is **recommended for production use** but not strictly required. The MCP Server can use your existing kubeconfig file (e.g., `~/.kube/config`), but using a dedicated ServiceAccount with limited permissions follows the principle of least privilege and is more secure. |
| 6 | +
|
| 7 | +> **Next:** After completing this guide, continue with the [Claude Code CLI guide](GETTING_STARTED_CLAUDE_CODE.md). See the [docs README](README.md) for all available guides. |
| 8 | +
|
| 9 | +## What You'll Create |
| 10 | + |
| 11 | +By the end of this guide, you'll have: |
| 12 | +- A dedicated `mcp-viewer` ServiceAccount with read-only cluster access |
| 13 | +- A secure, time-bound authentication token |
| 14 | +- A dedicated kubeconfig file (`~/.kube/mcp-viewer.kubeconfig`) |
| 15 | + |
| 16 | +## Prerequisites |
| 17 | + |
| 18 | +- A running Kubernetes cluster |
| 19 | +- `kubectl` CLI installed and configured |
| 20 | +- Cluster admin permissions to create ServiceAccounts and RBAC bindings |
| 21 | + |
| 22 | +## 1. Create a Read-Only ServiceAccount and RBAC |
| 23 | + |
| 24 | +A ServiceAccount represents a non-human identity. Binding it to a read-only role lets tools query the cluster safely without using administrator credentials. |
| 25 | + |
| 26 | +### Step 1.1: Create the Namespace and ServiceAccount |
| 27 | + |
| 28 | +First, create a Namespace for the ServiceAccount: |
| 29 | + |
| 30 | +```bash |
| 31 | +# Create or pick a Namespace for the ServiceAccount |
| 32 | +kubectl create namespace mcp |
| 33 | + |
| 34 | +# Create the ServiceAccount |
| 35 | +kubectl create serviceaccount mcp-viewer -n mcp |
| 36 | +``` |
| 37 | + |
| 38 | +### Step 1.2: Grant Read-Only Access (RBAC) |
| 39 | + |
| 40 | +Use a ClusterRoleBinding or RoleBinding to grant read-only permissions. |
| 41 | + |
| 42 | +#### Option A: Cluster-Wide Read-Only (Most Common) |
| 43 | + |
| 44 | +This binds the ServiceAccount to the built-in `view` ClusterRole, which provides read-only access across the whole cluster. |
| 45 | + |
| 46 | +```bash |
| 47 | +# Binds the view ClusterRole to the ServiceAccount |
| 48 | +kubectl create clusterrolebinding mcp-viewer-crb \ |
| 49 | + --clusterrole=view \ |
| 50 | + --serviceaccount=mcp:mcp-viewer |
| 51 | +``` |
| 52 | + |
| 53 | +#### Option B: Namespace-Scoped Only (Tighter Scope) |
| 54 | + |
| 55 | +This limits read access to the `mcp` namespace only, using the built-in `view` Role. |
| 56 | + |
| 57 | +```bash |
| 58 | +# Binds the view role to the ServiceAccount within the 'mcp' namespace |
| 59 | +kubectl create rolebinding mcp-viewer-rb \ |
| 60 | + --role=view \ |
| 61 | + --serviceaccount=mcp:mcp-viewer \ |
| 62 | + -n mcp |
| 63 | +``` |
| 64 | + |
| 65 | +### Quick Verification (Optional) |
| 66 | + |
| 67 | +Verify the permissions granted to the ServiceAccount: |
| 68 | + |
| 69 | +```bash |
| 70 | +# Check if the ServiceAccount can list pods cluster-wide |
| 71 | +# Expect 'yes' if you used the view ClusterRole (Option A) |
| 72 | +kubectl auth can-i list pods --as=system:serviceaccount:mcp:mcp-viewer --all-namespaces |
| 73 | +``` |
| 74 | + |
| 75 | +## 2. Mint a ServiceAccount Token |
| 76 | + |
| 77 | +Tools authenticate via a bearer token. We use the TokenRequest API (`kubectl create token`) to generate a secure, short-lived token. |
| 78 | + |
| 79 | +```bash |
| 80 | +# Create a time-bound token (choose a duration, e.g., 2 hours) |
| 81 | +TOKEN="$(kubectl create token mcp-viewer --duration=2h -n mcp)" |
| 82 | + |
| 83 | +# Verify the token was generated (Optional) |
| 84 | +echo "$TOKEN" |
| 85 | +``` |
| 86 | + |
| 87 | +**Note:** The `kubectl create token` command requires Kubernetes v1.24+. For older versions, you'll need to extract the token from the ServiceAccount's secret. |
| 88 | + |
| 89 | +## 3. Build a Dedicated Kubeconfig |
| 90 | + |
| 91 | +A dedicated kubeconfig file isolates this ServiceAccount's credentials from your personal admin credentials, making it easy to point external tools at. |
| 92 | + |
| 93 | +### Step 3.1: Get Cluster Details |
| 94 | + |
| 95 | +Get the API server address and certificate authority from your current active context: |
| 96 | + |
| 97 | +```bash |
| 98 | +# 1. Get the current cluster API server address |
| 99 | +API_SERVER="$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')" |
| 100 | + |
| 101 | +# 2. Get the cluster's Certificate Authority (CA) file path or data |
| 102 | +# First, try to get the CA file path |
| 103 | +CA_FILE="$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.certificate-authority}')" |
| 104 | + |
| 105 | +# If CA file is not set, extract the CA data and write it to a temp file |
| 106 | +if [ -z "$CA_FILE" ]; then |
| 107 | + CA_FILE="/tmp/k8s-ca-$$.crt" |
| 108 | + kubectl config view --minify --raw -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 -d > "$CA_FILE" |
| 109 | +fi |
| 110 | + |
| 111 | +# 3. Define the desired context name |
| 112 | +CONTEXT_NAME="mcp-viewer-context" |
| 113 | +KUBECONFIG_FILE="$HOME/.kube/mcp-viewer.kubeconfig" |
| 114 | +``` |
| 115 | + |
| 116 | +### Step 3.2: Create and Configure the Kubeconfig File |
| 117 | + |
| 118 | +Create the new kubeconfig file by defining the cluster, user (the ServiceAccount), and context: |
| 119 | + |
| 120 | +```bash |
| 121 | +# Create a new kubeconfig file with cluster configuration |
| 122 | +kubectl config --kubeconfig="$KUBECONFIG_FILE" set-cluster mcp-viewer-cluster \ |
| 123 | + --server="$API_SERVER" \ |
| 124 | + --certificate-authority="$CA_FILE" \ |
| 125 | + --embed-certs=true |
| 126 | + |
| 127 | +# Set the ServiceAccount token as the user credential |
| 128 | +kubectl config --kubeconfig="$KUBECONFIG_FILE" set-credentials mcp-viewer \ |
| 129 | + --token="$TOKEN" |
| 130 | + |
| 131 | +# Define the context (links the cluster and user) |
| 132 | +kubectl config --kubeconfig="$KUBECONFIG_FILE" set-context "$CONTEXT_NAME" \ |
| 133 | + --cluster=mcp-viewer-cluster \ |
| 134 | + --user=mcp-viewer |
| 135 | + |
| 136 | +# Set the new context as current |
| 137 | +kubectl config --kubeconfig="$KUBECONFIG_FILE" use-context "$CONTEXT_NAME" |
| 138 | + |
| 139 | +# Secure the file permissions |
| 140 | +chmod 600 "$KUBECONFIG_FILE" |
| 141 | + |
| 142 | +# Clean up temporary CA file if we created one |
| 143 | +if [[ "$CA_FILE" == /tmp/k8s-ca-*.crt ]]; then |
| 144 | + rm -f "$CA_FILE" |
| 145 | +fi |
| 146 | +``` |
| 147 | + |
| 148 | +### Quick Sanity Check |
| 149 | + |
| 150 | +You can now use this new file to verify access: |
| 151 | + |
| 152 | +```bash |
| 153 | +# Run a command using the dedicated kubeconfig file |
| 154 | +kubectl --kubeconfig="$KUBECONFIG_FILE" get pods -A |
| 155 | +``` |
| 156 | + |
| 157 | +This command should successfully list all Pods if you chose **Option A: Cluster-Wide Read-Only**, proving the ServiceAccount and its token are correctly configured. |
| 158 | + |
| 159 | +## 4. Use with Kubernetes MCP Server |
| 160 | + |
| 161 | +Now that you have a dedicated kubeconfig file, you can use it with the Kubernetes MCP Server: |
| 162 | + |
| 163 | +```bash |
| 164 | +# Run the MCP server with the dedicated kubeconfig |
| 165 | +./kubernetes-mcp-server --kubeconfig="$HOME/.kube/mcp-viewer.kubeconfig" |
| 166 | + |
| 167 | +# Or use npx |
| 168 | +npx -y kubernetes-mcp-server@latest --kubeconfig="$HOME/.kube/mcp-viewer.kubeconfig" |
| 169 | + |
| 170 | +# Or use uvx |
| 171 | +uvx kubernetes-mcp-server@latest --kubeconfig="$HOME/.kube/mcp-viewer.kubeconfig" |
| 172 | +``` |
| 173 | + |
| 174 | +Alternatively, you can set the `KUBECONFIG` environment variable: |
| 175 | + |
| 176 | +```bash |
| 177 | +export KUBECONFIG="$HOME/.kube/mcp-viewer.kubeconfig" |
| 178 | +./kubernetes-mcp-server |
| 179 | +``` |
| 180 | + |
| 181 | +## Token Expiration and Renewal |
| 182 | + |
| 183 | +The token created in Step 2 has a limited lifetime (2 hours in the example). When it expires, you'll need to: |
| 184 | + |
| 185 | +1. Generate a new token: |
| 186 | + ```bash |
| 187 | + TOKEN="$(kubectl create token mcp-viewer --duration=2h -n mcp)" |
| 188 | + ``` |
| 189 | + |
| 190 | +2. Update the kubeconfig file: |
| 191 | + ```bash |
| 192 | + kubectl config --kubeconfig="$KUBECONFIG_FILE" set-credentials mcp-viewer --token="$TOKEN" |
| 193 | + ``` |
| 194 | + |
| 195 | +For long-running applications, consider: |
| 196 | +- Using a longer token duration (up to the cluster's maximum, typically 24h) |
| 197 | +- Implementing automatic token renewal in your application |
| 198 | +- Using a different authentication method (e.g., client certificates) |
| 199 | + |
| 200 | +## Cleanup |
| 201 | + |
| 202 | +To remove the ServiceAccount and associated RBAC bindings: |
| 203 | + |
| 204 | +```bash |
| 205 | +# Delete the ClusterRoleBinding (if using Option A) |
| 206 | +kubectl delete clusterrolebinding mcp-viewer-crb |
| 207 | + |
| 208 | +# Delete the RoleBinding (if using Option B) |
| 209 | +kubectl delete rolebinding mcp-viewer-rb -n mcp |
| 210 | + |
| 211 | +# Delete the ServiceAccount |
| 212 | +kubectl delete serviceaccount mcp-viewer -n mcp |
| 213 | + |
| 214 | +# Delete the namespace (optional - only if you created it specifically for this) |
| 215 | +kubectl delete namespace mcp |
| 216 | + |
| 217 | +# Remove the kubeconfig file |
| 218 | +rm "$HOME/.kube/mcp-viewer.kubeconfig" |
| 219 | +``` |
| 220 | + |
| 221 | +## Troubleshooting |
| 222 | + |
| 223 | +### kubectl create token: command not found |
| 224 | + |
| 225 | +This command requires Kubernetes v1.24+. For older versions, you'll need to extract the token from the ServiceAccount's secret manually. |
| 226 | + |
| 227 | +### Permission denied errors |
| 228 | + |
| 229 | +Ensure you're using the correct kubeconfig file and that the ServiceAccount has the necessary RBAC permissions. Verify with: |
| 230 | + |
| 231 | +```bash |
| 232 | +kubectl auth can-i list pods --as=system:serviceaccount:mcp:mcp-viewer --all-namespaces |
| 233 | +``` |
| 234 | + |
| 235 | +## Next Steps |
| 236 | + |
| 237 | +Now that you have a working kubeconfig with read-only access, configure Claude Code CLI: |
| 238 | + |
| 239 | +- **[Using with Claude Code CLI](GETTING_STARTED_CLAUDE_CODE.md)** - Configure the MCP server with Claude Code CLI |
| 240 | + |
| 241 | +You can also: |
| 242 | +- Explore the [main README](../README.md) for more MCP server capabilities |
0 commit comments