Replace nginx ingress with istio virtual services

What is Istio : Istio helps reduce the complexity of these deployments. It is a completely open source service mesh that layers transparently onto existing distributed applications. It is also a platform, including APIs that let it integrate into any logging platform, or telemetry or policy system.

In this blog I will mainly talk about replacing nginx ingress with istio virtual services . Although I will not use the isio mesh telemetry ,side car here.

There are following steps to deploy istio and replace nginx

1. Deploy Istio :

 we can deploy istio using istioctl in the cluster or we can use the istio helm charts to do that.

so that istio gateway will get installed.

2. Get the existing nginx ingress configuration in the cluster.

    sample nginx ingress rules looks like. 

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: nginx-control-plane
    nginx.ingress.kubernetes.io/backend-protocol: HTTPS
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
  labels:
    app: custom-ui
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/name: api-kubernetes
    heritage: helm
  name: ui-proxies-https
  namespace: custom-ui
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: kubernetes-api
          servicePort: 443
        path: /api/kubernetes(/|$)(.*)
      - backend:
          serviceName: salt-api
          servicePort: 4507
        path: /api/salt(/|$)(.*)
status:
  loadBalancer:
    ingress:
    - ip: <IP>

3. In Istio to achieve the same functionality like above, we need to create virtualservice .

As we can see in nginx we have nginx.ingress.kubernetes.io/backend-protocol and 

nginx.ingress.kubernetes.io/rewrite-target annotations. 
those two we need to handle in istio.

for backend protocol https, we need to create a destination rule in istio.

corresponding virtual service: 

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
name: ui-proxies-https
  namespace: custom-ui
spec:
  gateways:
  - istio-system/istio-gateway
  hosts:
  - '*'
  http:
  - match:
    - uri:
        prefix: /api/kubernetes/
    rewrite:
      uri: /
    route:
    - destination:
        host: kubernetes.default.svc.cluster.local
        port:
          number: 443
      weight: 100
  - match:
    - uri:
        prefix: /api/salt/
    rewrite:
      uri: /
    route:
    - destination:
        host: salt-api.default.svc.cluster.local
        port:
        number: 4507
      weight: 100

Here main issue that I had faced was regarding the prefix, it should have the end '/' and rewrite should also present.

host: -> should point to proper service full qualified name ( check the service is in which namespace. give proper service name)


4. Now for the https backend part we need to write destination rule for each of the match..

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: kubernetes-dr
  namespace: custom-ui
spec:
  host: kubernetes.default.svc.cluster.local
  trafficPolicy:
    portLevelSettings:
    - loadBalancer:
        simple: ROUND_ROBIN
      port:
        number: 443
      tls:
        caCertificates: /etc/istio/ingressgateway-certs/kubeca.crt
        mode: SIMPLE

salt-api destination rule: 
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: ui-proxies-https-salt-api
  namespace: custom-ui
spec:
  host: salt-api.default.svc.cluster.local
  trafficPolicy:
    portLevelSettings:
    - loadBalancer:
        simple: ROUND_ROBIN
      port:
        number: 4507
      tls:
        caCertificates: /etc/istio/ingressgateway-certs/kube-api-ca.crt
        mode: SIMPLE

points to note:
host mentioned in the destination rule should match with host mentioned in virtual service.
add the backend service ca.crt in istio gateway pod.


Here the flow is 
client sends HTTPS -> TLS termination by the ingress gateway -> HTTP -> HTTP routing by the VirtualService -> TLS origination by the DestinationRule sends HTTPS -> destination https service.

Comments