Files
k3s/009-基础设施/008-portainer/README.md
2026-02-05 00:11:05 +08:00

4.8 KiB
Raw Blame History

Portainer 部署指南

概述

本文档记录了在 k3s 集群中部署 Portainer 的完整过程包括域名绑定、KEDA 自动缩放和 CSRF 校验问题的解决方案。

部署步骤

1. 使用 Helm 安装 Portainer

# 添加 Helm 仓库
helm repo add portainer https://portainer.github.io/k8s/
helm repo update

# 安装 Portainer使用 Longhorn 作为存储类)
helm install --create-namespace -n portainer portainer portainer/portainer \
  --set persistence.enabled=true \
  --set persistence.storageClass=longhorn \
  --set service.type=NodePort

2. 配置域名访问

2.1 Caddy 反向代理配置

修改 Caddy ConfigMap添加 Portainer 的反向代理规则:

# Portainer 容器管理 - 直接转发到 Portainer HTTPS 端口
portainer.u6.net3w.com {
    reverse_proxy https://portainer.portainer.svc.cluster.local:9443 {
        transport http {
            tls_insecure_skip_verify
        }
    }
}

关键点:

  • 直接转发到 Portainer 的 HTTPS 端口9443而不是通过 Traefik
  • 这样可以避免协议不匹配导致的 CSRF 校验失败

2.2 更新 Caddy ConfigMap

kubectl patch configmap caddy-config -n default --type merge -p '{"data":{"Caddyfile":"..."}}'

2.3 重启 Caddy Pod

kubectl delete pod -n default -l app=caddy

3. 配置 KEDA 自动缩放(可选)

如果需要实现访问时启动、空闲时缩容的功能,应用 KEDA 配置:

kubectl apply -f keda-scaler.yaml

配置说明:

  • 最小副本数0空闲时缩容到 0
  • 最大副本数3
  • 缩容延迟5 分钟无流量后缩容

4. 解决 CSRF 校验问题

问题描述

登录时提示 "Unable to login",日志显示:

Failed to validate Origin or Referer | error="origin invalid"

问题原因

Portainer 新版本对 CSRF 校验非常严格。当通过域名访问时,协议不匹配导致校验失败:

  • 客户端发送HTTPS 请求
  • Portainer 接收x_forwarded_proto=http

解决方案

步骤 1添加环境变量禁用 CSRF 校验

kubectl set env deployment/portainer -n portainer CONTROLLER_DISABLE_CSRF=true

步骤 2添加环境变量配置 origins

kubectl set env deployment/portainer -n portainer PORTAINER_ADMIN_ORIGINS="*"

步骤 3重启 Portainer

kubectl rollout restart deployment portainer -n portainer

步骤 4修改 Caddy 配置(最关键)

直接转发到 Portainer 的 HTTPS 端口,避免通过 Traefik 导致的协议转换问题:

portainer.u6.net3w.com {
    reverse_proxy https://portainer.portainer.svc.cluster.local:9443 {
        transport http {
            tls_insecure_skip_verify
        }
    }
}

配置文件

portainer-server.yaml

记录 Portainer deployment 的环境变量配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: portainer
  namespace: portainer
spec:
  template:
    spec:
      containers:
      - name: portainer
        env:
        - name: CONTROLLER_DISABLE_CSRF
          value: "true"
        - name: PORTAINER_ADMIN_ORIGINS
          value: "*"

keda-scaler.yaml

KEDA 自动缩放配置,实现访问时启动、空闲时缩容。

访问 Portainer

部署完成后,访问:

https://portainer.u6.net3w.com

常见问题

Q: 登录时提示 "Unable to login"

A: 这通常是 CSRF 校验失败导致的。检查以下几点:

  1. 确认已添加环境变量 CONTROLLER_DISABLE_CSRF=true
  2. 确认 Caddy 配置直接转发到 Portainer HTTPS 端口
  3. 检查 Portainer 日志中是否有 "origin invalid" 错误
  4. 重启 Portainer pod 使配置生效

Q: 为什么要直接转发到 HTTPS 端口而不是通过 Traefik

A: 因为通过 Traefik 转发时,协议头会被转换为 HTTP导致 Portainer 接收到的协议与客户端发送的协议不匹配,从而 CSRF 校验失败。直接转发到 HTTPS 端口可以保持协议一致。

Q: KEDA 自动缩放是否必须配置?

A: 不是必须的。KEDA 自动缩放是可选功能,用于节省资源。如果不需要自动缩放,可以跳过这一步。

相关文件

  • portainer-server.yaml - Portainer deployment 环境变量配置
  • keda-scaler.yaml - KEDA 自动缩放配置
  • ingress.yaml - 原始 Ingress 配置(已弃用,改用 Caddy 直接转发)

下次部署检查清单

  • 使用 Helm 安装 Portainer
  • 修改 Caddy 配置,直接转发到 Portainer HTTPS 端口
  • 添加 Portainer 环境变量CONTROLLER_DISABLE_CSRF、PORTAINER_ADMIN_ORIGINS
  • 重启 Caddy 和 Portainer pods
  • 测试登录功能
  • (可选)配置 KEDA 自动缩放

参考资源