云原生之旅:TCP 穿透,轻松暴露内网服务到公网

需求

目标: 将内网kubernetes集群中的的自签名 TLS 服务(ArgoCD)通过公网域名 example.com:5002 对外可见。

方案

有两种可行的方案:

我选择了方案2作为本教程的示例: 采用 TCP 代理类型,直接透传 HTTPS 流量。该方案最大的优势是 无需 frp 处理自签名证书,保证了端到端的加密,简化了配置,推荐用于自签名或自定义 TLS 服务的暴露。

开始

步骤如下:

  1. 安装示例服务(可选)
  2. 在公网服务器安装frp的服务端二进制文件并编写服务端(frps)配置
  3. 在本地(内网)安装frp的客户端二进制文件并编写客户端(frpc)配置
  4. 启动服务端和客户端
  5. 测试内网服务通过公网地址访问是否可行

安装示例服务(基于 Kubernetes/Helm)

如果你的环境不支持LoadBalancer暴露内网服务,那么就需要修改helm的安装参数server.service.type参数,可以使用NodePort,或者也可以使用IngressGateway

kubernetes的gateway示例,如果使用了gateway-api,那么server.service.type就可以保持默认的ClusterIP值, 这里使用HTTPRoute演示,有安全需求也可以使用TLSRoute

yml 复制代码
# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: argocd-gateway
  namespace: argocd
spec:
#  addresses:
#    - type: IPAddress
#      value: 192.168.3.106
  # 替换成你集群中实际安装的 Gateway Controller Class 名称
  gatewayClassName: cilium
  listeners:
    - name: server
      protocol: HTTP
      port: 443
---
# argocd-server-httproute.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: argocd-server
  namespace: argocd
spec:
  parentRefs:
    - name: argocd-gateway # 绑定到上面创建的 Gateway
  hostnames:
    - "argocd.app.com" # 替换成你的域名
  rules:
    - matches:
        # 需要匹配的路径
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: argocd-server
          port: 443 # 路由到 argocd server的端口

检查gatewayhttproutes, 验证PROGRAMMED是否为True

sh 复制代码
kubectl get gateway,httproutes -n argocd
bash 复制代码
#!/usr/bin/env bash
# 启用 POSIX 模式并设置严格的错误处理机制
set -o posix errexit -o pipefail

# https://github.com/argoproj/argo-helm/tree/main

mkdir -pv /home/kubernetes/argocd
cd /home/kubernetes/argocd

#git clone --depth 1 https://github.com/argoproj/argo-helm.git
helm repo add argo https://argoproj.github.io/argo-helm
helm pull argo/argo-cd
tar -zxvf argo-cd-*.tgz

cat > new-values.yaml <<EOF
controller:
  replicas: 1

server:
  ## Argo CD server Horizontal Pod Autoscaler
  autoscaling:
    enabled: false
    minReplicas: 2

repoServer:
  autoscaling:
    enabled: false
    minReplicas: 2

applicationSet:
  replicas: 1

server:
  replicas: 1
  service:
    type: LoadBalancer
  ingress:
    enabled: false
    ingressClassName: nginx
    annotations:
      nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
      nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
#    extraTls:
#      - hosts:
#        - argocd.example.com
#        # Based on the ingress controller used secret might be optional
#        secretName: wildcard-tls
EOF

helm upgrade --install argocd \
./argo-cd \
-n argocd \
--create-namespace \
-f new-values.yaml

列出安装的信息

sh 复制代码
helm ls -n argocd

检查服务

确保每个Pod都是Running状态,目前安装的argocd是无状态应用,一般只需要确认为Running状态基本就可以判定为服务正常运行了

bash 复制代码
kubectl get po,svc,secret -n argocd

记录其内网 IP 及端口。本例子是192.168.3.107:443

等待Pod安装部署完成后,测试访问:

sh 复制代码
curl -k -v https://argocd.app.com

检查示例服务响应的状态码,200即为正常

frps服务器配置

  1. 下载公网服务器的frp二进制文件
bash 复制代码
os="linux"
arch="amd64"
version="v0.65.0"
wget https://github.com/fatedier/frp/releases/download/$version/frp_$version_$os_$arch.tar.gz
tar -zxvf frp_$version_$os_$arch.tar.gz
cp frp_$version_$os_$arch/* /usr/local/bin
  1. 编写配置
bash 复制代码
cat > frps-argocd-custom-tls.toml <<EOF
# 基础配置
bindAddr = "0.0.0.0"
bindPort = 7000          # frpc 客户端连接到 frps 的端口

# HTTP/HTTPS 虚拟主机端口(TCP 透传不需要,但保持默认配置以备将来使用)
vhostHTTPPort = 80
vhostHTTPSPort = 443

# Dashboard 配置 (可选,用于监控)
webServer.addr = "127.0.0.1"
webServer.port = 7500
webServer.user = "admin"
webServer.password = "admin"

# 认证配置
auth.method = "token"
auth.token = "YOUR_SECURE_TOKEN_FOR_FRP" # <--- 修改为一个安全的 Token
# 将 YOUR_SECURE_TOKEN_FOR_FRP 替换为一个随机字符串,frpc 需使用相同的值。

log.to = "./frps.log"
log.level = "info"
EOF

配置客户端

  1. 下载公网服务器的frp二进制文件,将osarch改成你本地机器的系统架构
bash 复制代码
os="darwin"
arch="arm64"
version="v0.65.0"
wget https://github.com/fatedier/frp/releases/download/$version/frp_$version_$os_$arch.tar.gz
tar -zxvf frp_$version_$os_$arch.tar.gz
cp frp_$version_$os_$arch/* /usr/local/bin

该配置将内网的HTTPS 服务 (192.168.3.107:443) 映射到 frps 的 5002 端口上。

sh 复制代码
cat > frpc-argocd-custom-tls.toml <<EOF
# 您的 frps 服务器地址和端口
# 请根据您的实际 frps 部署地址进行修改
serverAddr = "apikv.com"
serverPort = 7000 # 假设您的 frps 监听在 7000 端口

#user = "your_argocd_user" # 可选,建议设置一个唯一标识
#loginFailExit = true

# 日志配置
log.to = "./frpc.log"
log.level = "info"
log.maxDays = 3

# 认证配置
#auth.method = "token"
#auth.token = "12345678" # **替换为您 frps 配置中实际的 token

# 传输配置
# 保持默认的 TLS 连接到 frps,增加安全性
transport.tls.enable = true
transport.protocol = "tcp"

# 代理配置
# --------------------------------------------------

[[proxies]]
# 代理名称,建议命名具有辨识度
name = "argocd_https_tcp"
# 使用 tcp 协议进行透传
type = "tcp"
# 内网 ArgoCD 服务器的 IP 和 HTTPS 端口
localIP = "192.168.3.107"
localPort = 443
# frps 服务器上监听的公网端口
remotePort = 5002

# 如果您希望增加一层加密和压缩,可以启用(但会增加 CPU 开销)
# transport.useEncryption = true
# transport.useCompression = false

# 可选:如果您的 frps 启用了健康检查或负载均衡
# healthCheck.type = "tcp"
# healthCheck.timeoutSeconds = 3
# healthCheck.maxFailed = 3
# healthCheck.intervalSeconds = 10
EOF

部署和访问步骤

  1. 修改 Token : 务必在 frps.tomlfrpc.toml 中将 auth.token 替换为一个安全的、唯一的字符串。

  2. frps 部署 : 在公网服务器上启动 frps,启动不报错即为正常运行,日志文件配置在了当前目录下的frpc.log

    bash 复制代码
    frps -c ./frps-argocd-custom-tls.toml

    查看日志:

    sh 复制代码
    cat frpc.log

确保公网服务器的防火墙已放行 TCP 端口 7000 (frp连接) 和 5002 (内网服务端口)

  1. frpc 部署 : 在内网机器上启动 frpc,启动不报错即为正常运行,日志文件是日志文件配置在了当前目录下的frpc.log

    bash 复制代码
    frpc -c ./frpc-argocd-custom-tls.toml

    查看日志:

    sh 复制代码
    cat frpc.log
  1. 公网访问: 通过以下地址访问您的内网服务:

    arduino 复制代码
    https://example.com:5002

    如果你的服务使用的是 自签名证书,浏览器访问时会提示"证书不安全/隐私错误",这是正常的,有需要可以另行配置,继续访问即可。

参考资料

  1. github.com/fatedier/fr...
  2. 完整的frps示例: github.com/fatedier/fr...
  3. 完整的frpc示例:github.com/fatedier/fr...
相关推荐
Victor3562 小时前
Redis(104)Redis的最大数据量是多少?
后端
Victor3563 小时前
Redis(105)Redis的数据类型支持哪些操作?
后端
鬼火儿10 小时前
SpringBoot】Spring Boot 项目的打包配置
java·后端
cr7xin10 小时前
缓存三大问题及解决方案
redis·后端·缓存
间彧11 小时前
Kubernetes的Pod与Docker Compose中的服务在概念上有何异同?
后端
间彧11 小时前
从开发到生产,如何将Docker Compose项目平滑迁移到Kubernetes?
后端
间彧11 小时前
如何结合CI/CD流水线自动选择正确的Docker Compose配置?
后端
间彧11 小时前
在多环境(开发、测试、生产)下,如何管理不同的Docker Compose配置?
后端
间彧11 小时前
如何为Docker Compose中的服务配置健康检查,确保服务真正可用?
后端
间彧11 小时前
Docker Compose和Kubernetes在编排服务时有哪些核心区别?
后端