Exercise
- Prerequisites
Make sure you have installed the helm client on your host machine.
- Install the Gateway API CRDs and Envoy Gateway controller
helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.4.2 -n envoy-gateway-system --create-namespaceWait for Envoy Gateway to be ready.
kubectl wait --timeout=5m -n envoy-gateway-system deployment/envoy-gateway --for=condition=AvailableCreate the GatewayClass.
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: eg
spec:
controllerName: gateway.envoyproxy.io/gatewayclass-controller
EOF- Create a pod named ghost based on the ghost:4 image and expose it with a ClusterIP service
Create a Gateway resource
Create an HTTPRoute resource to expose the ghost service
Verify you can access the ghost web interface
Create a self-signed TLS certificate for the ghost application
Update the Gateway to support HTTPS with TLS
Verify HTTPS access through the Gateway API
Clean up all resources
Documentation
https://kubernetes.io/docs/concepts/services-networking/gateway/
https://gateway-api.sigs.k8s.io/
Solution
- Install the Gateway API CRDs and Envoy Gateway controller
Commands provided in instructions.
- Create a pod named ghost based on the ghost:4 image and expose it with a ClusterIP service
kubectl run ghost --image=ghost:4 --port 2368 --expose- Create a Gateway resource
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ghost
spec:
gatewayClassName: eg
listeners:
- name: http
port: 80
protocol: HTTP
EOFThe Gateway will create a LoadBalancer service.
$ kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
envoy-default-ghost-c7075eaa LoadBalancer 10.96.231.63 <pending> 80:31283/TCP 2m38sThe following command gets the value of the NodePort assigned to the HTTP (80) port.
HTTP_NODEPORT=$(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==80)].nodePort}')
echo "Gateway HTTP accessible on NodePort: $HTTP_NODEPORT"As we’ll use the NodePort access, we need to patch the Service so we can reach the Pods from any node.
kubectl -n envoy-gateway-system patch $(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o name) -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'- Create an HTTPRoute resource to expose the ghost service
We create the following HTTPRoute (this is the Gateway API equivalent of an Ingress resource).
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ghost
spec:
parentRefs:
- name: ghost
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: ghost
port: 2368
EOF- Verify you can access the ghost web interface
# Get node IP
NODE_IP=$(kubectl get nodes -o jsonpath='{.items[0].status.addresses[?(@.type=="InternalIP")].address}')
# Get the NodePort (if not already set from previous step)
HTTP_NODEPORT=$(kubectl -n envoy-gateway-system get svc -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==80)].nodePort}')
echo "Ghost application accessible at: http://$NODE_IP:$HTTP_NODEPORT"
# Test HTTP access
curl http://$NODE_IP:$HTTP_NODEPORT/The ghost web interface should be accessible at http://$NODE_IP:$HTTP_NODEPORT
- Create a self-signed TLS certificate for the ghost application
# Generate private key and certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout ghost-tls.key \
-out ghost-tls.crt \
-subj "/CN=ghost.local"
# Create Kubernetes Secret
kubectl create secret tls ghost-tls-secret \
--cert=ghost-tls.crt \
--key=ghost-tls.key- Update the Gateway to support HTTPS with TLS
# Update Gateway to include HTTPS listener
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ghost
spec:
gatewayClassName: eg
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: ghost-tls-secret
EOFAs we’ll use the NodePort access, we need to patch the Service so we can reach the Pods from any node.
kubectl -n envoy-gateway-system patch $(kubectl get svc -n envoy-gateway-system -l gateway.envoyproxy.io/owning-gateway-name=ghost -o name) -p '{"spec":{"externalTrafficPolicy":"Cluster"}}'- Verify HTTPS access through the Gateway API
# Get the NodePort assigned to HTTPS (port 443)
HTTPS_NODEPORT=$(kubectl -n envoy-gateway-system get svc -l gateway.envoyproxy.io/owning-gateway-name=ghost -o jsonpath='{.items[0].spec.ports[?(@.port==443)].nodePort}')
echo "Gateway HTTPS accessible on NodePort: $HTTPS_NODEPORT"
# Test HTTPS access (with self-signed cert)
curl -k https://$NODE_IP:$HTTPS_NODEPORT/- Clean up all resources, and remove envoy gateway
kubectl delete httproute ghost
kubectl delete gateway ghost
kubectl delete secret ghost-tls-secret
kubectl delete pod ghost
kubectl delete service ghost
rm ghost-tls.key ghost-tls.crt
helm uninstall eg -n envoy-gateway-system