Introduction

Istio is the most widely adopted service mesh for Kubernetes, providing traffic management, security (mTLS), and observability without modifying application code. Managing Istio with Ansible brings repeatability and version control to service mesh configuration — deploy Istio, configure routing rules, enable mTLS, and set up monitoring with playbooks.

Prerequisites

```yaml


collections:

  • name: kubernetes.core version: ">=3.0.0"
  • name: community.general ```

```bash pip install kubernetes openshift ansible-galaxy collection install -r requirements.yml ```

Install Istio with Ansible

Download and Install istioctl

```yaml

  • name: Install Istio on Kubernetes hosts: localhost connection: local vars: istio_version: "1.24.0" istio_profile: "default" # minimal, default, demo, production tasks:
    • name: Download istioctl ansible.builtin.get_url: url: "https://github.com/istio/istio/releases/download/{{ istio_version }}/istioctl-{{ istio_version }}-linux-amd64.tar.gz" dest: "/tmp/istioctl.tar.gz"

    • name: Extract istioctl ansible.builtin.unarchive: src: "/tmp/istioctl.tar.gz" dest: /usr/local/bin/ remote_src: true

    • name: Install Istio with profile ansible.builtin.command: cmd: "istioctl install --set profile={{ istio_profile }} -y" register: istio_install changed_when: "'installed' in istio_install.stdout"

    • name: Enable sidecar injection for default namespace kubernetes.core.k8s: state: present definition: apiVersion: v1 kind: Namespace metadata: name: default labels: istio-injection: enabled

    • name: Verify Istio installation ansible.builtin.command: cmd: istioctl verify-install register: verify changed_when: false

    • name: Show Istio status ansible.builtin.debug: msg: "{{ verify.stdout }}" ```

Traffic Management

VirtualService and DestinationRule

```yaml

  • name: Configure traffic routing hosts: localhost connection: local tasks:
    • name: Create DestinationRule for versioned routing kubernetes.core.k8s: state: present definition: apiVersion: networking.istio.io/v1 kind: DestinationRule metadata: name: my-app namespace: production spec: host: my-app trafficPolicy: connectionPool: tcp: maxConnections: 100 http: h2UpgradePolicy: DEFAULT http1MaxPendingRequests: 100 subsets: - name: v1 labels: version: v1 - name: v2 labels: version: v2

    • name: Create VirtualService for canary routing kubernetes.core.k8s: state: present definition: apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: my-app namespace: production spec: hosts: - my-app http: - route: - destination: host: my-app subset: v1 weight: 90 - destination: host: my-app subset: v2 weight: 10 ```

Canary Deployment Playbook

```yaml

  • name: Canary deployment with Istio hosts: localhost connection: local vars: app_name: my-app namespace: production canary_weight: 10 stable_weight: 90 tasks:
    • name: Deploy canary version kubernetes.core.k8s: state: present definition: apiVersion: apps/v1 kind: Deployment metadata: name: "{{ app_name }}-v2" namespace: "{{ namespace }}" spec: replicas: 2 selector: matchLabels: app: "{{ app_name }}" version: v2 template: metadata: labels: app: "{{ app_name }}" version: v2 spec: containers: - name: "{{ app_name }}" image: "{{ app_image }}:{{ canary_tag }}" ports: - containerPort: 8080

    • name: Set canary traffic weight kubernetes.core.k8s: state: present definition: apiVersion: networking.istio.io/v1 kind: VirtualService metadata: name: "{{ app_name }}" namespace: "{{ namespace }}" spec: hosts: - "{{ app_name }}" http: - route: - destination: host: "{{ app_name }}" subset: v1 weight: "{{ stable_weight }}" - destination: host: "{{ app_name }}" subset: v2 weight: "{{ canary_weight }}"

    • name: Wait for canary pods to be ready kubernetes.core.k8s_info: kind: Deployment namespace: "{{ namespace }}" name: "{{ app_name }}-v2" register: canary_deploy until: canary_deploy.resources[0].status.readyReplicas | default(0) >= 2 retries: 30 delay: 10 ```

Enable mTLS

```yaml

  • name: Enable strict mTLS hosts: localhost connection: local tasks:
    • name: Enable mesh-wide strict mTLS kubernetes.core.k8s: state: present definition: apiVersion: security.istio.io/v1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICT

    • name: Create AuthorizationPolicy kubernetes.core.k8s: state: present definition: apiVersion: security.istio.io/v1 kind: AuthorizationPolicy metadata: name: allow-frontend-to-backend namespace: production spec: selector: matchLabels: app: backend action: ALLOW rules: - from: - source: principals: - cluster.local/ns/production/sa/frontend to: - operation: methods: ["GET", "POST"] paths: ["/api/*"] ```

Observability

```yaml

Troubleshooting

```bash

istioctl proxy-status

istioctl analyze --all-namespaces

kubectl get namespace -L istio-injection

istioctl proxy-config route <pod-name> -n <namespace>

kubectl logs -n istio-system -l app=istiod ```

Conclusion

Ansible + Istio provides declarative, version-controlled service mesh management. Use playbooks for Istio installation, traffic routing, mTLS policies, and observability stack deployment. Canary deployments with weighted routing give you safe, gradual rollouts with automatic traffic shifting.

For a production-focused walkthrough, see Luca Berton's guide on automating Kubernetes with Ansible.