更新时间:2024-10-14 GMT+08:00

通过kubectl对接多个集群

应用现状

kubectl命令行工具使用kubeconfig配置文件来查找选择集群所需的认证信息,并与集群的API服务器进行通信。默认情况下,kubectl会使用“$HOME/.kube/config”文件作为访问集群的凭证。

在CCE集群的日常使用过程中,我们通常需要同时管理多个集群,因此在使用kubectl命令行工具连接集群时需要经常切换kubeconfig配置文件,为日常运维带来许多不便。本文将为您介绍如何便捷地使用同一个kubectl客户端连接多个集群。

用于配置集群访问的文件称为kubeconfig配置文件,并不意味着文件名称为kubeconfig。

解决方案

在K8s集群的运维中,多集群之间的切换是无法避免的问题,常见的集群切换方案如下:

  • 方案一:您可以通过指定kubectl的“--kubeconfig”参数来选择每个集群所使用的kubeconfig配置文件,并可使用alias别名的方式来简化命令。
  • 方案二:将多个kubeconfig文件中的集群、用户和凭证合并成一个配置文件,并使用“kubectl config use-context”命令进行集群切换。

    该方案与方案一相比,需要手动配置kubeconfig文件,相对来说较为复杂。

图1 kubectl对接多集群示意

前提条件

  • 您需要在一台Linux虚拟机上安装kubectl命令行工具,kubectl的版本应该与集群版本相匹配,详情请参见安装kubectl
  • 安装kubectl的虚拟机需要可以访问每个集群的网络环境。

kubeconfig文件结构解析

kubeconfig是kubectl的配置文件,您可以在集群详情页面下载。

kubeconfig文件内容如下所示。

{
    "kind": "Config",
    "apiVersion": "v1",
    "preferences": {},
    "clusters": [{
        "name": "internalCluster",
        "cluster": {
            "server": "https://192.168.0.85:5443",
            "certificate-authority-data": "LS0tLS1CRUULIE..."
        }
    }, {
        "name": "externalCluster",
        "cluster": {
            "server": "https://xxx.xxx.xxx.xxx:5443",
            "insecure-skip-tls-verify": true
        }
    }],
    "users": [{
        "name": "user",
        "user": {
            "client-certificate-data": "LS0tLS1CRUdJTiBDRVJ...",
            "client-key-data": "LS0tLS1CRUdJTiBS..."
        }
    }],
    "contexts": [{
        "name": "internal",
        "context": {
            "cluster": "internalCluster",
            "user": "user"
        }
    }, {
        "name": "external",
        "context": {
            "cluster": "externalCluster",
            "user": "user"
        }
    }],
    "current-context": "external"
}

其中主要分为3部分内容。

  • clusters:描述集群的信息,主要是集群的访问地址。
  • users:描述访问集群访问用户的信息,主要是client-certificate-data和client-key-data这两个证书文件内容。
  • contexts:描述配置的上下文,用于使用时切换。上下文会关联user和cluster,也就是定义使用哪个user去访问哪个集群。

从上面的kubeconfig文件可以看出,此处将集群的内网地址和公网访问地址分别定义成一个集群,且定义了两个上下文,从而能够通过切换上下文选择使用不同的地址访问集群。

方案一:在命令中指定不同的kubeconfig配置文件

  1. 登录安装kubectl的虚拟机。
  2. 分别下载2个集群的kubeconfig文件到kubectl客户端机器的“/home”目录下,本文中使用以下名称作为示例。

    集群名称

    kubeconfig配置文件名称

    集群A

    kubeconfig-a.json

    集群B

    kubeconfig-b.json

  3. 假设以集群A作为kubectl的默认连接集群,将kubeconfig-a.json文件移动至“$HOME/.kube/config”

    cd /home 
    mkdir -p $HOME/.kube 
    mv -f kubeconfig-a.json $HOME/.kube/config

  4. 将集群B对应的kubeconfig-b.json文件移动至“$HOME/.kube/config-test”

    mv -f kubeconfig-b.json $HOME/.kube/config-test

    其中config-test文件名称可以自定义。

  5. 由于集群A为kubectl的默认连接集群,使用kubectl命令时无需添加“--kubeconfig”参数。而在使用kubectl连接集群B时,需要添加“--kubeconfig”参数用于指定kubectl命令所使用的凭证。例如查看集群B的节点命令如下:

    kubectl --kubeconfig=$HOME/.kube/config-test get node
    上述使用方式命令较长,频繁使用的情况下带来诸多不便,您可使用alias别名的方式简化命令,例如:
    alias ka='kubectl --kubeconfig=$HOME/.kube/config'
    alias kb='kubectl --kubeconfig=$HOME/.kube/config-test'

    其中ka、kb可根据喜好自定义。使用kubectl命令时,可直接输入ka或kb来代替kubectl,并自动添加“--kubeconfig”参数。例如上述查看集群B的节点命令可简化为:

    kb get node

方案二:将两个集群的kubeconfig文件合并

下面以配置2个集群为例演示如何修改kubeconfig文件访问多个集群。

为简洁文档篇幅,如下示例选取公网访问的方式,删除内网访问方式。如果您需要在内网访问多集群,只需要保留内网访问的集群clusters字段,保证能够从内网访问到集群即可,其方法与下面内容并无本质区别。

  1. 分别下载2个集群的kubeconfig文件,删除内网访问内容,如下所示。

    • 集群A:
      {
          "kind": "Config",
          "apiVersion": "v1",
          "preferences": {},
          "clusters": [ {
              "name": "externalCluster",
              "cluster": {
                  "server": "https://119.xxx.xxx.xxx:5443",
                  "insecure-skip-tls-verify": true
              }
          }],
          "users": [{
              "name": "user",
              "user": {
                  "client-certificate-data": "LS0tLS1CRUdJTxM...",
                  "client-key-data": "LS0tLS1CRUdJTiB...."
              }
          }],
          "contexts": [{
              "name": "external",
              "context": {
                  "cluster": "externalCluster",
                  "user": "user"
              }
          }],
          "current-context": "external"
      }
    • 集群B:
      {
          "kind": "Config",
          "apiVersion": "v1",
          "preferences": {},
          "clusters": [ {
              "name": "externalCluster",
              "cluster": {
                  "server": "https://124.xxx.xxx.xxx:5443",
                  "insecure-skip-tls-verify": true
              }
          }],
          "users": [{
              "name": "user",
              "user": {
                  "client-certificate-data": "LS0tLS1CRUdJTxM...",
                  "client-key-data": "LS0rTUideUdJTiB...."
              }
          }],
          "contexts": [{
              "name": "external",
              "context": {
                  "cluster": "externalCluster",
                  "user": "user"
              }
          }],
          "current-context": "external"
      }

      此时这两个文件除了集群访问地址clusters.cluster.server和user字段的client-certificate-data和client-key-data字段内容不同,文件结构完全一致。

  2. 修改两个配置文件中的名称,如下所示。

    • 集群A:
      {
          "kind": "Config",
          "apiVersion": "v1",
          "preferences": {},
          "clusters": [ {
              "name": "Cluster-A",
              "cluster": {
                  "server": "https://119.xxx.xxx.xxx:5443",
                  "insecure-skip-tls-verify": true
              }
          }],
          "users": [{
              "name": "Cluster-A-user",
              "user": {
                  "client-certificate-data": "LS0tLS1CRUdJTxM...",
                  "client-key-data": "LS0tLS1CRUdJTiB...."
              }
          }],
          "contexts": [{
              "name": "Cluster-A-Context",
              "context": {
                  "cluster": "Cluster-A",
                  "user": "Cluster-A-user"
              }
          }],
          "current-context": "Cluster-A-Context"
      }
    • 集群B:
      {
          "kind": "Config",
          "apiVersion": "v1",
          "preferences": {},
          "clusters": [ {
              "name": "Cluster-B",
              "cluster": {
                  "server": "https://124.xxx.xxx.xxx:5443",
                  "insecure-skip-tls-verify": true
              }
          }],
          "users": [{
              "name": "Cluster-B-user",
              "user": {
                  "client-certificate-data": "LS0tLS1CRUdJTxM...",
                  "client-key-data": "LS0rTUideUdJTiB...."
              }
          }],
          "contexts": [{
              "name": "Cluster-B-Context",
              "context": {
                  "cluster": "Cluster-B",
                  "user": "Cluster-B-user"
              }
          }],
          "current-context": "Cluster-B-Context"
      }

  3. 将两个文件的内容合并。

    文件结构不变,将clusters、users和contexts的内容合并即可,如下所示。

    {
        "kind": "Config",
        "apiVersion": "v1",
        "preferences": {},
        "clusters": [ {
            "name": "Cluster-A",
            "cluster": {
                "server": "https://119.xxx.xxx.xxx:5443",
                "insecure-skip-tls-verify": true
            }
        },
         {
            "name": "Cluster-B",
            "cluster": {
                "server": "https://124.xxx.xxx.xxx:5443",
                "insecure-skip-tls-verify": true
            }
        }],
        "users": [{
            "name": "Cluster-A-user",
            "user": {
                "client-certificate-data": "LS0tLS1CRUdJTxM...",
                "client-key-data": "LS0tLS1CRUdJTiB...."
            }
        },
        {
            "name": "Cluster-B-user",
            "user": {
                "client-certificate-data": "LS0tLS1CRUdJTxM...",
                "client-key-data": "LS0rTUideUdJTiB...."
            }
        }],
        "contexts": [{
            "name": "Cluster-A-Context",
            "context": {
                "cluster": "Cluster-A",
                "user": "Cluster-A-user"
            }
        },
        {
            "name": "Cluster-B-Context",
            "context": {
                "cluster": "Cluster-B",
                "user": "Cluster-B-user"
            }
        }],
        "current-context": "Cluster-A-Context"
    }

  4. 将两个文件内容合并到一个kubeconfig文件后,执行如下命令将文件复制到kubectl配置路径下。

    mkdir -p $HOME/.kube

    mv -f kubeconfig.json $HOME/.kube/config

  5. 执行kubectl命令验证是否能够连接两个集群。

    # kubectl config use-context Cluster-A-Context
    Switched to context "Cluster-A-Context".
    # kubectl cluster-info
    Kubernetes control plane is running at https://119.xxx.xxx.xxx:5443
    CoreDNS is running at https://119.xxx.xxx.xxx:5443/api/v1/namespaces/kube-system/services/coredns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
    
    # kubectl config use-context Cluster-B-Context
    Switched to context "Cluster-B-Context".
    # kubectl cluster-info
    Kubernetes control plane is running at https://124.xxx.xxx.xxx:5443
    CoreDNS is running at https://124.xxx.xxx.xxx:5443/api/v1/namespaces/kube-system/services/coredns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

    上述使用方式命令较长,频繁切换的情况下带来诸多不便,您也可以使用alias别名的方式简化命令,如下:

    alias ka='kubectl config use-context Cluster-A-Context;kubectl'
    alias kb='kubectl config use-context Cluster-B-Context;kubectl'

    其中ka、kb可根据喜好自定义。使用kubectl命令时,可直接输入ka或kb来代替kubectl,在使用时会先切换context,再执行kubectl命令。例如:

    # ka cluster-info
    Switched to context "Cluster-A-Context".
    Kubernetes control plane is running at https://119.xxx.xxx.xxx:5443
    CoreDNS is running at https://119.xxx.xxx.xxx:5443/api/v1/namespaces/kube-system/services/coredns:dns/proxy
    
    To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.