Install K3d on WSL Ubuntu with Gateway API support (NGF)

Setting up k3d with Docker Engine and NGINX Gateway Fabric on WSL2 Ubuntu

Setting up k3d on WSL2 Ubuntu with NGINX Gateway Fabric & Custom Docker Engine

Format: Blogspot / Blogger Optimized Template Code Architecture
Target Engine: Ubuntu Linux (WSL2 Distro - Fresh Installation Setup)
Key Frameworks: Docker Engine, k3d, Kubernetes Gateway API, NGINX Gateway Fabric (NGF)

Building a lightweight Kubernetes lab environment inside Windows Subsystem for Linux (WSL2) offers seamless speed and developer flexibility. However, combining modern architectures like the standard Kubernetes Gateway API via NGINX Gateway Fabric (NGF) while discarding the pre-baked cluster ingress configuration takes precise choreography.

This tutorial details a comprehensive engineering map to cleanly initialize a fresh WSL2 Ubuntu installation, decouple standard ingress controllers, compile natively backed Docker Engines, and implement a live-routed mock architecture setup.

Step 1: Systemd Initialization & Distro Optimization

Fresh installations of WSL2 Ubuntu natively omit standard systemd control configurations. Because standard native container engines require service daemons to consistently scale backgrounds, we must explicitly declare boot parameters.

Execute system packages alignment:

sudo apt update && sudo apt upgrade -y

Modify or create the internal WSL initialization metadata block via /etc/wsl.conf:

sudo nano /etc/wsl.conf

Append the target specification layout directly within the system configuration framework:

[boot]
systemd=true

Save and write structural changes via Ctrl+O, Enter, and exit using Ctrl+X. To ensure your host machine cleanly reinitializes the background partition, drop down to an external Windows PowerShell instance and force clear runtime processes:

wsl --shutdown

Relaunch your target Linux environment tab to bring the updated systemd context completely live.

Step 2: Bare-Metal Docker Engine Setup (Avoiding Desktop overhead)

To avoid massive software layers or license bounds from external host dashboards, we install the native Linux enterprise variant directly inside the kernel environment.

First, implement target prerequisite verification systems:

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
Troubleshooting Highlight: Ubuntu 24.04 (Noble) GPG Reference Changes

In modern Ubuntu builds, dropping absolute system keys to old binary paths throw GPG verification faults. If you encounter a NO_PUBKEY 7EA0A9C3F273FCD8 verification lock during setup, execute this updated armored format initialization sequence to clear the signature map:

# Force clean old references
sudo rm -f /etc/apt/sources.list.d/docker.list

# Fetch the updated ascii armor key architecture
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

With correct armor maps established, write the repository path into your source tree lists:

echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu   $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Trigger source parsing and download core functional engine runtime units:

sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Elevate privileges for your standard non-root shell profile to avoid structural sudo wrappers during local cluster builds:

sudo usermod -aG docker $USER
newgrp docker

Validate total loop integrity by running a containerized health test instance:

docker run hello-world

Step 3: Cluster Tooling Matrix Acquisition

With operational container environments running, configure standard control paths by pulling specific orchestration, configuration management, and hypervisor command tools:

# 1. Acquire Kubernetes Target Command Interface (kubectl)
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
rm kubectl

# 2. Acquire Helm Package Management Systems
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# 3. Acquire Native k3d Orchestration Boundary Tools
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash

Step 4: k3d Cluster Provisioning (Stripping Traefik)

Standard k3s patterns ship with Traefik embedded as a built-in proxy. To protect target network traffic paths for NGINX Gateway Fabric, we completely disable the default setup and explicitly reserve host network interfaces on ports 80 and 443.

Provision the targeted engine cluster instance topology:

k3d cluster create my-gateway-cluster   --port "80:80@loadbalancer"   --port "443:443@loadbalancer"   --k3s-arg "--disable=traefik@server:*"

Verify that core component services boot up smoothly with no remnants of the old default proxy layer:

kubectl get pods -A

Step 5: Modern Gateway API CRD Framework & NGF Provisioning

Because the classic Ingress resource paradigm is deprecated, we install the standardized CRD profiles managed directly by the Kubernetes SIG structure.

Pull and scale down channel resources:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
Troubleshooting Highlight: OCI Helm Chart Distribution Mapping

Unlike standard application indexes, NGINX distributes Gateway Fabric structures completely as an Open Container Initiative (OCI) package via the GitHub Container Registry. Traditional helm repo add workflows will fail with a 404 Not Found. Skip index additions entirely and download directly with an inline OCI reference flag:

helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric   --create-namespace   --namespace nginx-gateway   --set service.type=LoadBalancer

Step 6: Core Gateway Infrastructure Declarations

An abstract control plane installation won't respond to host ports until a physical Gateway instance resource binds directly to an edge adapter profile.

Construct a target configurations manifest named gateway.yaml:

nano gateway.yaml

Populate the file blueprint with the structural tracking manifest detailed below:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: nginx-gateway
  namespace: nginx-gateway
spec:
  gatewayClassName: nginx
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All

Apply changes directly into the orchestration environment engine:

kubectl apply -f gateway.yaml

Step 7: Smoke Testing cross-Namespace Ingress Controls

To verify proper functional routing end-to-end, create a running service instance in your target namespace environment and explicitly route to it from the cluster's gateway border using a custom HTTPRoute object.

Syntax & Configuration Architecture Warning

Ensure that structural parameters like backendRefs are configured directly under individual rules nodes, rather than buried deep within structural matches arrays. Improperly nested fields throw deep API schema structural validation errors (strict decoding error: unknown field).

Deploy a demo environment instance configuration into the cluster topology:

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-app
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-app
  template:
    metadata:
      labels:
        app: test-app
    spec:
      containers:
      - name: hello
        image: nginx:alpine
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: test-app-svc
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: test-app
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: test-route
  namespace: nginx-gateway
spec:
  parentRefs:
  - name: nginx-gateway
    namespace: nginx-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: test-app-svc
      namespace: default
      port: 80
EOF
Troubleshooting Highlight: Navigating 503 Service Errors

If curling your local endpoint displays an empty 503 Service Temporarily Unavailable banner, the NGINX control structure is functioning correctly, but the underlying service can't route traffic down to your backend instance pods. This is almost always caused by an ImagePullBackOff error during a standard Docker Hub rate limit lock. Swapping target tags over to streamlined configurations like nginx:alpine fixes pulling blocks instantly.

Step 8: Final Ingress Validation Sweep

Confirm that your app container status transitions completely into a stable 1/1 Running mode state:

kubectl get pods -n default

Now, query the host port directly from your terminal session to test routing behavior across the network:

curl http://localhost/
Verification Success Confirmation

When the platform responds with the official NGINX welcome screen raw code payload (<!DOCTYPE html>...<title>Welcome to nginx!</title>), your stack is verified! Windows and Linux host ports are perfectly mapped straight through the custom k3d load balancer array, managed securely by the active NGINX Gateway Fabric control framework.

Comments

Popular posts from this blog

Kursus Induksi

FreeBSD Apache HTTP Accept Filter Error

Docker error : The network name cannot be found.