Skip to content

Ingress

The objective of this lab is to expose the web-frontend service to the internet.

The Ingress gateway

When you installed Istio, in addition to deploying istiod to Kubernetes, the installation also provisioned an Ingress Gateway.

View the corresponding Istio ingress gateway pod in the istio-system namespace.

kubectl get pod -n istio-system

A corresponding LoadBalancer type service was also created:

kubectl get svc -n istio-system

Make a note of the external IP address for the load balancer.

Assign it to an environment variable.

export GATEWAY_IP=$(kubectl get svc -n istio-system istio-ingressgateway \
    -ojsonpath='{.status.loadBalancer.ingress[0].ip}')

When using K3D

If you have opted to run Kubernetes directly on your local machine with K3D, use "127.0.0.1" instead:

export GATEWAY_IP=127.0.0.1
A small investment

When the cloud shell connection is severed, or when opening a new terminal tab, $GATEWAY_IP will no longer be in scope.

Ensure GATEWAY_IP is set each time we start a new shell:

cat << EOF >> ~/.bashrc

export GATEWAY_IP=$(kubectl get svc -n istio-system istio-ingressgateway -ojsonpath='{.status.loadBalancer.ingress[0].ip}')

EOF

In normal circumstances we associate this IP address with a hostname via DNS. For the sake of simplicity, in this workshop we will use the gateway public IP address directly.

Configuring ingress

Configuring ingress with Istio is performed in two parts:

  1. Define a Gateway Custom Resource that governs the specific host, port, and protocol to expose.
  2. Specify how requests should be routed with a VirtualService Custom Resource.

Create a Gateway resource

  1. Review the following Gateway specification.

    gateway.yaml

    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: frontend-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    

    Above, we specify the HTTP protocol, port 80, and a wildcard ("*") host matcher which ensures that HTTP requests using the load balancer IP address $GATEWAY_IP will match.

    The selector istio: ingressgateway selects the Envoy gateway workload to be configured, the one residing in the istio-system namespace.

  2. Apply the gateway resource to your cluster.

    kubectl apply -f gateway.yaml
    
  3. Attempt an HTTP request in your browser to the gateway IP address.

    curl -v http://$GATEWAY_IP/
    

    It should return a 404: not found.

Create a VirtualService resource

  1. Review the following VirtualService specification.

    web-frontend-virtualservice.yaml
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: web-frontend
    spec:
      hosts:
      - "*"
      gateways:
      - frontend-gateway
      http:
      - route:
        - destination:
            host: web-frontend.default.svc.cluster.local
            port:
              number: 80
    

    Note how this specification references the name of the gateway ("frontend-gateway"), a matching host ("*"), and specifies a route for requests to be directed to the web-frontend service.

  2. Apply the VirtualService resource to your cluster.

    kubectl apply -f web-frontend-virtualservice.yaml
    
  3. List virtual services in the default namespace.

    kubectl get virtualservice
    

    The output indicates that the VirtualService named web-frontend is bound to the gateway frontend-gateway, as well as any hostname that routes to the load balancer IP address.

Finally, verify that you can now access web-frontend from your web browser using the gateway IP address.

What if I wanted to configure ingress with TLS?

Here is a recipe that illustrates how to configure secure ingress with a self-signed certificate:

  1. Generate the certificate:

    1. Generate a self-signed root certificate in the folder example_certs

      mkdir example_certs
      openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt
      
    2. Generate a certificate and private key for the hostname webfrontend.example.com:

      openssl req -out example_certs/webfrontend.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/webfrontend.example.com.key -subj "/CN=webfrontend.example.com/O=webfrontend organization"
      openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/webfrontend.example.com.csr -out example_certs/webfrontend.example.com.crt
      
  2. Store the certificate as a secret in your Kubernetes cluster:

    kubectl create -n istio-system secret tls webfrontend-credential \
      --key=example_certs/webfrontend.example.com.key \
      --cert=example_certs/webfrontend.example.com.crt
    
  3. Revise the gateway configuration to listen on port 443, and to reference the secret that the envoy listeners will present to incoming requests:

    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: frontend-gateway
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        tls:
          mode: SIMPLE
          credentialName: webfrontend-credential
        hosts:
        - webfrontend.example.com
    
  4. Apply the revised gateway configuration:

    kubectl apply -f gateway-tls.yaml
    
  5. Test your implementation by making a request to the ingress gateway:

    curl -k https://webfrontend.example.com/ --resolve webfrontend.example.com:443:$GATEWAY_IP
    

See the Istio documentation for additional examples relating to the topic of configuring secure gateways.

Next

The application is now running and exposed on the internet.

In the next lab, we turn our attention to the observability features that are built into Istio.