All Products
Search
Document Center

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

Last Updated:Oct 18, 2024

The multi-cluster Services (MCS) feature allows you to access Services across Kubernetes clusters without the need to create load balancers. A headless multi-cluster Service provides a domain name that you can use to access the specified backend pods of the Service across clusters. Headless multi-cluster Services are suitable for accessing applications deployed as StatefulSets across clusters, such as distributed databases and message queues. This topic describes how to use a headless multi-cluster Service to access a MySQL database across clusters.

Background Information

A headless Service does not have a cluster IP address. When you create a headless Service, Kubernetes generates a DNS record that points to the IP addresses of all pods that match the label selectors of the Service, instead of generating a Service IP address.

Clients can use the domain name of a headless multi-cluster Service to access applications deployed as StatefulSets across clusters, such as distributed databases and message queues.

You can use headless multi-cluster Services to implement read/write splitting for MySQL primary and secondary clusters. This helps improve the performance, throughput, reliability, and fault tolerance of the MySQL database.

Introduction

In this example, a headless multi-cluster Service is used to access a specified pod of a MySQL database across clusters.

  • A Distributed Cloud Container Platform for Kubernetes (ACK One) Fleet instance is associated with two Container Service for Kubernetes (ACK) clusters: ACK Cluster 1 and ACK Cluster 2. A MySQL Service is exported from ACK Cluster 1 and imported into ACK Cluster 2.

  • ACK Cluster 1 serves as a Service provider. A MySQL database and a ServiceExport are created in ACK Cluster 1. The MySQL database provides external services.

  • ACK Cluster 2 serves as a Service consumer. A ServiceImport and a client pod are created in ACK Cluster 2.

  • The client pod in ACK Cluster 1 can access the MySQL database in ACK Cluster 2 by using a domain name. In addition, the client pod can specify the pod that needs to be accessed.

image

Prerequisites

Step 1: Create a MySQL database and a ServiceExport in ACK Cluster 1

  1. Run the following command to create a namespace in ACK Cluster 1. In this example, the provider-ns namespace is created.

    kubectl create ns provider-ns
  2. Create a MySQL database in ACK Cluster 1

    1. Create a file named mysql.yaml and copy the following code block to the file:

      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: tpc
                    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
    2. Run the following command to deploy the MySQL database:

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

      Expected output:

      secret/mysecret created
      service/mysql created
      statefulset.apps/mysql created
  3. Create a ServiceExport in ACK Cluster 1 and specify the name of the Service that you want to expose to external access. In this example, the mysql Service is specified.

    1. Create a file named serviceexport.yaml and copy the following code block to the file:

      apiVersion: multicluster.x-k8s.io/v1alpha1
      kind: ServiceExport
      metadata:
        name: mysql           # Specify the name of the Service that you want to expose to external access.

    2. Run the following command to create the ServiceExport:

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

      Expected output:

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

Step 2: Create a namespace and a ServiceImport in ACK Cluster 2

  1. Run the following command to create a namespace in ACK Cluster 2. In this example, the provider-ns namespace is created.

    kubectl create ns provider-ns
  2. Create a ServiceImport in ACK Cluster 2.

    1. Create a file named serviceimport.yaml and copy the following code block to the file:

      Important

      Set the type parameter of the ServiceImport to Headless.

      apiVersion: multicluster.x-k8s.io/v1alpha1
      kind: ServiceImport
      metadata:
        name: mysql              # Specify the name of the Service that you want to expose to external access. 
      spec:
        ports:                   # Specify the ports of the Service that you want to expose to external access. 
        - name: tcp
          port: 3306
          protocol: TCP
        type: Headless
    2. Run the following command to create the ServiceImport:

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

      Expected output:

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

Step 3: Access the specified MySQL pod in ACK Cluster 1 from ACK Cluster 2 by using a domain name

You can use the following domain names to access the specified MySQL pod in ACK Cluster 1 from ACK Cluster 2:

  • ${pod name}.amcs-${service name}.${namespace}.svc.cluster.local

  • ${pod name}.${clusterid}.${service name}.${namespace}.svc.clusterset.local

Use ${pod name}.amcs-${service name}.${namespace}.svc.cluster.local

  1. Create a client pod in ACK Cluster 2.

    1. Create a file named mysqlclient.yaml and copy the following code block to the file:

      apiVersion: v1
      kind: Pod
      metadata:
        name: mysql-client
      spec:
        containers:
        - name: mysql-client
          image: mysql:5.6
          command: ["sh", "-c", "sleep 12000"]
    2. Run the following command to create the client pod:

      kubectl create -f mysqlclient.yaml

      Expected output:

      pod/mysql-client created
  2. Access the specified MySQL pod in ACK Cluster 1 from ACK Cluster 2.

    • Run the following command to access the mysql-0 pod:

      kubectl exec -it mysql-client -- mysql -h mysql-0.amcs-mysql.provider-ns.svc.cluster.local -P3306 -uroot -ppassword
    • Run the following command to access the mysql-1 pod:

      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.

Use ${pod name}.${clusterid}.${service name}.${namespace}.svc.clusterset.local

  1. Create a client pod in ACK Cluster 2.

    1. Create a file named mysqlclient.yaml and copy the following code block to the file:

      apiVersion: v1
      kind: Pod
      metadata:
        name: mysql-client
      spec:
        containers:
        - name: mysql-client
          image: mysql:5.6
          command: ["sh", "-c", "sleep 12000"]
    2. Run the following command to create the client pod:

      kubectl create -f mysqlclient.yaml

      Expected output:

      pod/mysql-client created
  2. Install or update CoreDNS in ACK Cluster 2. The version of CoreDNS must be 1.9.3 or later. For more information, see CoreDNS and Manage components.

  3. Modify the Corefile configurations of CoreDNS.

    1. Run the following command to modify the ConfigMap of CoreDNS:

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

      apiVersion: v1
      data:
        Corefile: |
          .:53 {
              errors
              health {
                 lameduck 15s
              }
              ready
              multicluster clusterset.local    # Add this configuration to enable domain name resolution for multi-cluster Services. 
              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
                                      
  4. Access a specified MySQL pod in ACK Cluster 1 from ACK Cluster 2.

    • Run the following command to access the mysql-0 pod:

      kubectl exec -it mysql-client -- mysql -h mysql-0.${clusterid}.mysql.provider-ns.svc.clusterset.local -P3306 -uroot -ppassword
    • Run the following command to access the mysql-1 pod:

      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.