Publishing applications using Istio

Application publishing with Istio is configured in two layers. The cluster administrator deploys the IngressIstioController (and related infrastructure) as described in “Istio Ingress Gateway”. Application developers create Gateway and VirtualService resources as shown below.

When deploying an application using Istio, choose one of the following options: “Publishing applications using Ingress NGINX” or “Publishing applications using Istio Ingress Gateway resource”.

Publishing applications using Ingress NGINX

To publish an application using Ingress NGINX, the cluster administrator must configure the Ingress controller by adding an Istio sidecar to it.

To publish an application, prepare an Ingress resource that references a Service. Set ingressClassName to the controller with the Istio sidecar (the administrator provides the value). Required annotations for the Ingress resource:

  • nginx.ingress.kubernetes.io/service-upstream: "true": With this annotation, the Ingress controller will send requests to the Service’s ClusterIP (from the Service CIDR range) instead of sending them directly to the application’s Pods. The istio-proxy sidecar container intercepts traffic only toward the Service CIDR range. All other requests are sent directly.
  • nginx.ingress.kubernetes.io/upstream-vhost: productpage.bookinfo.svc: With this annotation, the sidecar can identify the application service the request is intended for.

Examples:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: productpage
  namespace: bookinfo
  annotations:
    # Enables proxying traffic to the Service's ClusterIP via nginx instead of directly to Pod IPs.
    nginx.ingress.kubernetes.io/service-upstream: "true"
    # In Istio, all routing is based on the `Host:` request header.
    # This avoids the need to inform Istio about the existence of the external domain `productpage.example.com`;
    # the internal domain known to Istio is used instead.
    nginx.ingress.kubernetes.io/upstream-vhost: productpage.bookinfo.svc
spec:
  ingressClassName: nginx # IngressClass name of the controller with the Istio sidecar.
  rules:
    - host: productpage.example.com
      http:
        paths:
        - path: /
          pathType: Prefix
          backend:
            service:
              name: productpage
              port:
                number: 9080
apiVersion: v1
kind: Service
metadata:
  name: productpage
  namespace: bookinfo
spec:
  ports:
  - name: http
    port: 9080
  selector:
    app: productpage
  type: ClusterIP

Publishing applications using Istio Ingress Gateway resource

To publish an application using the Istio Ingress Gateway, the cluster administrator must create an IngressIstioController resource.

To publish an application using the Istio Ingress Gateway resource, create a Gateway. In spec.selector, specify the label that references ingressGatewayClass and the Secret name provided by the cluster administrator:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: gateway-app
  namespace: app-ns
spec:
  selector:
    # Value of ingressGatewayClass provided by the cluster administrator.
    istio.deckhouse.io/ingress-gateway-class: istio-hp
  servers:
    - port:
        # Standard template for using the HTTP protocol.
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - app.example.com
    - port:
        # Standard template for using the HTTPS protocol.
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        # Secret with the certificate and key created by the administrator in the d8-ingress-istio namespace.
        # Supported Secret formats: https://istio.io/latest/docs/tasks/traffic-management/ingress/secure-ingress/#key-formats.
        credentialName: app-tls-secret
      hosts:
        - app.example.com

Then define routing rules with a VirtualService that links the Gateway to the service it serves:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-app
  namespace: app-ns
spec:
  gateways:
    - gateway-app # Name of the Gateway resource created above.
  hosts:
    - app.example.com
  http:
    - route:
        - destination:
            host: app-svc # Name of the service that should receive traffic.

Canary deployment with VirtualService

For a general overview of canary in Deckhouse Platform (DP), see “Canary deployment”. The example below uses VirtualService and DestinationRule.

To shift traffic gradually between application versions, use a DestinationRule with subsets and weights in the VirtualService. The example below sends 90% of traffic to the stable version and 10% to canary:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: app-svc
  namespace: app-ns
spec:
  host: app-svc
  subsets:
    - name: stable
      labels:
        version: v1
    - name: canary
      labels:
        version: v2
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vs-app
  namespace: app-ns
spec:
  gateways:
    - gateway-app
  hosts:
    - app.example.com
  http:
    - route:
        - destination:
            host: app-svc
            subset: stable
          weight: 90
        - destination:
            host: app-svc
            subset: canary
          weight: 10

Pods of each version must have the version: v1 and version: v2 labels that match the DestinationRule subsets. Before changing weights, confirm that both versions are selected by the app-svc Service.

After you apply the manifests, send a few requests to app.example.com and check that traffic is split roughly 90/10. To identify which version responded, use whatever the application itself exposes to distinguish stable from canary — for example, a value in the response body or a dedicated HTTP header:

for i in $(seq 1 20); do curl -s https://app.example.com/ | grep version; done \
  | sort | uniq -c

Adjust the weights if needed and recheck.

Additional resources