Set up DNS Proxy

DNS Proxy is a feature for providing the following capabilities:

  1. Propagating DNS entries of Services across clusters in a multi-cluster setup.
  2. Populating DNS entries for ServiceEntry.

Kubernetes provides DNS resolution only for Services in the local cluster. When you need to provide name resolution for Services in a remote clusters or use an internal-only hostname with ServiceEntry without having an additional internal-only DNS server, DNS Proxy provides a way to resolve DNS names for such cases.

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...