name: 部署云原生Kubernetes description: | 使用CI/CD流水线将应用程序部署到云Kubernetes(AKS/GKE/DOKS)。 适用于生产环境部署、设置GitHub Actions、故障排除部署问题。 涵盖构建时与运行时变量、架构匹配以及经过实战检验的调试方法。
部署云原生Kubernetes
快速开始
- 检查集群架构:
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}' - 将构建平台与集群匹配(arm64 vs amd64)
- 使用路径过滤器设置GitHub Actions
- 使用Helm部署,通过
--set传递密钥
关键点:构建时与运行时变量
问题
Next.js的NEXT_PUBLIC_*变量在构建时嵌入,而非运行时:
# 错误:运行时ENV对NEXT_PUBLIC_*无效
ENV NEXT_PUBLIC_API_URL=https://api.example.com
# 正确:必须是构建ARG
ARG NEXT_PUBLIC_API_URL=https://api.example.com
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
构建时变量(Next.js)
| 变量 | 用途 |
|---|---|
NEXT_PUBLIC_SSO_URL |
浏览器OAuth的SSO端点 |
NEXT_PUBLIC_API_URL |
浏览器fetch的API端点 |
NEXT_PUBLIC_APP_URL |
重定向的应用URL |
运行时变量(ConfigMaps/Secrets)
| 变量 | 来源 |
|---|---|
DATABASE_URL |
密钥(Neon/托管数据库) |
SSO_URL |
ConfigMap(内部K8s:http://sso:3001) |
BETTER_AUTH_SECRET |
密钥 |
架构匹配
在任何部署之前,检查架构:
kubectl get nodes -o jsonpath='{.items[*].status.nodeInfo.architecture}'
# 输出:arm64 arm64 或 amd64 amd64
Docker构建
- uses: docker/build-push-action@v5
with:
platforms: linux/arm64 # 匹配你的集群!
provenance: false # 避免清单问题
no-cache: true # 调试时使用
为什么设置provenance: false? Buildx认证会创建复杂的清单列表,导致“no match for platform”错误。
GitHub Actions CI/CD
使用路径过滤器进行选择性构建
jobs:
changes:
runs-on: ubuntu-latest
outputs:
api: ${{ steps.filter.outputs.api }}
web: ${{ steps.filter.outputs.web }}
steps:
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
api:
- 'apps/api/**'
web:
- 'apps/web/**'
build-api:
needs: changes
if: needs.changes.outputs.api == 'true'
Next.js构建参数
- name: 构建并推送(web)
uses: docker/build-push-action@v5
with:
build-args: |
NEXT_PUBLIC_SSO_URL=https://sso.${{ vars.DOMAIN }}
NEXT_PUBLIC_API_URL=https://api.${{ vars.DOMAIN }}
Helm部署
- name: 部署
run: |
helm upgrade --install myapp ./helm/myapp \
--set global.imageTag=${{ github.sha }} \
--set "secrets.databaseUrl=${{ secrets.DATABASE_URL }}" \
--set "secrets.authSecret=${{ secrets.BETTER_AUTH_SECRET }}"
故障排除指南
快速诊断流程
Pod未运行?
│
├─► ImagePullBackOff
│ ├─► "not found" ──► 标签错误或注册表错误
│ ├─► "unauthorized" ──► 认证/imagePullSecrets问题
│ └─► "no match for platform" ──► 架构不匹配
│
├─► CrashLoopBackOff
│ ├─► "exec format error" ──► CPU架构错误
│ ├─► 退出代码1 ──► 应用启动失败
│ └─► OOMKilled ──► 内存限制过低
│
└─► Pending
├─► 资源不足 ──► 扩展集群
└─► 无匹配节点 ──► 检查nodeSelector
诊断命令
kubectl get pods -n <命名空间>
kubectl describe pod <pod名称> -n <命名空间> | grep -E "(Image:|Failed|Error)"
kubectl get events -n <命名空间> --sort-by='.lastTimestamp' | tail -20
kubectl logs <pod名称> -n <命名空间> --tail=50
错误:ImagePullBackOff “not found”
原因:
- 标签不存在(短SHA vs 完整SHA)
- 注册表路径错误
- 路径过滤器跳过了构建
修复: 验证部署时使用的确切标签是否已推送镜像
错误:“no match for platform in manifest”
原因: 镜像为错误架构构建 或 buildx认证问题
修复:
platforms: linux/arm64 # 匹配集群!
provenance: false # 简单清单
no-cache: true # 强制重建
错误:“exec format error”
原因: 二进制架构与节点不匹配
修复: 使用正确平台重建,使用no-cache: true
错误:Helm逗号解析
failed parsing --set data: key "com" has no value
原因: Helm将逗号解释为数组分隔符
修复: 使用heredoc值文件:
- name: 部署
run: |
cat > /tmp/overrides.yaml << EOF
sso:
env:
ALLOWED_ORIGINS: "https://a.com,https://b.com"
EOF
helm upgrade --install app ./chart --values /tmp/overrides.yaml
错误:密码认证失败
原因: 密码包含特殊字符(base64 +/=)
修复: 使用十六进制密码:
# 错误
openssl rand -base64 16 # 可能包含+/=
# 正确
openssl rand -hex 16 # 仅字母数字
错误:注销重定向到0.0.0.0
原因: request.url返回容器绑定地址
修复:
const APP_URL = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
const response = NextResponse.redirect(new URL("/", APP_URL));
部署前检查清单
架构
- [ ] 检查集群节点架构
- [ ] 构建平台与集群匹配
Docker构建
- [ ] 设置
provenance: false - [ ]
platforms: linux/<架构>匹配集群 - [ ] 构建和部署之间的镜像标签一致
CI/CD
- [ ] 所有
NEXT_PUBLIC_*作为构建参数 - [ ] 密钥通过
--set传递(不在values.yaml中) - [ ] 配置路径过滤器
Helm
- [ ]
--set值中没有逗号 - [ ] 内部K8s服务名称用于服务间通信
- [ ] 密码在values.yaml中单一来源
生产环境调试
追踪请求路径
# 1. 前端日志
kubectl logs deploy/web -n myapp --tail=50
# 2. API日志
kubectl logs deploy/api -n myapp --tail=100 | grep -i error
# 3. 边车日志(Dapr等)
kubectl logs deploy/api -n myapp -c daprd --tail=50
常见错误模式
| 错误 | 可能原因 |
|---|---|
AttributeError: no attribute 'X' |
模型/模式不匹配 |
内部调用404 Not Found |
端点URL错误 |
| 时间偏差数小时 | 时区处理错误 |
greenlet_spawn not called |
异步SQLAlchemy模式 |
使用ArgoCD的GitOps
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
source:
repoURL: https://github.com/org/repo.git
path: k8s/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: myapp
syncPolicy:
automated:
prune: true # 删除Git中不存在的资源
selfHeal: true # 自动修复漂移
可观测性
# Prometheus的ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: metrics
interval: 30s
安全性
# Pod安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 1000
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
弹性
# HPA + PDB
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
---
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
minAvailable: 1
完整GitOps、可观测性、安全性和弹性模式,请参阅references/production-patterns.md。
验证
运行:python scripts/verify.py
相关技能
containerizing-applications- Docker和Helm图表operating-k8s-local- 使用Minikube的本地Kubernetesbuilding-nextjs-apps- Next.js模式
参考资料
- references/production-patterns.md - GitOps、ArgoCD、Prometheus、RBAC、HPA、PDB