通过命令行管理多集群服务

更新时间: 2023-07-10 12:24:56

通过多集群服务,让您无需创建负载均衡,即可实现Kubernetes服务的跨集群访问。本文通过示例介绍如何在主控实例上创建ServiceExport、ServiceImport等资源来管理多集群服务,实现Kubernetes服务的跨集群访问。

前提条件

  • 已从ACK One控制台获取主控实例的KubeConfig,并通过kubectl连接至主控实例。

  • 主控实例已添加多个关联集群。具体操作,请参见添加关联集群

  • 已确保关联集群版本为1.21及以上版本。

  • 已安装AMC命令行工具。具体操作,请参见AMC命令行帮助

概述

通过多集群服务实现Kubernetes服务的跨集群访问,打破了多集群服务访问的边界。多集群服务示例如下图所示。

多集群服务
  1. 使用多集群主控实例的应用分发能力,管理员通过链路0在主控实例上创建应用相关资源,包含Namespace、Deployment、和Service,并创建应用分发规则将应用资源通过链路1分发到ACK Cluster 1上。

  2. 管理员通过链路0在主控实例上创建多集群服务Service Export和Service Import,并创建应用分发规则将Service Export分发到ACK Cluster 1上,分发Service Import到ACK Cluster 2上。

  3. 在ACK Cluster 2上,Client Pod跨集群访问ACK Cluster 1上的Service1。

    说明

    以上第一步第二步使用多集群主控实例的应用分发能力在ACK Cluster 1和ACK Cluster 2上创建Namespace、Deployment、Service、Service Export和Service Import资源,您也可以直接在ACK Cluster 1和ACK Cluster 2上创建相应资源实现跨集群服务访问。

步骤一:创建服务提供者相关资源

如果您的服务提供者集群Cluster 1已经部署了Kubernetes服务和相关资源,可以跳过此步骤,只需在后续创建多集群服务ServiceExport和Service Import资源时修改相应的资源名称,具体操作,请参见修改和删除多集群服务

  1. 执行以下命令,创建服务提供者命名空间。

    示例的命名空间为provider-ns

    kubectl create ns provider-ns
  2. 执行以下命令,获取关联集群。

    kubectl amc get managedclusters

    预期输出:

    Name        Alias      HubAccepted
    c984b0****   cluster2   true            # 示例中的服务消费者集群。
    cc36f4****   cluster1   true            # 示例中的服务提供者集群。
  3. 创建服务提供者Kubernetes服务和相关的Deployment等资源。

    1. 使用以下内容,创建app-meta.yaml文件,包括Kubernetes服务、相关的Deployment资源和分发规则。

      apiVersion: v1       # 服务提供者。
      kind: Service
      metadata:
        name: service1
        namespace: provider-ns
      spec:
        ports:
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector:
          app: web-demo
        sessionAffinity: None
        type: ClusterIP
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        labels:
          app: web-demo
        name: web-demo
        namespace: provider-ns
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: web-demo
        template:
          metadata:
            labels:
              app: web-demo
          spec:
            containers:
            - image: acr-multiple-clusters-registry.cn-hangzhou.cr.aliyuncs.com/ack-multiple-clusters/web-demo:0.4.0
              name: web-demo
              env:
              - name: ENV_NAME
                value: cluster1-beijing
      ---
      apiVersion: core.oam.dev/v1beta1
      kind: Application
      metadata:
        name: web-demo        # 定义应用包含的资源,以及分发规则。
        namespace: provider-ns
        annotations:
          app.oam.dev/publishVersion: version1
      spec:
        components:
          - name: web-demo
            type: ref-objects
            properties:
              objects:
                - resource: deployment
                  name: web-demo
                - resource: service
                  name: service1
        policies:
          - type: topology
            name: cluster1
            properties:
              clusters: ["cc36f4****"]    # 资源的分发目标,请替换为完整的集群ID。
    2. 执行以下命令,将资源下发到主控实例,进而下发到关联集群。

      kubectl apply -f app-meta.yaml
  4. 执行以下命令,查看应用部署情况。

    kubectl get app web-demo -n provider-ns

    预期输出:

    NAME       COMPONENT   TYPE          PHASE     HEALTHY   STATUS      AGE
    web-demo   web-demo    ref-objects   running   true      Ready:2/2   34s
  5. 执行如下命令,获取关联集群的资源运行状态。

    kubectl amc get deployment,service -n provider-ns -m cc36f4****  # 资源的分发目标,请替换为完整的集群ID。

    预期输出:

    Run on ManagedCluster cc36f4**** (cluster1)
    NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/web-demo   2/2     2            2           101s
    
    NAME               TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    service/service1   ClusterIP   172.16.39.201   <none>        80/TCP    101s

步骤二:创建多集群服务

  1. 使用以下内容,创建ServiceExport资源,指定需要开放多集群访问的Kubernetes服务。

    apiVersion: multicluster.x-k8s.io/v1alpha1
    kind: ServiceExport
    metadata:
      name: service1           # 名称与待开放的Kubernetes服务名称相同。
      namespace: provider-ns   # 与待开放的Kubernetes服务在同一个命名空间。

    ServiceExport为新增自定义资源,会分发到服务提供者集群,定义提供者集群需要开放的Kubernetes服务。具体的参数说明如下表所示。

    参数

    说明

    metadata.name

    待开放的Kubernetes服务名称。

    metadata.namespace

    待开放的Kubernetes服务所在的命名空间。

  2. 使用以下内容,创建ServiceImport资源。

    apiVersion: multicluster.x-k8s.io/v1alpha1
    kind: ServiceImport
    metadata:
      name: service1           
      namespace: provider-ns   
    spec:
      ports:                   # 与待开放的Kubernetes服务相同。
      - port: 80
        protocol: TCP
      type: ClusterSetIP

    ServiceImport为新增自定义资源,会分发到服务消费者集群,客户端通过此资源跨集群访问Kubernetes服务。以上代码示例中ServiceImport的spec字段仅定义了部分参数。关于spec完整参数说明如下表所示。

    参数

    说明

    metadata.name

    名称与待开放的Kubernetes服务名称相同。

    metadata.namespace

    命名空间名称与待开放的Kubernetes服务命名空间一致。

    spec. ports. name

    Port名称。需要与待开放的Kubernetes服务相应字段一致。

    spec. ports. protocol

    协议。需要与待开放的Kubernetes服务相应字段一致。

    spec. ports. appProtocol

    应用协议。需要与待开放的Kubernetes服务相应字段一致。

    spec. ports. port

    Port。需要与待开放的Kubernetes服务相应字段一致。

    spec. ips

    服务VIP。由主控实例分配,无需填写。

    spec. type

    支持ClusterSetIPHeadless。当待开放的Kubernetes服务的ClusterIPNone时,表示服务为Headless服务,设置typeHeadless。否则,设置typeClusterSetIP

    spec. sessionAffinity

    会话关联,支持ClientIPNone。需要与待开放的Kubernetes服务相应字段一致。

    spec. sessionAffinityConfig

    会话关联配置。需要与待开放的Kubernetes服务相应字段一致。

  3. 使用以下内容,创建分发规则mcs-service-policy.yaml,向关联集群分发ServiceExport和ServiceImport资源。

    apiVersion: core.oam.dev/v1beta1
    kind: Application
    metadata:
      name: amcs-export-service1
      namespace: provider-ns
      labels:
        amcs: export
        amcs-service: service1
      annotations:
        app.oam.dev/publishVersion: version1
    spec:
      components:
        - name: export-service
          type: ref-objects
          properties:
            objects:
              - resource: serviceexport  #引用ServiceExport资源。
                name: service1
      policies:
        - type: topology
          name: export-clusters
          properties:
            clusters: ["cc36f4****"]  #向服务提供者集群Cluster 1分发ServiceExport资源。
    ---
    apiVersion: core.oam.dev/v1beta1
    kind: Application
    metadata:
      name: amcs-import-service1
      namespace: provider-ns
      labels:
        amcs: import
        amcs-service: service1
      annotations:
        app.oam.dev/publishVersion: version1
    spec:
      components:
        - name: import-service
          type: ref-objects
          properties:
            objects:
              - resource: serviceimport  #引用ServiceImport资源。
                name: service1
      policies:
        - type: topology
          name: import-clusters
          properties:
            clusters: ["c984b0****"]  #向服务消费者集群Cluster 2分发ServiceImport资源。
  4. 执行以下命令,部署多集群服务。

    kubectl apply -f mcs-service-policy.yaml
  5. 执行以下命令,查看分发资源状态。

    kubectl amc get serviceexport,serviceimport -n provider-ns -m all

    预期输出:

    Run on ManagedCluster c984b0**** (cluster2)
    NAME                                           TYPE           IP                 AGE
    serviceimport.multicluster.x-k8s.io/service1   ClusterSetIP   ["172.xx.xx.xx"]   65s
    
    Run on ManagedCluster cc36f4**** (cluster1)
    NAME                                           AGE
    serviceexport.multicluster.x-k8s.io/service1   65s

    由预期输出看到:ServiceExport资源分发到服务提供者集群Cluster 1,ServiceImport资源分发到服务消费者集群Cluster 2。

步骤三:访问多集群服务

在服务消费者集群Cluster 2中的Client Pod可以通过以下两种方式访问服务提供者集群Cluster 1中的Service 1。

方式一:通过新的Service名称访问

服务消费者集群Cluster 2创建ServiceImport后,主控实例会创建一个以amcs-为前缀的Kubernetes服务代表多集群Service。在服务消费者集群Cluster 2的Client Pod,可以通过访问amcs-service1.provider-ns来访问服务提供者集群Cluster 1中的Service 1。

  1. 在主控实例上执行如下命令,获取相关Service信息。

    kubectl amc get service -n provider-ns -m all

    预期输出:

    Run on ManagedCluster c984b0**** (cluster2)
    NAME            TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    amcs-service1   ClusterIP   172.xx.xx.xx   <none>        80/TCP    26m
    
    Run on ManagedCluster cc36f4**** (cluster1)
    NAME       TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
    service1   ClusterIP   172.xx.xx.xx   <none>        80/TCP    169m
  2. 在服务消费者集群Cluster 2的Client Pod上执行如下命令,访问服务提供者集群Cluster 1中的Service 1。

    curl amcs-service1.provider-ns

方式二:通过新的Service域名访问

  1. 在服务消费者集群Cluster 2中安装或升级CoreDNS,版本要求1.9.3及以上。具体操作,请参见CoreDNS管理组件

  2. 修改CoreDNS组件的配置Corefile。

    1. 执行如下命令,修改CoreDNS组件的ConfigMap文件。

      kubectl edit configmap coredns -n kube-system
    2. 在Corefile文件中新增一行配置项multicluster clusterset.local,支持多集群服务域名解析。

      apiVersion: v1
      data:
        Corefile: |
          .:53 {
              errors
              health {
                 lameduck 15s
              }
              ready
              multicluster clusterset.local    #增加配置项,支持多集群服务域名解析。
              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. 在服务消费者集群Cluster 2的Client Pod上执行如下命令,访问服务提供者集群Cluster 1中的Service 1。

    服务消费者集群Cluster 2上创建ServiceImport之后,服务提供者集群Cluster 1会为多集群服务增加clusterset.local域名。

    curl service1.provider-ns.svc.clusterset.local
  4. (可选)通过修改服务消费者集群Cluster 2中Client Pod的dnsConfig.searches,访问多集群服务。

    1. 在Client Pod的dnsConfig.searches字段中增加搜索clusterset.local的域名。

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: client-pod
        namespace: consumer-ns
      spec:
        ...
        template:
          ...
          spec:
            dnsPolicy: "ClusterFirst"    
            dnsConfig:                   
              searches:                        #dnsConfig,增加搜索clusterset.local域名。
                - svc.clusterset.local
                - clusterset.local
                - consumer-ns.svc.cluster.local
                - svc.cluster.local
                - cluster.local
            containers:
            - name: client-pod
              ...
    2. 执行如下命令,访问多集群服务。

      curl service1.provider-ns

修改和删除多集群服务

修改多集群服务

  1. 修改创建ServiceExport创建ServiceImport中的ServiceExport和ServiceImport资源。

  2. 修改分发规则中的app.oam.dev/publishVersion,重新下发ServiceExport和ServiceImport资源。

删除多集群服务

  1. 执行以下命令,删除多集群服务分发规则。

    kubectl delete application amcs-export-service1 -n provider-ns
    kubectl delete application amcs-import-service1 -n provider-ns
  2. 执行以下命令,删除ServiceExport资源。

    kubectl delete serviceexport service1 -n provider-ns
  3. 执行以下命令,删除ServiceImport资源。

    kubectl delete serviceimport service1 -n provider-ns
阿里云首页 容器服务 Kubernetes 版 ACK 相关技术圈