HMK's blog

保持思考|00后|等待


  • Home
  • Archive
  • Tags
  •   

© 2026 Hekang

Theme Typography by Makito

Proudly published with Hexo

traefik反代证书续签frp内网穿透

Posted at 2026-05-21 云原生 

一、阿里云安装K3S

1
2
3
4
5
6
7
8
9
10
11
12
13
14
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -

mkdir -p /var/lib/rancher/k3s/agent/etc/containerd/certs.d/docker.io
cd /var/lib/rancher/k3s/agent/etc/containerd/certs.d/docker.io
cat > hosts.toml << EOF
server = "https://docker.io"
[host."https://dockerproxy.com"]
capabilities = ["pull", "resolve"]

[host."https://docker.m.daocloud.io"]
capabilities = ["pull", "resolve"]
EOF

systemctl restart k3s

1.1 k3s自带traefik

1
2
3
4
5
6
7
8
9
10
11
12
 [root@hmk /var/lib/rancher/k3s/server/manifests ]# ll
total 40
drwx------ 3 root root 4096 Apr 25 00:20 ./
drwx------ 8 root root 4096 May 19 10:33 ../
-rw------- 1 root root 1914 May 19 10:33 ccm.yaml
-rw------- 1 root root 5059 May 19 10:33 coredns.yaml
-rw------- 1 root root 3236 May 19 10:33 local-storage.yaml
drwx------ 2 root root 4096 Apr 24 14:06 metrics-server/
-rw------- 1 root root 1737 May 19 10:33 rolebindings.yaml
-rw------- 1 root root 927 May 19 10:33 runtimes.yaml
-rw------- 1 root root 1009 May 19 10:33 traefik.yaml

二、内网穿透服务端frps

2.1 创建frp配置的ConfigMap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 [root@hmk /etc/frp ]# cat frps.toml
bindAddr = "0.0.0.0"
bindPort = 18000
auth.method = "token"
auth.additionalScopes = ["HeartBeats"]
#auth.additionalScopes = ["NewWorkConns"]
auth.token = "hmklearn"
tcpmuxHTTPConnectPort = 18001
vhostHTTPPort = 18080
vhostHTTPSPort = 18443
kcpBindPort = 18003
quicBindPort = 18004
webServer.addr = "0.0.0.0"
webServer.port = 10080
webServer.user = "test"
webServer.password = "hmktest"
enablePrometheus = true
log.to = "/var/log/frps.log"
log.level = "info"
log.maxDays = 3
log.disablePrintColor = false
detailedErrorsToClient = true
transport.maxPoolCount = 5

1
2
3
4
5
6
mkdir -p /etc/frp/
root@hmk:/etc/frp# kubectl create ns frp
namespace/frp created
root@hmk:/etc/frp# kubectl create cm frp-config -n frp --from-file=./frps.toml
configmap/frp-config created
root@hmk:/etc/frp#

2.2 frps deploy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 [root@hmk /etc/frp ]# cat deploy-frp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frps
namespace: frp
spec:
replicas: 1
selector:
matchLabels:
app: frps
template:
metadata:
labels:
app: frps
spec:
containers:
- name: frps
image: registry.cn-hangzhou.aliyuncs.com/hemingkang/frps:v0.67.0
# 必须显式指定配置文件路径!
args: ["-c", "/etc/frp/frps.toml"]
ports:
- containerPort: 18000 # frpc 连接端口(对应 bindPort)
name: server
protocol: TCP
hostPort: 18000
- containerPort: 18080 # HTTP 虚拟主机端口(对应 vhostHTTPPort)
name: http
protocol: TCP
- containerPort: 18443 # HTTPS 虚拟主机端口(对应 vhostHTTPSPort)
name: https
protocol: TCP
- containerPort: 10080 # Dashboard 端口(对应 webServer.port)
name: dashboard
protocol: TCP
volumeMounts:
- name: config
mountPath: /etc/frp # 挂载到 /etc/frp
- name: log
mountPath: /var/log/frps.log
volumes:
- name: config
configMap:
name: frp-config
- name: log
hostPath:
path: /var/log/frps.log
type: FileOrCreate
---
apiVersion: v1
kind: Service
metadata:
name: frps
namespace: frp
spec:
selector:
app: frps
ports:
- name: frps # frpc TCP 连接端口
port: 18000
targetPort: 18000
protocol: TCP
- name: http # HTTP 虚拟主机端口
port: 18080
targetPort: 18080
protocol: TCP
- name: https # HTTPS 虚拟主机端口(如果需要)
port: 18443
targetPort: 18443
protocol: TCP
- name: dashboard # Dashboard 管理界面端口
port: 10080
targetPort: 10080
protocol: TCP
type: ClusterIP


三、安装Helm4

3.1 下载Helm二进制程序

1
2
3
4
5
6
7
8
root@hmk:~# curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4 | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 11929 100 11929 0 0 10839 0 0:00:01 0:00:01 --:--:-- 10844
Downloading https://get.helm.sh/helm-v4.1.4-linux-amd64.tar.gz
Verifying checksum... Done.
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm

四、实现证书自签

4.1 创建用于证书续签的AK.SK 创建secret

1
2
3
4
kubectl create secret generic hmk-alidns-secrets -n kube-system \
--from-literal=ALICLOUD_ACCESS_KEY="Your AliYun AK" \
--from-literal=ALICLOUD_SECRET_KEY="Your AliYun SK" \
--from-literal=ALICLOUD_REGION_ID="Your Resource Region"

4.2 traefik配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 [root@hmk /etc/frp ]# cat traefik-config.yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |
globalArguments:
- "--providers.kubernetescrd.allowCrossNamespace=true"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"

# 入口点配置
# entryPoints:
# web:
# address: ":8000"
# http:
# redirections:
# entryPoint:
# to: websecure
# scheme: https
# permanent: true
# websecure:
# address: ":8443"


# 证书解析器必须在根级别
certificatesResolvers:
alicloud:
acme:
email: 2733885168@qq.com
storage: /data/acme-hmk.json
dnsChallenge:
provider: alidns
delayBeforeCheck: 10
resolvers:
- "223.5.5.5:53"
- "223.6.6.6:53"

# 环境变量
env:
- name: ALICLOUD_ACCESS_KEY
valueFrom:
secretKeyRef:
name: hmk-alidns-secrets
key: ALICLOUD_ACCESS_KEY
- name: ALICLOUD_SECRET_KEY
valueFrom:
secretKeyRef:
name: hmk-alidns-secrets
key: ALICLOUD_SECRET_KEY
- name: ALICLOUD_REGION_ID
valueFrom:
secretKeyRef:
name: hmk-alidns-secrets
key: ALICLOUD_REGION_ID

# 持久化
persistence:
enabled: true
name: data
accessMode: ReadWriteOnce
size: 128Mi
storageClass: local-path
path: /data

# 安全上下文
securityContext:
readOnlyRootFilesystem: false
runAsNonRoot: false
runAsUser: 0
# http 重定向至https

4.3 traefik 路由规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 [root@hmk /etc/frp ]# cat frps-bindport.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: frps-tcp
namespace: frp
spec:
entryPoints:
- websecure
routes:
- match: HostSNI(`*`)
services:
- name: frps
port: 18000

路由规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 [root@hmk /etc/frp ]# cat frps-casaos.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: frps-dashboard
namespace: frp
spec:
entryPoints:
- web
- websecure
routes:
- match: Host(`frp.hmkcloud.cn`)
kind: Rule
services:
- name: frps
kind: Service
namespace: frp
port: 10800
- match: Host(`nas.hmkcloud.cn`)
kind: Rule
services:
- name: frps
kind: Service
namespace: frp
port: 18080
- match: Host(`wiki.hmkcloud.cn`)
kind: Rule
services:
- name: frps
kind: Service
namespace: frp
port: 18080
- match: Host(`mail.hmkcloud.cn`)
kind: Rule
services:
- name: frps
kind: Service
namespace: frp
port: 18080
tls:
certResolver: alicloud
domains:
- main: "*.hmkcloud.cn"

五、frpc配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
root@CasaOS:~/frp_0.67.0_linux_amd64# cat frpc.toml
serverAddr = "102.133.66.23"
serverPort = 18000
auth.method = "token"
auth.token = "hmklearn"。

[[proxies]]
name = "casaos"
type = "http"
localIP = "127.0.0.1"
localPort = 8008
customDomains = ["hmkcloud.cn"]

[[proxies]]
name = "file"
type = "http"
localIP = "127.0.0.1"
localPort = 10181
customDomains = ["nas.hmkcloud.cn"]

[[proxies]]
name = "pic"
type = "http"
localIP = "127.0.0.1"
localPort = 5555
customDomains = ["pic.hmkcloud.cn"]

[[proxies]]
name = "pic"
type = "http"
localIP = "127.0.0.1"
localPort = 10000
customDomains = ["bill.hmkcloud.cn"]
[[proxies]]
name = "note"
type = "http"
localIP = "127.0.0.1"
localPort = 6666
customDomains = ["wiki.hmkcloud.cn"]
[[proxies]]
name = "jd"
type = "http"
localIP = "127.0.0.1"
localPort = 7777
customDomains = ["mail.hmkcloud.cn"]

访问,通过traefik svc的端口对外服务

1
2
3
4
 [root@hmk /etc/frp ]# kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
kube-system traefik LoadBalancer 80 443 24d

                外部 80/443
                     ↓
          ┌──────────────────────┐
          │  traefik Service     │
          │  (LoadBalancer)      │
          │  10.46.193.53        │
          │  172.16.109.44       │
          └──────────────────────┘
                ↓         ↓
        port:80     ↓   port:443
        target:web  ↓   target:websecure
                ↓         ↓
          ┌──────────────────────┐
          │   Traefik Pod        │
          │   :8000 (web)        │
          │   :8443 (websecure)  │
          └──────────────────────┘
                     ↓
          IngressRoute 匹配
          Host(`frp.hmkcloud.cn`)
                     ↓
          ┌──────────────────────┐
          │   frps Service        │
          │   :10080              │
          └──────────────────────┘
                     ↓
          ┌──────────────────────┐
          │   frps Pod            │
          │   :10080              │
          └──────────────────────┘
  1. ✅ Service 做端口转换:外部 80/443 → Pod 8000/8443
  2. ✅ Traefik 监听这些端口:web(8000) 和 websecure(8443)
  3. ✅ IngressRoute 处理请求:根据域名路由到后端服务

六、traefik-dashboard 对外访问

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 [root@hmk ~ ]# cat traefik-dashboard.yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard
namespace: kube-system
spec:
entryPoints:
- websecure # 关键修正1:使用 'web' 入口点
routes:
- match: Host(`traefik.hmkcloud.cn`) && (PathPrefix(`/dashboard`) || PathPrefix(`/api`))
kind: Rule
services:
- name: api@internal
kind: TraefikService
tls:
certResolver: alicloud
domains:
- main: "traefik.hmkcloud.cn"

api@internal 的本质

api@internal 是一个虚拟服务,它不是真实的 Kubernetes Service,而是 Traefik 内部暴露的一个特殊端点。

它提供了什么?

当你访问 api@internal 时,可以获取:

  • Dashboard UI:/dashboard/
  • Raw Data API:/api/rawdata - 所有路由配置的 JSON 数据
  • HTTP Metrics:/api/http/metrics - HTTP 指标
  • Overview API:/api/overview - 概览信息
  • EntryPoints 信息:/api/entrypoints

什么时候使用 api@internal?

✅ 必须使用的场景

1. 访问 Traefik Dashboard

1
2
3
services:
- name: api@internal
kind: TraefikService

这是官方唯一推荐的 Dashboard 访问方式(从 Traefik v2.5+ 开始)。

2. 需要查看 Traefik 运行状态

1
2
3
4
5
# 获取所有路由配置
- match: Host(`api.hmk.cn`) && PathPrefix(`/rawdata`)
services:
- name: api@internal
kind: TraefikService

3. 集成 Prometheus 监控(非 metrics 端点)

虽然 Traefik 有独立的 metrics 端点,但有些高级指标需要通过 api@internal 获取。

4. 调试和排查问题

1
2
3
4
5
6
# 临时开启调试端点
- match: Host(`debug.hmk.cn`) && (PathPrefix(`/debug`) || PathPrefix(`/api`))
services:
- name: api@internal
kind: TraefikService
# 记得添加 IP 白名单限制!

❌ 不应该使用的场景

1. 转发业务流量

1
2
3
4
5
6
7
8
9
# 错误示例 - 业务应用不应该用 api@internal
services:
- name: api@internal # ❌ 错误!
kind: TraefikService

# 正确示例
services:
- name: my-app-service # ✅ 正确
port: 8080

2. 访问外部服务

1
2
3
4
5
6
7
8
# 错误示例
services:
- name: api@internal # ❌ 只能访问 Traefik 内部

# 正确示例 - 使用 ExternalName Service
services:
- name: external-service # ✅ 通过 K8s Service
port: 80

3. TCP/UDP 路由

1
2
3
4
5
6
7
8
9
# 错误示例 - api@internal 不支持 TCP
kind: IngressRouteTCP
services:
- name: api@internal # ❌ 不工作!

# 正确示例
services:
- name: mysql-service # ✅ 正常的 TCP 服务
port: 3306

kind: TraefikService 的作用

kind: TraefikService 告诉 Traefik:这个 service 名称不是 Kubernetes Service,而是 Traefik 内部定义的服务类型。

TraefikService 的其他类型

除了 api@internal,还有:

1. Weighted Round Robin

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: my-weighted-service
spec:
weighted:
services:
- name: app-v1
port: 80
weight: 80
- name: app-v2
port: 80
weight: 20

在 IngressRoute 中使用:

1
2
3
services:
- name: my-weighted-service
kind: TraefikService # 引用上面定义的 TraefikService

2. Mirroring

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: my-mirror-service
spec:
mirroring:
name: app-production
port: 80
mirrors:
- name: app-staging
port: 80
percent: 10

实际对比示例

普通 Kubernetes Service(业务流量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 部署你的应用
apiVersion: v1
kind: Service
metadata:
name: my-web-app
spec:
selector:
app: web
ports:
- port: 80
targetPort: 3000

---
# 通过 IngressRoute 暴露
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
spec:
entryPoints:
- web
routes:
- match: Host(`app.hmk.cn`)
services:
- name: my-web-app # 普通 Service,不需要 kind 字段
port: 80 # 或者使用 name: my-web-app@kubernetescrd

Traefik 内部服务(管理流量)

1
2
3
4
5
6
7
8
9
10
11
# 访问 Dashboard
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
spec:
entryPoints:
- web
routes:
- match: Host(`traefik.hmk.cn`) && PathPrefix(`/dashboard`)
services:
- name: api@internal # Traefik 内部服务
kind: TraefikService # 必须指定 kind!

核心规则总结

Service 类型 何时使用 是否需要 kind: TraefikService
普通 K8s Service 业务应用、数据库、API 等 ❌ 不需要(或写 kind: Service)
api@internal Dashboard、管理 API、调试 ✅ 必须
自定义 TraefikService 权重路由、流量镜像 ✅ 必须

快速判断方法

问自己一个问题:这个服务是 Traefik 自身的功能,还是我的业务应用?

  • 如果是业务应用 → 使用普通 Service
  • 如果是 Traefik Dashboard/API → 使用 api@internal + kind: TraefikService
  • 如果是其他特殊路由(权重、镜像)→ 先定义 TraefikService,再用 kind: TraefikService 引用

希望这个解释能帮你彻底理解 api@internal 和 TraefikService 的使用场景!

Share 

 Previous post: KubeKey安装K8s集群 Next post: 服务暴露traefik3.6.7 

© 2026 Hekang

Theme Typography by Makito

Proudly published with Hexo