你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
Important
AKS 预览功能可在自助服务和自愿选择的基础上启用。 预览版按“现状”和“视供应情况”提供,它们不包括在服务级别协议和有限保证范围内。 AKS 预览功能是由客户支持尽最大努力部分覆盖。 因此,这些功能并不适合用于生产。 有关详细信息,请参阅以下支持文章:
准备Azure Kubernetes 服务 (AKS)群集、网络、弹性节点池、主机和标识后,启动主机并将其附加到目标池。
在本文中,你将了解:
- 下载并验证 Flex node 发行版。
- 通过使用所选Azure标识来检索新的池数据,启动主机。
- 验证 Kubernetes 节点、Azure计算机、网络状态和代理服务。
- 验证工作负荷放置、Kubernetes 回调和跨节点连接。
在 Linux 兼容的 Bash 环境中运行具有所需工具和网络访问权限的本文中的管理命令。 本文将该环境称为你的 Bash 环境。 加入集群的独立机器是 flex 节点主机;仅当某个步骤明确指示您这样做时,才在该主机上运行命令。
对于专用 AKS 群集,请从可以解析并访问专用 API 服务器的 Bash 环境运行每个 kubectl 命令。 当 Bash 环境具有所需的Azure和主机访问权限时,可以从 Bash 环境中运行Azure CLI、项目下载、SSH 和 SCP 命令。 弹性节点主机网络还必须解析并访问专用 API 终结点。
在您开始之前
- 完成 配置网络并在 AKS 中创建弹性节点池。
- 完成 准备弹性节点主机和标识。
- 在你的 Bash 环境中安装 Azure CLI、
aks-preview扩展、与scp相差不超过一个次版本的kubectl版本、sha256sum、AKS_VERSION、jq、OpenSSH 客户端和curl。 - 对于托管标识或服务主体,请使用Azure帐户,该帐户可以检索所选弹性节点池的启动数据。
- 确保 Bash 环境可以通过批准的 SSH 管理路径访问弹性节点主机。
- 确保弹性节点主机能够通过 HTTPS 访问池引导数据中返回的发布工件终结点和引导工件终结点、Azure 资源管理器、Microsoft Entra ID 以及所选的 AKS API 终结点。
注释
不要在共享环境文件中存储凭据、证书、私钥、访问令牌、启动数据或 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>。 本文会推导出所需的其他变量。 如果尚未创建环境文件,请先 完成计划弹性节点部署 。 如果 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 节点发行版
标识主机体系结构并选择匹配的发布存档。
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}"从所选发布版本中下载归档文件和校验和清单。
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"为归档文件恰好选择一个校验和条目,并验证该文件。
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}"除非校验和命令显示该归档文件为
OK,否则请勿继续。从同一发布标记下载启动脚本并验证其 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 存在且不为空时,继续。 在一小时内完成传输和主机启动。 如果令牌过期,请再次运行该命令并替换旧文件。
传输文件并准备主机
创建一个非机密主机交接文件。
{ 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"将已验证的发布文件和移交文件复制到主机。
scp -i "${SSH_PRIVATE_KEY_PATH}" \ "${WORK_DIR}/${AGENT_ARCHIVE}" \ "${WORK_DIR}/bootstrap.sh" \ "${WORK_DIR}/host-bootstrap.env" \ "${FLEX_HOST_SSH_TARGET}:/tmp/"对于托管标识或服务主体,还请复制受保护的引导数据:
scp -i "${SSH_PRIVATE_KEY_PATH}" \ "${WORK_DIR}/base-config.json" \ "${FLEX_HOST_SSH_TARGET}:/tmp/"连接到主机并启动 root Shell:
ssh -i "${SSH_PRIVATE_KEY_PATH}" "${FLEX_HOST_SSH_TARGET}" sudo -i加载非机密交接值并验证已传输的文件:
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时,继续。 如果校验和或脚本语法检查失败,则停止。对于托管标识或服务主体,请安装引导数据:
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 处于活动状态,针对对应的确切 AKS 资源执行的 HIMDS 验证返回 HTTP 200,并且已存在作用域为 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 无法检索数据,请验证 Arc 连接、himdsd、AKS 范围的角色分配以及主机对 Azure 资源管理器的访问权限。
删除临时发布文件
引导成功后,从主机上删除临时脚本、归档文件和移交文件:
rm -f \
"/tmp/${AGENT_ARCHIVE}" \
/tmp/bootstrap.sh \
/tmp/base-config.json \
/tmp/host-bootstrap.env
exit
exit
第一个 exit 离开根 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 主机名。 首先,等待创建 Node 对象,然后等待它准备就绪:
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 时继续。 如果节点未创建或未准备就绪,请在重试启动之前验证启动输出、API 连接和代理服务。
验证 Azure Machine 资源
列出目标弹性节点池中的计算机。
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查找注册了已准备好的 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}"仅当该命令恰好返回一个机器名称时,才继续。
显示该机器:
az aks machine show \ --resource-group "${RESOURCE_GROUP}" \ --cluster-name "${CLUSTER_NAME}" \ --nodepool-name "${FLEX_POOL_NAME}" \ --machine-name "${FLEX_MACHINE_NAME}" \ --output yaml当机器存在、引用
FLEX_NODE_NAME且其预配状态为成功时,继续。 记录用于生命周期操作的机器名称:set_flexnode_env FLEX_MACHINE_NAME "${FLEX_MACHINE_NAME}"
验证弹性节点网络
显示 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"}'验证站点及相关的 Unbounded-Net 网络资源。
kubectl get \ sites,sitenodeslices,gatewaypools,sitegatewaypoolassignments,gatewaypoolpeerings \ -o wide显示已调度到 flex 节点的 Unbounded-Net Pod。
kubectl get pods --all-namespaces \ --field-selector "spec.nodeName=${FLEX_NODE_NAME}" \ -o wide
除非符合以下条件,否则不要继续进行工作负载验证:
- 节点为
Ready. - 该站点是网络文章中配置的“无界”灵活站点。
- Pod CIDR 属于计划中的
FLEX_POD_CIDR范围。 - WireGuard 公钥已填入。
-
cluster-flex-private-l3SitePeering 引用了cluster和flex-site站点。 - 节点上返回的每个 Unbounded-Net Pod 均为
Running。 - 对于公共 WireGuard 拓扑,已存在预期的网关池对等连接。
验证弹性节点代理
等待最多一分钟,直到服务变为活动状态。 如果未显示,则显示服务状态和最近日志:
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=runningResult=success时继续。
如果代理因无法列出 MachineOperation 资源而重复重启,请返回到配置网络中的临时弹性守护程序 RBAC 步骤,并在 AKS 中创建弹性节点池,验证角色和绑定是否存在,然后重启代理:
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
创建 Kubernetes 计划程序放置在弹性节点上的 HTTP 服务器,并通过 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,并从弹性节点工作负载访问该服务:
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}"
后续步骤
接下来, 管理、更新、升级或删除附加的弹性节点。