跳转至

应用跨集群通信

介绍

随着微服务进程发展,为了满足应用隔离、高可用/容灾以及运维管理的需求,许多企业选择部署多个 Kubernetes(K8s)集群。然而,这种多集群部署带来了一个问题:一些应用依赖于其他 K8s 集群中的 微服务,需要实现集群间的通信。具体而言,需要从一个集群的 Pod 去访问另外一个集群的 Pod 或者 Service。

前提条件

请确认操作系统 Kernel 版本号 >= v4.9.17,推荐 v5.10+。查看并安装升级最新的 Linux 内核版本,您可以按照如下命令进行操作:

  1. 查看当前内核版本:

    uname -r
    
  2. 安装 ELRepo 存储库,ELRepo 存储库中提供的最新 Linux 内核版本:

    rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
    rpm -Uvh https://www.elrepo.org/elrepo-release-7.el7.elrepo.noarch.rpm
    
  3. 安装最新的 Linux 内核版本:

    yum --enablerepo=elrepo-kernel install kernel-ml
    

    kernel-ml 是最新文档版内核,您可以根据需要选择其他版本。

  4. 更新 GRUB 配置,以便在启动时使用新内核版本:

    grub2-mkconfig -o /boot/grub2/grub.cfg
    

创建集群

关于创建集群的更多信息,可参考创建集群

  1. 创建两个名称不同的集群分别为 cluster01 和 cluster02。

    创建集群1

    • 集群 cluster01 的网络插件选择 Cilium
    • 添加两个参数 cluster-idcluster-name
    • 其他均使用默认配置项
  2. 以同样的步骤创建集群 cluster02。

    创建集群2

    两个集群使用的容器网段和服务网段一定不能冲突。两个参数的值不能冲突,便于标识集群确保唯一性,避免跨集群通信时出现冲突。

为 API Server 创建 Service

  1. 集群创建成功后,在两个集群上分别创建一个 Service,用于将该集群的 API server 对外暴露。

    创建service

    创建service

    • 集群 cluster01 访问类型选择 NodePort, 便于外部访问
    • 命名空间选择 kube-system,即 API Server 所在命名空间
    • 标签选择器筛选 API Server 组件,可返回查看 API Server 的选择器
    • 配置 Service 的访问端口,容器端口为 6443
    • 获取该 Service 的外部访问链接
  2. 再以同样方式在集群 cluster02 上为 API Server 创建 Service。

    创建service

    创建service

修改集群配置

通过 vi 命令开始编辑 集群 cluster01 和集群 cluster02 的 kubeconfig 文件:

vi $HOME/.kube/config
  1. 在两个集群 cluster01 和 cluster02 里分别添加新的 clustercontextuser 信息。

    • clusters 下面添加新的 cluster 信息:两个集群原有的 CA 颁发机构不变;新的 server 地址改为上述创建的 API Server Service 地址;name 改为两个集群本身的名称:cluster01 和 cluster02。

      API Server Service 的地址可以从 DCE5.0 的页面查看或复制,需要使用 https 协议。

    • contexts 下面添加新的 context 信息:将 context 中集群的 nameusercluster 三个字段的值均修改为两个集群本身的名称:cluster01 和 cluster02 。

    • users 下面添加新的 user 信息:两个集群 cluster01 和 cluster02 分别复制本身原有的证书信息,将 name 改为两个集群本身的名称:cluster01 和 cluster02。

  2. 在对端集群中分别互相添加已经创建好的 clustercontextuser 信息。

    如下为操作过程中的 yaml 示例:

    clusters:
    - cluster: #添加本集群 cluster01 `cluster`信息
        certificate-authority-data: {{cluster01}}
        server: https://{{https://10.6.124.66:31936}}
      name: {{cluster01 }}
    - cluster: #添加对端集群 cluster02`cluster`信息
        certificate-authority-data: {{cluster02}}
        server: https://{{https://10.6.124.67:31466}}
      name: {{cluster02}}
    
    contexts:
    - context: #添加本集群 cluster01 `context` 信息
        cluster: {{cluster01 name}}
        user: {{cluster01 name}}
      name: {{cluster01 name}}
    - context: #添加对端集群 cluster02 `context`信息
        cluster: {{cluster02 name}}
        user: {{cluster02 name}}
      name: {{cluster02 name}}
    current-context: kubernetes-admin@cluster.local
    
    users:
    - name: {{cluster01}} #添加本集群 cluster01 `user`信息
      user:
        client-certificate-data: {{cluster01 certificate-data}}
        client-key-data: {{cluster01 key-data}}
    - name: {{cluster02}} #添加对端集群 cluster02 `user`信息
      user:
        client-certificate-data: {{cluster02 certificate-data}}
        client-key-data: {{cluster02 key-data}}
    

配置集群连通性

执行如下命令验证集群的连通性:

  1. 在集群 cluster01 上输入:

    cilium clustermesh enable --create-ca --context cluster01 --service-type NodePort
    
  2. 集群 cluster02 开启 clustermesh 执行如下命令:

    cilium clustermesh enable --create-ca --context cluster02 --service-type NodePort
    
  3. 在集群 cluster01 上建立连接:

    cilium clustermesh connect --context cluster01 --destination-context cluster02
    
  4. 集群 cluster01 出现 connected cluster1 and cluster2! ,集群 cluster02 出现 ClusterMesh enabled! 说明两个集群通了。

    连通

    连通

创建演示应用

  1. 使用 Cilium 官方文档中提供的 rebel-base 应用,复制如下 yaml 文件:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: rebel-base
    spec:
      selector:
        matchLabels:
          name: rebel-base
      replicas: 2
      template:
        metadata:
          labels:
            name: rebel-base
        spec:
          containers:
          - name: rebel-base
            image: docker.io/nginx:1.15.8
            volumeMounts:
              - name: html
                mountPath: /usr/share/nginx/html/
            livenessProbe:
              httpGet:
                path: /
                port: 80
              periodSeconds: 1
            readinessProbe:
              httpGet:
                path: /
                port: 80
          volumes:
            - name: html
              configMap:
                name: rebel-base-response
                items:
                  - key: message
                    path: index.html
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: rebel-base-response
    data:
      message: "{\"Galaxy\": \"Alderaan\", \"Cluster\": \"Cluster-1\"}\n" #将 Cluster-1 修改为集群一的名称
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: x-wing
    spec:
      selector:
        matchLabels:
          name: x-wing
      replicas: 2
      template:
        metadata:
          labels:
            name: x-wing
        spec:
          containers:
          - name: x-wing-container
            image: quay.io/cilium/json-mock:v1.3.3@sha256:f26044a2b8085fcaa8146b6b8bb73556134d7ec3d5782c6a04a058c945924ca0
            livenessProbe:
              exec:
                command:
                - curl
                - -sS
                - -o
                - /dev/null
                - localhost
            readinessProbe:
              exec:
                command:
                - curl
                - -sS
                - -o
                - /dev/null
                - localhost
    
  2. 在 DCE 5.0 中通过 yaml 文件快速分别创建两个集群 cluster01 和 cluster02 的应用。

    创建应用

    分别修改 ConfigMap 的内容,使得访问集群 cluster01 和集群 cluster02 中的 Service 时,返回的数据分别带有 cluster01 和 cluster02 名称的标签。可在 rebel-base 应用中查看容器组标签。

  3. 在两个集群 cluster01 和 cluster02 中分别创建一个 global service video 的 Service,指向的是已创建的 rebel-base 应用。

    创建service应用

    创建service应用

    • Service 类型为 ClusterIP
    • 添加应用的容器组标签筛选对应的应用
    • 配置端口
    • 添加注解,使当前的 Service 在全局生效

    在创建集群 cluster02 的 Service 时,两个集群的 service name 必须相同,并位于相同的命名空间,拥有相同的端口名称和相同的 global 注解。

跨集群通信

  1. 先查看集群 cluster02 中应用的 Pod IP。

    查看pod ip

  2. 进入集群 cluster01 详情,点击应用 rebel-base 的 容器组 -> 控制台 ,curl 集群 cluster02 应用 rebel-base 的 Pod IP,成功返回 cluster02 信息,说明两个集群中的 Pod 可以相互通信。

    pod 通信

  3. 查看集群 cluster01 的 Service 名称,进入集群 cluster02 应用 rebel-base 的 容器组 -> 控制台curl 对应的 cluster01 的 Service 名称, 有些返回内容来自 cluster01,说明两个集群中的 Pod 和 Service 也可以互相通信。

    Pod 和 Service通信

评论