Todos os produtos
Search
Central de documentação

Container Service for Kubernetes:Criar um cluster de contêineres elásticos híbrido (ECS elástico)

Última atualização: Jun 27, 2026

Um cluster híbrido conecta seu cluster Kubernetes autogerenciado on-premises à Alibaba Cloud por meio de um cluster registrado. Esse recurso permite dimensionar o cluster local com nós do Elastic Compute Service (ECS) baseados em nuvem e gerenciar ambos os ambientes a partir de um único plano de controle.

Este guia usa como exemplo um cluster de data center que executa o Calico no modo route reflector. Na nuvem, o Container Service for Kubernetes (ACK) da Alibaba Cloud utiliza o plugin Terway para a rede de contêineres.

Pré-requisitos

Antes de começar, verifique se você tem:

  • Conectividade de rede entre o cluster on-premises e a Virtual Private Cloud (VPC) usada pelo cluster registrado. Essa conectividade deve abranger tanto a rede dos nós de computação quanto a rede de contêineres. Use a Cloud Enterprise Network (CEN) para estabelecer essa conexão. Para mais detalhes, consulte Estabelecer conexões multi-VPC em diferentes cenários.

Importante

A conectividade de rede entre o ambiente on-premises e a VPC é o requisito fundamental. Sem essa configuração, as etapas subsequentes não terão êxito.

  • Cluster on-premises conectado ao cluster registrado mediante a configuração do agente de importação de cluster privado fornecida pelo cluster registrado.

  • Nós de computação baseados em nuvem adicionados por meio do cluster registrado com acesso ao API Server do cluster on-premises.

  • Conexão kubectl com o cluster registrado. Consulte Obter o arquivo kubeconfig de um cluster e usar kubectl para conectar-se ao cluster.

Arquitetura do cluster híbrido

Em um cluster híbrido, o Calico roda on-premises e o Terway roda na nuvem. Os dois plugins de rede não devem interferir entre si: os pods do Calico permanecem nos nós on-premises, enquanto os pods do Terway rodam apenas nos nós ECS baseados em nuvem.

O diagrama a seguir ilustra a topologia de rede deste exemplo.

image

On-premises (data center):

  • Bloco CIDR privado: 192.168.0.0/24

  • Bloco CIDR da rede de contêineres: 10.100.0.0/16

  • Plugin de rede: Calico (modo route reflector)

Na nuvem:

  • Bloco CIDR da VPC: 10.0.0.0/8

  • Bloco CIDR do vSwitch para nós de computação: 10.10.24.0/24

  • Bloco CIDR do vSwitch para pods: 10.10.25.0/24

  • Plugin de rede: Terway (modo compartilhado)

Certifique-se de que o bloco CIDR da rede de contêineres on-premises ( 10.100.0.0/16 ) não se sobreponha ao bloco CIDR da VPC ( 10.0.0.0/8 ).

Configure o cluster híbrido

A configuração envolve sete etapas:

  1. Restringir o Calico aos nós on-premises

  2. Conceder permissões RAM ao Terway

  3. Instale o Terway

  4. Verifique o DaemonSet do Terway

  5. Configure o ConfigMap ENI do Terway

  6. Crie um script personalizado de inicialização de nó

  7. Crie um pool de nós e adicione nós ECS

Etapa 1: Restringir o Calico aos nós on-premises

Os nós ECS baseados em nuvem adicionados a um cluster ACK registrado recebem automaticamente o rótulo alibabacloud.com/external=true. Configure nodeAffinity no DaemonSet do Calico para garantir que os pods do Calico rodem apenas em nós on-premises (nós sem esse rótulo).

cat <<EOF > calico-ds.patch
spec:
  template:
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: alibabacloud.com/external
                operator: NotIn
                values:
                - "true"
              - key: type
                operator: NotIn
                values:
                - "virtual-kubelet"
EOF
kubectl -n kube-system patch ds calico-node -p "$(cat calico-ds.patch)"

Etapa 2: Conceder permissões RAM ao Terway

O Terway requer permissões do Resource Access Management (RAM) para gerencie elastic network interfaces (ENIs) nos nós ECS.

Opção A: Usar onectl (recomendado)

  1. Instale e configure o onectl. Consulte Gerencie clusters registrados usando onectl.

  2. Execute o comando:

    onectl ram-user grant --addon terway-eniip

    Saída esperada:

    Ram policy ack-one-registered-cluster-policy-terway-eniip granted to ram user ack-one-user-ce313528c3 successfully.

Opção B: Usar o console

Conceda a seguinte política RAM ao AccessKey usado pelo Terway. Para obter instruções, consulte Gerencie permissões de usuário RAM.

{
    "Version": "1",
    "Statement": [
        {
            "Action": [
                "ecs:CreateNetworkInterface",
                "ecs:DescribeNetworkInterfaces",
                "ecs:AttachNetworkInterface",
                "ecs:DetachNetworkInterface",
                "ecs:DeleteNetworkInterface",
                "ecs:DescribeInstanceAttribute",
                "ecs:AssignPrivateIpAddresses",
                "ecs:UnassignPrivateIpAddresses",
                "ecs:DescribeInstances",
                "ecs:ModifyNetworkInterfaceAttribute"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        },
        {
            "Action": [
                "vpc:DescribeVSwitches"
            ],
            "Resource": [
                "*"
            ],
            "Effect": "Allow"
        }
    ]
}

Etapa 3: Instale o Terway

Opção A: Usar onectl

onectl addon install terway-eniip

Saída esperada:

Addon terway-eniip, version **** installed.

Opção B: Usar o console

  1. Faça logon no Container Service Management Console. No painel de navegação à esquerda, clique em Clusters.

  2. Clique no nome do cluster e selecione Add-ons no painel de navegação à esquerda.

  3. Na página Add-ons, pesquise por terway-eniip. Clique em Install no canto inferior direito do cartão do componente e confirme clicando em OK.

Etapa 4: Verifique o DaemonSet do Terway

Antes de adicionar nós baseados em nuvem, confirme que o Terway não está agendado em nenhum nó on-premises.

kubectl -nkube-system get ds |grep terway

Saída esperada:

terway-eniip   0         0         0       0            0           alibabacloud.com/external=true      16s

O seletor de nó alibabacloud.com/external=true confirma que os pods do Terway rodarão apenas em nós ECS baseados em nuvem.

Etapa 5: Configure o ConfigMap ENI do Terway

Edite o ConfigMap eni-config no namespace kube-system para definir as credenciais AccessKey do Terway:

kubectl -n kube-system edit cm eni-config

Defina access_key e access_secret na seção eni_conf:

kind: ConfigMap
apiVersion: v1
metadata:
  name: eni-config
  namespace: kube-system
data:
  eni_conf: |
    {
     "version": "1",
     "max_pool_size": 5,
     "min_pool_size": 0,
     "vswitches": {"AZoneID":["VswitchId"]},
     "eni_tags": {"ack.aliyun.com":"{{.ClusterID}}"},
     "service_cidr": "{{.ServiceCIDR}}",
     "security_group": "{{.SecurityGroupId}}",
     "access_key": "",
     "access_secret": "",
     "vswitch_selection_policy": "ordered"
    }
  10-terway.conf: |
    {
     "cniVersion": "0.3.0",
     "name": "terway",
     "type": "terway"
    }

Substitua access_key e access_secret pelo AccessKey ID e AccessKey Secret do usuário RAM com as permissões concedidas na Etapa 2.

Etapa 6: Crie um script personalizado de inicialização de nó

Ao adicionar um nó ECS, o cluster ACK registrado executa um script de inicialização e transmite variáveis de ambiente específicas da nuvem. Estenda o script de inicialização on-premises existente (init-node.sh) para processar essas variáveis.

Variáveis de ambiente transmitidas pelo cluster registrado:

Variável de ambiente

Finalidade

ALIBABA_CLOUD_PROVIDER_ID

Defina --provider-id no kubelet

ALIBABA_CLOUD_NODE_NAME

Defina --hostname-override no kubelet

ALIBABA_CLOUD_LABELS

Defina --node-labels no kubelet

ALIBABA_CLOUD_TAINTS

Defina --register-with-taints no kubelet

6a. Estender o script de inicialização

O script personalizado init-node-ecs.sh inicia com a mesma configuração do init-node.sh (instalação de containerd, kubelet, kubeadm, etc.) e adiciona uma seção para ler as variáveis de ambiente da Alibaba Cloud e passá-las ao kubelet antes de ingressar no cluster.

Visualize o exemplo do script init-node.sh

#!/bin/bash

export K8S_VERSION=1.24.3

export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
yum remove -y containerd.io
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io-1.4.3
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i "s#k8s.gcr.io#registry.aliyuncs.com/k8sxio#g"  /etc/containerd/config.toml
sed -i '/containerd.runtimes.runc.options/a\            SystemdCgroup = true' /etc/containerd/config.toml
sed -i "s#https://registry-1.docker.io#${REGISTRY_MIRROR}#g"  /etc/containerd/config.toml
systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
yum install -y nfs-utils
yum install -y wget
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum remove -y kubelet kubeadm kubectl
yum install -y kubelet-$K8S_VERSION kubeadm-$K8S_VERSION kubectl-$K8S_VERSION
crictl config runtime-endpoint /run/containerd/containerd.sock
systemctl daemon-reload
systemctl enable kubelet && systemctl start kubelet
containerd --version
kubelet --version

kubeadm join 10.200.1.253:XXXX --token cqgql5.1mdcjcvhszol**** --discovery-token-unsafe-skip-ca-verification

Visualize o exemplo do script init-node-ecs.sh

#!/bin/bash

export K8S_VERSION=1.24.3

export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-cri.conf
net.bridge.bridge-nf-call-iptables  = 1
net.ipv4.ip_forward                 = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sysctl --system
yum remove -y containerd.io
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum install -y containerd.io-1.4.3
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
sed -i "s#k8s.gcr.io#registry.aliyuncs.com/k8sxio#g"  /etc/containerd/config.toml
sed -i '/containerd.runtimes.runc.options/a\            SystemdCgroup = true' /etc/containerd/config.toml
sed -i "s#https://registry-1.docker.io#${REGISTRY_MIRROR}#g"  /etc/containerd/config.toml
systemctl daemon-reload
systemctl enable containerd
systemctl restart containerd
yum install -y nfs-utils
yum install -y wget
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum remove -y kubelet kubeadm kubectl
yum install -y kubelet-$K8S_VERSION kubeadm-$K8S_VERSION kubectl-$K8S_VERSION
crictl config runtime-endpoint /run/containerd/containerd.sock
systemctl daemon-reload
systemctl enable kubelet && systemctl start kubelet
containerd --version
kubelet --version

####### Start of added section
# Configure node labels, taints, node name, and provider ID
# from environment variables passed by the registered ACK cluster
KUBELET_CONFIG_FILE="/etc/sysconfig/kubelet"

if [[ $ALIBABA_CLOUD_LABELS != "" ]];then
  option="--node-labels"
  if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_LABELS},@g" $KUBELET_CONFIG_FILE
  elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_LABELS} @g" $KUBELET_CONFIG_FILE
  else
    sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_LABELS}\"" $KUBELET_CONFIG_FILE
  fi
fi

if [[ $ALIBABA_CLOUD_TAINTS != "" ]];then
  option="--register-with-taints"
  if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_TAINTS},@g" $KUBELET_CONFIG_FILE
  elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_TAINTS} @g" $KUBELET_CONFIG_FILE
  else
    sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_TAINTS}\"" $KUBELET_CONFIG_FILE
  fi
fi

if [[ $ALIBABA_CLOUD_NODE_NAME != "" ]];then
  option="--hostname-override"
  if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_NODE_NAME},@g" $KUBELET_CONFIG_FILE
  elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_NODE_NAME} @g" $KUBELET_CONFIG_FILE
  else
    sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_NODE_NAME}\"" $KUBELET_CONFIG_FILE
  fi
fi

if [[ $ALIBABA_CLOUD_PROVIDER_ID != "" ]];then
  option="--provider-id"
  if grep -- "${option}=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@${option}=@${option}=${ALIBABA_CLOUD_PROVIDER_ID},@g" $KUBELET_CONFIG_FILE
  elif grep "KUBELET_EXTRA_ARGS=" $KUBELET_CONFIG_FILE &> /dev/null;then
    sed -i "s@KUBELET_EXTRA_ARGS=@KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_PROVIDER_ID} @g" $KUBELET_CONFIG_FILE
  else
    sed -i "/^\[Service\]/a\Environment=\"KUBELET_EXTRA_ARGS=${option}=${ALIBABA_CLOUD_PROVIDER_ID}\"" $KUBELET_CONFIG_FILE
  fi
fi

# Reload and restart kubelet with the new configuration
systemctl daemon-reload
systemctl enable kubelet && systemctl start kubelet
####### End of added section

kubeadm join 10.200.1.253:XXXX --token cqgql5.1mdcjcvhszol**** --discovery-token-unsafe-skip-ca-verification

6b. Hospedar o script e registrá-lo no cluster

  1. Carregue o arquivo init-node-ecs.sh em um servidor de arquivos HTTP acessível pela nuvem, como um bucket do Object Storage Service (OSS):

    https://kubelet-****.oss-cn-hangzhou-internal.aliyuncs.com/init-node-ecs.sh
  2. Defina addNodeScriptPath no ConfigMap ack-agent-config como a URL do script:

    apiVersion: v1
    data:
      addNodeScriptPath: https://kubelet-****.oss-cn-hangzhou-internal.aliyuncs.com/init-node-ecs.sh
    kind: ConfigMap
    metadata:
      name: ack-agent-config
      namespace: kube-system

Etapa 7: Crie um pool de nós e adicione nós ECS

  1. Faça logon no Container Service Management Console. No painel de navegação à esquerda, clique em Clusters.

  2. Clique no nome do cluster e selecione Nodes > Node Pools no painel de navegação à esquerda.

  3. Na página Node Pools, crie um pool de nós e adicione nós. Para mais detalhes, consulte Criar e gerencie um pool de nós.

Verifique o cluster híbrido

Após adicionar os nós, confirme que os novos nós ECS ingressaram no cluster com o rótulo correto:

kubectl get nodes --show-labels | grep external=true

Os nós com o rótulo alibabacloud.com/external=true são nós ECS baseados em nuvem. Nós sem esse rótulo são on-premises. Se ambos os tipos aparecerem na saída, o cluster híbrido estará operacional.

Próximos passos