迁移 Azure Function 到 Kubenetes
在 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 的定义中设置调度时间。