在 Azure Kubernetes 上实现成本高效的微服务平台

发布: (2026年1月19日 GMT+8 12:39)
7 min read
原文: Dev.to

Source: Dev.to

在 AKS 上实现成本高效的微服务

Scope and Assumptions

This post assumes:

  • Familiarity with Kubernetes fundamentals
  • Comfort reading Terraform and Helm
  • Interest in operating systems, not just deploying them

The platform runs on Azure Kubernetes Service, provisioned with Terraform, and deployed using Helm.

1. AKS 基准:小规模起步,按需扩展

最常见的 AKS 成本错误是为峰值负载预配资源。
我们改为:

  • 从最小基线容量开始
  • 启用集群自动伸缩器
  • 让需求决定节点数量

带自动伸缩的 AKS 集群

resource "azurerm_kubernetes_cluster" "aks" {
  name                = var.cluster_name
  location            = var.location
  resource_group_name = var.resource_group_name
  dns_prefix          = var.cluster_name

  default_node_pool {
    name                 = "default"
    vm_size              = "Standard_D2s_v5"
    auto_scaling_enabled = true
    min_count            = 1
    max_count            = 10
  }

  identity {
    type = "SystemAssigned"
  }
}

为什么这样有效

  • 空闲成本保持低
  • 只有在 pod 等待时才会添加节点
  • 容量匹配实际需求,而非估算

2. 可预测行为的水平 Pod 自动伸缩

自动伸缩的默认设置过于激进且常常不稳定。
我们显式地调优伸缩行为,以降低抖动和延迟峰值。

带稳定性的 HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: api-service
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: api-service
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300

关键结果

  • 防止在短暂流量下降期间快速缩容
  • 改善尾部延迟
  • 减少不必要的 Pod 重启

3. Spot节点池用于容错工作负载

Spot容量是最高杠杆的成本优化手段之一——前提是正确隔离。

Terraform:Spot节点池

resource "azurerm_kubernetes_cluster_node_pool" "spot" {
  name                  = "spot"
  kubernetes_cluster_id = azurerm_kubernetes_cluster.aks.id
  vm_size               = "Standard_D2as_v5"

  priority        = "Spot"
  eviction_policy = "Delete"
  spot_max_price  = -1

  auto_scaling_enabled = true
  min_count            = 0
  max_count            = 10

  node_taints = [
    "kubernetes.azure.com/scalesetpriority=spot:NoSchedule"
  ]
}

在 Spot 节点上调度工作者

tolerations:
- key: "kubernetes.azure.com/scalesetpriority"
  operator: "Equal"
  value: "spot"
  effect: "NoSchedule"

nodeSelector:
  kubernetes.azure.com/scalesetpriority: spot

我们遵循的规则

  • API 永不在 Spot 上运行
  • 工作者能够干净地处理 SIGTERM
  • 所有状态都存放在工作者之外

以这种方式使用时,Spot 容量在不影响用户体验的前提下实现了显著的成本节约。

4. 使用私有网络的托管 PostgreSQL

Databases are not where cost experiments belong.
PostgreSQL runs as a managed service with:

  • 子网委派
  • 私有 DNS
  • 无公共访问

PostgreSQL 的委派子网

resource "azurerm_subnet" "postgres" {
  name                 = "postgres-subnet"
  virtual_network_name = azurerm_virtual_network.main.name
  resource_group_name  = var.resource_group_name
  address_prefixes     = ["10.0.2.0/24"]

  delegation {
    name = "postgres"
    service_delegation {
      name = "Microsoft.DBforPostgreSQL/flexibleServers"
    }
  }
}

这为何重要

  • 数据库无法从公共互联网访问
  • 访问在网络层受到限制
  • 运营风险显著降低

5. 使用 Helm 默认进行安全部署

Helm charts 在编写时采用了 安全默认 的假设。

Pod 安全上下文

securityContext:
  runAsUser: 1000
  runAsGroup: 1000
  allowPrivilegeEscalation: false
  readOnlyRootFilesystem: true

这会立即:

  • 减少攻击面
  • 防止运行时变更
  • 及早暴露不安全的镜像

关键健康探针

livenessProbe:
  httpGet:
    path: /health/db-cache
    port: 8080
  initialDelaySeconds: 60

我们有意检查 依赖关系,而不仅仅是进程健康。

6. 工作负载身份:在 Kubernetes 中不使用 Secrets

在 Kubernetes Secrets 中存储云凭证是没有必要的。
我们使用 Workload Identity 实现 pod 与 Azure 的身份验证。

联合身份凭证

resource "azurerm_federated_identity_credential" "api" {
  name       = "api-federated"
  parent_id  = azurerm_user_assigned_identity.api.id
  issuer     = azurerm_kubernetes_cluster.aks.oidc_issuer_url
  subject    = "system:serviceaccount:default:api"
  audiences  = ["api://AzureADTokenExchange"]
}

7. 观察性无需基于摄取的定价

而不是使用托管日志摄取,我们使用:

  • Prometheus 用于指标
  • Loki 用于日志
  • 对象存储 用于保留

Loki 存储配置

storage_config:
  azure:
    container_name: logs
    account_name: ${ACCOUNT_NAME}
    access_tier: Cool

为什么这样可行

  • 日志查询频率低
  • 存储成本低廉
  • 摄取成本在托管观察性定价中占主导

8. 基础设施访问模式(安全且实用)

集群访问

Azure AD‑支持的 kubectl

  • 可审计
  • 无共享凭证

在实践中,cluster‑admin 访问仅限于一个小的引导组;大多数团队使用命名空间范围的角色。

数据库访问(偶尔的管理员任务)

kubectl run psql \
  --image=postgres:16 \
  --rm -it -- \
  psql -h <private‑endpoint> -U admin

数据库保持私有;访问经过身份验证且可审计。

可观测性仪表盘

Grafana 通过 Azure AD 使用 OAuth 进行保护。
OAuth2‑Proxy 运行多个副本并轮换 cookie 密钥,以避免成为单点故障。

  • 无需 VPN
  • 无需堡垒主机
  • 无需额外的托管服务

Operational Lessons (The Real Ones)

  • Defaults Are Rarely Production‑Safe
    自动伸缩、探针和安全上下文需要显式调优。

  • Spot Capacity Requires Discipline
    它的效果非常好——但仅在隔离的情况下。

  • Identity Scales Better Than Secrets
    它降低了运维负载和安全风险。

  • Kubernetes Is a Tool, Not a Destination
    在它能提供杠杆作用的地方使用它——不要把它当作垃圾场。

结束思考

此实现并非关于巧妙的技巧——而是关于 有意的权衡

通过:

  • 仅在需要时进行扩展
  • 负责任地使用 Spot 容量
  • 保持关键状态的管理
  • 避免基于摄取的可观测性成本
  • 将安全视为默认

我们最终得到一个系统,它是:

  • 可预测的运行
  • 空闲时成本高效
  • 在负载下具备弹性
  • 易于演进

架构指明方向。
实现决定它是否能经受现实的考验。

Back to Blog

相关文章

阅读更多 »

Rapg:基于 TUI 的密钥管理器

我们都有这种经历。你加入一个新项目,首先听到的就是:“在 Slack 的置顶消息里查找 .env 文件”。或者你有多个 .env …

技术是赋能者,而非救世主

为什么思考的清晰度比你使用的工具更重要。Technology 常被视为一种魔法开关——只要打开,它就能让一切改善。新的 software,...

踏入 agentic coding

使用 Copilot Agent 的经验 我主要使用 GitHub Copilot 进行 inline edits 和 PR reviews,让我的大脑完成大部分思考。最近我决定 t...