Verify dual-stack functionality and configure your services#

Overview#

When to follow these instructions#

Follow the instructions below only as part of a dual-stack clean installation and only when other instructions tell you to do so. Perform the tasks in order.

Install the debug sidecar proxy#

Introduction#

The Aspen Mesh release archive file includes a script (verify-dual-stack.sh) to verify your dual-stack configuration and provide information on your services and pods. If you install the debug sidecar proxy instead of the standard sidecar proxy, the script can also provide port information for your pods with sidecars, which includes the addresses that your applications are listening on.

Install the debug sidecar proxy#

  • Install the debug sidecar proxy.

    Because you won’t be collecting debug information, you can leave the logLevel and enableCoreDump fields commented out when adding information to your Aspen Mesh override values file.

Verify dual-stack functionality using sample services and applications#

Introduction#

Before you make any changes to your services and applications, verify dual-stack functionality using sample services and applications. Perform the following tasks in order.

Install the simpleserver dual-stack service and gateway#

  1. Create a namespace named simpleserver:

    $ kubectl create namespace simpleserver
    
  2. Apply the istio-injection label to the simpleserver namespace:

    $ kubectl label namespace simpleserver istio-injection=enabled --overwrite
    
  3. Change to the Aspen Mesh release directory.

  4. Install the simpleserver dual-stack service in the simpleserver namespace:

    $ helm install simpleserver-dualstack samples/simpleserver/ \
      --set mode=dualstack \
      --namespace simpleserver
    

Create the sleep single-stack service#

  1. Create a namespace named sleep:

    $ kubectl create namespace sleep
    
  2. Apply the istio-injection label to the sleep namespace:

    $ kubectl label namespace sleep istio-injection=enabled --overwrite
    
  3. Change to the Aspen Mesh release directory.

  4. Create the sleep service account, service, and deployment in the sleep namespace:

    $ kubectl apply -f samples/sleep/sleep.yaml --namespace sleep
    

Verify that the control plane and data plane are configured for dual-stack networking#

  1. In the Aspen Mesh release directory, execute the script to verify your dual-stack configuration:

    $ ./tools/verify-dual-stack.sh simpleserver
    
  2. Did the script complete without errors?

    • Yes: Go to the next task.

    • No: Correct the errors identified by the script and then execute it again.

Verify that the DNS server can return IPv4 and IPv6 addresses#

  1. Use the sleep service to verify that the DNS server can return an IPv4 (type A) record for the simpleserver service:

    $ kubectl exec -it --namespace sleep \
        $(kubectl get pod --selector app=sleep --namespace sleep -o jsonpath="{.items[0].metadata.name}") \
        -- nslookup -type=a simpleserver-dualstack.simpleserver.svc.cluster.local
    

    The last two lines of the output should include the domain name of the simpleserver service and its IPv4 address, like this:

    Name:	simpleserver-dualstack.simpleserver.svc.cluster.local
    Address: 10.122.180.62
    
  2. Use the sleep service to verify that the DNS server can return an IPv6 (type AAAA) record for the simpleserver service:

    $ kubectl exec -it --namespace sleep \
        $(kubectl get pod --selector app=sleep --namespace sleep -o jsonpath="{.items[0].metadata.name}") \
        -- nslookup -type=aaaa simpleserver-dualstack.simpleserver.svc.cluster.local
    

    The last two lines of the output should include the domain name of the simpleserver service and its IPv6 address, like this:

    Name:	simpleserver-dualstack.simpleserver.svc.cluster.local
    Address: fd00:abcd:2:122::44e5
    

Verify IPv4 and IPv6 data-plane connectivity#

  1. Verify IPv4 connectivity between services in your service mesh:

    $ kubectl exec -it --namespace sleep \
        $(kubectl get pod --selector app=sleep --namespace sleep -o jsonpath="{.items[0].metadata.name}") \
        -- curl simpleserver-dualstack.simpleserver:8090/headers -4
    

    The output should include either an IPv4 remote address and ipv4 handler, like this:

    remote addr: 127.0.0.1:58660
    host addr: simpleserver-dualstack.simpleserver:8090
    ipv4 handler
    

    Or an IPv6 remote address and ipv6 handler, like this:

    remote addr: [::1]:34312
    host addr: simpleserver-dualstack.simpleserver:8090
    ipv6 handler
    

    Note

    Sidecars are free to choose the IP family they use to address containers and other sidecars. Therefore, the IP family used between the sleep sidecar and the simpleserver sidecar—and between the simpleserver sidecar and container—may differ from the IP family used between the sleep container and sidecar.

  2. Verify IPv6 connectivity between services in your service mesh:

    $ kubectl exec -it --namespace sleep \
        $(kubectl get pod --selector app=sleep --namespace sleep -o jsonpath="{.items[0].metadata.name}") \
        -- curl simpleserver-dualstack.simpleserver:8090/headers -6
    

    The output should include either an IPv4 remote address and ipv4 handler, like this:

    remote addr: 127.0.0.1:58660
    host addr: simpleserver-dualstack.simpleserver:8090
    ipv4 handler
    

    Or an IPv6 remote address and ipv6 handler, like this:

    remote addr: [::1]:34312
    host addr: simpleserver-dualstack.simpleserver:8090
    ipv6 handler
    

    Note

    Sidecars are free to choose the IP family they use to address containers and other sidecars. Therefore, the IP family used between the sleep sidecar and the simpleserver sidecar—and between the simpleserver sidecar and container—may differ from the IP family used between the sleep container and sidecar.

Verify IPv4 and IPv6 connectivity between clients outside your cluster and services inside your service mesh#

  1. Get the IPv4 address of your ingress gateway service:

    If you’re using a cloud provider:

    LB=$(kubectl get service istio-ingressgateway --namespace <ingressNamespaceName> \
        -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    

    If you’re using bare metal:

    LB=$(kubectl get service istio-ingressgateway --namespace <ingressNamespaceName> \
        -o=jsonpath='{.status.loadBalancer.ingress[0].ip}')
    
  2. Verify IPv4 connectivity between clients outside your cluster and services inside your service mesh:

    $ curl -4 ${LB}
    
  3. Does the output indicate that the connection succeeded?

    • Yes: Go to step 4.

    • No: Contact Aspen Mesh Support.

  4. Get the IPv6 address of your ingress gateway service:

    If you’re using a cloud provider:

    LB=$(kubectl get service istio-ingressgateway --namespace <ingressNamespaceName> \
        -o=jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    

    If you’re using bare metal:

    LB=$(kubectl get service istio-ingressgateway --namespace <ingressNamespaceName> \
        -o=jsonpath='{.status.loadBalancer.ingress[1].ip}')
    
  5. Verify IPv6 connectivity between clients outside your cluster and services inside your service mesh:

    $ curl -6 "http://[${LB}]"
    
  6. Does the output indicate that the connection succeeded?

    • Yes: Go to the next task.

    • No: Contact Aspen Mesh Support.

Delete the verification environment#

  1. Uninstall the simpleserver dual-stack service:

    $ helm uninstall simpleserver-dualstack --namespace simpleserver --wait
    
  2. Delete the simpleserver namespace:

    $ kubectl delete namespace simpleserver
    
  3. Delete the sleep namespace:

    $ kubectl delete namespace sleep
    

Configure your services for dual-stack networking#

Introduction#

OpenShift 4.7 and later and Kubernetes 1.20 and later include fields that you use to configure dual-stack networking for services:

  • .spec.ipFamilyPolicy

  • .spec.ipFamilies

Configure your services for dual-stack networking#

Follow these steps for each of your services that you want to support dual-stack networking, regardless of whether the service is part of your service mesh:

  1. Look at the manifest for the service.

  2. Are the .spec.ipFamilyPolicy and .spec.ipFamilies fields set as shown in Recommended IP family specification for dual-stack networking above?

    • Yes: Stop. The service is configured correctly for dual-stack networking.

    • No: Go to step 3.

  3. Set the .spec.ipFamilyPolicy and .spec.ipFamilies fields as shown in Recommended IP family specification for dual-stack networking.

  4. Delete the service:

    $ kubectl delete -f <serviceManifestFilename> --namespace <namespaceName>
    
  5. Create the service:

    $ kubectl create -f <serviceManifestFilename> --namespace <namespaceName>
    
  6. Restart all pods with sidecars:

    $ kubectl delete pods --namespace <namespaceName> --selector security.istio.io/tlsMode=istio
    

Verify your dual-stack configuration#

Verify your dual-stack configuration#

Follow these steps for each namespace that contains services that should support dual-stack networking:

  1. In the Aspen Mesh release directory, execute the script to verify your dual-stack configuration:

    $ ./tools/verify-dual-stack.sh <namespaceName>
    
  2. Did the script complete without errors?

Uninstall the debug sidecar proxy#

Introduction#

Now that you’ve completed verifying your dual-stack configuration, you can uninstall the debug sidecar proxy.

Uninstall the debug sidecar proxy#

Verify that your applications support dual-stack networking#

Introduction#

In addition to configuring your services for dual-stack networking, you must verify that applications that are part of the service mesh—and that you want to respond to requests on both IPv4 and IPv6 addresses—are designed to listen on both IPv4 and IPv6 addresses. If an application doesn’t listen on one type of address, clients that make an HTTP request to that type of address will receive a 500 error (clients that make a TCP request will receive a connection-refused error).

How a service responds#

The following table illustrates how a service responds to a request from a client based on the service’s IP family specification and the addresses the application listens on. The combination shown in the last row ensures the desired behavior.

When a service’s IP family specification is set for

And the application listens on

Then

IPv4 only

IPv4 only

- IPv4: Requests are proxied and routed over IPv4 only.
- IPv6: (Requests can’t be made over IPv6.)

IPv4 only

IPv6 only

- IPv4: The client receives a 500 error.
- IPv6: (Requests can’t be made over IPv6.)

IPv4 only

IPv4 and IPv6

- IPv4: Requests are proxied and routed over IPv4 only.
- IPv6: (Requests can’t be made over IPv6.)

IPv6 only

IPv4 only

- IPv4: (Requests can’t be made over IPv4.)
- IPv6: The client receives a 500 error.

IPv6 only

IPv6 only

- IPv4: (Requests can’t be made over IPv4.)
- IPv6: Requests are proxied and routed over IPv6 only.

IPv6 only

IPv4 and IPv6

- IPv4: (Requests can’t be made over IPv4.)
- IPv6: Requests are proxied and routed over IPv6 only.

IPv4 and IPv6

IPv4 only

- IPv4: Requests are proxied and routed over IPv4 only.
- IPv6: The client receives a 500 error.

IPv4 and IPv6

IPv6 only

- IPv4: The client receives a 500 error.
- IPv6: Requests are proxied and routed over IPv6 only.

IPv4 and IPv6

IPv4 and IPv6

- IPv4: Requests are proxied and routed over IPv4 or IPv6.
- IPv6: Requests are proxied and routed over IPv4 or IPv6.

Addresses that your applications should listen on#

Applications that are part of the service mesh—and that you want to respond to requests on both IPv4 and IPv6 addresses—should be designed to listen on both of the following addresses:

  • 0.0.0.0 (IPv4)

  • :: (IPv6)

Note

Listening on the localhost addresses (127.0.0.1 and ::1) is not supported.

Verify that your applications support dual-stack networking#