在本文中,你将在 AKS 上部署高度可用的 PostgreSQL 数据库。
- 如果尚未为此部署创建所需的基础结构,请按照创建基础结构以在 AKS 上部署高度可用的 PostgreSQL 数据库中的步骤进行设置,然后可返回到本文。
重要
AKS 文档和示例中都提到了开源软件。 AKS 服务级别协议、有限保修和 Azure 支持不涵盖你部署的软件。 将开源技术与 AKS 一起使用时,请查阅相应社区和项目维护者提供的支持选项来制定计划。
例如,Ray GitHub 存储库描述了多个在响应时间、用途和支持级别方面各不相同的平台。
Microsoft 将负责生成我们在 AKS 上部署的开源包。 该责任包括对生成、扫描、签名、验证和修补过程拥有完整的所有权,以及对容器映像中的二进制文件的控制。 如需了解详细信息,请参阅 AKS 漏洞管理和 AKS 支持范围。
为启动应用用户创建机密
- 使用
kubectl create secret
命令为启动应用用户生成一个机密,通过交互式登录来验证 PostgreSQL 部署。
重要
Microsoft建议使用可用的最安全的身份验证流。 此过程中所述的身份验证流要求在应用程序中高度信任,并且存在其他流中不存在的风险。 仅当其他更安全的流(如托管标识)不可行时,才应使用此流。
PG_DATABASE_APPUSER_SECRET=$(echo -n | openssl rand -base64 16)
kubectl create secret generic db-user-pass \
--from-literal=username=app \
--from-literal=password="${PG_DATABASE_APPUSER_SECRET}" \
--namespace $PG_NAMESPACE \
--context $AKS_PRIMARY_CLUSTER_NAME
使用
kubectl get
命令验证是否已成功创建机密。kubectl get secret db-user-pass --namespace $PG_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME
设置用于 PostgreSQL 群集的环境变量
部署 ConfigMap,使用以下
kubectl apply
命令为 PostgreSQL 群集设置环境变量:cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -f - apiVersion: v1 kind: ConfigMap metadata: name: cnpg-controller-manager-config data: ENABLE_AZURE_PVC_UPDATES: 'true' EOF
安装 Prometheus PodMonitor
Prometheus 使用 CNPG GitHub 示例存储库中存储的一组默认记录规则为 CNPG 实例创建 PodMonitor。 在生产环境中,将根据需要修改这些规则。
使用
helm repo add
命令添加 Prometheus 社区 Helm 存储库。helm repo add prometheus-community \ https://prometheus-community.github.io/helm-charts
升级 Prometheus 社区 Helm 存储库,并使用带有
helm upgrade
标志的--install
命令在主群集上安装它。helm upgrade --install \ --namespace $PG_NAMESPACE \ -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/docs/src/samples/monitoring/kube-stack-config.yaml \ prometheus-community \ prometheus-community/kube-prometheus-stack \ --kube-context=$AKS_PRIMARY_CLUSTER_NAME
创建联合凭据
在本部分,你将创建 PostgreSQL 备份的联合标识凭据,以允许 CNPG 使用 AKS 工作负载标识向存储帐户目标进行身份验证来进行备份。 CNPG 运算符会创建一个与 CNPG 群集部署清单中使用的群集同名的 Kubernetes 服务帐户。
使用
az aks show
命令获取群集 OIDC 颁发者 URL。export AKS_PRIMARY_CLUSTER_OIDC_ISSUER="$(az aks show \ --name $AKS_PRIMARY_CLUSTER_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --query "oidcIssuerProfile.issuerUrl" \ --output tsv)"
使用
az identity federated-credential create
命令创建联合标识凭据。az identity federated-credential create \ --name $AKS_PRIMARY_CLUSTER_FED_CREDENTIAL_NAME \ --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \ --resource-group $RESOURCE_GROUP_NAME \ --issuer "${AKS_PRIMARY_CLUSTER_OIDC_ISSUER}" \ --subject system:serviceaccount:"${PG_NAMESPACE}":"${PG_PRIMARY_CLUSTER_NAME}" \ --audience api://AzureADTokenExchange
部署高度可用的 PostgreSQL 群集
在本部分,你将使用 CNPG 群集自定义资源定义 (CRD) 部署高度可用的 PostgreSQL 群集。
群集 CRD 参数
下表概述了在群集 CRD 的 YAML 部署清单中设置的关键属性:
properties | 定义 |
---|---|
inheritedMetadata |
特定于 CNPG 运算符。 元数据由与群集相关的所有对象继承。 |
annotations: service.beta.kubernetes.io/azure-dns-label-name |
公开读写和只读 Postgres 群集终结点时要使用的 DNS 标签。 |
labels: azure.workload.identity/use: "true" |
指示 AKS 应将工作负载标识依赖项注入托管 PostgreSQL 群集实例的 Pod。 |
topologySpreadConstraints |
需要不同的区域和具有 "workload=postgres" 标签的不同节点。 |
resources |
配置服务质量 (QoS) 类 Guaranteed。 在生产环境中,这些值是最大限度使用基础节点 VM 的关键,根据所使用的 Azure VM SKU 而有所不同。 |
bootstrap |
特定于 CNPG 运算符。 使用空的应用数据库进行初始化。 |
storage / walStorage |
特定于 CNPG 运算符。 为数据和日志存储的 PersistentVolumeClaim (PVC) 定义存储模板。 还可以为表空间指定存储来进行分片,以增加 IOPs。 |
replicationSlots |
特定于 CNPG 运算符。 启用复制槽来实现高可用性。 |
postgresql |
特定于 CNPG 运算符。 映射 postgresql.conf 、pg_hba.conf 和 pg_ident.conf config 的设置。 |
serviceAccountTemplate |
包含生成服务帐户所需的模板,并将 AKS 联合标识凭据映射到 UAMI,从而能够从托管 PostgreSQL 实例的 Pod 进行 AKS 工作负载标识身份验证来访问外部 Azure 资源。 |
barmanObjectStore |
特定于 CNPG 运算符。 使用 AKS 工作负载标识配置 barman-cloud 工具套件,以便向 Azure Blob 存储对象存储进行身份验证。 |
PostgreSQL 性能参数
PostgreSQL 性能在很大程度上取决于群集的基础资源。 下表提供了有关如何计算高性能的关键参数的一些建议:
properties | 建议的值 | 定义 |
---|---|---|
wal_compression |
lz4 | 使用指定方法压缩 WAL 文件中的整页写入 |
max_wal_size |
6GB | 设置触发检查点的 WAL 大小 |
checkpoint_timeout |
15 分钟 | 在自动 WAL 检查点之间设置最长时间 |
checkpoint_flush_after |
2MB(兆字节) | 在将以前执行的写入刷新到磁盘之前所要达到的页数 |
wal_writer_flush_after |
2MB(兆字节) | WAL 写入器写出的 WAL 数量,达到该数量将触发刷新 |
min_wal_size |
4GB | 设置要将 WAL 收缩到的最小大小 |
shared_buffers |
25% 的节点内存 | 设置服务器使用的共享内存缓冲区数 |
effective_cache_size |
75% 的节点内存 | 设置规划器关于数据缓存总大小的假设 |
work_mem |
1/256 的节点内存 | 设置要用于查询工作区的最大内存 |
maintenance_work_mem |
6.25% 的节点内存 | 设置用于维护操作的最大内存 |
autovacuum_vacuum_cost_limit |
2400 | autovacuum 在短暂睡眠之前可用的清空成本量 |
random_page_cost |
1.1 | 设置规划器对不按顺序提取磁盘页的成本估计值 |
effective_io_concurrency |
64 | 磁盘子系统可有效处理的同时请求数 |
maintenance_io_concurrency |
64 | 用于维护工作的“effective_io_concurrency”变体 |
部署 PostgreSQL
使用
kubectl apply
命令通过群集 CRD 部署 PostgreSQL 群集。cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -v 9 -f - apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: $PG_PRIMARY_CLUSTER_NAME spec: inheritedMetadata: annotations: service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX labels: azure.workload.identity/use: "true" instances: 3 startDelay: 30 stopDelay: 30 minSyncReplicas: 1 maxSyncReplicas: 1 replicationSlots: highAvailability: enabled: true updateInterval: 30 topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule labelSelector: matchLabels: cnpg.io/cluster: $PG_PRIMARY_CLUSTER_NAME affinity: nodeSelector: workload: postgres resources: requests: memory: '8Gi' cpu: 2 limits: memory: '8Gi' cpu: 2 bootstrap: initdb: database: appdb owner: app secret: name: db-user-pass dataChecksums: true storage: size: 32Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 32Gi storageClassName: $POSTGRES_STORAGE_CLASS walStorage: size: 32Gi pvcTemplate: accessModes: - ReadWriteOnce resources: requests: storage: 32Gi storageClassName: $POSTGRES_STORAGE_CLASS monitoring: enablePodMonitor: true postgresql: parameters: wal_compression: lz4 max_wal_size: 6GB checkpoint_timeout: 15min checkpoint_flush_after: 2MB wal_writer_flush_after: 2MB min_wal_size: 4GB shared_buffers: 4GB effective_cache_size: 12GB work_mem: 62MB maintenance_work_mem: 1GB autovacuum_vacuum_cost_limit: "2400" random_page_cost: "1.1" effective_io_concurrency: "64" maintenance_io_concurrency: "64" pg_hba: - host all all all scram-sha-256 serviceAccountTemplate: metadata: annotations: azure.workload.identity/client-id: "$AKS_UAMI_WORKLOAD_CLIENTID" labels: azure.workload.identity/use: "true" backup: barmanObjectStore: destinationPath: "https://${PG_PRIMARY_STORAGE_ACCOUNT_NAME}.blob.core.chinacloudapi.cn/backups" azureCredentials: inheritFromAzureAD: true retentionPolicy: '7d' EOF
使用
kubectl get
命令验证是否已成功创建主要 PostgreSQL 群集。 CNPG 群集 CRD 指定了三个实例,可以在启动并加入每个实例进行复制后查看正在运行的 Pod 来验证。 请耐心等待,因为所有三个实例需要一些时间才能联机并加入群集。kubectl get pods --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME
示例输出
NAME READY STATUS RESTARTS AGE pg-primary-cnpg-r8c7unrw-1 1/1 Running 0 4m25s pg-primary-cnpg-r8c7unrw-2 1/1 Running 0 3m33s pg-primary-cnpg-r8c7unrw-3 1/1 Running 0 2m49s
验证 Prometheus PodMonitor 是否正在运行
CNPG 运算符使用在 Prometheus 社区安装期间创建的记录规则自动为主实例创建 PodMonitor。
使用
kubectl get
命令验证 PodMonitor 是否正在运行。kubectl --namespace $PG_NAMESPACE \ --context $AKS_PRIMARY_CLUSTER_NAME \ get podmonitors.monitoring.coreos.com \ $PG_PRIMARY_CLUSTER_NAME \ --output yaml
示例输出
kind: PodMonitor metadata: annotations: cnpg.io/operatorVersion: 1.23.1 ...
如果使用 Azure Monitor for Managed Prometheus,则需要使用自定义组名称添加另一个 Pod 监视器。 托管版 Prometheus 不会从 Prometheus 社区获取自定义资源定义(CRDs)。 除了组名外,CRD 是相同的。 这使得托管 Prometheus 的 Pod 监视器能够与使用社区 Pod 监视器的项并排存在。 如果不使用托管 Prometheus,可以跳过这一步。 创建新的 Pod 监视器:
cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -f -
apiVersion: azmonitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cnpg-cluster-metrics-managed-prometheus
namespace: ${PG_NAMESPACE}
labels:
azure.workload.identity/use: "true"
cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
spec:
selector:
matchLabels:
azure.workload.identity/use: "true"
cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
podMetricsEndpoints:
- port: metrics
EOF
验证是否已创建 Pod 监视器(请注意组名的差异)。
kubectl --namespace $PG_NAMESPACE \
--context $AKS_PRIMARY_CLUSTER_NAME \
get podmonitors.azmonitoring.coreos.com \
-l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME \
-o yaml
选项 A - Azure Monitor 工作区
部署 Postgres 群集和 Pod 监视器后,可以在 Azure Monitor 工作区中使用 Azure 门户查看指标。
选项 B - 托管 Grafana
或者,部署 Postgres 群集和 Pod 监视器后,可以在部署脚本创建的托管 Grafana 实例上创建指标仪表板,可视化导出到 Azure Monitor 工作区的指标。 可以通过 Azure 门户访问托管 Grafana。 导航到部署脚本创建的托管 Grafana 实例,然后选择端点链接,如下所示:
选择“终结点”链接将打开一个新的浏览器窗口,你可以在托管 Grafana 实例上创建仪表板。 按照说明配置 Azure Monitor 数据源,然后就可添加可视化效果,创建 Postgres 群集指标仪表板。 设置数据源连接后,从主菜单中选择“数据源”选项。 您应该能看到用于数据源连接的一组数据源选项,正如这里所示。
在“托管 Prometheus”选项上,选择“生成仪表板”选项以打开仪表板编辑器。 编辑器窗口打开后,选择“添加可视化效果”选项,然后选择“托管 Prometheus”选项以浏览 Postgres 群集中的指标。 选择要可视化的指标后,选择“运行查询”按钮以获取可视化效果的数据,如下所示:
选择“保存”图标,将面板添加到仪表板。 在仪表板编辑器中选择“添加”按钮后,可以添加其他面板,并通过重复此过程来可视化其他指标。 添加指标可视化效果后,应会显示如下所示的内容:
选择“保存”图标以保存仪表板。
后续步骤
供稿人
Microsoft 会维护本文。 本系列文章为以下参与者的原创作品:
- Ken Kilty | 首席 TPM
- Russell de Pina | 首席 TPM
- Adrian Joian | 高级客户工程师
- Jenny Hayes | 高级内容开发人员
- Carol Smith | 高级内容开发人员
- Erin Schaffer | 内容开发人员 2
- Adam Sharif | 客户工程师 2