Exercise 7: Ingress with the Gateway API

In this exercise, you will expose your application using the Kubernetes Gateway API via the managed Application Routing add-on, giving it a single external IP address. The Gateway API is the successor to the older Ingress resource and is the recommended way to manage external access to services in your cluster.

Info

Your cluster was created with the Application Routing Gateway API add-on (--enable-app-routing-istio) and the Managed Gateway API CRDs (--enable-gateway-api) back in Exercise 1 . This add-on deploys a managed Istio control plane that provisions the infrastructure behind your Gateway API resources using the approuting-istio GatewayClass. You only work with standard Gateway and HTTPRoute you do not interact with Istio directly.resources

Task 1 - Confirm the Gateway API add-on is ready

  1. Confirm the managed Gateway API CRDs are installed:

    kubectl get crds | Select-String "gateway.networking.k8s.io"
    kubectl get crds | grep "gateway.networking.k8s.io"

    You should see CRDs such as gateways.gateway.networking.k8s.io and httproutes.gateway.networking.k8s.io.

  2. Confirm the approuting-istio GatewayClass exists and the control plane is running:

    kubectl get gatewayclass
    kubectl get pods -n aks-istio-system
    kubectl get gatewayclass
    kubectl get pods -n aks-istio-system

    You should see a GatewayClass named approuting-istio and istiod pods running in the aks-istio-system namespace.

Task 2 - Create a Gateway

  1. Create a Gateway resource that listens for HTTP traffic on port 80. This provisions a managed external load balancer for your ingress traffic.

    $gatewayYaml = @"
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: sample-gateway
    spec:
      gatewayClassName: approuting-istio
      listeners:
      - name: http
        port: 80
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: Same
    "@
    
    # Apply the Gateway manifest
    $gatewayYaml | kubectl apply -f -
    cat << EOF | kubectl apply -f -
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: sample-gateway
    spec:
      gatewayClassName: approuting-istio
      listeners:
      - name: http
        port: 80
        protocol: HTTP
        allowedRoutes:
          namespaces:
            from: Same
    EOF
  2. The add-on provisions a Deployment, Service, and load balancer named sample-gateway-approuting-istio. Wait for the Gateway to be programmed and get its assigned public IP address:

    kubectl wait --for=condition=programmed gateway/sample-gateway --timeout=120s
    kubectl get gateway sample-gateway
    kubectl wait --for=condition=programmed gateway/sample-gateway --timeout=120s
    kubectl get gateway sample-gateway

    The ADDRESS column shows the public IP you will use to access your app.

Task 3 - Create an HTTPRoute

  1. Create an HTTPRoute that routes HTTP traffic to your existing service (sample-svc) on port 80 when requests are sent to the lab.kubernetes.demo host:

    $httpRouteYaml = @"
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: sample-route
    spec:
      parentRefs:
      - name: sample-gateway
      hostnames:
      - lab.kubernetes.demo
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: sample-svc
          port: 80
    "@
    
    # Apply the HTTPRoute manifest
    $httpRouteYaml | kubectl apply -f -
    cat << EOF | kubectl apply -f -
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: sample-route
    spec:
      parentRefs:
      - name: sample-gateway
      hostnames:
      - lab.kubernetes.demo
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: sample-svc
          port: 80
    EOF
  2. Check that the HTTPRoute is created and accepted:

    kubectl get httproute
    kubectl get httproute

Task 4 - Test Access via the Gateway

Important

At this point, if you were doing this for real, you would need to configure your DNS to point lab.kubernetes.demo to the Gateway’s public IP address. You would also want to set up a TLS certificate for secure access.

For the purposes of this lab, we will test the Gateway by calling its public IP from the command line, with a host header set to lab.kubernetes.demo.

  1. Capture the Gateway’s public IP address into a variable:

    $INGRESS_IP = kubectl get gateway sample-gateway -o jsonpath='{.status.addresses[0].value}'
    Write-Host $INGRESS_IP
    INGRESS_IP=$(kubectl get gateway sample-gateway -o jsonpath='{.status.addresses[0].value}')
    echo "$INGRESS_IP"
  2. Use the following command to test access to your service via the Gateway:

    Invoke-WebRequest -Uri "http://$INGRESS_IP" -Headers @{ Host = "lab.kubernetes.demo" }
    curl -H "Host: lab.kubernetes.demo" http://$INGRESS_IP
  3. If you used PowerShell, you should see the response from your service, with a 200 OK code, indicating that the Gateway is correctly routing traffic to your service.

    If you used Bash, you will see the raw HTML of the webpage being displayed, and near the top you should see a line like this:

        <title>Welcome to Color Demo</title>

Task 5 - Clean Up

  1. Deleting any pod within our current Deployment will simply tell Kubernetes that the Deployment is not in its desired state and it will automatically create a replacement. You can only delete pods that were spawned by a Deployment by deleting the Deployment.

  2. Delete the Deployment.

    kubectl delete deployment sample-dep
    kubectl delete deployment sample-dep
  3. The Service is independent of the pods it services, so it’s not affected when the Deployment is deleted. Anyone trying to access the service’s address will simply get an error message. If the Deployment is ever re-created, the Service will automatically start sending traffic to the new pods.

  4. Delete the Service. This may take a little while to complete, as Kubernetes will first remove the public IP and then delete the Service.

    kubectl delete service sample-svc
    kubectl delete service sample-svc
  5. Finally, delete the HTTPRoute and Gateway:

    kubectl delete httproute sample-route
    kubectl delete gateway sample-gateway
    kubectl delete httproute sample-route
    kubectl delete gateway sample-gateway