All Products
Search
Document Center

Container Service for Kubernetes:Use headless multi-cluster Services to access specified pods of StatefulSets across clusters

Last Updated:Mar 26, 2026

Multi-cluster Services (MCS) let pods in one cluster reach specific pods in another cluster by domain name—without a load balancer. Headless Services make this possible for stateful workloads managed by StatefulSet, such as distributed databases and message queues, where targeting a specific pod instance matters.

This topic walks through how to expose a MySQL StatefulSet from one ACK cluster and access individual pods from a second cluster using a headless MCS.

How it works

A headless Service has no ClusterIP (clusterIP: None). Instead of resolving to a single Service IP, its DNS record resolves directly to the IP addresses of all matching pods. When you export a headless Service with a ServiceExport and import it with a ServiceImport of type Headless, ACK One extends this resolution across clusters.

In this example:

  • ACK Cluster 1 is the service provider. It runs a MySQL StatefulSet and a ServiceExport that makes the mysql Service available to other clusters.

  • ACK Cluster 2 is the service consumer. It has a ServiceImport that maps to the exported mysql Service, plus a client pod that connects to specific MySQL pods by domain name.

image

Prerequisites

Before you begin, ensure that you have:

Fleet-level requirements:

Cluster-level requirements:

Step 1: Deploy a MySQL StatefulSet and create a ServiceExport in ACK Cluster 1

  1. Create the provider-ns namespace:

    kubectl create ns provider-ns
  2. Create a file named mysql.yaml with the following content:

    apiVersion: v1
    kind: Secret
    metadata:
        name: mysecret
    type: Opaque
    data:
       ROOT_PASSWORD: cGFzc3dvcmQ=
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: mysql
      labels:
        app: mysql
    spec:
      clusterIP: None
      selector:
        app: mysql
      ports:
        - name: tcp
          protocol: TCP
          port: 3306
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mysql
    spec:
      replicas: 2  # Two replicated pods are provisioned for the MySQL database.
      serviceName: mysql
      selector:
        matchLabels:
          app: mysql
      template:
        metadata:
          labels:
            app: mysql
        spec:
          terminationGracePeriodSeconds: 10
          containers:
            - name: mysql
              image: mysql:5.6
              ports:
                - name: tcp
                  protocol: TCP
                  containerPort: 3306
              env:
                - name: MYSQL_ROOT_PASSWORD
                  valueFrom:
                   secretKeyRef:
                    key: ROOT_PASSWORD
                    name: mysecret
              volumeMounts:
                - name: data
                  mountPath: /var/lib/mysql
      volumeClaimTemplates:
        - metadata:
            name: data
          spec:
            storageClassName: standard
            accessModes:
              - ReadWriteOnce
            resources:
              requests:
                storage: 50Gi
            storageClassName: alicloud-disk-topology-alltype
  3. Deploy the MySQL StatefulSet:

    kubectl -n provider-ns create -f mysql.yaml

    Expected output:

    secret/mysecret created
    service/mysql created
    statefulset.apps/mysql created
  4. Create a file named serviceexport.yaml with the following content:

    apiVersion: multicluster.x-k8s.io/v1alpha1
    kind: ServiceExport
    metadata:
      name: mysql           # Specify the name of the Service to export.
  5. Create the ServiceExport:

    kubectl -n provider-ns create -f serviceexport.yaml

    Expected output:

    serviceexport.multicluster.x-k8s.io/mysql created

Step 2: Create a ServiceImport in ACK Cluster 2

  1. Create the provider-ns namespace in ACK Cluster 2:

    kubectl create ns provider-ns
  2. Create a file named serviceimport.yaml with the following content:

    Important

    Set type to Headless. This tells ACK One to resolve the import to individual pod IPs rather than a virtual Service IP.

    apiVersion: multicluster.x-k8s.io/v1alpha1
    kind: ServiceImport
    metadata:
      name: mysql              # Must match the ServiceExport name.
    spec:
      ports:
      - name: tcp
        port: 3306
        protocol: TCP
      type: Headless
  3. Create the ServiceImport:

    kubectl -n provider-ns create -f serviceimport.yaml

    Expected output:

    serviceimport.multicluster.x-k8s.io/mysql created

Step 3: Access a specific MySQL pod from ACK Cluster 2

Within a single cluster, a StatefulSet pod is reachable at <pod-name>.<svc-name>.<namespace>.svc.cluster.local. Across clusters, ACK One extends this pattern with two domain name formats:

FormatDomain name patternCoreDNS change required
Method 1<pod-name>.amcs-<svc-name>.<namespace>.svc.cluster.localNo
Method 2<pod-name>.<cluster-id>.<svc-name>.<namespace>.svc.clusterset.localYes

Method 1 uses the cluster's existing DNS and requires no extra configuration—the amcs- prefix routes cross-cluster pod resolution through the local DNS server. Method 2 uses the clusterset.local domain, which requires the CoreDNS multicluster plugin. Install or update CoreDNS to version 1.9.3 or later and add a plugin entry before using it.

Use Method 1 for simplicity. Use Method 2 when you need the cluster ID embedded in the domain, for example, to target pods in a specific member cluster of the Fleet.

Both methods require a client pod in ACK Cluster 2. Create a file named mysqlclient.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: mysql-client
spec:
  containers:
  - name: mysql-client
    image: mysql:5.6
    command: ["sh", "-c", "sleep 12000"]

Deploy the client pod:

kubectl create -f mysqlclient.yaml

Expected output:

pod/mysql-client created

Method 1: Use the amcs- domain (no CoreDNS changes)

Access mysql-0:

kubectl exec -it mysql-client -- mysql -h mysql-0.amcs-mysql.provider-ns.svc.cluster.local -P3306 -uroot -ppassword

Access mysql-1:

kubectl exec -it mysql-client -- mysql -h mysql-1.amcs-mysql.provider-ns.svc.cluster.local -P3306 -uroot -ppassword

Expected output:

Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.51 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

Method 2: Use the clusterset.local domain (requires CoreDNS update)

Before using this method, install or update CoreDNS in ACK Cluster 2 to version 1.9.3 or later. For instructions, see CoreDNS and Manage components.

The clusterset.local domain requires the CoreDNS multicluster plugin, which is not enabled by default. Add it to the Corefile:

  1. Open the CoreDNS ConfigMap for editing:

    kubectl edit configmap coredns -n kube-system
  2. In the Corefile field, add multicluster clusterset.local to enable DNS resolution for multi-cluster Services:

    apiVersion: v1
    data:
      Corefile: |
        .:53 {
            errors
            health {
               lameduck 15s
            }
            ready
            multicluster clusterset.local    # Add this line.
            kubernetes cluster.local in-addr.arpa ip6.arpa {
              pods verified
              ttl 30
              fallthrough in-addr.arpa ip6.arpa
            }
            ...
        }
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
  3. Access mysql-0, replacing ${clusterid} with the cluster ID of ACK Cluster 1:

    kubectl exec -it mysql-client -- mysql -h mysql-0.${clusterid}.mysql.provider-ns.svc.clusterset.local -P3306 -uroot -ppassword
  4. Access mysql-1:

    kubectl exec -it mysql-client -- mysql -h mysql-1.${clusterid}.mysql.provider-ns.svc.clusterset.local -P3306 -uroot -ppassword

    Expected output:

    Warning: Using a password on the command line interface can be insecure.
    Welcome to the MySQL monitor.  Commands end with ; or \g.
    Your MySQL connection id is 1
    Server version: 5.6.51 MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
    
    Oracle is a registered trademark of Oracle Corporation and/or its
    affiliates. Other names may be trademarks of their respective
    owners.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.