K8s环境AliYun内网穿透配合traefik反向代理试下证书自签

一、阿里云安装K3S

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

 [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

 [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

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

 [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二进制程序

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

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配置

 [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 路由规则

 [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

路由规则

 [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配置

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的端口对外服务

 [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 对外访问

 [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

services:
- name: api@internal
  kind: TraefikService

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

2. 需要查看 Traefik 运行状态

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

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

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

4. 调试和排查问题

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

不应该使用的场景

1. 转发业务流量

# 错误示例 - 业务应用不应该用 api@internal
services:
- name: api@internal          # ❌ 错误!
  kind: TraefikService

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

2. 访问外部服务

# 错误示例
services:
- name: api@internal          # ❌ 只能访问 Traefik 内部

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

3. TCP/UDP 路由

# 错误示例 - 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

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 中使用:

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

2. Mirroring

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(业务流量)

# 部署你的应用
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 内部服务(管理流量)

# 访问 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@internalTraefikService 的使用场景!

posted @ 2026-05-20 11:11  给我一碗炒粉  阅读(46)  评论(0)    收藏  举报