將 flex 節點附加到 AKS 叢集(預覽)

Important

AKS 預覽功能以自助方式提供,並採選擇加入制。 預覽版本係依「現狀」及「可用情況」提供,且不適用於服務等級協定與有限保固。 客戶支援部門會盡最大努力,部分支援 AKS 預覽。 因此,這些功能不適合實際執行用途。 如需詳細資訊,請參閱下列支援文章:

當你準備好 Azure Kubernetes Service (AKS) 叢集、網路、彈性節點池、主機和身份後,啟動主機並將其附加到目標池。

在本文中,您可以:

  • 下載並驗證 flex node 的釋出版本。
  • 使用其所選的 Azure 身分初始化主機,以擷取最新的集區資料。
  • 驗證 Kubernetes 節點、Azure 機器、網路狀態和代理服務。
  • 驗證工作負載部署位置、Kubernetes 回呼,以及跨節點連線。

請在具備所需工具與網路存取的 Linux 相容 Bash 環境中執行本文中的管理指令。 本文將該環境稱為你的 Bash 環境。 加入叢集的獨立機器是 彈性節點主機;只有當步驟明確指示你時,才會在那裡執行指令。

對於私有 AKS 叢集,請從可解析並連線到私有 API 伺服器的 Bash 環境中執行每個 kubectl 指令。 只要 Bash 環境具備必要的 Azure 和主機權限,你可以執行 Azure CLI、artifact download、SSH 和 SCP 指令。 Flex Node 主機網路也必須解析並連接到私有 API 端點。

開始之前

  • 完成 設定網路並在 AKS 中建立一個彈性節點池。
  • 完成 準備一個彈性節點主機與身份。
  • 在您的 Bash 環境中安裝 Azure CLI、aks-preview 擴充功能、與 jq 相差不超過一個次要版本的 kubectl 版本、sha256sum、curl、AKS_VERSION、OpenSSH 用戶端,以及 scp。
  • 對於管理身份或服務主體,請使用一個 Azure 帳號,該帳號能取得所選 Flex Node pool 的 bootstrap 資料。
  • 確保您的 Bash 環境能透過核准的 SSH 管理路徑連接到 flex node 主機。
  • 確保 flex node 主機可透過 HTTPS 連線到 pool bootstrap 資料中傳回的 release 和 bootstrap artifact 端點,以及 Azure Resource Manager、Microsoft Entra ID 和所選的 AKS API 端點。

Note

不要在共享環境檔案中儲存憑證、憑證、私鑰、存取權杖、啟動資料或 kubeconfig 內容。

載入部署環境

開始一個新的 Bash 工作階段,辨識環境檔案並載入。 將 <deployment-name> 替換為前述文章中使用的部署標籤。

export FLEXNODE_DEPLOYMENT="<deployment-name>"
export FLEXNODE_ENV_FILE="${HOME}/.config/aks-flexnode/${FLEXNODE_DEPLOYMENT}.env"
test -s "${FLEXNODE_ENV_FILE}"
source "${FLEXNODE_ENV_FILE}"
export KUBECONFIG="${FLEXNODE_KUBECONFIG}"
install -d -m 0700 "${WORK_DIR:?Load the deployment environment first.}"

環境檔案提供本文會讀取的共用部署值,包括 WORK_DIR,也就是本文在 Bash 環境中用來儲存下載內容和產生檔案的目錄。 根據預設,WORK_DIR 是 ~/.local/share/aksflexnode/<deployment-name>。 文章會推導出所需的其他變數。 如果你還沒建立環境檔案,先完成 Plan 你的 Flex 節點部署 。 如果 Shell 回報錯誤,請勿繼續進行下一步。

設定有效訂閱並顯示 Azure、Kubernetes 和主機目標:

az account set --subscription "${SUBSCRIPTION_ID}"

az aks show \
    --resource-group "${RESOURCE_GROUP}" \
    --name "${CLUSTER_NAME}" \
    --query "{Cluster:name,ResourceId:id,ApiServer:(privateFqdn || fqdn)}" \
    --output table
kubectl cluster-info

printf 'Recorded flex host: %s\n' "${FLEX_HOST_NAME}"
ssh -i "${SSH_PRIVATE_KEY_PATH}" "${FLEX_HOST_SSH_TARGET}" hostname

確認 ResourceID 與 相符 AKS_RESOURCE_ID,Kubernetes 控制平面主機名稱與 ApiServer 相符,則 SSH 指令回傳 FLEX_HOST_NAME。 如果有目標不匹配,請在傳輸或執行檔案前先停止並修正環境檔案、kubeconfig 或 SSH 目標。

下載並驗證 flex node 的發布版本

  1. 識別主機架構並選擇匹配的版本封存檔。

    HOST_ARCH="$(ssh \
        -i "${SSH_PRIVATE_KEY_PATH}" \
        "${FLEX_HOST_SSH_TARGET}" \
        uname -m)"
    export HOST_ARCH
    
    case "${HOST_ARCH}" in
        x86_64) export AGENT_ARCH="amd64" ;;
        aarch64|arm64) export AGENT_ARCH="arm64" ;;
        *)
            printf 'Unsupported host architecture: %s\n' "${HOST_ARCH}" >&2
            false
            ;;
    esac
    
    export AGENT_ARCHIVE="aks-flex-node-linux-${AGENT_ARCH}.tar.gz"
    printf 'Selected release archive: %s\n' "${AGENT_ARCHIVE}"
    
  2. 從所選發行版本下載封存檔與總和檢查碼資訊清單。

    curl --fail --location --silent --show-error \
        --proto '=https' \
        --tlsv1.2 \
        "https://github.com/Azure/AKSFlexNode/releases/download/${AKS_FLEX_NODE_VERSION}/${AGENT_ARCHIVE}" \
        --output "${WORK_DIR}/${AGENT_ARCHIVE}"
    
    curl --fail --location --silent --show-error \
        --proto '=https' \
        --tlsv1.2 \
        "https://github.com/Azure/AKSFlexNode/releases/download/${AKS_FLEX_NODE_VERSION}/checksums.txt" \
        --output "${WORK_DIR}/checksums.txt"
    
  3. 請為封存檔恰好選取一個檢查碼項目,並驗證該檔案。

    AGENT_CHECKSUM_ENTRY="$(awk \
        -v file="${AGENT_ARCHIVE}" \
        '$2 == file {print}' \
        "${WORK_DIR}/checksums.txt")"
    export AGENT_CHECKSUM_ENTRY
    
    test "$(printf '%s\n' "${AGENT_CHECKSUM_ENTRY}" |
        sed '/^$/d' |
        wc -l)" -eq 1
    
    (
        cd "${WORK_DIR:?Load the deployment environment first.}"
        printf '%s\n' "${AGENT_CHECKSUM_ENTRY}" |
            sha256sum --check --strict -
    )
    
    export AGENT_SHA256="${AGENT_CHECKSUM_ENTRY%% *}"
    test -n "${AGENT_SHA256}"
    

    除非 checksum 指令回報該封存檔為 OK,否則請勿繼續。

  4. 從同一發佈標籤下載自舉腳本,並驗證其 Bash 語法。

    curl --fail --location --silent --show-error \
        --proto '=https' \
        --tlsv1.2 \
        "https://raw.githubusercontent.com/Azure/AKSFlexNode/${AKS_FLEX_NODE_VERSION}/scripts/bootstrap.sh" \
        --output "${WORK_DIR}/bootstrap.sh"
    
    chmod 0700 "${WORK_DIR}/bootstrap.sh"
    bash -n "${WORK_DIR}/bootstrap.sh"
    

    目前版本並未針對此腳本發布獨立校驗碼。 下載時不要將其透過管線傳送到 shell,讓其版本與已驗證的代理程式封存檔一致,並在語法檢查失敗時停止。

擷取目前集區的啟動引導資料

受管理身份與服務主體路徑使用你在 Bash 環境中取得的啟動程式資料。 如果您選擇了 Azure Arc 管理身份,請跳過此區。 Arc bootstrap 命令會透過 Arc 機器身分識別擷取最新資料。

對於受控識別或服務主體,請在將檔案傳輸到主機之前立即擷取資料。 回覆中包含一個啟動引導權杖,其有效期限為一小時。 不要列印回應或存放在筆記中。

az aks nodepool get-bootstrap-data \
    --resource-group "${RESOURCE_GROUP}" \
    --cluster-name "${CLUSTER_NAME}" \
    --name "${FLEX_POOL_NAME}" \
    --output json \
    > "${WORK_DIR}/base-config.json"

chmod 0600 "${WORK_DIR}/base-config.json"
test -s "${WORK_DIR}/base-config.json"

當 ${WORK_DIR}/base-config.json 存在且不空時繼續。 請在一小時內完成轉移並啟動主機。 如果令牌過期,請重新執行指令並替換舊檔案。

傳輸檔案並準備主機

  1. 建立一個非秘密的主機交接檔案。

    {
        printf 'export AGENT_ARCHIVE=%q\n' "${AGENT_ARCHIVE}"
        printf 'export AGENT_SHA256=%q\n' "${AGENT_SHA256}"
        printf 'export AKS_FLEX_NODE_VERSION=%q\n' "${AKS_FLEX_NODE_VERSION}"
        printf 'export AKS_RESOURCE_ID=%q\n' "${AKS_RESOURCE_ID}"
        printf 'export FLEX_POOL_NAME=%q\n' "${FLEX_POOL_NAME}"
        printf 'export FLEX_HOST_PRIVATE_IP=%q\n' "${FLEX_HOST_PRIVATE_IP}"
        printf 'export HOST_IDENTITY_CLIENT_ID=%q\n' "${HOST_IDENTITY_CLIENT_ID:-}"
        printf 'export SP_TENANT_ID=%q\n' "${SP_TENANT_ID:-}"
        printf 'export SP_CLIENT_ID=%q\n' "${SP_CLIENT_ID:-}"
    } > "${WORK_DIR}/host-bootstrap.env"
    
    chmod 0600 "${WORK_DIR}/host-bootstrap.env"
    
  2. 將已驗證的釋出檔案和交接檔複製給主機。

    scp -i "${SSH_PRIVATE_KEY_PATH}" \
        "${WORK_DIR}/${AGENT_ARCHIVE}" \
        "${WORK_DIR}/bootstrap.sh" \
        "${WORK_DIR}/host-bootstrap.env" \
        "${FLEX_HOST_SSH_TARGET}:/tmp/"
    
  3. 對於管理身份或服務主體,也要複製受保護的引導式資料:

    scp -i "${SSH_PRIVATE_KEY_PATH}" \
        "${WORK_DIR}/base-config.json" \
        "${FLEX_HOST_SSH_TARGET}:/tmp/"
    
  4. 連線至主機並啟動 root Shell:

    ssh -i "${SSH_PRIVATE_KEY_PATH}" "${FLEX_HOST_SSH_TARGET}"
    sudo -i
    
  5. 載入非秘密的切換值並驗證傳輸檔案:

    source /tmp/host-bootstrap.env
    chmod 0600 "/tmp/${AGENT_ARCHIVE}" /tmp/host-bootstrap.env
    chmod 0700 /tmp/bootstrap.sh
    bash -n /tmp/bootstrap.sh
    printf '%s  %s\n' \
        "${AGENT_SHA256}" \
        "/tmp/${AGENT_ARCHIVE}" |
        sha256sum --check --strict -
    

    當檢查碼指令顯示封存檔為 OK 時,請繼續。 如果校驗碼或腳本語法檢查失敗,就停止。

  6. 針對受控識別或服務主體,請安裝引導資料:

    install -d -o root -g root -m 0700 /etc/aks-flex-node
    install -o root -g root -m 0600 \
        /tmp/base-config.json \
        /etc/aks-flex-node/base-config.json
    test -s /etc/aks-flex-node/base-config.json
    

初始化主機

請僅完成與上一篇文章中已設定身分相符的章節。

只有在 Arc 機器資源與 SSH 主機匹配、 himdsd 啟用、HIMDS 驗證回傳 HTTP 200 對應相同 AKS 資源,且 AKS 範圍的角色指派存在(如前一篇文章所驗證)後,才可使用此區段。 此路徑透過 Arc 機器身份取得新的引導資料,且不會使用你的 Bash 環境中的檔案 base-config.json 。

CONFIG_OVERRIDES="$(jq -cn \
    --arg nodeIP "${FLEX_HOST_PRIVATE_IP}" \
    '{node:{kubelet:{nodeIP:$nodeIP}}}')"
export CONFIG_OVERRIDES

bash /tmp/bootstrap.sh \
    --auth arc \
    --fetch-bootstrap-data \
    --cluster-resource-id "${AKS_RESOURCE_ID}" \
    --agent-pool-name "${FLEX_POOL_NAME}" \
    --agent-url "file:///tmp/${AGENT_ARCHIVE}" \
    --agent-sha256 "${AGENT_SHA256}" \
    --config-overrides "${CONFIG_OVERRIDES}"

當輸出回報 Arc preflight: OK,機器註冊完成,且 bootstrap 腳本回報 flex node agent 服務已啟動時,繼續進行。 如果 bootstrap 無法取得資料,請確認 Arc 連線、himdsdAKS 範圍內的角色指派,以及主機對 Azure Resource Manager 的存取權。

移除臨時釋出檔案

bootstrap 成功後,從主機移除暫態腳本、歸檔及交接檔案:

rm -f \
    "/tmp/${AGENT_ARCHIVE}" \
    /tmp/bootstrap.sh \
    /tmp/base-config.json \
    /tmp/host-bootstrap.env
exit
exit

第一個 exit 會離開 root shell。 第二個會關閉 SSH 會話並回到你的 Bash 環境。

在你的 Bash 環境中移除這些副本:

rm -f \
    "${WORK_DIR:?Load the deployment environment first.}/${AGENT_ARCHIVE}" \
    "${WORK_DIR}/bootstrap.sh" \
    "${WORK_DIR}/base-config.json" \
    "${WORK_DIR}/host-bootstrap.env" \
    "${WORK_DIR}/checksums.txt"

在主機仍處於附加狀態時,請保留 /etc/aks-flex-node 和服務主體認證。 執行中的代理程式會使用此設定來進行節點與 Azure 機器的對帳。

驗證 Kubernetes 節點

將節點名稱設為共享環境中記錄的 Linux 主機名稱。 首先,等待節點物件建立完成,然後等待它準備好:

export FLEX_NODE_NAME="$(printf '%s' "${FLEX_HOST_NAME}" | tr -d '[:space:]' | tr '[:upper:]' '[:lower:]')"

kubectl wait \
    --for=create \
    "node/${FLEX_NODE_NAME}" \
    --timeout=5m

kubectl wait \
    --for=condition=Ready \
    "node/${FLEX_NODE_NAME}" \
    --timeout=10m

kubectl get node "${FLEX_NODE_NAME}" -o wide

當節點為 Ready時繼續。 如果節點尚未建立或尚未準備好,請在重試 bootstrap 前先確認 bootstrap 輸出、API 連線和代理服務。

驗證 Azure Machine 資源

  1. 列出目標彈性節點池中的機器。

    az aks machine list \
        --resource-group "${RESOURCE_GROUP}" \
        --cluster-name "${CLUSTER_NAME}" \
        --nodepool-name "${FLEX_POOL_NAME}" \
        --query "[].{name:name,state:properties.provisioningState,nodeName:properties.kubernetes.nodeName,version:properties.kubernetes.currentOrchestratorVersion}" \
        --output table
    
  2. 找出註冊已準備好 Kubernetes 節點的機器:

    FLEX_MACHINE_NAME="$(az aks machine list \
        --resource-group "${RESOURCE_GROUP}" \
        --cluster-name "${CLUSTER_NAME}" \
        --nodepool-name "${FLEX_POOL_NAME}" \
        --query "[?properties.kubernetes.nodeName=='${FLEX_NODE_NAME}'].name | [0]" \
        --output tsv)"
    export FLEX_MACHINE_NAME
    
    printf 'Machine: %s\n' "${FLEX_MACHINE_NAME}"
    

    僅當指令恰好傳回一個機器名稱時,才繼續。

  3. 展示該機器:

    az aks machine show \
        --resource-group "${RESOURCE_GROUP}" \
        --cluster-name "${CLUSTER_NAME}" \
        --nodepool-name "${FLEX_POOL_NAME}" \
        --machine-name "${FLEX_MACHINE_NAME}" \
        --output yaml
    

    當 Machine 存在、參考 FLEX_NODE_NAME,且回報佈建狀態為成功時,繼續進行。 記錄供生命週期作業使用的機器名稱:

    set_flexnode_env FLEX_MACHINE_NAME "${FLEX_MACHINE_NAME}"
    

驗證彈性節點網路

  1. 顯示 flex 網站、pod CIDR 和 WireGuard 公鑰。

    kubectl get node "${FLEX_NODE_NAME}" \
        -L net.unbounded-cloud.io/site \
        -o wide
    
    kubectl get node "${FLEX_NODE_NAME}" \
        -o jsonpath='{.metadata.name}{" site="}{.metadata.labels.net\.unbounded-cloud\.io/site}{" podCIDR="}{.spec.podCIDR}{" wg="}{.metadata.annotations.net\.unbounded-cloud\.io/wg-pubkey}{"\n"}'
    
  2. 請驗證網站及相關的 Unbounded-Net 網路資源。

    kubectl get \
        sites,sitenodeslices,gatewaypools,sitegatewaypoolassignments,gatewaypoolpeerings \
        -o wide
    
  3. 顯示已排定於 flex 節點的 Unbounded-Net Pod。

    kubectl get pods --all-namespaces \
        --field-selector "spec.nodeName=${FLEX_NODE_NAME}" \
        -o wide
    

除非符合下列條件,否則請勿繼續進行工作負載驗證:

  • 節點為 Ready。
  • 該網站是在 networking 文章中設定的 Unbounded-Net Flex 網站。
  • Pod CIDR 屬於規劃的 FLEX_POD_CIDR 範圍。
  • WireGuard 公開金鑰已填入。
  • cluster-flex-private-l3 SitePeering 參照 cluster 和 flex-site 站台。
  • 在該節點上,每個傳回的 Unbounded-Net Pod 都是 Running。
  • 對於公開的 WireGuard 拓撲,預期的閘道池對等關係存在。

驗證 Flex 節點代理程式

等待最多一分鐘,服務才會啟動。 如果沒有,請顯示服務狀態和最近的日誌:

ssh -i "${SSH_PRIVATE_KEY_PATH}" "${FLEX_HOST_SSH_TARGET}" \
    'set -euo pipefail
     for attempt in {1..12}; do
         if sudo systemctl is-active --quiet aks-flex-node-agent; then
             sudo systemctl show aks-flex-node-agent \
                 -p ActiveState \
                 -p SubState \
                 -p Result \
                 -p NRestarts
             exit 0
         fi
         sleep 5
     done

     sudo systemctl show aks-flex-node-agent \
         -p ActiveState \
         -p SubState \
         -p Result \
         -p NRestarts
     sudo journalctl -u aks-flex-node-agent --no-pager -n 80
     exit 1'

當輸出包含 ActiveState=active、 SubState=running、 和 Result=success時繼續。

如果代理程式因無法列出 MachineOperation 資源而一再重新啟動,請返回 在 AKS 中設定網路並建立彈性節點集區 中的暫時性 flex daemon RBAC 步驟,確認角色和繫結存在,然後重新啟動代理程式:

ssh -i "${SSH_PRIVATE_KEY_PATH}" "${FLEX_HOST_SSH_TARGET}" \
    'sudo systemctl restart aks-flex-node-agent'

驗證工作負載的配置與連接性

建立驗證工作負載

建立一個專用的命名空間。 如果這個命名空間已經存在,請在重試前清理之前的驗證執行。

export VALIDATION_NAMESPACE="flex-node-validation"

if kubectl get namespace "${VALIDATION_NAMESPACE}" >/dev/null 2>&1; then
    printf 'Validation namespace already exists: %s\n' \
        "${VALIDATION_NAMESPACE}" >&2
    false
fi

kubectl create namespace "${VALIDATION_NAMESPACE}"
kubectl label namespace "${VALIDATION_NAMESPACE}" \
    app.kubernetes.io/managed-by=flex-node-article

建立一個 HTTP 伺服器,讓 Kubernetes 排程器放置於 flex 節點,並透過 ClusterIP 服務公開:

kubectl --namespace "${VALIDATION_NAMESPACE}" run flex-http-server \
    --image=busybox:1.36 \
    --restart=Never \
    --labels app=flex-http \
    --overrides="{\"spec\":{\"nodeSelector\":{\"kubernetes.io/hostname\":\"${FLEX_NODE_NAME}\"},\"tolerations\":[{\"operator\":\"Exists\"}]}}" \
    --command -- sh -c \
    'mkdir -p /www; echo flex-network-ok >/www/index.html; exec httpd -f -p 8080 -h /www'

kubectl --namespace "${VALIDATION_NAMESPACE}" wait \
    --for=condition=Ready \
    pod/flex-http-server \
    --timeout=3m

kubectl --namespace "${VALIDATION_NAMESPACE}" expose pod flex-http-server \
    --name=flex-http-service \
    --port=8080 \
    --target-port=8080

驗證回撥與本地服務連線

透過 Kubernetes API 伺服器回調路徑檢查日誌與指令執行:

kubectl --namespace "${VALIDATION_NAMESPACE}" logs flex-http-server --tail=5
kubectl --namespace "${VALIDATION_NAMESPACE}" exec flex-http-server -- \
    sh -c 'printf "exec-callback-ok\n"'

取得 ClusterIP,並從 flex node 工作負載向該服務發出請求:

SERVICE_IP="$(kubectl --namespace "${VALIDATION_NAMESPACE}" \
    get service flex-http-service \
    --output jsonpath='{.spec.clusterIP}')"
export SERVICE_IP

kubectl --namespace "${VALIDATION_NAMESPACE}" exec flex-http-server -- \
    wget -qO- "http://${SERVICE_IP}:8080"

預期的回應是:

flex-network-ok

驗證埠轉發

在目前終端機中,透過 Kubernetes API 伺服器轉發本地埠。 這個指令使用你之前載入的部署環境和 kubeconfig:

kubectl --namespace "${VALIDATION_NAMESPACE}" \
    port-forward pod/flex-http-server 18080:8080

在第二個終端機中,請求轉發端點:

curl -fsS http://127.0.0.1:18080

預期的回應為 flex-network-ok。 勾選後在第一個終端機按 Ctrl+C 。

驗證 AKS 受控節點的連線能力

尋找一個準備好的 AKS 管理系統節點:

SYSTEM_NODE="$(kubectl get nodes \
    --selector agentpool=systempool \
    --output json |
    jq -r '
        .items[]
        | select(any(.status.conditions[];
            .type == "Ready" and .status == "True"))
        | .metadata.name
    ' |
    head -n 1)"
export SYSTEM_NODE

test -n "${SYSTEM_NODE}"
printf 'Managed-node test target: %s\n' "${SYSTEM_NODE}"

在該節點上執行一個用戶端 Pod,並確認是否得到預期的回應:

kubectl --namespace "${VALIDATION_NAMESPACE}" run system-http-client \
    --image=busybox:1.36 \
    --restart=Never \
    --overrides="{\"spec\":{\"nodeSelector\":{\"kubernetes.io/hostname\":\"${SYSTEM_NODE}\"}}}" \
    --command -- sh -c \
    "test \"\$(wget -qO- http://${SERVICE_IP}:8080)\" = flex-network-ok"

kubectl --namespace "${VALIDATION_NAMESPACE}" wait \
    --for=jsonpath='{.status.phase}'=Succeeded \
    pod/system-http-client \
    --timeout=3m

kubectl --namespace "${VALIDATION_NAMESPACE}" \
    get pod flex-http-server system-http-client -o wide

一個處於 Ready 狀態的 Kubernetes 節點會顯示節點註冊。 它本身無法證明工作負載網路、回調操作或 Azure 生命週期操作。

清理驗證工作量

請只移除你在本文中建立的臨時資源。

kubectl delete namespace "${VALIDATION_NAMESPACE}"

後續步驟

接著, 管理、更新、升級或移除連接的彈性節點。