Overview
MicroK8s is a lightweight, CNCF-certified Kubernetes distribution developed by Canonical. By default, the Kubernetes API server in MicroK8s binds to localhost (127.0.0.1), which means it's only accessible from the machine where it's installed. To connect remotely from development tools like VS Code, WebStorm, or any kubectl client, you need to configure the API server to listen on an external IP address.
This guide walks you through configuring MicroK8s for remote access, generating the kubeconfig file, and setting up your local development environment.
Prerequisites
Before proceeding, ensure you have:
- MicroK8s installed on a remote Ubuntu server (or any supported Linux distribution)
- SSH access to the remote server
- kubectl installed on your local machine (optional, but recommended)
- Network connectivity between your local machine and the remote server on port
16443
Security Note: Exposing the Kubernetes API server to a network increases the attack surface. Ensure you have proper firewall rules in place and consider using a VPN or SSH tunnel for production environments.
Understanding the Architecture
When you connect remotely to a Kubernetes cluster, your local kubectl client communicates with the kube-apiserver component running on the control plane. The connection is authenticated using certificates embedded in the kubeconfig file.
Key components involved:
| Component | Description | Default Port |
|---|---|---|
| kube-apiserver | Main API endpoint for all cluster operations | 16443 (MicroK8s) |
| etcd/dqlite | Distributed key-value store for cluster state | 2379 |
| kubelet | Node agent running on each node | 10250 |
Step 1: Bind IP to MicroK8s API Server
The kube-apiserver configuration in MicroK8s is managed through argument files located in /var/snap/microk8s/current/args/. You need to modify two critical parameters:
--advertise-address: The IP address that the API server advertises to cluster members. This should be the external IP of your server that other machines can reach.--bind-address: The IP address on which the API server listens. Setting this to0.0.0.0allows connections from any network interface.
1sudo nano /var/snap/microk8s/current/args/kube-apiserver2
3--advertise-address=<your_server_ip>4--bind-address=0.0.0.0Configuration Parameters Explained:
| Parameter | Value | Purpose |
|---|---|---|
--advertise-address | Your server's IP (e.g., 192.168.0.100) | Tells other components where to find the API server |
--bind-address | 0.0.0.0 | Listens on all network interfaces |
Alternative: View All Available kube-apiserver Options
You can view the current configuration and all available options:
1# View current kube-apiserver arguments2cat /var/snap/microk8s/current/args/kube-apiserver3
4# List all configurable Kubernetes component files5ls -la /var/snap/microk8s/current/args/Step 2: Restart MicroK8s to Apply Changes
After modifying the API server configuration, you must restart MicroK8s for the changes to take effect. MicroK8s manages its services through snap, so we use the microk8s stop and microk8s start commands.
1sudo microk8s stop2sudo microk8s startVerify the API Server is Listening
After restarting, verify that the API server is now listening on the configured IP:
1# Check if the API server is listening on the correct port2sudo ss -tlnp | grep 164433
4# Expected output should show 0.0.0.0:16443 or your specific IP5# LISTEN 0 4096 0.0.0.0:16443 0.0.0.0:* users:(("kube-apiserver",pid=xxxx,fd=7))6
7# Verify MicroK8s status8sudo microk8s status --wait-ready9
10# Test cluster connectivity locally11sudo microk8s kubectl cluster-infoTroubleshooting: If the cluster doesn't start properly, check the logs:
bash sudo journalctl -u snap.microk8s.daemon-kubelite -f
Step 3: Generate the Kubeconfig File
The kubeconfig file contains all the necessary information for kubectl to authenticate and connect to your cluster, including:
- Cluster information: API server URL and CA certificate
- User credentials: Client certificate and key for authentication
- Context: Links a cluster with user credentials
1sudo microk8s kubectl config view --raw > ~/.kube/configUnderstanding the Kubeconfig Structure
The generated kubeconfig follows a standard structure:
1# Example kubeconfig structure (for reference)2apiVersion: v13kind: Config4clusters:5 - cluster:6 certificate-authority-data: <base64-encoded-ca-cert>7 server: https://<server-ip>:164438 name: microk8s-cluster9contexts:10 - context:11 cluster: microk8s-cluster12 user: admin13 name: microk8s14current-context: microk8s15users:16 - name: admin17 user:18 client-certificate-data: <base64-encoded-client-cert>19 client-key-data: <base64-encoded-client-key>Set Proper Permissions
Ensure the kubeconfig file has appropriate permissions:
1# Set secure permissions (readable only by owner)2chmod 600 ~/.kube/config3
4# Verify the configuration is valid5sudo microk8s kubectl config viewStep 4: Copy Config to Your Local Machine
Now transfer the kubeconfig file from the remote server to your local development machine using SCP (Secure Copy Protocol).
1scp [email protected]:/home/admin/.kube/config ~/.kube/config2
3export KUBECONFIG=~/.kube/configUpdate the Server Address in Kubeconfig
After copying, you may need to update the server address in your local kubeconfig if it still references 127.0.0.1:
1# Edit the config file to update the server address2sed -i 's/127.0.0.1/<your_server_ip>/g' ~/.kube/config3
4# On macOS, use:5sed -i '' 's/127.0.0.1/<your_server_ip>/g' ~/.kube/configVerify Remote Connection
Test that you can connect to the cluster from your local machine:
1# Verify connection to the remote cluster2kubectl cluster-info3
4# Expected output:5# Kubernetes control plane is running at https://192.168.0.100:164436
7# List nodes in the cluster8kubectl get nodes9
10# List all pods across namespaces11kubectl get pods --all-namespacesIDE Integration
VS Code Setup
- Install the Kubernetes extension from the VS Code marketplace
- The extension automatically detects your kubeconfig file at
~/.kube/config - Open the Kubernetes sidebar to browse cluster resources
WebStorm / IntelliJ IDEA Setup
- Navigate to Settings → Plugins and install the Kubernetes plugin
- Configure the kubeconfig path in Settings → Build, Execution, Deployment → Kubernetes
- Set the config file path to
~/.kube/config
Managing Multiple Clusters
If you work with multiple Kubernetes clusters, you can manage contexts easily:
1# List all available contexts2kubectl config get-contexts3
4# Switch to a specific context5kubectl config use-context microk8s6
7# Set a default namespace for the current context8kubectl config set-context --current --namespace=my-namespaceMerging Multiple Kubeconfig Files
You can merge multiple kubeconfig files by setting the KUBECONFIG environment variable:
1# Merge multiple kubeconfig files2export KUBECONFIG=~/.kube/config:~/.kube/microk8s-config:~/.kube/other-cluster3
4# View merged configuration5kubectl config view --flatten > ~/.kube/merged-configSecurity Best Practices
| Practice | Description |
|---|---|
| Use firewall rules | Restrict access to port 16443 to trusted IP addresses only |
| Enable RBAC | Use Role-Based Access Control to limit user permissions |
| Rotate certificates | Regularly rotate TLS certificates for enhanced security |
| Use SSH tunnels | For production, consider tunneling through SSH instead of exposing the API directly |
| Network policies | Implement Kubernetes NetworkPolicies to control pod-to-pod traffic |
Secure Access via SSH Tunnel (Alternative)
Instead of exposing the API server directly, you can use an SSH tunnel:
1# Create an SSH tunnel to the API server2ssh -L 16443:127.0.0.1:16443 [email protected] -N3
4# In another terminal, use kubectl with localhost5kubectl --server=https://127.0.0.1:16443 get nodesTroubleshooting
Useful Diagnostic Commands
1# Check MicroK8s service status2sudo microk8s inspect3
4# View API server logs5sudo journalctl -u snap.microk8s.daemon-kubelite --no-pager -n 506
7# Test API server connectivity from remote machine8curl -k https://<server-ip>:16443/healthz9
10# Check certificate details11openssl s_client -connect <server-ip>:16443 </dev/null 2>/dev/null | openssl x509 -text -noout | grep -A1 "Subject Alternative Name"