Set up DNS Proxy

Kubernetes natively resolves DNS names only for Services in the local cluster. DNS Proxy lets you resolve Kubernetes Services across remote clusters in a multi-cluster setup and generate DNS records for ServiceEntry resources. This helps you route traffic to internal hostnames without maintaining additional internal DNS servers.

Configuring DNS Proxy

To configure DNS proxy, configure ISTIO_META_DNS_CAPTURE flag as follows. You can choose either the cluster or per-proxy wide configuration.

Cluster wide configuration

To configure DNS proxy in the cluster, add ISTIO_META_DNS_CAPTURE proxy metadata to the ConfigMap for MeshConfig. The name of the ConfigMap has a format of istio-<revision_name>. For the details of revision, refer to the overview of the revision

apiVersion: v1
data:
  mesh: |-
    ...
    defaultConfig:
      proxyMetadata:
        ISTIO_META_DNS_CAPTURE: "true"        
    ...
kind: ConfigMap
metadata:
  name: istio-<revision_name>
  namespace: istio-system

Per-proxy configuration

To configure DNS proxy for a proxy, add the ISTIO_META_DNS_CAPTURE proxy metadata annotation as follows:

kind: Deployment
metadata:
  name: app1
  namespace: ns1
spec:
...
  template:
    metadata:
      annotations:
        proxy.istio.io/config: |
          proxyMetadata:
            ISTIO_META_DNS_CAPTURE: "true"
...

Verifying

To verify everything is configured correctly, run the steps.

Name resolution for Service across clusters

After the multi-cluster setup, deploy a Service only in one of the clusters to verify the cross-cluster name resolution.

When you have the following example Service ns1/svc1, you can find ClusterIP in Service.

$ kubectl get -n ns1 svc1
kind: Service
metadata:
  name: svc1
  namespace: ns1
spec:
...
  ClusterIP: 210.200.1.1
...

Then, when using curl from the other cluster to the Service, it should show the ClusterIP as follows.

curl -sS -v svc1.ns1.svc.cluster.local
*   Trying 210.200.1.1:80...

Name resolution for ServiceEntry

Add a ServiceEntry with a hostname not registered in your DNS. To verify the name resolution the following example has explicit address 192.168.123.123.

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: test-service-entry
spec:
  addresses:
  - "192.168.123.123"
  hosts:
  - not-existing-hostname.internal
  ports:
  - name: http
    number: 80
    protocol: HTTP
EOF

Then, try DNS resolution in a Pod where DNS Proxy is enabled. For example, if you run a curl in the Pod, it should display the IP address as follows:

curl -sS -v not-existing-hostname.internal
*   Trying 192.168.123.123:80...

IP auto-allocation for ServiceEntry

When using ServiceEntry with DNS Proxy, you can optionally enable IP auto-allocation. When enabled, internal IP addresses (from the 240.240.0.0/16 range) are automatically allocated for ServiceEntry hosts that don't specify explicit IP addresses in spec.addresses.

Enabling IP auto-allocation

To enable IP auto-allocation, follow the instructions for your control plane implementation:

TRAFFIC_DIRECTOR

For the TRAFFIC_DIRECTOR control plane implementation, configure IP auto-allocation in the asm-options ConfigMap within the istio-system namespace by setting ip_auto_allocation: "true".

The following example shows an asm-options ConfigMap with IP auto-allocation enabled:

apiVersion: v1
kind: ConfigMap
metadata:
  name: asm-options
  namespace: istio-system
data:
  # Enable IP auto-allocation for ServiceEntry (Rapid channel)
  ip_auto_allocation: "true"

You can also apply this configuration using kubectl patch:

kubectl patch configmap/asm-options -n istio-system --type merge \
  -p '{"data":{"ip_auto_allocation":"true"}}'

ISTIOD

For clusters using the ISTIOD control plane implementation (in-cluster or managed ISTIOD), configure IP auto-allocation by adding ISTIO_META_DNS_AUTO_ALLOCATE: "true" to your proxy metadata within MeshConfig:

apiVersion: v1
data:
  mesh: |-
    defaultConfig:
      proxyMetadata:
        ISTIO_META_DNS_CAPTURE: "true"
        ISTIO_META_DNS_AUTO_ALLOCATE: "true"
kind: ConfigMap
metadata:
  name: istio-<revision_name>
  namespace: istio-system

Verifying IP auto-allocation

You can verify the IP auto-allocation works using the following steps.

Before the verification, create a ServiceEntry without specifying spec.addresses:

$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1beta1
kind: ServiceEntry
metadata:
  name: auto-allocated-service-entry
  namespace: ns1
spec:
  hosts:
  - auto-allocated.internal
  ports:
  - name: http
    number: 80
    protocol: HTTP
  resolution: DNS
EOF

1. Check allocated address in status.addresses (TRAFFIC_DIRECTOR only)

In the TRAFFIC_DIRECTOR implementation, the controller allocates a VIP and populates the status.addresses field of the ServiceEntry:

$ kubectl get serviceentry auto-allocated-service-entry -n ns1 -o yaml

The output displays the allocated address under status.addresses:

status:
  addresses:
  - host: auto-allocated.internal
    value: 240.240.0.1

2. Test DNS resolution from a Pod (TRAFFIC_DIRECTOR and ISTIOD)

In both TRAFFIC_DIRECTOR and ISTIOD implementations, send a request from a Pod where DNS Proxy is enabled to verify that name resolution resolves to the allocated VIP:

$ kubectl exec deploy/curl -n ns1 -- curl -sS -v http://auto-allocated.internal

The connection attempt should resolve to the automatically allocated VIP (for example, 240.240.0.1:80):

*   Trying 240.240.0.1:80...