基于k8s的内网穿透与服务共存

背景

由于国内的vps要搭建网站都需要备案,所以目前自己的一些服务是在香港的一台vps上;同时自己家里部署了一些服务比如nas需要在外部访问,当前是用另一台vps做的内网穿透,本着能省一点是一点的原则,遂想着将这两个能力放到一台vps上。

核心问题

由于不想每次访问时还需要输入端口号,最理想的方案肯定是都是用80/443端口来访问,但这样内网穿透的端口就会和ingress的端口冲突;
理想的方案是内网穿透的服务不直接占用主机端口,而是通过域名区分,需要穿透的域名转发到内网穿透服务。

解决方案

搭建步骤

vps端部署

搭建k8s集群

由于vps上资源并不富裕,所以这里我使用的是k3s,执行curl -sfL https://get.k3s.io | sh - --disable traefik,注意我后面使用了ingress nginx所以增加了--disable traefik参数禁止默认使用traefik,理论上traefik也行,但是后面ingress的配置可能会有点不同。

部署ingress nginx

# 添加官方 Nginx Ingress helm repository
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# 使用 Helm 安装 Nginx Ingress
helm install nginx-ingress ingress-nginx/ingress-nginx --namespace kube-system

部署frps

其他没啥特别的,只有service中注意frps的连接端口需要使用NodePort

apiVersion: v1
kind: Service
metadata:
  labels:
    app: frps-svc
  name: frps-svc
  namespace: frps
spec:
  ports:
    - name: server
      port: 10000
      protocol: TCP
      targetPort: 10000
      nodePort: 34567
  selector:
    app: frps-server
  type: NodePort

部署cert manager

由于需要在k8s侧就要做域名的区分,所以需要将tls证书放到k8s侧,同时使用cert manager能够自动进行证书的renew,简化后续维护

helm repo add jetstack https://charts.jetstack.io --force-update
helm repo update

helm install \
  cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.14.2 \
  --set installCRDs=true

创建letsencrypt issuer

issuer有ClusterIssuer和Issuer两种,ClusterIssuer是全集群生效,一种只在对应的namespace生效,相应的ingress需要创建在这个namespace。这里我们使用Issuer,因为我们后续需要生成泛域名证书,如果使用ClusterIssuer其中有一步报错一直没查到原因(可能是不支持)。泛域名证书的solver只能使用dns01,关于这里的配置可以参考这里,这里我是用的是Cloudflare

apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: letsencrypt-dns
  namespace: frps
spec:
  acme:
    email: example@youmail.com
    privateKeySecretRef:
      name: letsencrypt-dns
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
      - dns01:
          cloudflare:
            apiTokenSecretRef:
              key: api-token
              name: cloudflare-api-token-secret

创建内网穿透的service

后续请求经过ingress后通过这个service转发到内网穿透服务

apiVersion: v1
kind: Service
metadata:
  labels:
    app: frps-http
  name: frps-http
  namespace: frps
spec:
  ports:
    - name: server-http
      port: 38080
      protocol: TCP
      targetPort: 38080
  selector:
    app: frps-server
  type: ClusterIP

创建ingress

注意这里创建的是泛域名的ingress,这样后续要增加服务,在vps侧是不需要增加任何配置的

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: wildcard-ingress
  namespace: frps
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - "*.yourdomain.com"
      secretName: my-tls
  rules:
    - host: "*.yourdomain.com"
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frps-http
                port:
                  number: 38080

到这里,在vps上的配置就ok了

内网服务搭建

由于家里的服务不止一个,如果经过内网穿透直接映射到服务的endpoint,则frpc的配置就会变得比较复杂,vps侧的service也需要配置多个端口,所以我在内网再部署了一层nginx,再通过nginx转发到各个服务上,这样内网穿透就只需要配置一个80端口即可。nginx的具体配置这里就不列出来了,需要注意的是只需要配置listen 80端口即可,server name需要和vps侧配置相同。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容