Exercise 2: Deploy an Application into the Mesh

In this exercise, you will create a namespace that participates in the mesh and deploy two versions of a simple web application.

Task 1: Create a Mesh-Enabled Namespace

  1. Create a namespace for the demo application and enable sidecar injection using the installed Istio revision.

    kubectl create namespace istio-demo
    kubectl label namespace istio-demo istio.io/rev=$ISTIO_REVISION
    kubectl create namespace istio-demo
    kubectl label namespace istio-demo istio.io/rev=$ISTIO_REVISION
    Warning

    With the AKS Istio add-on you must use the revision label istio.io/rev=<revision> (for example istio.io/rev=asm-1-24), not the generic istio-injection=enabled label you may have seen in the upstream open-source Istio documentation.

    The add-on runs a revisioned control plane so it can manage canary upgrades between Istio versions. The plain istio-injection=enabled label does not match a revisioned control plane, so the add-on skips sidecar injection for that namespace and your pods come up without a proxy. This is why the lab reads the installed revision into $ISTIO_REVISION in Exercise 1 and uses it here.

Task 2: Deploy Two Application Versions

  1. Deploy two versions of a simple web application and a single Kubernetes service that targets both versions.

    @"
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-v1
      namespace: istio-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: web
          version: v1
      template:
        metadata:
          labels:
            app: web
            version: v1
        spec:
          containers:
          - name: web
            image: ghcr.io/microsoft/k8s-on-azure-workshop/hello-app:1.0
            ports:
            - containerPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-v2
      namespace: istio-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: web
          version: v2
      template:
        metadata:
          labels:
            app: web
            version: v2
        spec:
          containers:
          - name: web
            image: ghcr.io/microsoft/k8s-on-azure-workshop/hello-app:2.0
            ports:
            - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web
      namespace: istio-demo
    spec:
      selector:
        app: web
      ports:
      - port: 80
        targetPort: 8080
        name: http
    "@ | kubectl apply -f -
    cat <<EOF | kubectl apply -f -
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-v1
      namespace: istio-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: web
          version: v1
      template:
        metadata:
          labels:
            app: web
            version: v1
        spec:
          containers:
          - name: web
            image: ghcr.io/microsoft/k8s-on-azure-workshop/hello-app:1.0
            ports:
            - containerPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web-v2
      namespace: istio-demo
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: web
          version: v2
      template:
        metadata:
          labels:
            app: web
            version: v2
        spec:
          containers:
          - name: web
            image: ghcr.io/microsoft/k8s-on-azure-workshop/hello-app:2.0
            ports:
            - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: web
      namespace: istio-demo
    spec:
      selector:
        app: web
      ports:
      - port: 80
        targetPort: 8080
        name: http
    EOF
  2. Confirm that each application pod has an Istio sidecar.

    kubectl get pods -n istio-demo
    kubectl get pods -n istio-demo

    Each pod should show 2/2 containers ready: the application container and the Istio sidecar proxy.

  3. List the individual containers in each pod to confirm that the Istio sidecar (istio-proxy) has been injected alongside the application container (web).

    kubectl get pods -n istio-demo `
      -o "custom-columns=NAME:.metadata.name,INIT-CONTAINERS:.spec.initContainers[*].name,CONTAINERS:.spec.containers[*].name"
    kubectl get pods -n istio-demo \
      -o 'custom-columns=NAME:.metadata.name,INIT-CONTAINERS:.spec.initContainers[*].name,CONTAINERS:.spec.containers[*].name'

    You should see output similar to the following:

    NAME                      INIT-CONTAINERS         CONTAINERS
    web-v1-7f9c8b8d6f-abcde   istio-validation,istio-proxy   web
    web-v1-7f9c8b8d6f-fghij   istio-validation,istio-proxy   web
    web-v2-6d5b7c9a4e-klmno   istio-validation,istio-proxy   web
    web-v2-6d5b7c9a4e-pqrst   istio-validation,istio-proxy   web
    Info

    The AKS Istio add-on uses Kubernetes native sidecar containers (an initContainer with restartPolicy: Always), which is why istio-proxy appears under INIT-CONTAINERS rather than alongside web in the CONTAINERS column. The behaviour is otherwise identical to a classic sidecar — Envoy runs for the lifetime of the pod, intercepts all traffic, and counts toward the pod’s READY status. The istio-validation init container runs once at startup to verify that iptables rules were applied correctly.