在 vSphere 叢集中新增或移除節點

本文說明如何在 Google Cloud的 VMware 解決方案中,使用 VMware Cloud Foundation (VCF) 9.1,將一或多個 Compute Engine 裸機節點新增至現有 vSphere 叢集 (叢集擴充),以及從叢集移除一或多個節點 (叢集壓縮)。如需增加或減少管理網域或 VI 工作負載網域中現有叢集的運算和 vSAN 儲存空間容量,請擴充或壓縮叢集。無論是新增或移除單一節點或多個節點,程序都相同:在 ADD_HOSTS 或 REMOVE_HOSTS 環境變數中列出一或多個節點。

架構摘要

在現有 vSphere 叢集中新增或移除節點時,工作流程會使用下列架構:

  • 新增節點:每個新節點都是 z3-highmem-192-highlssd-metal 裸機執行個體,部署在與叢集現有節點相同的可用區、配置政策和機型。每個節點在虛擬私有雲 (VPC) 網路的 ESXi 管理子網路上都有一個主要網路介面 (nic0),以及用於 vMotion、vSAN 和 NSX 通道端點 (TEP) 的 VLAN 標記 Dynamic Network Interface。節點會加入現有的可用區網路端點群組 (NEG)。接著,您在 SDDC Manager 中使用叢集的網路集區委任節點,並將節點新增至叢集。
  • 移除節點:首先,您要從 VCF 的叢集中移除節點,這會遷移工作負載 VM 並撤出主機的 vSAN 資料。接著,您會從 SDDC Manager 停用主機,並從可用區 NEG 移除主機,然後刪除基礎 Compute Engine 裸機執行個體。
  • IP 位址一致性:與建立叢集時相同,VCF 會從叢集的網路集區分配 vMotion 和 vSAN IP 位址,NSX 則會從 NSX IP 位址集區分配 TEP (vmk10) IP 位址。您將新節點的 Compute Engine Dynamic NIC 與 VCF 分配的 IP 位址對齊,同時保持所有 VCF 驗證啟用。
  • 不需變更設備:新增或移除叢集節點時,不需為管理設備建立新的 Cloud DNS 記錄、後端服務、高可用性 (HA) 政策或轉送規則。

事前準備

新增或移除節點前,請先確認下列各節的需求條件,並設定環境變數。

確認環境需求

確認環境符合下列需求:

  • 權限:您在目標專案中具備必要的 Identity and Access Management (IAM) 角色,包括 Compute 管理員 (roles/compute.admin)、DNS 管理員 (roles/dns.admin) 和 Secret Manager 密鑰存取者 (roles/secretmanager.secretAccessor)。
  • Secret Manager 中的憑證:如果在初始部署後,您在 VCF 中變更或輪替 ESXi root、SDDC Manager、vCenter Server 或 NSX Manager 密碼,Secret Manager 不會自動更新。執行本文件中的指令前,請先更新 Secret Manager 中的對應密鑰,或直接提供更新後的密碼,確保與有效的 VCF 憑證相符。
  • 叢集和網域健康狀態:目標叢集及其網域健康狀態良好 (vCenter Server、vSAN、NSX Manager、SDDC Manager 和 VCF Operations),且沒有失敗的工作。
  • 新增節點:

    • 專案在目標區域和可用區有足夠的 z3 裸機配額。
    • 新節點會使用與叢集中現有節點相同的機型 (vSAN Express Storage Architecture (ESA) 為 z3-highmem-192-highlssd-metal),並指派給叢集的現有配置政策 (每項配置政策僅屬於一個叢集)。
    • 每個新節點都有 NVMe 本機 SSD 裝置,且沒有預先存在的磁碟分割。
    • 如果貴組織強制執行 constraints/compute.trustedImageProjects 組織政策,或使用 VPC Service Controls service perimeter,請確認專案允許映像檔存取 smve-prod-public-images 專案 (projects/999037279871)。詳情請參閱「管理節點容量」。
    • 以 VLAN 為基礎的網路:VMware 解決方案要求虛擬私有雲網路的子網路將「Resolve Subnet Mask」(解析子網路遮罩) 屬性設為「Broadcast primary range only with learning」(僅透過學習廣播主要範圍),以支援以 VLAN 為基礎的網路。在Google Cloud 控制台支援中心提交支援單,並附上以下資訊:

      • 產品:Google Cloud VMware Engine
      • Priority:P2
      • 類別:網路連線
      • 業務影響:一般技術問題
      • 提供更多詳細資料:Allowlist L2 network connectivity for my project,以及專案 ID、專案編號,以及部署作業的目標區域和可用區

      如要進一步瞭解 VLAN 網路支援,請參閱「第 2 層模擬:ARP 廣播和自訂 MAC 學習」。

  • 移除節點:

    • 其餘節點有足夠的運算和 vSAN 儲存空間容量,可處理有效工作負載。
    • 移除節點後,叢集會保留至少三個節點 (vSAN 的最低要求,可容許一個故障 (FTT=1)),或有效儲存空間政策規定的最低主機數量 (請參閱「vSAN 可容許的故障和主機數量」)。
  • Jumpbox VM:您可以使用已安裝 gcloud CLI、curl 和 jq 的 Jumpbox VM,並與虛擬私有雲網路建立網路連線 (例如在 bm-gcp-demo 子網路中)。

查看範例環境參數

本文件中的指令使用下列範例參數:

輸入參數 範例值 說明
專案 ID、區域和可用區 PROJECT_ID / us-east4 / us-east4-b 與目標叢集位於相同的專案、區域和可用區
客戶 ID demo 現有資源名稱中使用的 ID
目標叢集 cl02 (esxi-h7、esxi-h8、esxi-h9) 管理網域或 VI 工作負載網域中的現有叢集
配置政策 bm-cl02 叢集現有的群組配置政策
網路集區和 VDS cl02-np01/cl02-vds-01 叢集的現有網路集區和 vSphere Distributed Switch (VDS)
NSX TEP IP 集區 cl02-tep-pool 叢集的現有 NSX IP 位址集區
NSX Manager nsx01.vmware.gve 叢集網域的 NSX Manager (或 wld01 工作負載網域的 nsx05.vmware.gve,具有專屬 NSX 執行個體)
機型 z3-highmem-192-highlssd-metal 與叢集中現有節點相同的機型
虛擬私有雲網路和子網路 (VLAN ID) bm-demo;bm-mgmt-demo (未標記)、bm-vmotion-demo (2)、bm-vsan-demo (3)、bm-nsx-demo (4) 現有的虛擬私有雲網路和第 2 層子網路
區域性 NEG bm-mgmt-demo、bm-nsx-tep-demo 現有的管理和 NSX TEP NEG
SDDC Manager sddcm.vmware.gve (192.168.0.3) 現有的 SDDC Manager 設備
ESXi root 密碼 esxi-root-password 現有的 Secret Manager 密鑰,內含 ESXi root 密碼

規劃 IP 位址和主機名稱

以下範例會將兩個節點 (esxi-h10 和 esxi-h11) 新增至 cl02 叢集,然後移除其中一個節點 (esxi-h11)。如要新增或移除單一節點,請在環境變數陣列中僅加入該節點:

ESXi 主機 管理 IP (nic0) vMotion (VLAN 2) vSAN (VLAN 3) NSX TEP (VLAN 4) 可用性網域 動作
esxi-h10 192.168.0.164 192.168.2.24 192.168.3.24 192.168.4.24 4 新增
esxi-h11 192.168.0.165 192.168.2.25 192.168.3.25 192.168.4.25 5 先新增再移除

依據叢集的配置政策,將叢集的節點分配至不同的可用性網域:由於現有節點 (esxi-h7 到 esxi-h9) 使用可用性網域 1 到 3,因此新節點會使用可用性網域 4 和 5。

驗證區域配額

佈建裸機節點或建立叢集前,請確認專案有足夠的區域和全域 Compute Engine 配額。請先將該區域中所有現有叢集的資源加到下列增量值,再與專案配額進行比較:

配額指標 每個裸機節點所需的資源 3 節點叢集所需的資源
Z3 專用的「compute.googleapis.com/cpus_per_vm_family」 192 個 vCPU 3 × 192 = 576 個 vCPU
Z3 專用的「compute.googleapis.com/local_ssd_total_storage_per_vm_family」 72 TB 3 × 72 TB = 216 TB
compute.googleapis.com/hyperdisk_balanced_total_storage 128 GB 3 × 128 GB = 384 GB
compute.googleapis.com/resource_policies 將節點新增至現有叢集時,則為 0 每個叢集 1 項分散配置政策
compute.googleapis.com/regional_backend_services_protocol_forwarding_fast_ha 新增節點或叢集時,如未新增設備,則為 0 每個新的 VCF 管理設備 VIP 或 NSX Edge 端點需要 1 個

如需必要配額的完整清單,以及如何查看或要求提高配額的操作說明,請參閱「配額與限制」。

設定環境變數

在跳板機殼層中設定下列環境變數。在 ADD_HOSTS 環境變數中列出要新增的節點,並在 REMOVE_HOSTS 環境變數中列出要移除的節點 (每個變數一或多個項目):

export PROJECT_ID="PROJECT_ID"
export REGION="us-east4"
export ZONE="us-east4-b"
export CUSTOMER_ID="demo"
export VPC_NETWORK="bm-${CUSTOMER_ID}"
export DOMAIN="vmware.gve"
export DNS_ZONE="dns-zone-${CUSTOMER_ID}"
export REV_DNS_ZONE="rev-dns-zone-${CUSTOMER_ID}"
export MGMT_SUBNET="bm-mgmt-${CUSTOMER_ID}"
export VMOTION_SUBNET="bm-vmotion-${CUSTOMER_ID}"
export VSAN_SUBNET="bm-vsan-${CUSTOMER_ID}"
export TEP_SUBNET="bm-nsx-${CUSTOMER_ID}"
export MGMT_NEG="bm-mgmt-${CUSTOMER_ID}"
export TEP_NEG="bm-nsx-tep-${CUSTOMER_ID}"
export CLUSTER_NAME="cl02"
export PLACEMENT_POLICY="bm-${CLUSTER_NAME}"          # Existing placement policy of the cluster
export NETWORK_POOL_NAME="${CLUSTER_NAME}-np01"        # Existing network pool of the cluster
export VDS_NAME="${CLUSTER_NAME}-vds-01"               # Existing VDS of the cluster
export MACHINE_TYPE="z3-highmem-192-highlssd-metal"    # Same machine type as existing nodes
export ESXI_IMAGE_FAMILY="astra-vcf-9-1-x"
export ESXI_IMAGE_PROJECT="smve-prod-offline-depot"
export SDDC_MANAGER="sddcm.vmware.gve"                 # 192.168.0.3
export VCF_USER="admin@local"
export VCF_PASSWORD="VCF_ADMIN_PASSWORD"
export ESXI_PASSWORD_SECRET="esxi-root-password"
export NSX_MANAGER="nsx01.vmware.gve"                  # NSX Manager of the cluster's domain
export MTU=8896

# Nodes to add: name mgmt_ip vmotion_ip vsan_ip tep_ip availability_domain
ADD_HOSTS=(
  "esxi-h10 192.168.0.164 192.168.2.24 192.168.3.24 192.168.4.24 4"
  "esxi-h11 192.168.0.165 192.168.2.25 192.168.3.25 192.168.4.25 5"
)

# Nodes to remove (short hostnames)
REMOVE_HOSTS=(esxi-h11)

# Retrieve an SDDC Manager API token (re-run when the token expires)
TOKEN=$(curl -s -X POST "https://${SDDC_MANAGER}/v1/tokens" \
    -H "Content-Type: application/json" \
    -d "{\"username\":\"${VCF_USER}\",\"password\":\"${VCF_PASSWORD}\"}" | jq -r '.accessToken')

執行指令前,請先替換下列項目:

  • PROJECT_ID:目標 Google Cloud專案的 ID。
  • VCF_ADMIN_PASSWORD:SDDC Manager 管理員密碼。

確認現有的轉送規則或執行個體,並未使用您預計採用的 IP 位址:

gcloud compute forwarding-rules list --project="${PROJECT_ID}" --regions="${REGION}" \
    --format="table(name,IPAddress,subnetwork.basename())"
gcloud compute instances list --project="${PROJECT_ID}" --zones="${ZONE}" \
    --format="table(name,networkInterfaces[].networkIP.list())"

將節點新增至叢集

如要新增裸機節點來擴充現有的 vSphere 叢集,請完成下列各節的步驟。

建立 DNS 記錄

由於正向和反向 Cloud DNS 代管區域已存在,因此只需為新節點建立正向 (A) 和反向 (PTR) 記錄:

for entry in "${ADD_HOSTS[@]}"; do
  read -r HOST MGMT_IP _ <<< "${entry}"
  gcloud dns record-sets create "${HOST}.${DOMAIN}." \
      --rrdatas="${MGMT_IP}" --type=A --ttl=300 \
      --zone="${DNS_ZONE}" --project="${PROJECT_ID}"
  REV=$(echo "${MGMT_IP}" | awk -F. '{print $4"."$3"."$2"."$1".in-addr.arpa."}')
  gcloud dns record-sets create "${REV}" \
      --rrdatas="${HOST}.${DOMAIN}." --type=PTR --ttl=300 \
      --zone="${REV_DNS_ZONE}" --project="${PROJECT_ID}"
done

# Verify DNS records
gcloud dns record-sets list --zone="${DNS_ZONE}" --project="${PROJECT_ID}" \
    --filter="name~'esxi-h1[01]'"

建立裸機執行個體

在叢集現有的配置政策中建立每個新節點,並使用主要 ESXi 管理 NIC (nic0) 和 VLAN 標記的 Dynamic NIC,用於 vMotion (VLAN 2)、vSAN (VLAN 3) 和 NSX TEP (VLAN 4)。

for entry in "${ADD_HOSTS[@]}"; do
  read -r HOST MGMT_IP VMOTION_IP VSAN_IP TEP_IP AD <<< "${entry}"
  # Create boot disk
  gcloud compute disks create "${HOST}" \
      --image-project="${ESXI_IMAGE_PROJECT}" \
      --image-family="${ESXI_IMAGE_FAMILY}" \
      --type=hyperdisk-balanced --interface=NVME --size=128GB \
      --guest-os-features=IDPF \
      --zone="${ZONE}" --project="${PROJECT_ID}"

  # Create bare-metal ESXi host
  gcloud compute instances create "${HOST}" \
      --zone="${ZONE}" \
      --machine-type="${MACHINE_TYPE}" \
      --can-ip-forward \
      --resource-policies="${PLACEMENT_POLICY}" \
      --availability-domain="${AD}" \
      --hostname="${HOST}.${DOMAIN}" \
      --disk="name=${HOST},boot=yes,auto-delete=yes" \
      --labels=gcve-node=true \
      --tags=mm-gcve-node \
      --deletion-protection \
      --maintenance-policy=TERMINATE \
      --restart-on-failure \
      --network-performance-configs=total-egress-bandwidth-tier=TIER_1 \
      --project="${PROJECT_ID}" \
      --network-interface="network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=${MGMT_SUBNET},no-address,private-network-ip=${MGMT_IP}" \
      --network-interface="network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=${VMOTION_SUBNET},no-address,private-network-ip=${VMOTION_IP},vlan=2" \
      --network-interface="network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=${VSAN_SUBNET},no-address,private-network-ip=${VSAN_IP},vlan=3" \
      --network-interface="network-tier=PREMIUM,stack-type=IPV4_ONLY,subnet=${TEP_SUBNET},no-address,private-network-ip=${TEP_IP},vlan=4"
done

# Verify instance creation and network interfaces
gcloud compute instances list --project="${PROJECT_ID}" --zones="${ZONE}" \
    --filter="resourcePolicies~${PLACEMENT_POLICY}" \
    --format="table(name,status,networkInterfaces[].vlan.list(),networkInterfaces[].networkIP.list())"

更新 NEG 成員

可用區中叢集的所有節點,都必須屬於子網路的同一個可用區 NEG。將新節點新增至管理 NEG 和 NSX TEP NEG。您不需要修改高可用性政策或轉送規則:

for entry in "${ADD_HOSTS[@]}"; do
  read -r HOST _ <<< "${entry}"
  for NEG in "${MGMT_NEG}" "${TEP_NEG}"; do
    gcloud compute network-endpoint-groups update "${NEG}" \
        --zone="${ZONE}" --add-endpoint="instance=${HOST}" --project="${PROJECT_ID}"
  done
done

# Verify NEG endpoints
for NEG in "${MGMT_NEG}" "${TEP_NEG}"; do
  gcloud compute network-endpoint-groups list-network-endpoints "${NEG}" \
      --zone="${ZONE}" --project="${PROJECT_ID}" \
      --format="table(networkEndpoint.instance,networkEndpoint.ipAddress)"
done

重設 ESXi 根密碼

重設每個新節點的 root 密碼,使其與 Secret Manager 中儲存的 ESXi root 密碼相符。在後續步驟中,您會使用相同的密鑰來委任節點。如果您在初始部署後變更或輪替 ESXi root 或 VCF 密碼,請先在 Secret Manager 中更新對應的密鑰,再執行這些指令。

如要重設每個新節點的 root 密碼,請從 jumpbox VM 執行下列指令,並在系統提示時輸入初始 ESXi root 密碼:

ESXI_ROOT_PASSWORD=$(gcloud secrets versions access latest \
    --secret="${ESXI_PASSWORD_SECRET}" --project="${PROJECT_ID}")

for entry in "${ADD_HOSTS[@]}"; do
  read -r HOST _ <<< "${entry}"
  ssh -o StrictHostKeyChecking=no "root@${HOST}.${DOMAIN}" \
      "esxcli system account set -i root -p '${ESXI_ROOT_PASSWORD}' -c '${ESXI_ROOT_PASSWORD}'"
done

將新的 IP 位址新增至網路集區和 TEP 集區

叢集的網路集區 (cl02-np01) 和 NSX TEP 集區 (cl02-tep-pool) 一開始只會包含現有叢集節點的 IP 位址。將新節點的確切 Compute Engine Dynamic NIC IP 位址新增至這兩個集區,讓 VCF 和 NSX 從 Compute Engine NIC 上已設定的集合中分配 IP 位址。

  1. 更新網路集區 (vMotion 和 vSAN):使用 VCF Operations 或 SDDC Manager API,將新節點的 vMotion 和 vSAN IP 位址新增至 cl02-np01 網路集區:

    VCF Operations

    在「VCF Operations」(VCF 作業) 中,前往「Network pool management」(網路集區管理),選取 cl02-np01 網路集區,編輯 vMotion 和 vSAN 網路,然後新增新節點的 IP 位址範圍。

    SDDC Manager API

    執行下列指令,為每個新節點新增一個單一 IP 範圍至網路集區:

    POOL_ID=$(curl -s "https://${SDDC_MANAGER}/v1/network-pools" -H "Authorization: Bearer ${TOKEN}" \
        | jq -r --arg n "${NETWORK_POOL_NAME}" '.elements[] | select(.name==$n) | .id')
    NETWORKS=$(curl -s "https://${SDDC_MANAGER}/v1/network-pools/${POOL_ID}/networks" \
        -H "Authorization: Bearer ${TOKEN}")
    VMOTION_NET_ID=$(echo "${NETWORKS}" | jq -r '.elements[] | select(.type=="VMOTION") | .id')
    VSAN_NET_ID=$(echo "${NETWORKS}" | jq -r '.elements[] | select(.type=="VSAN") | .id')
    
    for entry in "${ADD_HOSTS[@]}"; do
      read -r HOST MGMT_IP VMOTION_IP VSAN_IP _ <<< "${entry}"
      curl -s -X POST "https://${SDDC_MANAGER}/v1/network-pools/${POOL_ID}/networks/${VMOTION_NET_ID}/ip-pools" \
          -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
          -d "{\"start\":\"${VMOTION_IP}\",\"end\":\"${VMOTION_IP}\"}"
      curl -s -X POST "https://${SDDC_MANAGER}/v1/network-pools/${POOL_ID}/networks/${VSAN_NET_ID}/ip-pools" \
          -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
          -d "{\"start\":\"${VSAN_IP}\",\"end\":\"${VSAN_IP}\"}"
    done
    
    # Verify the network pool IP ranges
    curl -s "https://${SDDC_MANAGER}/v1/network-pools/${POOL_ID}/networks" -H "Authorization: Bearer ${TOKEN}" \
        | jq -r '.elements[] | [.type, (.ipPools | map(.start + "-" + .end) | join(","))] | @tsv'
    
  2. 更新 NSX TEP IP 集區:在 NSX Manager (NSX_MANAGER 主機) 中,依序前往「Networking」(網路) >「IP Address Pools」(IP 位址集區),編輯 cl02-tep-pool IP 位址集區,然後將新節點的 TEP IP 位址新增至子網路的 IP 範圍 (在本例中為 192.168.4.24–192.168.4.25),同時將閘道設為 192.168.4.1。驗證更新後的集區設定:

    NSX_PW="NSX_ADMIN_PASSWORD"
    curl -s -u "admin:${NSX_PW}" "https://${NSX_MANAGER}/policy/api/v1/infra/ip-pools" \
        | jq -r '.results[] | [.id, .display_name] | @tsv'
    
    TEP_POOL_ID="TEP_POOL_ID"   # ID of cl02-tep-pool from the preceding output
    curl -s -u "admin:${NSX_PW}" \
        "https://${NSX_MANAGER}/policy/api/v1/infra/ip-pools/${TEP_POOL_ID}/ip-subnets" \
        | jq '.results[] | {cidr, gateway_ip, allocation_ranges}'
    

    執行指令前,請先替換下列項目:

    • NSX_ADMIN_PASSWORD:NSX Manager admin 密碼 (可從 SDDC Manager /v1/credentials 端點或 VCF Operations 取得)。
    • TEP_POOL_ID:cl02-tep-pool IP 位址集區的 ID。

委任節點

使用 VCF Operations 或 SDDC Manager API,將新節點委託至 SDDC Manager 清單:

VCF Operations

  1. 在「VCF Operations」中,依序前往「Inventory」 >「Hosts」 >「Commission Hosts」。
  2. 選取 cl02-np01 網路集區,然後選取「vSAN ESA」儲存空間類型。
  3. 輸入新的主機 FQDN 和 root 憑證。
  4. 接受 SSL 指紋、驗證主機,然後按一下「Commission」(委任)。

SDDC Manager API

執行下列指令,驗證並委託主機,然後輪詢工作狀態,直到傳回 Successful:

ADD_FQDNS=$(for entry in "${ADD_HOSTS[@]}"; do
  read -r HOST _ <<< "${entry}"; echo "${HOST}.${DOMAIN}"
done | jq -R . | jq -s .)

HOSTS_JSON=$(jq -n --argjson f "${ADD_FQDNS}" --arg p "${ESXI_ROOT_PASSWORD}" \
    --arg np "${POOL_ID}" --arg npn "${NETWORK_POOL_NAME}" \
    '$f | map({fqdn: ., username: "root", password: $p, storageType: "VSAN_ESA",
               networkPoolId: $np, networkPoolName: $npn})')

# 1. Validate hosts
curl -s -X POST "https://${SDDC_MANAGER}/v1/hosts/validations" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" -d "${HOSTS_JSON}"

# 2. Commission hosts and poll until Successful
TASK_ID=$(curl -s -X POST "https://${SDDC_MANAGER}/v1/hosts" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${HOSTS_JSON}" | jq -r '.id')
curl -s "https://${SDDC_MANAGER}/v1/tasks/${TASK_ID}" -H "Authorization: Bearer ${TOKEN}" | jq -r '.status'

如果主機 SSL 指紋顯示內部 (非 FQDN) 憑證名稱,請在主機上執行 esxcli network ip dns search add -d vmware.gve 指令,重新執行 /var/lib/vmware/osdata/init.sh 指令碼,然後執行 /sbin/generate-certificates 指令,並重新啟動 rhttpproxy 和 hostd 服務。

檢查擴充前的 IP 對齊方式

在 SDDC Manager 中,請一律啟用所有 vSAN、vMotion 和網路連線驗證。只有在 VCF 指派給每個新節點的 vmk1 和 vmk2 IP 位址,與其 Compute Engine Dynamic NIC IP 位址相符時,這些驗證檢查才會通過。

  1. 確認未使用的集區 IP 位址與新的 Compute Engine NIC IP 位址相符:比較網路集區範圍與現有主機已使用的 IP 位址,以及新節點的 Compute Engine NIC。現有主機未使用的集區 IP 位址,應只有新節點的 IP 位址:

    # List vMotion and vSAN IP addresses already used by hosts
    curl -s "https://${SDDC_MANAGER}/v1/hosts" -H "Authorization: Bearer ${TOKEN}" | jq -r '
      .elements | sort_by(.fqdn)[] | [.fqdn,
        (([.ipAddresses[]? | select(.type=="VMOTION") | .ipAddress] | first) // "-"),
        (([.ipAddresses[]? | select(.type=="VSAN")    | .ipAddress] | first) // "-")] | @tsv'
    
    # List Compute Engine dynamic NIC IPs of the new nodes (VLAN 2 = vMotion, 3 = vSAN, 4 = TEP)
    for entry in "${ADD_HOSTS[@]}"; do
      read -r HOST _ <<< "${entry}"
      echo "== ${HOST}"
      gcloud compute instances describe "${HOST}" --zone="${ZONE}" --project="${PROJECT_ID}" \
          --format="table(networkInterfaces[].name,networkInterfaces[].vlan,networkInterfaces[].networkIP)"
    done
    
  2. 確認 SDDC Manager 不會略過驗證:在 SDDC Manager 設備上 (以 root 身分),確認 application.properties 檔案不含任何 validation.disable.* 屬性:

    # Must return no output. If any validation.disable.* line is present, remove it
    # and run: systemctl restart domainmanager
    grep -n 'validation.disable' /etc/vmware/vcf/domainmanager/application.properties
    

展開叢集

使用 VCF Operations 或 SDDC Manager API,將已委任的節點新增至目標叢集:

VCF Operations

在 VCF Operations (或 SDDC Manager UI) 中,開啟叢集的網域,選取 cl02 叢集,依序選擇「Actions」(動作) >「Add Host」(新增主機),選取已委任的節點,將 vmnic0 介面對應至叢集 VDS 的 uplink1 上行,然後提交工作流程。依序前往「Fleet Management」(機群管理) >「Tasks」(工作),監控工作並記錄其 ID (在下一節中將 TASK_ID 變數設為這個值)。

SDDC Manager API

執行下列指令,驗證擴充規格並擴充叢集:

CLUSTER_ID=$(curl -s "https://${SDDC_MANAGER}/v1/clusters" -H "Authorization: Bearer ${TOKEN}" \
    | jq -r --arg c "${CLUSTER_NAME}" '.elements[] | select(.name==$c) | .id')

HOST_SPECS=$(curl -s "https://${SDDC_MANAGER}/v1/hosts?status=UNASSIGNED_USEABLE" \
    -H "Authorization: Bearer ${TOKEN}" \
    | jq --argjson f "${ADD_FQDNS}" --arg vds "${VDS_NAME}" '
        [.elements[] | select(.fqdn as $x | $f | index($x))
         | {id, hostNetworkSpec: {vmNics: [{id: "vmnic0", uplink: "uplink1", vdsName: $vds}]}}]')
echo "${HOST_SPECS}" | jq 'length'   # Must equal the number of ADD_HOSTS

EXPANSION_SPEC=$(jq -n --argjson h "${HOST_SPECS}" \
    '{clusterExpansionSpec: {hostSpecs: $h, deployWithoutLicenseKeys: true}}')

# 1. Validate (resolve any reported error before continuing)
curl -s -X POST "https://${SDDC_MANAGER}/v1/clusters/${CLUSTER_ID}/validations" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${EXPANSION_SPEC}" | jq '{executionStatus, resultStatus}'

# 2. Expand the cluster and poll the task
TASK_ID=$(curl -s -X PATCH "https://${SDDC_MANAGER}/v1/clusters/${CLUSTER_ID}" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${EXPANSION_SPEC}" | jq -r '.id')
curl -s "https://${SDDC_MANAGER}/v1/tasks/${TASK_ID}" -H "Authorization: Bearer ${TOKEN}" | jq -r '.status'

擴充叢集時,SDDC Manager 會從網路集區分配 vMotion 和 vSAN IP 位址,不會保留主機順序。如果 SDDC Manager 指派給新節點的 IP 位址與 Compute Engine Dynamic NIC 不同,工作會在 vSAN 和 vMotion 連線能力的驗證步驟暫停。請將工作維持在失敗狀態,完成「調整 vMotion 和 vSAN 動態 NIC」中的步驟,然後重試相同工作。請勿對這些節點提出新的擴充要求:擴充失敗後,節點就不再處於未指派狀態,SDDC Manager 會拒絕新的擴充要求。

調整 vMotion 和 vSAN 動態 NIC

如果叢集擴充工作在 vSAN 和 vMotion 連線能力的驗證步驟暫停,請完成本節的步驟。如果工作通過該步驟,請僅執行步驟 1 確認對齊,然後繼續進行「對齊 NSX TEP Dynamic NIC」。

  1. 讀取 VCF 分配的 IP 位址,並與 Compute Engine NIC 進行比較:執行「檢查擴充前的 IP 對齊情形」步驟 1 的兩項指令。只有新節點在範圍內。

  2. 先刪除所有不相符的 Dynamic NIC,然後重新新增:先刪除每個新節點上所有不相符的 Dynamic NIC (vMotion 的 nic0.2 介面和 vSAN 的 nic0.3 介面),再重新新增任何介面,否則交換的 IP 位址會失敗,並顯示 IP_IN_USE 錯誤:

    # Example: VCF swapped the IP addresses of esxi-h10 and esxi-h11
    HOST="esxi-h10"
    VCF_VMOTION_IP="192.168.2.25"
    VCF_VSAN_IP="192.168.3.25"
    
    # 2a. Delete mismatched NICs (run on all mismatched nodes before running 2b)
    gcloud compute instances network-interfaces delete "${HOST}" \
        --network-interface=nic0.2 --zone="${ZONE}" --project="${PROJECT_ID}" --quiet
    gcloud compute instances network-interfaces delete "${HOST}" \
        --network-interface=nic0.3 --zone="${ZONE}" --project="${PROJECT_ID}" --quiet
    
    # 2b. Add the dynamic NICs back with the VCF-allocated IP addresses
    gcloud compute instances network-interfaces add "${HOST}" \
        --parent-nic-name=nic0 --vlan=2 \
        --network="${VPC_NETWORK}" --subnetwork="${VMOTION_SUBNET}" \
        --private-network-ip="${VCF_VMOTION_IP}" --no-address \
        --zone="${ZONE}" --project="${PROJECT_ID}"
    gcloud compute instances network-interfaces add "${HOST}" \
        --parent-nic-name=nic0 --vlan=3 \
        --network="${VPC_NETWORK}" --subnetwork="${VSAN_SUBNET}" \
        --private-network-ip="${VCF_VSAN_IP}" --no-address \
        --zone="${ZONE}" --project="${PROJECT_ID}"
    
  3. 重試失敗的工作:在 VCF Operations 中,前往「Fleet Management」

    Tasks,重試擴充工作,或執行下列 SDDC Manager API 指令:

    curl -s -X PATCH "https://${SDDC_MANAGER}/v1/tasks/${TASK_ID}" \
        -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
        -d '{"status": "RETRY"}'
    

    如果工作再次失敗,請重複步驟 1 和 2,然後再試一次。

調整 NSX TEP Dynamic NIC

NSX 將新節點設為傳輸節點後,請驗證並調整新節點上的 VLAN 4 NSX TEP (vmk10) Dynamic NIC。

  1. 擷取 NSX 分配的 TEP IP 位址:查詢 NSX Manager (或在每個 ESXi 主機上執行 esxcli network ip interface ipv4 get -i vmk10 指令):

    # Map transport node ID to hostname
    curl -s -u "admin:${NSX_PW}" "https://${NSX_MANAGER}/api/v1/transport-nodes" \
        | jq -r '.results[] | [.id, .display_name] | @tsv'
    
    # Map transport node ID to TEP device and IP address
    curl -s -u "admin:${NSX_PW}" "https://${NSX_MANAGER}/api/v1/transport-nodes/state" \
        | jq -r '.results[] | [.transport_node_id, .state,
            ([.host_switch_states[]?.endpoints[]? | .device_name + "=" + .ip] | join(","))] | @tsv'
    
  2. 重新建立不相符的 TEP NIC:比較 NSX 分配的 vmk10 IP 位址與每個新節點的 Compute Engine TEP NIC (VLAN 4)。只有新節點在範圍內,請勿修改現有節點的 TEP NIC。對於所有不相符的新節點,請先將每個節點與 TEP NEG 分離,然後刪除所有不相符節點的 nic0.4 介面。接著,您重新新增 nic0.4 介面,並將節點重新附加至 TEP NEG:

    # Example: Compute Engine has 192.168.4.24 on esxi-h10, but NSX assigned 192.168.4.25
    HOST="esxi-h10"
    CURRENT_TEP_IP="192.168.4.24"
    NSX_TEP_IP="192.168.4.25"
    
    # 2a. Detach the node from the TEP NEG
    gcloud compute network-endpoint-groups update "${TEP_NEG}" \
        --zone="${ZONE}" --project="${PROJECT_ID}" \
        --remove-endpoint="instance=${HOST},ip=${CURRENT_TEP_IP}"
    
    # 2b. Delete the mismatched TEP NIC on all mismatched nodes first
    gcloud compute instances network-interfaces delete "${HOST}" \
        --network-interface=nic0.4 --zone="${ZONE}" --project="${PROJECT_ID}" --quiet
    
    # 2c. Re-add nic0.4 with the NSX-allocated IP address
    gcloud compute instances network-interfaces add "${HOST}" \
        --parent-nic-name=nic0 --vlan=4 \
        --network="${VPC_NETWORK}" --subnetwork="${TEP_SUBNET}" \
        --private-network-ip="${NSX_TEP_IP}" --no-address \
        --zone="${ZONE}" --project="${PROJECT_ID}"
    
    # 2d. Re-attach the node to the TEP NEG
    gcloud compute network-endpoint-groups update "${TEP_NEG}" \
        --zone="${ZONE}" --project="${PROJECT_ID}" \
        --add-endpoint="instance=${HOST}"
    

驗證叢集擴充

叢集擴充工作成功後,請確認下列事項:

  • vCenter Server:新節點已連線且在 cl02 叢集中正常運作,沒有網路警報。
  • vSAN:針對 cl02 叢集,依序前往「Monitor」(監控) >「vSAN」 >「Skyline Health」,確認所有健康狀態檢查均通過,且資料儲存庫容量包含新節點。
  • NSX Manager:依序前往「System」 >「Fabric」 >「Hosts」,確認每個新節點都顯示「Success」和「Up」,且疊加通道已啟動。
  • VCF 作業:新節點會指派給 cl02 叢集,且工作清單中沒有失敗的工作。

從 ESXi 主機殼層 (例如 esxi-h10) 驗證巨型框架連線 (8896 MTU 減去 28 位元組 IP/ICMP 標頭 = 8868 位元組):

esxcli network ip interface ipv4 get                        # Verify vmk0, vmk1, vmk2, and vmk10 IPs
vmkping -S vmotion -I vmk1 -d -s 8868 192.168.2.21          # vMotion (netstack might be default)
vmkping -I vmk2 -d -s 8868 192.168.3.21                     # vSAN
vmkping ++netstack=vxlan -I vmk10 -d -s 8868 192.168.4.21   # NSX TEP

vSAN 容錯數量和主機數量

請參閱下表,判斷新增節點時叢集需要多少節點,或移除節點時必須保留多少節點:

可容許的故障數 資料放置配置 主機數量下限
FTT=1 RAID-1 (鏡像) 或 RAID-5 (糾刪碼) 3 (建議 4 個以上,以便在主機故障或維護期間重建)
FTT=2 RAID-1 (鏡像) 5
FTT=2 RAID-6 (糾刪碼) 6

從叢集移除節點

完成移除前檢查

從叢集移除任何節點前,請確認下列事項:

  • 主機數量:移除節點後,叢集至少會保留三個節點,且至少會保留「vSAN 容許故障數和主機數量」中列出的最低主機數量,這是有效儲存空間政策所要求的。
  • 容量:在 vCenter Server 中,針對 cl02 叢集,前往「Monitor」(監控) >「vSAN」 >「Data Migration Pre-check」(資料遷移預先檢查),針對您打算移除的每個節點 (使用「Full data migration」(完整資料遷移) 選項),確認其餘節點有足夠的 vSAN 和運算容量。
  • 健康狀態:vSAN Skyline Health 通過檢查,沒有任何錯誤,且 VCF Operations 或 SDDC Manager 中沒有失敗的工作。
  • 高可用性政策領導者:確認沒有後端服務使用您要移除的節點做為高可用性政策領導者。如果後端服務使用其中一個節點做為領導者,請將領導者更新為剩餘的節點 (遷移後執行設備 VM 的主機):

    gcloud compute backend-services list --regions="${REGION}" --project="${PROJECT_ID}" \
        --format="table(name,haPolicy.leader.networkEndpoint.instance)"
    
    # Run only if a node being removed is an HA policy leader (example: move rbs-vc02-demo to esxi-h0)
    NEG_LINK=$(gcloud compute network-endpoint-groups describe "${MGMT_NEG}" \
        --zone="${ZONE}" --project="${PROJECT_ID}" --format="value(selfLink)")
    gcloud compute backend-services update "rbs-vc02-${CUSTOMER_ID}" \
        --ha-policy-leader-backend-group="${NEG_LINK}" --ha-policy-leader-instance=esxi-h0 \
        --region="${REGION}" --project="${PROJECT_ID}"
    

從叢集移除節點

從 VCF 的叢集中移除目標節點。VCF 會將每個節點設為維護模式、遷移 VM,並撤離 vSAN 資料。您可以使用 VCF Operations 或 SDDC Manager API 移除節點:

VCF Operations

在 VCF Operations (或 SDDC Manager UI) 中,開啟叢集的網域,選取 cl02 叢集,依序選擇「Actions」(動作) >「Remove Host」(移除主機),選取要移除的節點,然後確認。

SDDC Manager API

執行下列指令,驗證壓縮規格並從叢集移除主機:

CLUSTER_ID=$(curl -s "https://${SDDC_MANAGER}/v1/clusters" -H "Authorization: Bearer ${TOKEN}" \
    | jq -r --arg c "${CLUSTER_NAME}" '.elements[] | select(.name==$c) | .id')

REMOVE_FQDNS=$(for HOST in "${REMOVE_HOSTS[@]}"; do echo "${HOST}.${DOMAIN}"; done | jq -R . | jq -s .)

COMPACTION_SPEC=$(curl -s "https://${SDDC_MANAGER}/v1/hosts" -H "Authorization: Bearer ${TOKEN}" \
    | jq --argjson f "${REMOVE_FQDNS}" '
        {clusterCompactionSpec: {hosts: [.elements[] | select(.fqdn as $x | $f | index($x)) | {id}]}}')
echo "${COMPACTION_SPEC}" | jq '.clusterCompactionSpec.hosts | length'   # Must equal the number of REMOVE_HOSTS

# 1. Validate the compaction specification
curl -s -X POST "https://${SDDC_MANAGER}/v1/clusters/${CLUSTER_ID}/validations" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${COMPACTION_SPEC}" | jq '{executionStatus, resultStatus}'

# 2. Remove the hosts and poll the task until Successful
TASK_ID=$(curl -s -X PATCH "https://${SDDC_MANAGER}/v1/clusters/${CLUSTER_ID}" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${COMPACTION_SPEC}" | jq -r '.id')
curl -s "https://${SDDC_MANAGER}/v1/tasks/${TASK_ID}" -H "Authorization: Bearer ${TOKEN}" | jq -r '.status'

停用節點

從叢集移除節點後,請使用 VCF Operations 或 SDDC Manager API,從 SDDC Manager 清查項目中停用這些節點:

VCF Operations

在 VCF Operations 中,依序前往 「Inventory」(庫存) > 「Hosts」(主機),選取未指派的節點,然後按一下 「Decommission」(停用) (詳情請參閱 VMware Cloud Foundation 說明文件中的「Decommission hosts」(停用主機))。

SDDC Manager API

執行下列指令,傳送停用要求並輪詢工作,直到傳回 Successful 為止:

DECOMMISSION_SPEC=$(echo "${REMOVE_FQDNS}" | jq 'map({fqdn: .})')
TASK_ID=$(curl -s -X DELETE "https://${SDDC_MANAGER}/v1/hosts?skipFailedHosts=false" \
    -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
    -d "${DECOMMISSION_SPEC}" | jq -r '.id')
curl -s "https://${SDDC_MANAGER}/v1/tasks/${TASK_ID}" -H "Authorization: Bearer ${TOKEN}" | jq -r '.status'

# Verify that the nodes are no longer listed in the inventory
curl -s "https://${SDDC_MANAGER}/v1/hosts" -H "Authorization: Bearer ${TOKEN}" \
    | jq -r '.elements[] | [.fqdn, .status] | @tsv'

從 NEG 移除節點

從管理 NEG 和 NSX TEP NEG 移除已停用的節點:

for HOST in "${REMOVE_HOSTS[@]}"; do
  for NEG in "${MGMT_NEG}" "${TEP_NEG}"; do
    gcloud compute network-endpoint-groups update "${NEG}" \
        --zone="${ZONE}" --remove-endpoint="instance=${HOST}" --project="${PROJECT_ID}"
  done
done

# Verify NEG endpoints
for NEG in "${MGMT_NEG}" "${TEP_NEG}"; do
  gcloud compute network-endpoint-groups list-network-endpoints "${NEG}" \
      --zone="${ZONE}" --project="${PROJECT_ID}" \
      --format="table(networkEndpoint.instance,networkEndpoint.ipAddress)"
done

如果 gcloud CLI 拒絕從 TEP NEG 移除,且未提供明確的 IP 位址,請在 --remove-endpoint 旗標中加入端點 IP 位址 (如驗證指令所示):--remove-endpoint="instance=HOST,ip=TEP_IP"。

刪除裸機執行個體

清除每個已停用主機的防刪除功能,並刪除 Compute Engine 裸機執行個體 (Compute Engine 會自動刪除執行個體的開機磁碟):

for HOST in "${REMOVE_HOSTS[@]}"; do
  # Clear deletion protection, and then delete the instance and its boot disk
  gcloud compute instances update "${HOST}" --no-deletion-protection \
      --zone="${ZONE}" --project="${PROJECT_ID}"
  gcloud compute instances delete "${HOST}" \
      --zone="${ZONE}" --project="${PROJECT_ID}" --quiet
done

# Verify remaining instances in the placement policy
gcloud compute instances list --project="${PROJECT_ID}" --zones="${ZONE}" \
    --filter="resourcePolicies~${PLACEMENT_POLICY}" --format="table(name,status)"

清除 DNS 記錄和 IP 集區

刪除已移除節點的正向 (A) 和反向 (PTR) Cloud DNS 記錄:

for HOST in "${REMOVE_HOSTS[@]}"; do
  MGMT_IP=$(gcloud dns record-sets describe "${HOST}.${DOMAIN}." --type=A \
      --zone="${DNS_ZONE}" --project="${PROJECT_ID}" --format="value(rrdatas[0])")
  REV=$(echo "${MGMT_IP}" | awk -F. '{print $4"."$3"."$2"."$1".in-addr.arpa."}')
  gcloud dns record-sets delete "${REV}" --type=PTR --zone="${REV_DNS_ZONE}" --project="${PROJECT_ID}"
  gcloud dns record-sets delete "${HOST}.${DOMAIN}." --type=A --zone="${DNS_ZONE}" --project="${PROJECT_ID}"
done

移除節點後,其 vMotion、vSAN 和 TEP IP 位址會回到網路集區和 NSX TEP 集區,可供再次使用。您可以保留這些 IP 位址,供日後的節點使用 (方法是將相同的 Compute Engine NIC IP 位址指派給該節點),也可以從集區中移除這些位址,這樣 VCF 和 NSX 就不會將這些位址分配給 Compute Engine NIC 使用不同 IP 位址的日後節點。

確認節點已移除

完成節點移除工作流程後,請確認下列事項:

  • vCenter Server:cl02 叢集只會顯示剩餘的節點,所有節點都已連線且健康狀態良好,vSphere HA 和 DRS 也未回報任何錯誤。
  • vSAN:Skyline Health 通過,且所有虛擬物件皆符合規範 (針對 cl02 叢集,依序前往「Monitor」(監控) >「vSAN」 >「Virtual Objects」(虛擬物件))。
  • NSX Manager:移除的節點不會再列為傳輸節點,其餘節點則會顯示「Up」(運作中)。
  • VCF Operations 和 SDDC Manager:移除的節點不再列於主機清單,且沒有失敗的工作。
  • Google Cloud:系統會刪除已移除節點的裸機執行個體、開機磁碟、NEG 端點和 DNS 記錄。

疑難排解叢集擴充和節點移除問題

下表列出在 vSphere 叢集中新增或移除節點時,常見的問題、原因和解決方法:

問題 原因 解析度
叢集擴充作業在 vSAN 和 vMotion 的連線檢查失敗,新節點回報健康狀態不良 擴充叢集時,SDDC Manager 會從網路集區分配 vmk1 和 vmk2 IP 位址,不會保留主機順序。 請保持啟用驗證功能。僅將新節點的 IP 位址新增至網路集區;如果工作在連線檢查時暫停,請調整動態 NIC 並重試相同工作。
NSX 主機狀態為「Degraded」,或新節點上的通道已關閉 NSX Manager 會從 IP 集區隨機指派 TEP (vmk10) IP 位址,因此可能與 Compute Engine TEP NIC 不符。 按照「調整 NSX TEP Dynamic NIC」一節所述,調整 NSX TEP Dynamic NIC。
NSX 無法準備新節點 叢集的 NSX TEP IP 集區沒有可用的 IP 位址。 將新節點的 TEP IP 位址新增至 TEP IP 集區,然後重試工作。
SDDC Manager 拒絕相同節點的新擴充要求 如果擴充工作失敗,節點會處於 UNASSIGNED_USEABLE 以外的狀態。 重試失敗的工作 (PATCH /v1/tasks/TASK_ID,{"status": "RETRY"}),而非提交新的擴充要求。
節點已委任,因此無法委任 無法重複委任主機。 請繼續擴充叢集,或先停用節點,再重新啟用 (例如使用不同的網路集區)。
重新新增動態 NIC 時發生 IP_IN_USE 錯誤 兩個節點交換了 IP 位址,或預定 IP 位址與其他節點重疊。 請先刪除所有新節點中不相符的 Dynamic NIC,再重新新增任何介面,並確認 IP 位址方案。
節點移除驗證失敗 移除節點後,叢集的主機數量會低於大小下限,或剩餘節點的容量不足。 請先移除較少節點或新增容量,不要使用 "force": true 屬性。
gcloud CLI 拒絕刪除裸機執行個體 執行個體已啟用防刪除功能。 請先執行 gcloud compute instances update HOST --no-deletion-protection 指令,再刪除執行個體。
新增節點後,vSAN 容錯網域不正確 您在其他配置政策中建立了新節點,或兩個叢集共用一項配置政策。 在叢集本身的配置政策中建立新節點,並將節點分配至不同的可用性網域。
vSAN 錯誤、vMotion 逾時或 NSX 疊加層分割 設定的 MTU 大於虛擬私有雲網路 MTU (8896 個位元組)。 新節點會沿用叢集的 VDS 和集區;所有元件的 MTU 應維持設為 8896 個位元組。
主機 SSL 指紋或憑證顯示內部名稱 主機未設定 DNS 搜尋網域。 執行 esxcli network ip dns search add -d vmware.gve 指令,重新執行 /var/lib/vmware/osdata/init.sh 指令碼,然後執行 /sbin/generate-certificates 指令,並重新啟動 rhttpproxy 和 hostd 服務。
主機無法對子網路閘道 (.1) 執行連線偵測 (ping) Google Cloud 不會回應子網路閘道 IP 位址上的 ICMP 回應要求。 這是預期行為,請忽略閘道連線偵測 (ping) 警告。

後續步驟