Kubernetes Gateway API CRDs and cluster-level Gateway resources for drunk.charts
The drunk-k8s-gateway chart automates the installation and configuration of:
This chart reuses drunk-lib to maintain consistency across the drunk.charts ecosystem.
# Install CRDs first
./scripts/install-crds.sh
# Install the chart with default settings
helm install gateway drunk-charts/drunk-k8s-gateway
# Or install from local directory
helm install gateway . -n gateway-system --create-namespace
If you’re working with the chart locally, build it first to download Gateway API CRDs:
# Build the chart (downloads Gateway API CRDs automatically)
./build.sh
# This will:
# - Download Gateway API CRDs to templates/gateway-api-crds.yaml
# - Update chart dependencies
# - Package the chart
Note: Pre-built charts from the Helm repository already include the CRDs.
The Gateway API CRDs are now included in the chart and will be installed automatically.
Option A: Install with Helm (Recommended)
# CRDs are included in the chart
helm install gateway drunk-charts/drunk-k8s-gateway \
-n gateway-system \
--create-namespace
Option B: Install CRDs separately (if needed)
If you prefer to install CRDs separately or need to update them independently:
# Using the provided script
cd scripts
chmod +x install-crds.sh
./install-crds.sh
# Or manually with kubectl
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# For experimental features (GRPC, TCP, TLS, UDP routes)
./install-crds.sh --channel experimental
Verify installation:
kubectl get crd | grep gateway
Expected output:
gatewayclasses.gateway.networking.k8s.io
gateways.gateway.networking.k8s.io
httproutes.gateway.networking.k8s.io
referencegrants.gateway.networking.k8s.io
Choose and install a Gateway controller implementation. This chart vendors the official Traefik Helm chart for lightweight, K3s-friendly Gateway API support.
This chart vendors the official traefik Helm chart (version 33.2.0) with Kubernetes Gateway API support enabled. This is the lightest-weight option and perfect for K3s, kind, or minikube.
Minimal values enabling Traefik (disables duplicate parent GatewayClass):
gatewayClass:
enabled: false # Let Traefik create the GatewayClass
traefik:
enabled: true
experimental:
kubernetesGateway:
enabled: true
providers:
kubernetesGateway:
enabled: true
service:
type: NodePort # For kind/minikube/k3s; use LoadBalancer in cloud
ports:
web:
nodePort: 31437
websecure:
nodePort: 31438
Install with the above saved as values-traefik.yaml:
helm upgrade --install gateway ./drunk-k8s-gateway \
-n drunk-gateway --create-namespace \
-f values-traefik.yaml
You can override any upstream chart setting under the traefik: key. For example to set resources:
helm upgrade --install gateway ./drunk-k8s-gateway \
-n drunk-gateway --create-namespace \
--set gatewayClass.enabled=false \
--set traefik.enabled=true \
--set traefik.resources.requests.memory=100Mi
If you prefer independent lifecycle management:
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik \
--namespace traefik --create-namespace \
--set experimental.kubernetesGateway.enabled=true \
--set providers.kubernetesGateway.enabled=true
Istio:
istioctl install --set profile=default
Other implementations: See Gateway API Implementations
For Azure AKS deployments, use values.aks.yaml:
values.aks.yaml — ready-to-go values for Azure AKS deployments using an
internal Azure Load Balancer. Customize loadBalancerIP and (optionally)
the internal-LB subnet annotation before installing. See QUICKSTART.md.You have two options to install cert-manager:
Option A: Install as a dependency (Recommended)
cert-manager can be installed automatically with this chart:
# Install drunk-k8s-gateway with cert-manager
helm install gateway drunk-charts/drunk-k8s-gateway \
--set certManager.install=true \
--set certManager.installCRDs=true \
-n gateway-system \
--create-namespace
# Verify cert-manager installation
kubectl get pods -n cert-manager
Option B: Install separately
Install cert-manager independently before this chart:
# Install cert-manager using Helm
helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
--version v1.19.1 \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=true
# Verify installation
kubectl get pods -n cert-manager
For more information: cert-manager documentation
# Create a values file
cat > values-production.yaml << EOF
gatewayClass:
enabled: true
name: nginx
controllerName: gateway.nginx.org/nginx-gateway-controller
gateway:
enabled: true
name: shared-gateway
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "*"
allowedRoutes:
namespaces:
from: All
- name: https
protocol: HTTPS
port: 443
hostname: "*"
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: wildcard-tls
allowedRoutes:
namespaces:
from: All
EOF
# Install the chart
helm install gateway drunk-charts/drunk-k8s-gateway \
-f values-production.yaml \
-n gateway-system \
--create-namespace
| Parameter | Description | Default |
|---|---|---|
gatewayAPI.version |
Gateway API version embedded at build | v1.2.0 |
gatewayAPI.channel |
Installation channel (standard/experimental) | standard |
gatewayClass.enabled |
Create GatewayClass resource | true |
gatewayClass.name |
Name of the GatewayClass | nginx |
gatewayClass.controllerName |
Controller identifier | gateway.nginx.org/nginx-gateway-controller |
gateway.enabled |
Create default Gateway | false |
gateway.name |
Name of the Gateway | shared-gateway |
gateway.gatewayClassName |
GatewayClass to use | nginx |
certManager.enabled |
Install cert-manager as dependency | false |
certManager.installCRDs |
Install cert-manager CRDs | true |
certManager.clusterIssuersEnabled |
Create ClusterIssuers (ACME) | false |
If Gateway API CRDs were installed previously (manually or by another chart), helm install may fail with an ownership error similar to:
Error: Unable to continue with install: CustomResourceDefinition "gatewayclasses.gateway.networking.k8s.io" ... exists and cannot be imported ... missing key "app.kubernetes.io/managed-by" ... missing key "meta.helm.sh/release-name"
Options to resolve:
./scripts/adopt-crds.sh gateway drunk-gateway
helm upgrade --install gateway ./drunk-k8s-gateway \
-n drunk-gateway --create-namespace -f values.local.yaml
helm install gateway ./drunk-k8s-gateway --skip-crds \
-n drunk-gateway --create-namespace -f values.local.yaml
kubectl delete crd gatewayclasses.gateway.networking.k8s.io \
gateways.gateway.networking.k8s.io httproutes.gateway.networking.k8s.io \
tcproutes.gateway.networking.k8s.io tlsroutes.gateway.networking.k8s.io \
udproutes.gateway.networking.k8s.io grpcroutes.gateway.networking.k8s.io \
referencegrants.gateway.networking.k8s.io
helm upgrade --install gateway ./drunk-k8s-gateway \
-n drunk-gateway --create-namespace -f values.local.yaml
Adoption simply adds Helm ownership annotations:
meta.helm.sh/release-name, meta.helm.sh/release-namespace and label app.kubernetes.io/managed-by=Helm.
Create a Gateway specifically for your domain (e.g., drunk.dev):
# values-drunk-dev.yaml
gatewayClass:
enabled: true
name: nginx
controllerName: gateway.nginx.org/nginx-gateway-controller
domains:
- name: drunk-dev
enabled: true
gatewayClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "*.drunk.dev"
allowedRoutes:
namespaces:
from: Same
- name: https
protocol: HTTPS
port: 443
hostname: "*.drunk.dev"
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: drunk-dev-tls
allowedRoutes:
namespaces:
from: Same
Install:
helm install drunk-gateway drunk-charts/drunk-k8s-gateway \
-f values-drunk-dev.yaml \
-n default
Prerequisites: Ensure cert-manager is installed (see Step 3 above).
Automatically create ClusterIssuers for TLS certificate management:
# values-with-certmanager.yaml
certManager:
enabled: true
clusterIssuers:
- name: letsencrypt-prod
email: admin@drunk.dev
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- http01:
gatewayHTTPRoute:
parentRefs:
- kind: Gateway
name: shared-gateway
namespace: default
- name: letsencrypt-staging
email: admin@drunk.dev
server: https://acme-staging-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-key
solvers:
- http01:
gatewayHTTPRoute:
parentRefs:
- kind: Gateway
name: shared-gateway
namespace: default
gateway:
enabled: true
name: shared-gateway
gatewayClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: "*.drunk.dev"
tls:
mode: Terminate
certificateRefs:
- kind: Secret
name: drunk-dev-tls
For wildcard certificates, use DNS-01 challenge:
certManager:
enabled: true
clusterIssuers:
- name: letsencrypt-prod
email: admin@drunk.dev
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-prod-key
solvers:
- dns01:
cloudflare:
apiTokenSecretRef:
name: cloudflare-api-token
key: api-token
selector:
dnsZones:
- "drunk.dev"
If you haven’t installed cert-manager yet, use Helm:
# Install cert-manager with CRDs
helm install cert-manager oci://quay.io/jetstack/charts/cert-manager \
--version v1.19.1 \
--namespace cert-manager \
--create-namespace \
--set crds.enabled=true
# Verify the installation
kubectl get pods -n cert-manager
kubectl get crd | grep cert-manager
For more information and configuration options:
gateway:
enabled: true
name: http-gateway
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
hostname: "*"
allowedRoutes:
namespaces:
from: All
domains:
- name: production
enabled: true
gatewayClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
listeners:
- name: https-prod
protocol: HTTPS
port: 443
hostname: "*.prod.example.com"
tls:
mode: Terminate
certificateRefs:
- name: prod-tls
- name: staging
enabled: true
gatewayClassName: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-staging
listeners:
- name: https-staging
protocol: HTTPS
port: 8443
hostname: "*.staging.example.com"
tls:
mode: Terminate
certificateRefs:
- name: staging-tls
Once your Gateway is deployed, use it with drunk-app:
# Application values
httpRoute:
enabled: true
parentRefs:
- name: shared-gateway
namespace: default
hostnames:
- myapp.drunk.dev
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: myapp-service
port: 80
Deploy:
helm install myapp drunk-charts/drunk-app \
--set httpRoute.enabled=true \
--set httpRoute.parentRefs[0].name=shared-gateway
kubectl get gatewayclass
kubectl describe gatewayclass nginx
kubectl get gateway -A
kubectl describe gateway shared-gateway
Expected status:
status:
conditions:
- type: Programmed
status: "True"
addresses:
- type: IPAddress
value: "10.96.100.100"
kubectl get gateway shared-gateway -o jsonpath='{.status.addresses[0].value}'
GATEWAY_IP=$(kubectl get gateway shared-gateway -o jsonpath='{.status.addresses[0].value}')
curl -H "Host: myapp.drunk.dev" http://$GATEWAY_IP/
# Check current version
kubectl get crd gateways.gateway.networking.k8s.io -o jsonpath='{.metadata.labels.gateway\.networking\.k8s\.io/bundle-version}'
# Upgrade to new version
./scripts/install-crds.sh --version v1.2.0
helm upgrade gateway drunk-charts/drunk-k8s-gateway \
-f values-production.yaml \
--reuse-values
helm uninstall gateway -n gateway-system
Warning: This will delete ALL Gateway API resources (Gateways, HTTPRoutes, etc.)
./scripts/uninstall-crds.sh
Symptom: Gateway shows Programmed: False
Solutions:
# Check Gateway events
kubectl describe gateway <gateway-name>
# Check controller logs
kubectl logs -n gateway-system -l app=gateway-controller
# Verify GatewayClass exists
kubectl get gatewayclass
Symptom: HTTPS not working or certificate errors
Solutions:
# Check if secret exists
kubectl get secret <tls-secret-name>
# If using cert-manager, check Certificate
kubectl get certificate
kubectl describe certificate <cert-name>
# Check ClusterIssuer
kubectl get clusterissuer
kubectl describe clusterissuer <issuer-name>
Symptom: HTTPRoute shows no parent
Solutions:
# Verify Gateway name and namespace
kubectl get gateway -A
# Check allowed routes in Gateway
kubectl get gateway <gateway-name> -o yaml | grep -A 10 allowedRoutes
# Verify HTTPRoute parent references
kubectl describe httproute <route-name>
gatewayClass:
enabled: true
name: nginx-custom
controllerName: gateway.nginx.org/nginx-gateway-controller
parametersRef:
group: gateway.nginx.org
kind: NginxProxy
name: nginx-proxy-config
Deploy separate charts for different controllers:
# NGINX Gateway
helm install nginx-gateway drunk-charts/drunk-k8s-gateway \
--set gatewayClass.name=nginx \
--set gatewayClass.controllerName=gateway.nginx.org/nginx-gateway-controller
# Istio Gateway
helm install istio-gateway drunk-charts/drunk-k8s-gateway \
--set gatewayClass.name=istio \
--set gatewayClass.controllerName=istio.io/gateway-controller
This chart is designed to work seamlessly with drunk-app:
parentRefsExample workflow:
# 1. Deploy Gateway infrastructure
helm install gateway drunk-charts/drunk-k8s-gateway -f gateway-values.yaml
# 2. Deploy application with HTTPRoute
helm install myapp drunk-charts/drunk-app \
--set httpRoute.enabled=true \
--set httpRoute.parentRefs[0].name=shared-gateway \
--set httpRoute.hostnames[0]=myapp.drunk.dev
Contributions are welcome! Please see the main drunk.charts repository for contribution guidelines.
This chart is part of the drunk.charts project and follows the same license.