首次提交:初始化项目
This commit is contained in:
191
009-基础设施/008-portainer/README.md
Normal file
191
009-基础设施/008-portainer/README.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# Portainer 部署指南
|
||||
|
||||
## 概述
|
||||
|
||||
本文档记录了在 k3s 集群中部署 Portainer 的完整过程,包括域名绑定、KEDA 自动缩放和 CSRF 校验问题的解决方案。
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 使用 Helm 安装 Portainer
|
||||
|
||||
```bash
|
||||
# 添加 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 的反向代理规则:
|
||||
|
||||
```yaml
|
||||
# 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
|
||||
|
||||
```bash
|
||||
kubectl patch configmap caddy-config -n default --type merge -p '{"data":{"Caddyfile":"..."}}'
|
||||
```
|
||||
|
||||
#### 2.3 重启 Caddy Pod
|
||||
|
||||
```bash
|
||||
kubectl delete pod -n default -l app=caddy
|
||||
```
|
||||
|
||||
### 3. 配置 KEDA 自动缩放(可选)
|
||||
|
||||
如果需要实现访问时启动、空闲时缩容的功能,应用 KEDA 配置:
|
||||
|
||||
```bash
|
||||
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 校验**
|
||||
|
||||
```bash
|
||||
kubectl set env deployment/portainer -n portainer CONTROLLER_DISABLE_CSRF=true
|
||||
```
|
||||
|
||||
**步骤 2:添加环境变量配置 origins**
|
||||
|
||||
```bash
|
||||
kubectl set env deployment/portainer -n portainer PORTAINER_ADMIN_ORIGINS="*"
|
||||
```
|
||||
|
||||
**步骤 3:重启 Portainer**
|
||||
|
||||
```bash
|
||||
kubectl rollout restart deployment portainer -n portainer
|
||||
```
|
||||
|
||||
**步骤 4:修改 Caddy 配置(最关键)**
|
||||
|
||||
直接转发到 Portainer 的 HTTPS 端口,避免通过 Traefik 导致的协议转换问题:
|
||||
|
||||
```yaml
|
||||
portainer.u6.net3w.com {
|
||||
reverse_proxy https://portainer.portainer.svc.cluster.local:9443 {
|
||||
transport http {
|
||||
tls_insecure_skip_verify
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 配置文件
|
||||
|
||||
### portainer-server.yaml
|
||||
|
||||
记录 Portainer deployment 的环境变量配置:
|
||||
|
||||
```yaml
|
||||
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 自动缩放
|
||||
|
||||
## 参考资源
|
||||
|
||||
- Portainer 官方文档:https://docs.portainer.io/
|
||||
- k3s 官方文档:https://docs.k3s.io/
|
||||
- KEDA 官方文档:https://keda.sh/
|
||||
20
009-基础设施/008-portainer/ingress.yaml
Normal file
20
009-基础设施/008-portainer/ingress.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: portainer-ingress
|
||||
namespace: portainer
|
||||
annotations:
|
||||
traefik.ingress.kubernetes.io/router.entrypoints: web
|
||||
spec:
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: portainer.u6.net3w.com
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: portainer
|
||||
port:
|
||||
number: 9000
|
||||
58
009-基础设施/008-portainer/keda-scaler.yaml
Normal file
58
009-基础设施/008-portainer/keda-scaler.yaml
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
# HTTPScaledObject - 用于实现缩容到 0 的核心配置
|
||||
apiVersion: http.keda.sh/v1alpha1
|
||||
kind: HTTPScaledObject
|
||||
metadata:
|
||||
name: portainer-http-scaler
|
||||
namespace: portainer
|
||||
spec:
|
||||
hosts:
|
||||
- portainer.u6.net3w.com
|
||||
pathPrefixes:
|
||||
- /
|
||||
scaleTargetRef:
|
||||
name: portainer
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
service: portainer
|
||||
port: 9000
|
||||
replicas:
|
||||
min: 0 # 空闲时缩容到 0
|
||||
max: 3 # 最多 3 个副本
|
||||
scalingMetric:
|
||||
requestRate:
|
||||
granularity: 1s
|
||||
targetValue: 50 # 每秒 50 个请求时扩容
|
||||
window: 1m
|
||||
scaledownPeriod: 300 # 5 分钟无流量后缩容到 0
|
||||
|
||||
---
|
||||
# Traefik Middleware - 设置正确的协议头
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: portainer-headers
|
||||
namespace: keda
|
||||
spec:
|
||||
headers:
|
||||
customRequestHeaders:
|
||||
X-Forwarded-Proto: "https"
|
||||
|
||||
---
|
||||
# Traefik IngressRoute - 将流量路由到 KEDA HTTP Add-on 的拦截器
|
||||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: portainer-ingress
|
||||
namespace: keda
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`portainer.u6.net3w.com`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
- name: portainer-headers
|
||||
services:
|
||||
- name: keda-add-ons-http-interceptor-proxy
|
||||
port: 8080
|
||||
16
009-基础设施/008-portainer/portainer-server.yaml
Normal file
16
009-基础设施/008-portainer/portainer-server.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: portainer
|
||||
namespace: portainer
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: portainer
|
||||
env:
|
||||
- name: CONTROLLER_DISABLE_CSRF
|
||||
value: "true"
|
||||
# 说明:禁用 CSRF 校验是因为 Portainer 新版本对 CSRF 校验非常严格
|
||||
# 当使用域名访问时(如 portainer.u6.net3w.com),需要禁用此校验
|
||||
# 如果需要重新启用,将此值改为 "false" 或删除此环境变量
|
||||
10
009-基础设施/008-portainer/readme.md
Normal file
10
009-基础设施/008-portainer/readme.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# 添加 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
|
||||
Reference in New Issue
Block a user