在本文中,你将使用 CloudNativePG(CNPG) 作员创建在 AKS 上部署高度可用的 PostgreSQL 数据库所需的基础结构资源。
重要
AKS 文档和示例中都提到了开源软件。 部署的软件不包括在 AKS 服务级别协议、有限保修和 Azure 支持中。 与 AKS 一起使用开源技术时,请查阅各自社区和project维护人员提供的支持选项,以制定计划。
Microsoft 将负责生成我们在 AKS 上部署的开源包。 该责任包括对生成、扫描、签名、验证和修补过程拥有完整的所有权,以及对容器映像中的二进制文件的控制。 如需了解详细信息,请参阅 AKS 漏洞管理和 AKS 支持范围。
开始之前
设置环境变量。
设置以下环境变量以在本指南中使用:
export SUFFIX=$(cat /dev/urandom | LC_ALL=C tr -dc 'a-z0-9' | fold -w 8 | head -n 1)
export LOCAL_NAME="cnpg"
export TAGS="owner=user"
export RESOURCE_GROUP_NAME="rg-${LOCAL_NAME}-${SUFFIX}"
export PRIMARY_CLUSTER_REGION="chinanorth3"
export AKS_PRIMARY_CLUSTER_NAME="aks-primary-${LOCAL_NAME}-${SUFFIX}"
export AKS_PRIMARY_MANAGED_RG_NAME="rg-${LOCAL_NAME}-primary-aksmanaged-${SUFFIX}"
export AKS_PRIMARY_CLUSTER_FED_CREDENTIAL_NAME="pg-primary-fedcred1-${LOCAL_NAME}-${SUFFIX}"
export AKS_PRIMARY_CLUSTER_PG_DNSPREFIX=$(echo $(echo "a$(openssl rand -hex 5 | cut -c1-11)"))
export AKS_UAMI_CLUSTER_IDENTITY_NAME="mi-aks-${LOCAL_NAME}-${SUFFIX}"
export AKS_CLUSTER_VERSION="1.32"
export PG_NAMESPACE="cnpg-database"
export PG_SYSTEM_NAMESPACE="cnpg-system"
export PG_PRIMARY_CLUSTER_NAME="pg-primary-${LOCAL_NAME}-${SUFFIX}"
export PG_PRIMARY_STORAGE_ACCOUNT_NAME="hacnpgpsa${SUFFIX}"
export PG_STORAGE_BACKUP_CONTAINER_NAME="backups"
export MY_PUBLIC_CLIENT_IP=$(dig +short myip.opendns.com @resolver3.opendns.com)
安装所需的扩展
安装 Kubernetes 集成和监视所需的扩展:
az extension add --upgrade --name k8s-extension --yes
az extension add --upgrade --name amg --yes
作为使用 kubectl先决条件,需要先安装 Krew,然后安装 CNPG 插件。 这些安装允许使用后续命令管理 PostgreSQL 运算符。
(
set -x; cd "$(mktemp -d)" &&
OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
KREW="krew-${OS}_${ARCH}" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
tar zxvf "${KREW}.tar.gz" &&
./"${KREW}" install krew
)
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"
kubectl krew install cnpg
创建资源组
使用 az group create 命令创建资源组以保存在本指南中创建的资源。
az group create \
--name $RESOURCE_GROUP_NAME \
--location $PRIMARY_CLUSTER_REGION \
--tags $TAGS \
--query 'properties.provisioningState' \
--output tsv
创建用户分配的托管标识
在本部分中,您将创建一个用户分配的托管标识(UAMI),以便 CNPG PostgreSQL 可以使用 AKS 工作负载标识来访问 Azure Blob Storage。 此配置允许 AKS 上的 PostgreSQL 群集在没有机密的情况下连接到Azure Blob Storage。
使用
az identity create命令创建用户分配的托管标识。AKS_UAMI_WI_IDENTITY=$(az identity create \ --name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --location $PRIMARY_CLUSTER_REGION \ --output json)使用以下命令启用 AKS 工作负载标识并生成服务帐户,以在本指南的后面部分使用:
export AKS_UAMI_WORKLOAD_OBJECTID=$( \ echo "${AKS_UAMI_WI_IDENTITY}" | jq -r '.principalId') export AKS_UAMI_WORKLOAD_RESOURCEID=$( \ echo "${AKS_UAMI_WI_IDENTITY}" | jq -r '.id') export AKS_UAMI_WORKLOAD_CLIENTID=$( \ echo "${AKS_UAMI_WI_IDENTITY}" | jq -r '.clientId') echo "ObjectId: $AKS_UAMI_WORKLOAD_OBJECTID" echo "ResourceId: $AKS_UAMI_WORKLOAD_RESOURCEID" echo "ClientId: $AKS_UAMI_WORKLOAD_CLIENTID"
对象 ID 是客户端 ID(也称为应用程序 ID)的唯一标识符,用于唯一标识Microsoft Entra ID租户中Application类型的安全主体。 资源 ID 是一个唯一标识符,用于管理和查找Azure中的资源。 启用 AKS 工作负载标识需要这些值。
CNPG 自动生成一个名为 postgres 的服务帐户,您会在指南的后续部分使用该帐户来创建一个联合凭据,以启用从 PostgreSQL 到 Azure Storage 的 OAuth 访问。
在主要区域内创建存储帐户
使用
az storage account create命令创建对象storage帐户,将 PostgreSQL 备份存储在主要区域中。az storage account create \ --name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --location $PRIMARY_CLUSTER_REGION \ --sku Standard_ZRS \ --kind StorageV2 \ --query 'provisioningState' \ --output tsv使用
az storage container create命令创建storage容器来存储预写日志(WAL)和常规 PostgreSQL 按需备份和计划备份。az storage container create \ --name $PG_STORAGE_BACKUP_CONTAINER_NAME \ --account-name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --auth-mode login示例输出:
{ "created": true }注意事项
如果遇到错误消息:
The request may be blocked by network rules of storage account. Please check network rule set using 'az storage account show -n accountname --query networkRuleSet'. If you want to change the default action to apply when no rule matches, please use 'az storage account update'。 请确保验证 Azure Blob Storage 的用户权限;如果有必要,请使用提供的命令将角色提升为Storage Blob Data Owner,然后重试az storage container create命令。export USER_ID=$(az ad signed-in-user show --query id --output tsv) export STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID=$(az storage account show \ --name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --query "id" \ --output tsv) az role assignment list --scope $STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID --output table az role assignment create \ --assignee-object-id $USER_ID \ --assignee-principal-type User \ --scope $STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID \ --role "Storage Blob Data Owner" \ --output tsv
为存储账户分配 RBAC
若要启用备份,PostgreSQL 群集需要读取和写入对象存储。 在 AKS 上运行的 PostgreSQL 群集使用工作负载标识,通过 CNPG 操作符配置参数 inheritFromAzureAD 访问存储帐户。
使用
az storage account show命令获取存储帐户的主资源 ID。export STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID=$(az storage account show \ --name $PG_PRIMARY_STORAGE_ACCOUNT_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --query "id" \ --output tsv) echo $STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID使用
az role assignment create命令将“Storage Blob 数据参与者”Azure内置角色分配给具有与每个 AKS 群集托管标识关联的 UAMI storage 帐户资源 ID 范围的对象 ID。az role assignment create \ --role "Storage Blob Data Contributor" \ --assignee-object-id $AKS_UAMI_WORKLOAD_OBJECTID \ --assignee-principal-type ServicePrincipal \ --scope $STORAGE_ACCOUNT_PRIMARY_RESOURCE_ID \ --query "id" \ --output tsv
设置监视基础结构
在本部分中,您将部署 Azure Managed Grafana 实例、Azure Monitor 工作区和 Azure Monitor Log Analytics 工作区,以启用 PostgreSQL 群集的监视。 在本指南的后续步骤中,您还会将创建的监控基础设施的引用作为输入存储,以便在创建 Azure Kubernetes Service (AKS) 群集的过程中使用。 本节可能需要一些时间才能完成。
注意事项
Azure Managed Grafana实例和 AKS 群集单独计费。 有关详细信息,请参阅 Azure Managed Grafana 定价。
使用
az grafana create命令创建Azure Managed Grafana实例。export GRAFANA_PRIMARY="grafana-${LOCAL_NAME}-${SUFFIX}" export GRAFANA_RESOURCE_ID=$(az grafana create \ --resource-group $RESOURCE_GROUP_NAME \ --name $GRAFANA_PRIMARY \ --location $PRIMARY_CLUSTER_REGION \ --zone-redundancy Enabled \ --tags $TAGS \ --query "id" \ --output tsv) echo $GRAFANA_RESOURCE_ID使用
az monitor account create命令创建Azure监视工作区。export AMW_PRIMARY="amw-${LOCAL_NAME}-${SUFFIX}" export AMW_RESOURCE_ID=$(az monitor account create \ --name $AMW_PRIMARY \ --resource-group $RESOURCE_GROUP_NAME \ --location $PRIMARY_CLUSTER_REGION \ --tags $TAGS \ --query "id" \ --output tsv) echo $AMW_RESOURCE_ID使用
az monitor log-analytics workspace create命令创建 Azure Monitor Log Analytics 工作区。export ALA_PRIMARY="ala-${LOCAL_NAME}-${SUFFIX}" export ALA_RESOURCE_ID=$(az monitor log-analytics workspace create \ --resource-group $RESOURCE_GROUP_NAME \ --workspace-name $ALA_PRIMARY \ --location $PRIMARY_CLUSTER_REGION \ --query "id" \ --output tsv) echo $ALA_RESOURCE_ID
创建 AKS 群集以托管 PostgreSQL 群集
在本节中,使用系统节点池创建多区域 AKS 群集。 AKS 群集托管 PostgreSQL 群集主副本和两个备用副本,每个副本都与不同的可用性区域保持一致,以实现区域冗余。
还可将用户节点池添加到 AKS 群集,以托管 PostgreSQL 群集。 使用单独的节点池可以控制用于 PostgreSQL 的 Azure VM SKU,并使 AKS 系统池能够优化性能和成本。 将标签应用于用户节点池,在本指南后面部署 CNPG 运算符时,可引用该标签进行节点选择。 本节可能需要一些时间才能完成。
重要
如果选择在本指南的后续部分中将本地 NVMe 用作 PostgreSQL storage,则需要选择支持本地 NVMe 驱动器的 VM SKU,例如,Storage优化的 VM SKU或 GPU 加速 VM SKU。 相应地更新 $USER_NODE_POOL_VMSKU 。
使用
az aks create命令创建 AKS 群集。export SYSTEM_NODE_POOL_VMSKU="standard_d2s_v3" export USER_NODE_POOL_NAME="postgres" export USER_NODE_POOL_VMSKU="standard_d4s_v3" az aks create \ --name $AKS_PRIMARY_CLUSTER_NAME \ --tags $TAGS \ --resource-group $RESOURCE_GROUP_NAME \ --location $PRIMARY_CLUSTER_REGION \ --generate-ssh-keys \ --node-resource-group $AKS_PRIMARY_MANAGED_RG_NAME \ --enable-managed-identity \ --assign-identity $AKS_UAMI_WORKLOAD_RESOURCEID \ --network-plugin azure \ --network-plugin-mode overlay \ --network-dataplane cilium \ --nodepool-name systempool \ --enable-oidc-issuer \ --enable-workload-identity \ --enable-cluster-autoscaler \ --min-count 2 \ --max-count 3 \ --node-vm-size $SYSTEM_NODE_POOL_VMSKU \ --enable-azure-monitor-metrics \ --azure-monitor-workspace-resource-id $AMW_RESOURCE_ID \ --grafana-resource-id $GRAFANA_RESOURCE_ID \ --api-server-authorized-ip-ranges $MY_PUBLIC_CLIENT_IP \ --tier standard \ --kubernetes-version $AKS_CLUSTER_VERSION \ --zones 1 2 3 \ --output table等待初始群集操作通过使用
az aks wait命令完成,以确保添加用户节点池等其他更新不会与正在进行的托管群集更新发生冲突:az aks wait \ --resource-group $RESOURCE_GROUP_NAME \ --name $AKS_PRIMARY_CLUSTER_NAME \ --created使用
az aks nodepool add命令将用户节点池添加到 AKS 群集。az aks nodepool add \ --resource-group $RESOURCE_GROUP_NAME \ --cluster-name $AKS_PRIMARY_CLUSTER_NAME \ --name $USER_NODE_POOL_NAME \ --enable-cluster-autoscaler \ --min-count 3 \ --max-count 6 \ --node-vm-size $USER_NODE_POOL_VMSKU \ --zones 1 2 3 \ --labels workload=postgres \ --output table
连接到 AKS 群集并创建命名空间
在本节中,获取 AKS 群集凭据,这些凭据充当允许你进行身份验证并与群集交互的密钥。 连接后,创建两个命名空间:一个用于 CNPG 控制器管理器服务,一个用于 PostgreSQL 群集及其相关服务。
使用
az aks get-credentials命令获取 AKS 群集凭据。az aks get-credentials \ --resource-group $RESOURCE_GROUP_NAME \ --name $AKS_PRIMARY_CLUSTER_NAME \ --output none使用
kubectl create namespace命令为 CNPG 控制器管理器服务、PostgreSQL 群集及其相关服务创建命名空间。kubectl create namespace $PG_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME kubectl create namespace $PG_SYSTEM_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME
现在,可以根据所需的存储选项定义另一个环境变量,并在稍后部署 PostgreSQL 时引用该环境变量。
可以引用默认预安装的 Azure 高级 SSD 磁盘 CSI 驱动的存储类:
export POSTGRES_STORAGE_CLASS="managed-csi-premium"
更新监视基础结构
在创建群集的过程中,Azure 监视的托管 Prometheus 和 Azure Managed Grafana 工作区会自动链接到 AKS 群集,用于指标收集和可视化。 在本节中,通过 AKS 容器见解启用日志收集,并验证托管的 Prometheus 是否正在抓取指标,以及容器见解是否正在引入日志。
使用
az aks enable-addons命令在 AKS 群集上启用容器见解监视。az aks enable-addons \ --addon monitoring \ --name $AKS_PRIMARY_CLUSTER_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --workspace-resource-id $ALA_RESOURCE_ID \ --output table使用
kubectl get命令和az aks show命令检查 DaemonSet,以验证托管的 Prometheus 是否正在抓取指标,以及 Container Insights 是否从 AKS 群集收集日志。kubectl get ds ama-metrics-node \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace=kube-system kubectl get ds ama-logs \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace=kube-system az aks show \ --resource-group $RESOURCE_GROUP_NAME \ --name $AKS_PRIMARY_CLUSTER_NAME \ --query addonProfiles输出应类似于以下示例输出,共 6 个节点(3 个用于系统节点池,3 个用于 PostgreSQL 节点池),且容器见解显示
"enabled": true:NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR ama-metrics-node 6 6 6 6 6 <none> NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR ama-logs 6 6 6 6 6 <none> { "omsagent": { "config": { "logAnalyticsWorkspaceResourceID": "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e/resourceGroups/rg-cnpg-9vbin3p8/providers/Microsoft.OperationalInsights/workspaces/ala-cnpg-9vbin3p8", "useAADAuth": "true" }, "enabled": true, "identity": null } }
为 PostgreSQL 群集入口创建公共静态 IP
若要验证 PostgreSQL 群集的部署并使用客户端 PostgreSQL 工具(如 psql 和 PgAdmin),需要向入口公开主要副本和只读副本。 在本部分中,你将创建一个 Azure 公共 IP 资源,稍后将其提供给 Azure 负载均衡器,从而公开 PostgreSQL 终结点以供查询。
使用
az aks show命令获取 AKS 群集节点资源组的名称。export AKS_PRIMARY_CLUSTER_NODERG_NAME=$(az aks show \ --name $AKS_PRIMARY_CLUSTER_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --query nodeResourceGroup \ --output tsv) echo $AKS_PRIMARY_CLUSTER_NODERG_NAME使用
az network public-ip create命令创建公共 IP 地址。export AKS_PRIMARY_CLUSTER_PUBLICIP_NAME="$AKS_PRIMARY_CLUSTER_NAME-pip" az network public-ip create \ --resource-group $AKS_PRIMARY_CLUSTER_NODERG_NAME \ --name $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME \ --location $PRIMARY_CLUSTER_REGION \ --sku Standard \ --zone 1 2 3 \ --allocation-method static \ --output table使用
az network public-ip show命令获取新创建的公共 IP 地址。export AKS_PRIMARY_CLUSTER_PUBLICIP_ADDRESS=$(az network public-ip show \ --resource-group $AKS_PRIMARY_CLUSTER_NODERG_NAME \ --name $AKS_PRIMARY_CLUSTER_PUBLICIP_NAME \ --query ipAddress \ --output tsv) echo $AKS_PRIMARY_CLUSTER_PUBLICIP_ADDRESS使用
az group show命令获取节点资源组的资源 ID。export AKS_PRIMARY_CLUSTER_NODERG_NAME_SCOPE=$(az group show --name \ $AKS_PRIMARY_CLUSTER_NODERG_NAME \ --query id \ --output tsv) echo $AKS_PRIMARY_CLUSTER_NODERG_NAME_SCOPE使用
az role assignment create命令,使用节点资源组范围将“网络参与者”角色分配给 UAMI 对象 ID。az role assignment create \ --assignee-object-id ${AKS_UAMI_WORKLOAD_OBJECTID} \ --assignee-principal-type ServicePrincipal \ --role "Network Contributor" \ --scope ${AKS_PRIMARY_CLUSTER_NODERG_NAME_SCOPE}
在 AKS 集群中安装 CNPG Operator
在本节中,使用 Helm 或 YAML 清单在 AKS 群集中安装 CNPG 操作器。
使用
helm repo add命令添加 CNPG Helm 存储库。helm repo add cnpg https://cloudnative-pg.github.io/charts升级 CNPG Helm 存储库,并使用带有
helm upgrade标志的--install命令在 AKS 群集上安装它。helm upgrade --install cnpg \ --namespace $PG_SYSTEM_NAMESPACE \ --create-namespace \ --kube-context=$AKS_PRIMARY_CLUSTER_NAME \ cnpg/cloudnative-pg使用
kubectl get命令验证 AKS 群集上的运算符安装。kubectl get deployment \ --context $AKS_PRIMARY_CLUSTER_NAME \ --namespace $PG_SYSTEM_NAMESPACE cnpg-cloudnative-pg
后续步骤
供稿人
Microsoft 会维护本文。 以下贡献者是该作品的原作者:
- Ken Kilty | 首席技术项目经理 (TPM)
- Russell de Pina | 首席技术项目经理
- Adrian Joian | 高级客户工程师
- Jenny Hayes | 高级内容开发人员
- Carol Smith | 高级内容开发人员
- Erin Schaffer | 内容开发人员 2