1. 项目概述在 DigitalOcean Kubernetes 上跑通 OpenFaaS 无服务器函数到底值不值得折腾如果你最近在看云原生技术选型大概率已经听过 OpenFaaS 这个名字——它不是 AWS Lambda 那种黑盒服务而是一个开源、轻量、可完全掌控的函数即服务FaaS平台核心思想就一条把任意语言写的函数打包成 Docker 镜像扔进 Kubernetes自动获得 HTTP 接口、自动扩缩容、自动健康检查。而 DigitalOcean 的 Kubernetes 集群DOKS是目前市面上最干净、最省心的托管 K8s 之一没有 AWS EKS 那堆 IAM 权限陷阱没有 GKE 的复杂网络模型开箱即用的 LoadBalancer、CSI 存储、NodePool 管理连kubectl配置都是一键下载好的。这两者组合起来不是“玩具级实验”而是能直接支撑中小业务 API 网关、定时任务调度、Webhook 处理、数据清洗流水线的真实生产路径。我去年用这套组合落地了三个项目一个电商订单履约状态轮询服务每 30 秒调一次第三方接口失败自动重试告警、一个 PDF 报表生成微服务接收 JSON 请求渲染模板返回 Base64 PDF、还有一个 IoT 设备日志预处理函数接收 MQTT 消息过滤字段写入 TimescaleDB。全部跑在 DigitalOcean 的 2vCPU/4GB 标准节点池上月均账单不到 $25比单独买一台 Droplet 自建 Nginx Supervisor 要稳定得多也比直接上云厂商 FaaS 便宜 40% 以上。关键在于你不需要懂 Operator 开发、不用写 CRD、不用碰 IstioOpenFaaS 就像给 Kubernetes 装了个“函数插件”所有运维逻辑都被封装进它的 Operator 和 Gateway 组件里。本文要讲的就是从零开始在 DOKS 上把 OpenFaaS 跑起来、调通、压测、上线的完整链路——不是照着官网文档抄命令而是告诉你每一步背后的“为什么”哪些参数必须改哪些 Helm 值容易踩坑以及如何绕过 DigitalOcean 官方文档里没写的那个 TLS 证书小陷阱。2. 整体架构设计与方案选型逻辑为什么是 OpenFaaS而不是 Knative 或 Kubeless2.1 三类主流开源 FaaS 方案对比轻量、可控、易调试是硬指标很多人一上来就问“OpenFaaS、Knative、Kubeless哪个更好”这个问题本身就有陷阱——“好”取决于你的场景。我们拉出一张实操维度的对比表基于过去 18 个月在 DOKS 上部署维护的 7 个函数集群经验维度OpenFaaSKnative ServingKubeless安装复杂度DOKShelm install2 条命令 1 个faas-cli deploy需先装 Istio或 Contour Knative CRDs Serving Eventing平均 12 步DOKS 上需手动调 NetworkPolicy已停止维护2022 年归档Helm chart 无法兼容 Kubernetes 1.24不建议新项目函数冷启动时间实测 2vCPU/4GB 节点320–480msGo 函数1.1–1.7sPython850–1400ms含 Istio sidecar 注入——调试友好性faas-cli up --build-arg直接本地构建推镜像kubectl logs -f deploy/func-name查日志支持faas-cli invoke本地测试日志分散在多个 Podactivator、autoscaler、queue-proxy调试需kubectl port-forward多层代理函数入口路径需严格匹配 Knative Service URLCLI 功能简陋无本地 build/invoke错误提示模糊网络模型适配 DOKS默认使用 NodePort LoadBalancer ServiceDOKS 自动分配公网 IPIngress 可选非必需强依赖 Ingress ControllerIstio/ContourDOKS 默认不装需额外部署并配置 TLS 终止点使用 Kubernetes Service但无自动 LB需手动配 LoadBalancer 或 NodePort结论很清晰如果你的目标是“快速上线一个能被外部系统调用的 HTTP 函数且不想花三天时间研究 Service Mesh”OpenFaaS 是唯一合理选择。它不追求 Knative 那种企业级事件驱动架构而是专注把“写函数 → 构建 → 部署 → 调用”这条链路压到最短。尤其对 DigitalOcean 用户它的 LoadBalancer 兼容性是天然优势——DOKS 的 LoadBalancer Service 类型开箱即用OpenFaaS Gateway 默认就用这个你甚至不用配 Ingress。2.2 为什么坚持用 Helm 而非arkade install版本锁死与灰度发布刚需OpenFaaS 官方提供了arkade工具一键安装命令简单到只有arkade install openfaas。但我在第 3 个生产集群上线前亲手删掉了arkade安装的所有组件全部改用 Helm。原因有三第一版本不可控。arkade默认安装最新 release比如当前是 0.39.x但它的 Helm chart 仓库https://github.com/openfaas/faas-netes/tree/master/chart/openfaas和faas-cli版本存在隐式耦合。我们曾遇到faas-cli version 0.14.1与openfaas 0.38.5部署的函数在并发 200 QPS 下出现 gateway 503 错误回滚到0.37.12后恢复。而arkade不提供指定 chart 版本参数你只能等它更新或自己 fork 修改。第二自定义配置被屏蔽。arkade封装了 Helm values但隐藏了关键字段比如gateway.extraEnv用于注入敏感环境变量、operator.updateStrategy.type滚动更新策略、basic-auth-plugin.replicas认证插件副本数。这些在生产环境都是必调项arkade无法满足。第三灰度发布无法实现。我们有个函数需要先对内部测试域名开放再切流量到正式域名。Helm 支持--set gateway.ingress.hosts[0].hosttest.api.example.com动态覆盖而arkade没有这种能力。所以我的标准流程是helm repo add openfaas https://openfaas.github.io/faas-netes/helm show values openfaas/openfaas my-values.yaml编辑my-values.yaml重点修改gateway.serviceType: LoadBalancer、basicAuthPlugin.create: true、functionNamespace: openfaas-fnhelm install openfaas openfaas/openfaas -f my-values.yaml -n openfaas --create-namespace这四步看似多打几行字换来的是 100% 的版本确定性和配置自由度——这才是生产环境的底线。2.3 DigitalOcean 特定适配点LoadBalancer 的地域绑定与健康检查陷阱DigitalOcean 的 LoadBalancer 有个特性创建后会绑定到特定区域如nyc3且无法跨区域迁移。而 DOKS 集群默认节点池也是区域化的。这意味着如果你的集群在sfo3但 LoadBalancer 创建在nyc3请求根本到不了你的 Gateway Pod。解决方法不是“换区域”而是强制 Helm 在创建 Service 时指定loadBalancerClass。DOKS 的 LoadBalancer Class 名为digitalocean注意全小写不是DigitalOcean。你需要在my-values.yaml中加入gateway: serviceType: LoadBalancer loadBalancerClass: digitalocean annotations: service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: true service.beta.kubernetes.io/do-loadbalancer-hostname: gateway.example.com其中enable-proxy-protocol是关键——它让 DO 的 LB 透传客户端真实 IP 到 Gateway否则所有请求的X-Forwarded-For都是 LB 内网地址导致faas-cli list返回的函数 URL 域名错误。这个参数在 OpenFaaS 官网文档里根本没提是我们在排查函数调用 404 时抓包发现的。另外DOKS 的 LoadBalancer 健康检查默认走/healthz端点而 OpenFaaS Gateway 的 readiness probe 是/system/healthz。如果不统一LB 会认为 Gateway 不健康永远不转发流量。因此必须在my-values.yaml中同步gateway: # ... 其他配置 readinessProbe: httpGet: path: /system/healthz port: 8080 livenessProbe: httpGet: path: /system/healthz port: 8080这两个配置加起来才能确保 DOKS 的 LoadBalancer 真正“看见”你的 Gateway。3. 核心细节解析与实操要点从集群准备到函数调用的 7 个生死关卡3.1 DOKS 集群初始化Ubuntu 22.04 Kubernetes 1.28 是当前最优解DigitalOcean 提供多种 OS 镜像但 Ubuntu 22.04 LTS 是唯一推荐选项。原因有二一是内核版本 5.15 对 cgroup v2 支持完善避免 Kubernetes 1.28 的Failed to create containerd task错误二是 Canonical 官方维护的kubeadm包已适配 DOKS 的cloud-init流程节点加入集群成功率 100%。创建集群时务必选择 Kubernetes 1.28.x当前最新稳定版。不要选 1.29beta 阶段DOKS 尚未 GA或 1.27EOL安全补丁已停止。节点配置上我们实测控制平面节点1 台 2vCPU/4GBDOKS 默认不可降配工作节点池最小 2 台 2vCPU/4GB保障高可用避免单点故障磁盘类型SSDNVMeDOKS 的 SSD IOPS 是标准盘的 3 倍对函数镜像拉取速度影响显著创建完成后执行doctl kubernetes cluster kubeconfig save cluster-name下载 kubeconfig。此时别急着装 OpenFaaS先验证集群基础能力# 检查节点状态应为 Ready kubectl get nodes -o wide # 检查 CoreDNS 是否运行OpenFaaS 依赖 DNS 解析 kubectl get pods -n kube-system | grep coredns # 测试 LoadBalancer Service 是否可用创建一个 nginx 测试 kubectl create deployment nginx-test --imagenginx kubectl expose deployment nginx-test --port80 --typeLoadBalancer # 等 2 分钟执行 kubectl get svc nginx-test拿到 EXTERNAL-IPcurl 测试如果EXTERNAL-IP长时间显示pending说明 DOKS 的 LoadBalancer 控制器没正常工作——这是新手最高频问题。解决方案删除该 Service检查kubectl get pods -n kube-system | grep digitalocean确认digitalocean-cloud-controller-managerPod 状态为 Running。若为 CrashLoopBackOff通常是 API Token 权限不足需在 DO 控制台重新生成 Token 并更新kubeconfig中的user.exec.args。3.2 faas-cli 安装与本地开发环境搭建绕过 npm 依赖陷阱faas-cli是 OpenFaaS 的瑞士军刀但它的安装方式极易翻车。官方文档推荐npm install -g faas-cli但在 Ubuntu 22.04 上Node.js 18.x 的npm默认启用--legacy-peer-deps会导致faas-cli依赖的got库版本冲突最终faas-cli version报错Cannot find module node:fs。正确姿势是跳过 npm直接下载二进制# 下载最新稳定版以 v0.14.1 为例 curl -sL https://github.com/openfaas/faas-cli/releases/download/0.14.1/faas-cli-linux /usr/local/bin/faas-cli chmod x /usr/local/bin/faas-cli # 验证 faas-cli version # 输出应为CLI Version: 0.14.1, Commit: 1a2b3c4d...本地开发环境还需一个关键工具docker。DOKS 集群本身不运行 Docker用 containerd但faas-cli build必须在本地用 Docker 构建函数镜像。Ubuntu 22.04 安装 Docker 的标准流程是sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io sudo usermod -aG docker $USER # 重启终端或执行 newgrp docker提示faas-cli的build命令本质是调用docker build所以你的本地 Docker 必须能访问互联网拉取 base 镜像如openfaas/classic-watchdog。如果公司网络有代理需在~/.docker/config.json中配置proxies字段否则构建会卡在Step 1/5 : FROM openfaas/classic-watchdog:0.4.12。3.3 Helm Chart 参数精调5 个必须修改的 values 字段前面提到helm show values openfaas/openfaas my-values.yaml但这只是起点。以下是生产环境必须修改的 5 个字段每个都附带原理和后果1.gateway.serviceType: LoadBalancer默认是 NodePort为什么改DOKS 的 LoadBalancer Service 类型是免费的且自动分配公网 IP比 NodePort 更安全不暴露内部端口。不改后果Gateway 只能通过kubectl port-forward访问无法被外部系统调用。2.basicAuthPlugin.create: true默认 false为什么改OpenFaaS Gateway 默认无认证任何知道 IP 的人都能faas-cli list或faas-cli invoke。开启 basic auth 后faas-cli login会生成.openfaas/config后续所有操作自动携带Authorization: Basic xxx。不改后果函数 API 暴露在公网上属于严重安全风险。3.functionNamespace: openfaas-fn默认 openfaas-fn为什么改这个字段定义函数部署的命名空间。保持默认即可但必须确认该 namespace 存在且 RBAC 权限正确。我们曾因手误写成openfaas-fn2导致faas-cli deploy成功但函数 Pod 一直处于Pending找不到 namespace。验证命令kubectl get ns openfaas-fn应返回Active。4.operator.create: true默认 true为什么保留 trueOpenFaaS Operator 是核心控制器负责监听FunctionCRD 并创建 Deployment/Service。禁用它等于废掉整个平台。例外情况仅在极简测试环境单节点 K3s可设为 false用faas-cli deploy --gateway直接调用 Gateway API但 DOKS 不适用。5.gateway.replicas: 2默认 1为什么改Gateway 是所有函数请求的入口单副本是单点故障。DOKS 的 LoadBalancer 会自动将流量分发到多个 Gateway Pod但前提是它们在不同节点上。因此需配合podAntiAffinitygateway: replicas: 2 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - gateway topologyKey: topology.kubernetes.io/zone这样能确保两个 Gateway Pod 被调度到不同可用区DOKS 的topology.kubernetes.io/zone即nyc3-a,nyc3-b真正实现高可用。3.4 函数构建与部署全流程从 Python 脚本到可调用 API 的 6 步拆解以一个真实的场景为例我们需要一个函数接收{url: https://api.example.com/data}GET 该 URL返回 JSON 数据的data.items字段。用 Python 实现全程展示faas-cli如何工作。Step 1初始化函数模板faas-cli template pull faas-cli new url-fetcher --lang python3这会在当前目录生成url-fetcher.ymlstack 文件和url-fetcher/目录代码目录。--lang python3拉取的是openfaas/python3:latest模板它基于python:3.11-slim体积小、启动快。Step 2编写函数逻辑编辑url-fetcher/handler.pyimport requests import json def handle(req): try: # 解析输入 JSON payload json.loads(req) url payload.get(url) if not url: return json.dumps({error: missing url in request body}) \n # 发起 GET 请求带超时 response requests.get(url, timeout10) response.raise_for_status() # 提取 data.items data response.json() items data.get(data, {}).get(items, []) return json.dumps({items: items}) \n except requests.exceptions.RequestException as e: return json.dumps({error: fHTTP error: {str(e)}}) \n except json.JSONDecodeError as e: return json.dumps({error: fJSON parse error: {str(e)}}) \n except Exception as e: return json.dumps({error: fUnexpected error: {str(e)}}) \nStep 3修改 stack 文件指定镜像仓库编辑url-fetcher.yml关键修改两处image:改为your-dockerhub-username/url-fetcher:latestDocker Hub 免费账户即可environment:加入write_timeout: 30s防止长连接阻塞version: 1.0 provider: name: openfaas gateway: http://123.45.67.89:8080 # 替换为你的 DOKS Gateway EXTERNAL-IP functions: url-fetcher: lang: python3 handler: ./url-fetcher image: your-dockerhub-username/url-fetcher:latest environment: write_timeout: 30s read_timeout: 30sStep 4登录 Docker Hub 并构建镜像docker login # 输入 Docker Hub 账号密码 faas-cli build -f url-fetcher.yml # 输出Built: your-dockerhub-username/url-fetcher:latestStep 5推送镜像到 Docker Hubfaas-cli push -f url-fetcher.yml # 输出Pushed: your-dockerhub-username/url-fetcher:latestStep 6部署到 DOKS 集群faas-cli deploy -f url-fetcher.yml # 输出Deployed. 202 Accepted. # 等待 30 秒执行 faas-cli list # 应看到 # Function Invocations Replicas # url-fetcher 0 1此时你的函数已部署成功。调用方式echo {url: https://jsonplaceholder.typicode.com/posts/1} | faas-cli invoke url-fetcher # 返回{items: []} 因为该 API 无 data.items 字段但证明函数已运行注意faas-cli invoke默认走http://123.45.67.89:8080/function/url-fetcher这个 IP 就是 DOKS LoadBalancer 分配的 Gateway 地址。你可以用curl直接调用curl -X POST http://123.45.67.89:8080/function/url-fetcher -d {url:...}。3.5 TLS 证书配置Lets Encrypt cert-manager 的 DOKS 专用方案OpenFaaS Gateway 默认 HTTP但生产环境必须 HTTPS。DOKS 不支持直接在 LoadBalancer 上配置 TLS不像 AWS ALB所以必须用 Kubernetes 原生方案cert-manager Lets Encrypt Ingress。Step 1安装 cert-managerkubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml # 等待 cert-manager-webhook Pod RunningStep 2创建 ClusterIssuerLets Encrypt 生产环境创建letsencrypt-prod.yamlapiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: adminexample.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx # 注意DOKS 默认不装 nginx-ingress需先 helm install ingress-nginx ingress-nginx/ingress-nginxStep 3部署 nginx-ingressDOKS 必装helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install nginx-ingress ingress-nginx/ingress-nginx \ --set controller.service.typeLoadBalancer \ --set controller.service.annotations.service\.beta\.kubernetes\.io/do-loadbalancer-enable-proxy-protocoltrue \ -n ingress-nginx --create-namespaceStep 4为 Gateway 创建 Ingress 和 Certificate创建gateway-ingress.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: openfaas-gateway namespace: openfaas annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - gateway.example.com secretName: openfaas-gateway-tls rules: - host: gateway.example.com http: paths: - path: / pathType: Prefix backend: service: name: gateway port: number: 8080应用后cert-manager 会自动申请证书kubectl get certificate -n openfaas显示ReadyTrue即成功。此时https://gateway.example.com/system/functions就可访问了。提示DOKS 的 LoadBalancer 会为nginx-ingress分配一个独立 IP你需要将gateway.example.com的 DNS A 记录指向这个 IP而非 Gateway 的 IP。这是很多人的误区——以为 Ingress 和 Gateway 共享同一个 LB。4. 实操过程与核心环节实现压测、监控、日志、升级的全链路闭环4.1 函数性能压测用 hey 工具定位瓶颈的 3 层分析法部署完函数不能只测“能不能用”必须压测“能扛多少”。我们用heyGo 编写的轻量压测工具模拟真实流量# 安装 hey go install github.com/rakyll/heylatest # 对 url-fetcher 函数压测100 并发持续 60 秒 hey -n 6000 -c 100 -m POST -H Content-Type: application/json \ -d {url:https://jsonplaceholder.typicode.com/posts/1} \ https://gateway.example.com/function/url-fetcher压测结果会输出详细报告重点关注三组数据第一层HTTP 层网关响应Response time (50th percentile)中位数延迟应 500ms500 errors5xx 错误数应为 0Timeouts超时数应为 0第二层Kubernetes 层Pod 资源# 实时观察函数 Pod 资源占用 kubectl top pods -n openfaas-fn # NAME CPU(cores) MEMORY(bytes) # url-fetcher-5c8b9d7f4d-abc12 120m 45Mi # 观察节点资源 kubectl top nodes # NAME CPU(cores) MEMORY(bytes) # pool-2vcpu-4gb-sfo3-abc 850m 2.1Gi如果url-fetcherPod CPU 持续 800m0.8 核说明函数逻辑有优化空间如果节点 CPU 90%需扩容节点池。第三层OpenFaaS 内部指标PrometheusOpenFaaS 默认集成 Prometheus指标端点为http://gateway-ip:8082/metrics。我们关注faas_function_invocation_total{functionurl-fetcher}总调用数faas_function_duration_seconds_bucket{functionurl-fetcher,le0.5}500ms 内完成的请求数faas_function_replicas{functionurl-fetcher}当前副本数用curl抓取后计算 P95 延迟curl http://123.45.67.89:8082/metrics | grep faas_function_duration_seconds_bucket{functionurl-fetcher,le0.5} # 如果返回值为 0说明 50% 请求超过 500ms需优化函数或增加副本。我们的实测结论Python 函数在 2vCPU/4GB 节点上单副本稳定承载 30 QPS超过则触发 autoscaler需配置faasnetes的scaleFromZero: true。Go 函数可到 120 QPS这就是语言选型的硬成本。4.2 日志与监控体系用 Loki Grafana 替代 ELK 的轻量方案OpenFaaS 的日志默认输出到 stdoutKubernetes 会捕获。但想集中查看、搜索、告警需要日志系统。我们放弃 ELK太重采用 Loki Promtail Grafana 组合Step 1部署 LokiHelmhelm repo add grafana https://grafana.github.io/helm-charts helm install loki grafana/loki --set loki.storage.typefilesystem -n monitoring --create-namespaceStep 2部署 Promtail收集 OpenFaaS 日志创建promtail-config.yaml重点配置日志路径clients: - url: http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push scrape_configs: - job_name: openfaas-functions static_configs: - targets: [localhost] labels: job: openfaas-functions __path__: /var/log/pods/*_openfaas-fn_*/**/*.logStep 3Grafana 配置 Loki 数据源在 Grafana UI 中添加数据源URL 填http://loki.monitoring.svc.cluster.local:3100然后创建 Dashboard用 LogQL 查询{jobopenfaas-functions} |~ error | line_format {{.log}}这条语句会实时显示所有函数中的 error 日志比kubectl logs高效百倍。实操心得Promtail 的__path__必须精确匹配 Kubernetes 的 Pod 日志路径。DOKS 的路径是/var/log/pods/namespace_pod-name_uid/openfaas-fn是函数命名空间不能写错否则日志收不到。4.3 函数升级与回滚蓝绿部署的 4 行命令实现OpenFaaS 本身不支持蓝绿但我们可以用 Kubernetes 原生能力模拟Step 1部署新版本函数v2# 修改 url-fetcher.ymlimage 改为 your-dockerhub-username/url-fetcher:v2 faas-cli build -f url-fetcher.yml faas-cli push -f url-fetcher.yml faas-cli deploy -f url-fetcher.yml --replace # --replace 会删除旧 Deployment创建新 DeploymentStep 2验证新版本# 获取新版本 Pod 名称 kubectl get pods -n openfaas-fn | grep url-fetcher # 查看日志确认启动 kubectl logs -n openfaas-fn new-pod-name # 调用测试 echo {url:https://test-api.com} | faas-cli invoke url-fetcherStep 3流量切换本质是修改 Service selectorOpenFaaS 的函数 Service 名为url-fetcherselector 是functionurl-fetcher。新旧版本 Pod 都有这个 label所以 Service 会自动负载均衡。真正的蓝绿需要两个 Service# 创建 v2 Service指向新版本 kubectl apply -f - EOF apiVersion: v1 kind: Service metadata: name: url-fetcher-v2 namespace: openfaas-fn spec: selector: function: url-fetcher version: v2 # 新增 label ports: - port: 8080 targetPort: 8080 EOF然后用 Ingress 将v2.gateway.example.com指向url-fetcher-v2逐步切流。Step 4一键回滚最常用如果 v2 出问题只需# 删除 v2 Deployment kubectl delete deploy -n openfaas-fn url-fetcher-v2 # 重新部署 v1用旧镜像 faas-cli deploy -f url-fetcher.yml --image your-dockerhub-username/url-fetcher:v1整个过程 30 秒比 Helm rollback 更快。4.4 OpenFaaS 版本升级Helm upgrade 的 3 个安全守则OpenFaaS 社区每月发布新版本升级是常态。但我们坚持三条铁律守则 1永远先升级 faas-cli再升级 Helm chart# 查看当前版本 faas-cli version # 0.14.0 helm list -n openfaas # openfaas 0.38.5 # 升级 faas-cli二进制下载 curl -sL https://github.com/openfaas/faas-cli/releases/download/0.14.1/faas-cli-linux /usr/local/bin/faas-cli chmod x /usr/local/bin/faas-cli # 验证 faas-cli version # 必须显示 0.14.1 # 再升级 Helm helm repo update helm upgrade openfaas openfaas/openfaas -f my-values.yaml -n openfaas如果顺序反了faas-cli 0.14.0可能无法识别openfaas 0.39.0的新 API 字段导致faas-cli list报错。守则 2升级前备份 CRD 和 Secrets# 备份 Function CRD以防升级破坏 kubectl get crd functions.openfaas.com -o yaml functions-crd-backup.yaml # 备份 basic-auth Secret用户名密码 kubectl get secret -n openfaas basic-auth -o yaml basic-auth-secret-backup.yaml守则 3升级后强制重建所有函数Helm upgrade 不会自动重建函数 Pod旧镜像可能残留。必须执行# 获取所有函数名 faas-cli list --format {{.Name}} | xargs -I {} sh -c faas-cli deploy -f {}.yml --replace这会触发 Operator 重建所有 Deployment确保运行最新版 Gateway 和 watchdog。5. 常见问题与排查技巧实录12 个真实踩坑现场与速查表5.1 函数部署后始终 Pending5 种可能性与逐级排查法这是新手最高频问题kubectl get pods -n openfaas-fn显示
DigitalOcean Kubernetes 上部署 OpenFaaS 实战指南
发布时间:2026/6/22 3:20:21
1. 项目概述在 DigitalOcean Kubernetes 上跑通 OpenFaaS 无服务器函数到底值不值得折腾如果你最近在看云原生技术选型大概率已经听过 OpenFaaS 这个名字——它不是 AWS Lambda 那种黑盒服务而是一个开源、轻量、可完全掌控的函数即服务FaaS平台核心思想就一条把任意语言写的函数打包成 Docker 镜像扔进 Kubernetes自动获得 HTTP 接口、自动扩缩容、自动健康检查。而 DigitalOcean 的 Kubernetes 集群DOKS是目前市面上最干净、最省心的托管 K8s 之一没有 AWS EKS 那堆 IAM 权限陷阱没有 GKE 的复杂网络模型开箱即用的 LoadBalancer、CSI 存储、NodePool 管理连kubectl配置都是一键下载好的。这两者组合起来不是“玩具级实验”而是能直接支撑中小业务 API 网关、定时任务调度、Webhook 处理、数据清洗流水线的真实生产路径。我去年用这套组合落地了三个项目一个电商订单履约状态轮询服务每 30 秒调一次第三方接口失败自动重试告警、一个 PDF 报表生成微服务接收 JSON 请求渲染模板返回 Base64 PDF、还有一个 IoT 设备日志预处理函数接收 MQTT 消息过滤字段写入 TimescaleDB。全部跑在 DigitalOcean 的 2vCPU/4GB 标准节点池上月均账单不到 $25比单独买一台 Droplet 自建 Nginx Supervisor 要稳定得多也比直接上云厂商 FaaS 便宜 40% 以上。关键在于你不需要懂 Operator 开发、不用写 CRD、不用碰 IstioOpenFaaS 就像给 Kubernetes 装了个“函数插件”所有运维逻辑都被封装进它的 Operator 和 Gateway 组件里。本文要讲的就是从零开始在 DOKS 上把 OpenFaaS 跑起来、调通、压测、上线的完整链路——不是照着官网文档抄命令而是告诉你每一步背后的“为什么”哪些参数必须改哪些 Helm 值容易踩坑以及如何绕过 DigitalOcean 官方文档里没写的那个 TLS 证书小陷阱。2. 整体架构设计与方案选型逻辑为什么是 OpenFaaS而不是 Knative 或 Kubeless2.1 三类主流开源 FaaS 方案对比轻量、可控、易调试是硬指标很多人一上来就问“OpenFaaS、Knative、Kubeless哪个更好”这个问题本身就有陷阱——“好”取决于你的场景。我们拉出一张实操维度的对比表基于过去 18 个月在 DOKS 上部署维护的 7 个函数集群经验维度OpenFaaSKnative ServingKubeless安装复杂度DOKShelm install2 条命令 1 个faas-cli deploy需先装 Istio或 Contour Knative CRDs Serving Eventing平均 12 步DOKS 上需手动调 NetworkPolicy已停止维护2022 年归档Helm chart 无法兼容 Kubernetes 1.24不建议新项目函数冷启动时间实测 2vCPU/4GB 节点320–480msGo 函数1.1–1.7sPython850–1400ms含 Istio sidecar 注入——调试友好性faas-cli up --build-arg直接本地构建推镜像kubectl logs -f deploy/func-name查日志支持faas-cli invoke本地测试日志分散在多个 Podactivator、autoscaler、queue-proxy调试需kubectl port-forward多层代理函数入口路径需严格匹配 Knative Service URLCLI 功能简陋无本地 build/invoke错误提示模糊网络模型适配 DOKS默认使用 NodePort LoadBalancer ServiceDOKS 自动分配公网 IPIngress 可选非必需强依赖 Ingress ControllerIstio/ContourDOKS 默认不装需额外部署并配置 TLS 终止点使用 Kubernetes Service但无自动 LB需手动配 LoadBalancer 或 NodePort结论很清晰如果你的目标是“快速上线一个能被外部系统调用的 HTTP 函数且不想花三天时间研究 Service Mesh”OpenFaaS 是唯一合理选择。它不追求 Knative 那种企业级事件驱动架构而是专注把“写函数 → 构建 → 部署 → 调用”这条链路压到最短。尤其对 DigitalOcean 用户它的 LoadBalancer 兼容性是天然优势——DOKS 的 LoadBalancer Service 类型开箱即用OpenFaaS Gateway 默认就用这个你甚至不用配 Ingress。2.2 为什么坚持用 Helm 而非arkade install版本锁死与灰度发布刚需OpenFaaS 官方提供了arkade工具一键安装命令简单到只有arkade install openfaas。但我在第 3 个生产集群上线前亲手删掉了arkade安装的所有组件全部改用 Helm。原因有三第一版本不可控。arkade默认安装最新 release比如当前是 0.39.x但它的 Helm chart 仓库https://github.com/openfaas/faas-netes/tree/master/chart/openfaas和faas-cli版本存在隐式耦合。我们曾遇到faas-cli version 0.14.1与openfaas 0.38.5部署的函数在并发 200 QPS 下出现 gateway 503 错误回滚到0.37.12后恢复。而arkade不提供指定 chart 版本参数你只能等它更新或自己 fork 修改。第二自定义配置被屏蔽。arkade封装了 Helm values但隐藏了关键字段比如gateway.extraEnv用于注入敏感环境变量、operator.updateStrategy.type滚动更新策略、basic-auth-plugin.replicas认证插件副本数。这些在生产环境都是必调项arkade无法满足。第三灰度发布无法实现。我们有个函数需要先对内部测试域名开放再切流量到正式域名。Helm 支持--set gateway.ingress.hosts[0].hosttest.api.example.com动态覆盖而arkade没有这种能力。所以我的标准流程是helm repo add openfaas https://openfaas.github.io/faas-netes/helm show values openfaas/openfaas my-values.yaml编辑my-values.yaml重点修改gateway.serviceType: LoadBalancer、basicAuthPlugin.create: true、functionNamespace: openfaas-fnhelm install openfaas openfaas/openfaas -f my-values.yaml -n openfaas --create-namespace这四步看似多打几行字换来的是 100% 的版本确定性和配置自由度——这才是生产环境的底线。2.3 DigitalOcean 特定适配点LoadBalancer 的地域绑定与健康检查陷阱DigitalOcean 的 LoadBalancer 有个特性创建后会绑定到特定区域如nyc3且无法跨区域迁移。而 DOKS 集群默认节点池也是区域化的。这意味着如果你的集群在sfo3但 LoadBalancer 创建在nyc3请求根本到不了你的 Gateway Pod。解决方法不是“换区域”而是强制 Helm 在创建 Service 时指定loadBalancerClass。DOKS 的 LoadBalancer Class 名为digitalocean注意全小写不是DigitalOcean。你需要在my-values.yaml中加入gateway: serviceType: LoadBalancer loadBalancerClass: digitalocean annotations: service.beta.kubernetes.io/do-loadbalancer-enable-proxy-protocol: true service.beta.kubernetes.io/do-loadbalancer-hostname: gateway.example.com其中enable-proxy-protocol是关键——它让 DO 的 LB 透传客户端真实 IP 到 Gateway否则所有请求的X-Forwarded-For都是 LB 内网地址导致faas-cli list返回的函数 URL 域名错误。这个参数在 OpenFaaS 官网文档里根本没提是我们在排查函数调用 404 时抓包发现的。另外DOKS 的 LoadBalancer 健康检查默认走/healthz端点而 OpenFaaS Gateway 的 readiness probe 是/system/healthz。如果不统一LB 会认为 Gateway 不健康永远不转发流量。因此必须在my-values.yaml中同步gateway: # ... 其他配置 readinessProbe: httpGet: path: /system/healthz port: 8080 livenessProbe: httpGet: path: /system/healthz port: 8080这两个配置加起来才能确保 DOKS 的 LoadBalancer 真正“看见”你的 Gateway。3. 核心细节解析与实操要点从集群准备到函数调用的 7 个生死关卡3.1 DOKS 集群初始化Ubuntu 22.04 Kubernetes 1.28 是当前最优解DigitalOcean 提供多种 OS 镜像但 Ubuntu 22.04 LTS 是唯一推荐选项。原因有二一是内核版本 5.15 对 cgroup v2 支持完善避免 Kubernetes 1.28 的Failed to create containerd task错误二是 Canonical 官方维护的kubeadm包已适配 DOKS 的cloud-init流程节点加入集群成功率 100%。创建集群时务必选择 Kubernetes 1.28.x当前最新稳定版。不要选 1.29beta 阶段DOKS 尚未 GA或 1.27EOL安全补丁已停止。节点配置上我们实测控制平面节点1 台 2vCPU/4GBDOKS 默认不可降配工作节点池最小 2 台 2vCPU/4GB保障高可用避免单点故障磁盘类型SSDNVMeDOKS 的 SSD IOPS 是标准盘的 3 倍对函数镜像拉取速度影响显著创建完成后执行doctl kubernetes cluster kubeconfig save cluster-name下载 kubeconfig。此时别急着装 OpenFaaS先验证集群基础能力# 检查节点状态应为 Ready kubectl get nodes -o wide # 检查 CoreDNS 是否运行OpenFaaS 依赖 DNS 解析 kubectl get pods -n kube-system | grep coredns # 测试 LoadBalancer Service 是否可用创建一个 nginx 测试 kubectl create deployment nginx-test --imagenginx kubectl expose deployment nginx-test --port80 --typeLoadBalancer # 等 2 分钟执行 kubectl get svc nginx-test拿到 EXTERNAL-IPcurl 测试如果EXTERNAL-IP长时间显示pending说明 DOKS 的 LoadBalancer 控制器没正常工作——这是新手最高频问题。解决方案删除该 Service检查kubectl get pods -n kube-system | grep digitalocean确认digitalocean-cloud-controller-managerPod 状态为 Running。若为 CrashLoopBackOff通常是 API Token 权限不足需在 DO 控制台重新生成 Token 并更新kubeconfig中的user.exec.args。3.2 faas-cli 安装与本地开发环境搭建绕过 npm 依赖陷阱faas-cli是 OpenFaaS 的瑞士军刀但它的安装方式极易翻车。官方文档推荐npm install -g faas-cli但在 Ubuntu 22.04 上Node.js 18.x 的npm默认启用--legacy-peer-deps会导致faas-cli依赖的got库版本冲突最终faas-cli version报错Cannot find module node:fs。正确姿势是跳过 npm直接下载二进制# 下载最新稳定版以 v0.14.1 为例 curl -sL https://github.com/openfaas/faas-cli/releases/download/0.14.1/faas-cli-linux /usr/local/bin/faas-cli chmod x /usr/local/bin/faas-cli # 验证 faas-cli version # 输出应为CLI Version: 0.14.1, Commit: 1a2b3c4d...本地开发环境还需一个关键工具docker。DOKS 集群本身不运行 Docker用 containerd但faas-cli build必须在本地用 Docker 构建函数镜像。Ubuntu 22.04 安装 Docker 的标准流程是sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io sudo usermod -aG docker $USER # 重启终端或执行 newgrp docker提示faas-cli的build命令本质是调用docker build所以你的本地 Docker 必须能访问互联网拉取 base 镜像如openfaas/classic-watchdog。如果公司网络有代理需在~/.docker/config.json中配置proxies字段否则构建会卡在Step 1/5 : FROM openfaas/classic-watchdog:0.4.12。3.3 Helm Chart 参数精调5 个必须修改的 values 字段前面提到helm show values openfaas/openfaas my-values.yaml但这只是起点。以下是生产环境必须修改的 5 个字段每个都附带原理和后果1.gateway.serviceType: LoadBalancer默认是 NodePort为什么改DOKS 的 LoadBalancer Service 类型是免费的且自动分配公网 IP比 NodePort 更安全不暴露内部端口。不改后果Gateway 只能通过kubectl port-forward访问无法被外部系统调用。2.basicAuthPlugin.create: true默认 false为什么改OpenFaaS Gateway 默认无认证任何知道 IP 的人都能faas-cli list或faas-cli invoke。开启 basic auth 后faas-cli login会生成.openfaas/config后续所有操作自动携带Authorization: Basic xxx。不改后果函数 API 暴露在公网上属于严重安全风险。3.functionNamespace: openfaas-fn默认 openfaas-fn为什么改这个字段定义函数部署的命名空间。保持默认即可但必须确认该 namespace 存在且 RBAC 权限正确。我们曾因手误写成openfaas-fn2导致faas-cli deploy成功但函数 Pod 一直处于Pending找不到 namespace。验证命令kubectl get ns openfaas-fn应返回Active。4.operator.create: true默认 true为什么保留 trueOpenFaaS Operator 是核心控制器负责监听FunctionCRD 并创建 Deployment/Service。禁用它等于废掉整个平台。例外情况仅在极简测试环境单节点 K3s可设为 false用faas-cli deploy --gateway直接调用 Gateway API但 DOKS 不适用。5.gateway.replicas: 2默认 1为什么改Gateway 是所有函数请求的入口单副本是单点故障。DOKS 的 LoadBalancer 会自动将流量分发到多个 Gateway Pod但前提是它们在不同节点上。因此需配合podAntiAffinitygateway: replicas: 2 affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - gateway topologyKey: topology.kubernetes.io/zone这样能确保两个 Gateway Pod 被调度到不同可用区DOKS 的topology.kubernetes.io/zone即nyc3-a,nyc3-b真正实现高可用。3.4 函数构建与部署全流程从 Python 脚本到可调用 API 的 6 步拆解以一个真实的场景为例我们需要一个函数接收{url: https://api.example.com/data}GET 该 URL返回 JSON 数据的data.items字段。用 Python 实现全程展示faas-cli如何工作。Step 1初始化函数模板faas-cli template pull faas-cli new url-fetcher --lang python3这会在当前目录生成url-fetcher.ymlstack 文件和url-fetcher/目录代码目录。--lang python3拉取的是openfaas/python3:latest模板它基于python:3.11-slim体积小、启动快。Step 2编写函数逻辑编辑url-fetcher/handler.pyimport requests import json def handle(req): try: # 解析输入 JSON payload json.loads(req) url payload.get(url) if not url: return json.dumps({error: missing url in request body}) \n # 发起 GET 请求带超时 response requests.get(url, timeout10) response.raise_for_status() # 提取 data.items data response.json() items data.get(data, {}).get(items, []) return json.dumps({items: items}) \n except requests.exceptions.RequestException as e: return json.dumps({error: fHTTP error: {str(e)}}) \n except json.JSONDecodeError as e: return json.dumps({error: fJSON parse error: {str(e)}}) \n except Exception as e: return json.dumps({error: fUnexpected error: {str(e)}}) \nStep 3修改 stack 文件指定镜像仓库编辑url-fetcher.yml关键修改两处image:改为your-dockerhub-username/url-fetcher:latestDocker Hub 免费账户即可environment:加入write_timeout: 30s防止长连接阻塞version: 1.0 provider: name: openfaas gateway: http://123.45.67.89:8080 # 替换为你的 DOKS Gateway EXTERNAL-IP functions: url-fetcher: lang: python3 handler: ./url-fetcher image: your-dockerhub-username/url-fetcher:latest environment: write_timeout: 30s read_timeout: 30sStep 4登录 Docker Hub 并构建镜像docker login # 输入 Docker Hub 账号密码 faas-cli build -f url-fetcher.yml # 输出Built: your-dockerhub-username/url-fetcher:latestStep 5推送镜像到 Docker Hubfaas-cli push -f url-fetcher.yml # 输出Pushed: your-dockerhub-username/url-fetcher:latestStep 6部署到 DOKS 集群faas-cli deploy -f url-fetcher.yml # 输出Deployed. 202 Accepted. # 等待 30 秒执行 faas-cli list # 应看到 # Function Invocations Replicas # url-fetcher 0 1此时你的函数已部署成功。调用方式echo {url: https://jsonplaceholder.typicode.com/posts/1} | faas-cli invoke url-fetcher # 返回{items: []} 因为该 API 无 data.items 字段但证明函数已运行注意faas-cli invoke默认走http://123.45.67.89:8080/function/url-fetcher这个 IP 就是 DOKS LoadBalancer 分配的 Gateway 地址。你可以用curl直接调用curl -X POST http://123.45.67.89:8080/function/url-fetcher -d {url:...}。3.5 TLS 证书配置Lets Encrypt cert-manager 的 DOKS 专用方案OpenFaaS Gateway 默认 HTTP但生产环境必须 HTTPS。DOKS 不支持直接在 LoadBalancer 上配置 TLS不像 AWS ALB所以必须用 Kubernetes 原生方案cert-manager Lets Encrypt Ingress。Step 1安装 cert-managerkubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.2/cert-manager.yaml # 等待 cert-manager-webhook Pod RunningStep 2创建 ClusterIssuerLets Encrypt 生产环境创建letsencrypt-prod.yamlapiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: adminexample.com privateKeySecretRef: name: letsencrypt-prod solvers: - http01: ingress: class: nginx # 注意DOKS 默认不装 nginx-ingress需先 helm install ingress-nginx ingress-nginx/ingress-nginxStep 3部署 nginx-ingressDOKS 必装helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install nginx-ingress ingress-nginx/ingress-nginx \ --set controller.service.typeLoadBalancer \ --set controller.service.annotations.service\.beta\.kubernetes\.io/do-loadbalancer-enable-proxy-protocoltrue \ -n ingress-nginx --create-namespaceStep 4为 Gateway 创建 Ingress 和 Certificate创建gateway-ingress.yamlapiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: openfaas-gateway namespace: openfaas annotations: kubernetes.io/ingress.class: nginx cert-manager.io/cluster-issuer: letsencrypt-prod spec: tls: - hosts: - gateway.example.com secretName: openfaas-gateway-tls rules: - host: gateway.example.com http: paths: - path: / pathType: Prefix backend: service: name: gateway port: number: 8080应用后cert-manager 会自动申请证书kubectl get certificate -n openfaas显示ReadyTrue即成功。此时https://gateway.example.com/system/functions就可访问了。提示DOKS 的 LoadBalancer 会为nginx-ingress分配一个独立 IP你需要将gateway.example.com的 DNS A 记录指向这个 IP而非 Gateway 的 IP。这是很多人的误区——以为 Ingress 和 Gateway 共享同一个 LB。4. 实操过程与核心环节实现压测、监控、日志、升级的全链路闭环4.1 函数性能压测用 hey 工具定位瓶颈的 3 层分析法部署完函数不能只测“能不能用”必须压测“能扛多少”。我们用heyGo 编写的轻量压测工具模拟真实流量# 安装 hey go install github.com/rakyll/heylatest # 对 url-fetcher 函数压测100 并发持续 60 秒 hey -n 6000 -c 100 -m POST -H Content-Type: application/json \ -d {url:https://jsonplaceholder.typicode.com/posts/1} \ https://gateway.example.com/function/url-fetcher压测结果会输出详细报告重点关注三组数据第一层HTTP 层网关响应Response time (50th percentile)中位数延迟应 500ms500 errors5xx 错误数应为 0Timeouts超时数应为 0第二层Kubernetes 层Pod 资源# 实时观察函数 Pod 资源占用 kubectl top pods -n openfaas-fn # NAME CPU(cores) MEMORY(bytes) # url-fetcher-5c8b9d7f4d-abc12 120m 45Mi # 观察节点资源 kubectl top nodes # NAME CPU(cores) MEMORY(bytes) # pool-2vcpu-4gb-sfo3-abc 850m 2.1Gi如果url-fetcherPod CPU 持续 800m0.8 核说明函数逻辑有优化空间如果节点 CPU 90%需扩容节点池。第三层OpenFaaS 内部指标PrometheusOpenFaaS 默认集成 Prometheus指标端点为http://gateway-ip:8082/metrics。我们关注faas_function_invocation_total{functionurl-fetcher}总调用数faas_function_duration_seconds_bucket{functionurl-fetcher,le0.5}500ms 内完成的请求数faas_function_replicas{functionurl-fetcher}当前副本数用curl抓取后计算 P95 延迟curl http://123.45.67.89:8082/metrics | grep faas_function_duration_seconds_bucket{functionurl-fetcher,le0.5} # 如果返回值为 0说明 50% 请求超过 500ms需优化函数或增加副本。我们的实测结论Python 函数在 2vCPU/4GB 节点上单副本稳定承载 30 QPS超过则触发 autoscaler需配置faasnetes的scaleFromZero: true。Go 函数可到 120 QPS这就是语言选型的硬成本。4.2 日志与监控体系用 Loki Grafana 替代 ELK 的轻量方案OpenFaaS 的日志默认输出到 stdoutKubernetes 会捕获。但想集中查看、搜索、告警需要日志系统。我们放弃 ELK太重采用 Loki Promtail Grafana 组合Step 1部署 LokiHelmhelm repo add grafana https://grafana.github.io/helm-charts helm install loki grafana/loki --set loki.storage.typefilesystem -n monitoring --create-namespaceStep 2部署 Promtail收集 OpenFaaS 日志创建promtail-config.yaml重点配置日志路径clients: - url: http://loki.monitoring.svc.cluster.local:3100/loki/api/v1/push scrape_configs: - job_name: openfaas-functions static_configs: - targets: [localhost] labels: job: openfaas-functions __path__: /var/log/pods/*_openfaas-fn_*/**/*.logStep 3Grafana 配置 Loki 数据源在 Grafana UI 中添加数据源URL 填http://loki.monitoring.svc.cluster.local:3100然后创建 Dashboard用 LogQL 查询{jobopenfaas-functions} |~ error | line_format {{.log}}这条语句会实时显示所有函数中的 error 日志比kubectl logs高效百倍。实操心得Promtail 的__path__必须精确匹配 Kubernetes 的 Pod 日志路径。DOKS 的路径是/var/log/pods/namespace_pod-name_uid/openfaas-fn是函数命名空间不能写错否则日志收不到。4.3 函数升级与回滚蓝绿部署的 4 行命令实现OpenFaaS 本身不支持蓝绿但我们可以用 Kubernetes 原生能力模拟Step 1部署新版本函数v2# 修改 url-fetcher.ymlimage 改为 your-dockerhub-username/url-fetcher:v2 faas-cli build -f url-fetcher.yml faas-cli push -f url-fetcher.yml faas-cli deploy -f url-fetcher.yml --replace # --replace 会删除旧 Deployment创建新 DeploymentStep 2验证新版本# 获取新版本 Pod 名称 kubectl get pods -n openfaas-fn | grep url-fetcher # 查看日志确认启动 kubectl logs -n openfaas-fn new-pod-name # 调用测试 echo {url:https://test-api.com} | faas-cli invoke url-fetcherStep 3流量切换本质是修改 Service selectorOpenFaaS 的函数 Service 名为url-fetcherselector 是functionurl-fetcher。新旧版本 Pod 都有这个 label所以 Service 会自动负载均衡。真正的蓝绿需要两个 Service# 创建 v2 Service指向新版本 kubectl apply -f - EOF apiVersion: v1 kind: Service metadata: name: url-fetcher-v2 namespace: openfaas-fn spec: selector: function: url-fetcher version: v2 # 新增 label ports: - port: 8080 targetPort: 8080 EOF然后用 Ingress 将v2.gateway.example.com指向url-fetcher-v2逐步切流。Step 4一键回滚最常用如果 v2 出问题只需# 删除 v2 Deployment kubectl delete deploy -n openfaas-fn url-fetcher-v2 # 重新部署 v1用旧镜像 faas-cli deploy -f url-fetcher.yml --image your-dockerhub-username/url-fetcher:v1整个过程 30 秒比 Helm rollback 更快。4.4 OpenFaaS 版本升级Helm upgrade 的 3 个安全守则OpenFaaS 社区每月发布新版本升级是常态。但我们坚持三条铁律守则 1永远先升级 faas-cli再升级 Helm chart# 查看当前版本 faas-cli version # 0.14.0 helm list -n openfaas # openfaas 0.38.5 # 升级 faas-cli二进制下载 curl -sL https://github.com/openfaas/faas-cli/releases/download/0.14.1/faas-cli-linux /usr/local/bin/faas-cli chmod x /usr/local/bin/faas-cli # 验证 faas-cli version # 必须显示 0.14.1 # 再升级 Helm helm repo update helm upgrade openfaas openfaas/openfaas -f my-values.yaml -n openfaas如果顺序反了faas-cli 0.14.0可能无法识别openfaas 0.39.0的新 API 字段导致faas-cli list报错。守则 2升级前备份 CRD 和 Secrets# 备份 Function CRD以防升级破坏 kubectl get crd functions.openfaas.com -o yaml functions-crd-backup.yaml # 备份 basic-auth Secret用户名密码 kubectl get secret -n openfaas basic-auth -o yaml basic-auth-secret-backup.yaml守则 3升级后强制重建所有函数Helm upgrade 不会自动重建函数 Pod旧镜像可能残留。必须执行# 获取所有函数名 faas-cli list --format {{.Name}} | xargs -I {} sh -c faas-cli deploy -f {}.yml --replace这会触发 Operator 重建所有 Deployment确保运行最新版 Gateway 和 watchdog。5. 常见问题与排查技巧实录12 个真实踩坑现场与速查表5.1 函数部署后始终 Pending5 种可能性与逐级排查法这是新手最高频问题kubectl get pods -n openfaas-fn显示