Secure Communication in Kubernetes with Istio Service Mesh and Vault Agent Injector


Bicycle

Securing Communication in Kubernetes with Istio Service Mesh and Vault Agent Injector

In modern cloud-native Kubernetes environments, security is paramount. One of the key challenges is ensuring secure communication between microservices while also managing secrets securely. Whether you're running a monolithic application or a set of microservices in Kubernetes, securing inter-service communication and secret management is crucial to prevent unauthorized access and ensure data privacy. Enter Istio Service Mesh combined with HashiCorp Vault Agent Injector, a powerful combination that allows you to secure communication between services and manage secrets without the need to modify your application code.

In this blog post, we'll explore how you can secure the communication of your workloads in Kubernetes using Istio service mesh while leveraging Vault Agent Injector for dynamic secret management, building upon the concepts we demonstrated in our previous posts.

Note: This article combines concepts from our previous posts about Kubernetes and Vault Agent Injector: Dynamic Secrets Management and extends them with service mesh security patterns similar to those shown in Secure Communication on HashiCorp Nomad with Consul Connect.

What is Istio Service Mesh?

Istio is an open-source service mesh that provides a uniform way to secure, connect, and monitor microservices. It achieves this by enabling mutual Transport Layer Security (mTLS) between services, traffic management, observability, and policy enforcement. Each service gets its own identity, and Istio enforces that only trusted services can communicate with each other. By using Istio, service communication is authenticated and encrypted, ensuring that the network's security is maintained even in hostile or compromised environments.

Key Features of Istio:

  • mTLS (Mutual TLS): Ensure that all service-to-service communication is encrypted, and both the client and server verify each other's identity.
  • Service Identity: Each service in the mesh has a unique identity based on Kubernetes Service Accounts, which can be used for fine-grained access control.
  • Authorization Policies: You can define policies that control which services are allowed to communicate, adding an extra layer of security.
  • Automatic Certificate Management: Istio manages certificate lifecycle through Citadel, ensuring that certificates are renewed and rotated automatically.
  • Traffic Management: Advanced traffic routing, load balancing, and fault injection capabilities.
  • Observability: Built-in metrics, logs, and tracing for all service communications.

Why Combine Istio with Vault Agent Injector?

Kubernetes provides excellent orchestration capabilities, but securing service-to-service communication and managing secrets requires additional tools. Istio provides the service mesh layer for secure communication, while Vault Agent Injector handles dynamic secret management. This combination gives you:

  • Comprehensive Security: Both network-level security (Istio) and secret management (Vault)
  • Zero-Trust Architecture: Services must be explicitly authorized to communicate, and secrets are dynamically provisioned
  • Operational Simplicity: Both solutions integrate seamlessly with Kubernetes without requiring application code changes
  • Scalability: Both solutions scale with your Kubernetes infrastructure

Setting Up Istio and Vault Agent Injector

Prerequisites:

  1. Kubernetes cluster with sufficient resources for Istio
  2. External HashiCorp Vault cluster running at vault.example.com:8200
  3. Helm for installing components
  4. kubectl configured for your cluster

Step 1: Install Istio

First, install Istio in your Kubernetes cluster:

 1# Download and install Istio
 2curl -L https://istio.io/downloadIstio | sh -
 3export PATH="$PATH:./istio-1.20.0/bin"
 4
 5# Install Istio with default configuration
 6istioctl install --set values.defaultRevision=default -y
 7
 8# Enable Istio injection for the demo namespace
 9kubectl create namespace demo
10kubectl label namespace demo istio-injection=enabled
11
12# Verify Istio installation
13kubectl get pods -n istio-system

Step 2: Install Vault Agent Injector

Install the Vault Agent Injector as we demonstrated in our previous post:

1helm repo add hashicorp https://helm.releases.hashicorp.com
2helm repo update
3
4# Install only the Agent Injector (no Vault server)
5helm install vault-injector hashicorp/vault \
6  --set "global.externalVaultAddr=https://vault.example.com:8200" \
7  --set "injector.enabled=true" \
8  --set "server.enabled=false" \
9  --set "csi.enabled=false"

Step 3: Configure Vault Authentication

Set up the same Vault configuration as in our previous Kubernetes post:

 1# Set Vault address environment variable
 2export VAULT_ADDR="https://vault.example.com:8200"
 3
 4# Enable Kubernetes auth method
 5vault auth enable kubernetes
 6
 7# Configure Kubernetes auth (same as previous post)
 8KUBERNETES_HOST=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.server}')
 9KUBERNETES_CA_CERT=$(kubectl config view --raw --minify --flatten -o jsonpath='{.clusters[].cluster.certificate-authority-data}' | base64 -d)
10
11# Create service account and configure auth
12kubectl create serviceaccount vault-auth
13kubectl apply -f - <<EOF
14apiVersion: rbac.authorization.k8s.io/v1
15kind: ClusterRoleBinding
16metadata:
17  name: role-tokenreview-binding
18roleRef:
19  apiGroup: rbac.authorization.k8s.io
20  kind: ClusterRole
21  name: system:auth-delegator
22subjects:
23- kind: ServiceAccount
24  name: vault-auth
25  namespace: default
26EOF
27
28TOKEN_REVIEWER_JWT=$(kubectl create token vault-auth)
29
30vault write auth/kubernetes/config \
31    token_reviewer_jwt="$TOKEN_REVIEWER_JWT" \
32    kubernetes_host="$KUBERNETES_HOST" \
33    kubernetes_ca_cert="$KUBERNETES_CA_CERT"

Step 4: Configure Vault Secrets (Same as Previous Post)

 1# Enable database secrets engine
 2vault secrets enable -path=dynamic-app/db database
 3
 4# Configure MySQL connection
 5vault write dynamic-app/db/config/mysql \
 6    plugin_name=mysql-database-plugin \
 7    connection_url="{{username}}:{{password}}@tcp(mysql-server.demo.svc.cluster.local:3306)/" \
 8    allowed_roles="*" \
 9    username="root" \
10    password="super-duper-password"
11
12# Create dynamic credentials role
13vault write dynamic-app/db/roles/app \
14    db_name=mysql \
15    creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';GRANT ALL ON my_app.* TO '{{name}}'@'%';" \
16    default_ttl="1h" \
17    max_ttl="24h"
18
19# Create Vault policy
20vault policy write dynamic-app-istio - <<EOF
21path "dynamic-app/db/creds/app" {
22  capabilities = ["read"]
23}
24EOF
25
26# Create Kubernetes role
27vault write auth/kubernetes/role/dynamic-app-istio \
28    bound_service_account_names=dynamic-app-istio \
29    bound_service_account_namespaces=demo \
30    policies=dynamic-app-istio \
31    ttl=24h

Deploy Services with Istio and Vault Integration

Step 5: Deploy MySQL Database with Istio

 1# mysql-istio-deployment.yaml
 2apiVersion: apps/v1
 3kind: Deployment
 4metadata:
 5  name: mysql-server
 6  namespace: demo
 7  labels:
 8    app: mysql-server
 9    version: v1
10spec:
11  replicas: 1
12  selector:
13    matchLabels:
14      app: mysql-server
15      version: v1
16  template:
17    metadata:
18      labels:
19        app: mysql-server
20        version: v1
21    spec:
22      containers:
23      - name: mysql
24        image: mysql:9
25        env:
26        - name: MYSQL_ROOT_PASSWORD
27          value: "super-duper-password"
28        ports:
29        - containerPort: 3306
30          name: mysql
31        resources:
32          requests:
33            cpu: 500m
34            memory: 1Gi
35          limits:
36            cpu: 500m
37            memory: 1Gi
38
39---
40# MySQL Service
41apiVersion: v1
42kind: Service
43metadata:
44  name: mysql-server
45  namespace: demo
46  labels:
47    app: mysql-server
48    service: mysql-server
49spec:
50  ports:
51  - port: 3306
52    name: mysql
53    targetPort: 3306
54  selector:
55    app: mysql-server

Step 6: Deploy Dynamic App with Vault Agent Injector and Istio

  1# dynamic-app-istio.yaml
  2apiVersion: v1
  3kind: ServiceAccount
  4metadata:
  5  name: dynamic-app-istio
  6  namespace: demo
  7
  8---
  9apiVersion: apps/v1
 10kind: Deployment
 11metadata:
 12  name: dynamic-app
 13  namespace: demo
 14  labels:
 15    app: dynamic-app
 16    version: v1
 17spec:
 18  replicas: 1
 19  selector:
 20    matchLabels:
 21      app: dynamic-app
 22      version: v1
 23  template:
 24    metadata:
 25      labels:
 26        app: dynamic-app
 27        version: v1
 28      annotations:
 29        # Vault Agent Injector annotations
 30        vault.hashicorp.com/agent-inject: "true"
 31        vault.hashicorp.com/agent-inject-status: "update"
 32        vault.hashicorp.com/agent-inject-vault-addr: "https://vault.example.com:8200"
 33        vault.hashicorp.com/role: "dynamic-app-istio"
 34        vault.hashicorp.com/agent-inject-secret-config.ini: "dynamic-app/db/creds/app"
 35        vault.hashicorp.com/agent-inject-template-config.ini: |
 36          [DEFAULT]
 37          LogLevel = DEBUG
 38          Port = 8080
 39
 40          [DATABASE]
 41          Address = mysql-server.demo.svc.cluster.local
 42          Port = 3306
 43          Database = my_app
 44          User = {{ .Data.username }}
 45          Password = {{ .Data.password }}
 46
 47          [VAULT]
 48          Enabled = True
 49          InjectToken = True
 50          Namespace =
 51          Address = https://vault.example.com:8200
 52          KeyPath = dynamic-app/transit
 53          KeyName = app
 54    spec:
 55      serviceAccountName: dynamic-app-istio
 56      containers:
 57      - name: dynamic-app
 58        image: ghcr.io/infralovers/nomad-vault-mysql:1.0.0
 59        ports:
 60        - containerPort: 8080
 61          name: http
 62        env:
 63        - name: CONFIG_FILE
 64          value: "/vault/secrets/config.ini"
 65        - name: VAULT_ADDR
 66          value: "https://vault.example.com:8200"
 67        resources:
 68          requests:
 69            cpu: 256m
 70            memory: 256Mi
 71          limits:
 72            cpu: 256m
 73            memory: 256Mi
 74        livenessProbe:
 75          httpGet:
 76            path: /health
 77            port: 8080
 78          initialDelaySeconds: 30
 79          periodSeconds: 10
 80        readinessProbe:
 81          httpGet:
 82            path: /health
 83            port: 8080
 84          initialDelaySeconds: 5
 85          periodSeconds: 5
 86
 87---
 88# Dynamic App Service
 89apiVersion: v1
 90kind: Service
 91metadata:
 92  name: dynamic-app
 93  namespace: demo
 94  labels:
 95    app: dynamic-app
 96    service: dynamic-app
 97spec:
 98  ports:
 99  - port: 8080
100    name: http
101    targetPort: 8080
102  selector:
103    app: dynamic-app

Configure Istio Security Policies

Step 7: Enable Strict mTLS

Enable strict mTLS for the entire demo namespace:

1# demo-peer-authentication.yaml
2apiVersion: security.istio.io/v1beta1
3kind: PeerAuthentication
4metadata:
5  name: demo-strict-mtls
6  namespace: demo
7spec:
8  mtls:
9    mode: STRICT

Step 8: Define Authorization Policies

Create authorization policies to control service-to-service communication:

 1# mysql-authorization-policy.yaml
 2apiVersion: security.istio.io/v1beta1
 3kind: AuthorizationPolicy
 4metadata:
 5  name: mysql-server-policy
 6  namespace: demo
 7spec:
 8  selector:
 9    matchLabels:
10      app: mysql-server
11  rules:
12  - from:
13    - source:
14        principals: ["cluster.local/ns/demo/sa/dynamic-app-istio"]
15    to:
16    - operation:
17        ports: ["3306"]
18
19---
20# Dynamic App Authorization Policy
21apiVersion: security.istio.io/v1beta1
22kind: AuthorizationPolicy
23metadata:
24  name: dynamic-app-policy
25  namespace: demo
26spec:
27  selector:
28    matchLabels:
29      app: dynamic-app
30  rules:
31  - from:
32    - source:
33        namespaces: ["istio-system"]  # Allow health checks from Istio
34  - to:
35    - operation:
36        ports: ["8080"]

Step 9: Create Gateway and VirtualService for External Access

 1# dynamic-app-gateway.yaml
 2apiVersion: networking.istio.io/v1beta1
 3kind: Gateway
 4metadata:
 5  name: dynamic-app-gateway
 6  namespace: demo
 7spec:
 8  selector:
 9    istio: ingressgateway
10  servers:
11  - port:
12      number: 80
13      name: http
14      protocol: HTTP
15    hosts:
16    - dynamic-app.local
17
18---
19apiVersion: networking.istio.io/v1beta1
20kind: VirtualService
21metadata:
22  name: dynamic-app-vs
23  namespace: demo
24spec:
25  hosts:
26  - dynamic-app.local
27  gateways:
28  - dynamic-app-gateway
29  http:
30  - match:
31    - uri:
32        prefix: /
33    route:
34    - destination:
35        host: dynamic-app.demo.svc.cluster.local
36        port:
37          number: 8080

Benefits of Using Istio with Vault Agent Injector

  1. End-to-End Security: Network-level encryption via Istio mTLS and secure secret management via Vault
  2. Zero Trust Architecture: Services must be explicitly authorized to communicate and receive appropriate secrets
  3. Automatic Certificate Management: Istio handles mTLS certificates while Vault manages application secrets
  4. Policy-Based Security: Fine-grained control over both network traffic and secret access
  5. Observability: Complete visibility into service communications and secret usage
  6. No Code Changes: Both Istio and Vault integrate without requiring application modifications

Security Best Practices

  1. Principle of Least Privilege: Only allow necessary service communications
  2. Regular Policy Reviews: Periodically audit authorization policies
  3. Monitor Certificate Health: Use Istio's built-in certificate monitoring
  4. Secret Rotation: Leverage Vault's automatic secret rotation capabilities
  5. Network Segmentation: Use Kubernetes namespaces with strict policies

Conclusion

Combining Istio Service Mesh with HashiCorp Vault Agent Injector provides a comprehensive security solution for Kubernetes workloads. This approach delivers both secure service-to-service communication and dynamic secret management without requiring changes to your application code.

Key benefits of this integrated approach:

  • Comprehensive Security: Network encryption (mTLS) and secret management in one solution
  • Operational Simplicity: Declarative configuration through Kubernetes resources
  • Scalability: Both solutions scale seamlessly with your Kubernetes infrastructure
  • Zero Trust: Services and secrets require explicit authorization
  • Observability: Complete visibility into both network traffic and secret access

By leveraging these technologies together, you can build a robust, secure, and observable microservices architecture that follows cloud-native best practices while maintaining operational efficiency.

Start enhancing your Kubernetes deployments today by integrating Istio service mesh with Vault Agent Injector, and take advantage of secure, authenticated, and encrypted communication combined with dynamic secret management across your services.

Go Back explore our courses

We are here for you

You are interested in our courses or you simply have a question that needs answering? You can contact us at anytime! We will do our best to answer all your questions.

Contact us