
# 通过kubectl对接多个集群
#### 应用现状
kubectl命令行工具使用kubeconfig配置文件来查找选择集群所需的认证信息，并与集群的API服务器进行通信。默认情况下，kubectl会使用"$HOME/.kube/config"文件作为访问集群的凭证。
在CCE集群的日常使用过程中，我们通常需要同时管理多个集群，因此在使用kubectl命令行工具连接集群时需要经常切换kubeconfig配置文件，为日常运维带来许多不便。本文将为您介绍如何便捷地使用同一个kubectl客户端连接多个集群。
![](https://support.huaweicloud.com/bestpractice-cce/public_sys-resources/note_3.0-zh-cn.png)
用于配置集群访问的文件称为kubeconfig配置文件，并不意味着文件名称为kubeconfig。
#### 解决方案
在K8s集群的运维中，多集群之间的切换是无法避免的问题，常见的集群切换方案如下：
- [方案一]：您可以通过指定kubectl的"--kubeconfig"参数来选择每个集群所使用的kubeconfig配置文件，并可使用alias别名的方式来简化命令。
- [方案二]：将多个kubeconfig文件中的集群、用户和凭证合并成一个配置文件，并使用"kubectl config use-context"命令进行集群切换。
  该方案与方案一相比，需要手动配置kubeconfig文件，相对来说较为复杂。
  
图1kubectl对接多集群示意   
![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0261820020.png)
#### 前提条件
- 您需要在一台Linux虚拟机上安装kubectl命令行工具，kubectl的版本应该与集群版本相匹配，详情请参见[安装kubectl](https://kubernetes.io/zh-cn/docs/tasks/tools/)。
- 安装kubectl的虚拟机需要可以访问每个集群的网络环境。
 
#### kubeconfig文件结构解析
kubeconfig是kubectl的配置文件，您可以在集群详情页面下载。
![](https://support.huaweicloud.com/bestpractice-cce/zh-cn_image_0000001262363819.png "点击放大")
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'.
   ```
   
   
 
