迁移 Azure Function 到 Kubenetes

2025-08-12#Kubenetes#Azure

在 Azure 上运行 Azure Function 和在 AKS 上运行存在显著差异。因此,如果可能,应该优先采用主流的 Web 框架(如 Express.js)来实现 HTTP API,或者使用 Kubernetes CronJob 实现定时任务。强烈不建议先开发 Azure Function 应用再迁移到 AKS,而是建议直接采用如 Express.js 这类主流框架进行 NodeJS 应用开发。

通用改动 🔗

以非 root 用户身份运行容器 🔗

作为一个安全实践,大部分的 Kubenetes 集群都不允许使用 root 用户运行容器。大多数现代的 Docker 镜像都内置了一个 UID 为 1000 的非 root 用户。如果没有,那么在 Dockerfile 中创建一个非 root 用户,并通过 USER 指令设置运行用户。

Linux 用户信息记录在 /etc/passwd 文件中。要检查镜像中是否有内置用户,可以启动容器并查看该文件的最后一行。例如:

docker run --it --rm --entrypoint /bin/sh <docker image> cat /etc/passwd

日志 🔗

Azure Function App 默认使用 Application Insights 进行日志记录。因此需要禁用它,并将日志打印到控制台,或者在应用代码中将日志写入第三方日志服务器。

在 host.json 中禁用 ApplicationInsights(将 isEnabled 设为 false):

{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": false,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}

HTTP API 🔗

使用非特权端口 🔗

Azure Function 应用默认监听 80 端口,这需要 root 权限。应将监听端口改为非特权端口(如 5000),可在 Dockerfile 设置环境变量 ASPNETCORE_URLS:

ENV ASPNETCORE_URLS="http://+:5000"

虽然环境变量名看似用于 ASP .NET 应用,但对于 NodeJS 应用同样适用。可能是因为运行时本身为 ASP .NET 应用。

认证 🔗

在 AKS 上运行 Function 时,无法复用 Azure 提供的认证机制,需自行实现认证。

简单场景下可以将静态 API Key 注入环境变量,通过函数校验请求头中的 API Key。例如使用如下的认证函数:

import { HttpRequest } from '@azure/functions'
const FUNCTION_KEY = process.env.FUNCTION_KEY;
export function validateFunctionKey(req: HttpRequest): boolean {
  const providedKey = req.headers.get("api-key");
  if (!FUNCTION_KEY) return false;
  return FUNCTION_KEY === providedKey;
}

注意事项:

  • 不要尝试从请求头 x-functions-key 获取 API Key,否则运行时会在函数处理前直接返回 500 错误。

定时任务 🔗

使用 Kubenetes 中的 CronJob 运行定时任务,并在 CronJob 的定义中设置调度时间。