Transitioning from IBM Cloud Kubernetes Service Ingress to Istio Ingres

10 min read

Three stages to transition from Kubernetes Ingress resources to Istio’s ingress gateway.

Istio adds additional layers of management on top of those available in Kubernetes and allows developers to connect, secure, and manage microservices. You can learn more about the basics of Istio by reading our post, “What is Istio?”.

This tutorial will provide steps for migrating services from Kubernetes Ingress resources to Istio’s ingress gateways in an IBM Cloud Kubernetes Service environment.

Prerequisites

  • IBM Cloud Kubernetes Cluster with Istio installed—you can install manually by going to istio.io, or use the Managed Istio add-on.
  • Download Istio.

Use IBM Kubernetes Service ALB and Kubernetes Ingress resources to access a service

First, we will deploy a simple application (without Istio) and expose it using the normal Kubernetes Ingress. 

IBM Cloud Kubernetes Service exposes applications deployed within your cluster using Kubernetes Ingress resources. The application load balancer (ALB) accepts incoming traffic and forwards the requests to the corresponding service. Your cluster ALB is assigned a URL to expose the deployed services using the name format <cluster_name>.<region>.containers.appdomain.cloud. Retrieve your cluster’s Ingress subdomain and configure this value as an environment variable for the steps that follow:

export CLUSTER_NAME=<cluster>
export INGRESS_HOST=$(ibmcloud ks cluster get -c $CLUSTER_NAME | grep Subdomain | awk '{print $3}')
echo $INGRESS_HOST

For this tutorial, we will use a simple HTTP request and response service called httpbin. Begin by deploying a copy of this service to your space in IBM Cloud Kubernetes Service:

kubectl apply -f samples/httpbin/httpbin.yaml

Next, apply a Kubernetes Ingress resource to access the httpbin service and expose the /headers API:

kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: simple-ingress
  namespace: default
spec:
  rules:
    - host: $INGRESS_HOST
      http:
        paths:
          - path: /headers
            backend:
              serviceName: httpbin
              servicePort: 8000
EOF

The serviceName and servicePort match those specified in the Kubernetes service definition in samples/httpbin/httpbin.yaml. Verify that the httpbin service is now accessible using curl:

curl -i http://$INGRESS_HOST/headers

Example output:

HTTP/1.1 200 OK
Date: Mon, 13 Aug 2018 21:43:04 GMT
Content-Type: application/json
Content-Length: 304
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
{
  "headers": {
    "Accept": "*/*", 
    "Host": "istio-integration.us-south.containers.appdomain.cloud", 
    "User-Agent": "curl/7.54.0", 
    "X-Forwarded-Host": "istio-integration.us-south.containers.appdomain.cloud", 
    "X-Global-K8Fdic-Transaction-Id": "ba234fb0a36e57a20ee68e9da27ae6fd"
  }
}

Use Kubernetes Ingress to access Istio-enabled workloads 

With the Istio default configuration, you can continue using the standard Kubernetes Ingress resources to expose Istioe-nabled services (pods that have Istiosidecar). The Ingress resource configures the IBM Cloud Kubernetes Service nginx application load balancers that come with the service (in kube-system namespace). 

By default (permissive mtls policy), the sidecar will allow traffic from the ALB pods. Let's see this working by adding httpbin to the Istio service mesh and accessing it using the same Ingress from the previous section.

Label the namespace for automatic Istio sidecar injection:

kubectl label namespace default istio-injection=enabled

With this configured, any new pods will automatically get deployed with Istio’s sidecar proxy. Since httpbin is already deployed, deleting the httpbin pod will cause it to get redeployed with the sidecar in place:

kubectl delete pod -l app=httpbin
kubectl get pods
kubectl delete pod -l app=httpbin kubectl get pods

The httpbin pod now has two containers: httpbin app and istio-proxy sidecar. Verify the new httpbin pod is running and curl the httpbin service again:

curl -i http://$INGRESS_HOST/headers

Example output:

HTTP/1.1 200 OK
Date: Tue, 14 Aug 2018 00:19:47 GMT
Content-Type: application/json
Content-Length: 533
Connection: keep-alive
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 3
x-envoy-decorator-operation: httpbin.default.svc.cluster.local:8000/*
{
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "0", 
    "Host": "istio-integration.us-south.containers.appdomain.cloud", 
    "User-Agent": "curl/7.54.0", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "f1a011b53ba9cc4b", 
    "X-B3-Traceid": "f1a011b53ba9cc4b", 
    "X-Envoy-Internal": "true", 
    "X-Forwarded-Host": "istio-integration.us-south.containers.appdomain.cloud", 
    "X-Global-K8Fdic-Transaction-Id": "f9327e92e4aec58c04c19451a50967c8", 
    "X-Request-Id": "612a99ee-cf5e-94b7-b2ae-cbe1f98ef4a9"
  }
}

Observe the additional headers returned in the response this time around. The Envoy proxy running in the Istio sidecar captures all traffic to the httpbin service, applies any traffic management policies, and then routes the request to the httpbin service.

Note: If Istio was deployed with STRICT mTLS policy, the curl command above will fail since the Kubernetes Ingress resource does not have mTLS configured between the ALB and httpbin service. To direct encrypted traffic from IBM Cloud Kubernetes Service Ingress to Istio ingress gateway, see this blog.

Chain the IBM Cloud Kubernetes Service ALB to the Istio gateway

In this section, you will create an Ingress resource to point to the istio-ingressgateway Service and then use standard Istio Gateway and VirtualServices to route traffic from Istio Gateway to your Istio-enabled workloads.

The ALB relies on Kubernetes Ingress resources to control how traffic is routed to services deployed in your cluster. In Istio, Ingress traffic is configured via Gateways and VirtualServices. Gateways and VirtualServices provide a super set of the functionality provided by the Kubernetes Ingress resource in a more flexible format. In the same way that the routing behavior of the ALB is configured by Kubernetes Ingress resources, Istio uses Gateways and VirtualServices to configure Istio’s ingress gateway. Traffic from outside the Istio service mesh is routed by the ingress gateway:

kubectl get pods -n istio-system -l istio=ingressgateway
kubectl get pods -n istio-system -l istio=ingressgateway

To make the transition easier for users who may already have Kubernetes Ingress resources defined for their services, Istio provides a converter tool as part of istioctl for migrating Ingress resource definitions to corresponding VirtualServices:

kubectl get ingress simple-ingress -o yaml > ingress.yaml
istioctl convert-ingress -f ingress.yaml > vservice.yaml
cat vservice.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
....
spec:
  gateways:
  - istio-system/istio-autogenerated-k8s-ingress
  hosts:
  - gihanson-test.us-south.containers.appdomain.cloud
  http:
  - match:
    - uri:
        exact: /headers
    route:
    - destination:
        host: httpbin.default.svc.cluster.local
        port:
          number: 8000
      weight: 100

The VirtualService tells Istio which service to route to based on the request host and request path from a bound Gateway rule. The Gateway is required to open a port on the Istio ingress gateway for incoming requests but this has already been created during the install process:

kubectl get gateway istio-ingressgateway -n istio-system -o yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
....
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP2

Edit vservice.yaml and change gateways section to point to the above gateway:

  gateways:
  - istio-system/istio-ingressgateway

Apply the VirtualService:

kubectl apply -f vservice.yaml

Finally, the original Kubernetes Ingress resource needs to be deleted and recreated so that it points to the Istio ingress gateway rather than the httpbin service directly:

kubectl delete ingress simple-ingress
kubectl apply -f - <<EOF
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: simple-ingress
  namespace: istio-system
spec:
  rules:
    - host: $INGRESS_HOST
      http:
        paths:
          - path: /headers
            backend:
              serviceName: istio-ingressgateway
              servicePort: 80
EOF

Perform the curl command once more to verify that traffic is now routed from the ALB to the Istio ingress gateway and finally the httpbin service:

curl -i http://$INGRESS_HOST/headers

Create a host name to access the Istio ingress gateway directly

IBM Cloud Kubernetes Service allows users to configure a subdomain which will resolve directly to a Kubernetes network load balancer (NLB) IP. The steps below will enable the Istio ingress gateway to accept web traffic directly instead of first going through the ALB.

First, retrieve the NLB IP for the Istio ingress gateway:

export INGRESS_IP=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')

Then, create the host name for your cluster:

ibmcloud ks nlb-dns create classic --cluster $CLUSTER_NAME --ip $INGRESS_IP
ibmcloud ks nlb-dnss --cluster $CLUSTER_NAME

This will create a host name using the following format: 

<cluster_name>-<globally_unique_account_HASH>-0001.<region>.containers.appdomain.cloud.

Update Istio with the new host name. Replace the original INGRESS_HOST defined above with the host name created above:

export INGRESS_HOST=<new subdomain created above>

Apply the VirtualService rule (vservice.yaml) again so that the updated INGRESS_HOST value is picked up:

kubectl apply -f vservice.yaml

Now, you can curl the Istio ingress gateway directly using the NLB host name provided for your cluster:

curl -i http://$INGRESS_HOST/headers

Conclusions

With these instructions, existing services can be migrated from the default IBM Cloud Kubernetes Service ALB to using the Istio ingress gateway. After migration is complete, you can begin exploring the additional Ingress configuration options for your service mesh available with Istio Gateways and VirtualServices.

Related links 

Be the first to hear about news, product updates, and innovation from IBM Cloud