배경

Traefik Ingress를 붙인 덕에, tailnet(Tailscale 사설망) 안에서는 세 노드 IP 아무거나 80번 포트로 접속하면 target-tracking-service가 항상 정상 라우팅되는 상태였다. 데모 URL을 다른 사람에게 공유하려면 한 단계가 더 필요했다 — 그게 Tailscale Funnel이다.

개념 정리 — mesh / Serve / Funnel은 다른 층위다

<table header-row="true"><tr><td></td><td>접속 범위</td><td>용도</td></tr><tr><td>Tailscale mesh (기본)</td><td>같은 tailnet에 속한 기기끼리만 (100.x.x.x)</td><td>kubectl 클러스터 접속, 노드 간 통신</td></tr><tr><td>tailscale serve</td><td>mesh 안에서 포트 매핑</td><td>tailnet 내부용 리버스 프록시</td></tr><tr><td>tailscale funnel</td><td>공인 인터넷 전체</td><td>serve의 매핑 중 지정한 것 하나만 인터넷에도 노출</td></tr></table>

즉 funnel은 serve 위에 얹히는 "이 매핑 하나만 공개해도 좋다"는 명시적 오픈 아웃 스위치다.

실제 확인한 설정

k3s-master 노드(100.103.119.1)에서 sudo tailscale funnel status로 확인한 결과:

Funnel on:
    - https://k3s-master.taildcdcee.ts.net

https://k3s-master.taildcdcee.ts.net (Funnel on)
|-- / proxy http://localhost:80

이 상태는 그 노드에서 sudo tailscale funnel 80을 실행하면 만들어지는 결과와 일치한다 — 로컬 80번 포트를 [https://k3s-master.taildcdcee.ts.net(443,](https://k3s-master.taildcdcee.ts.net(443,) TLS)로 공개 매핑한 것.

인증서는 어디서 나오나

*.ts.net 서브도메인용 인증서는 Tailscale이 Let's Encrypt를 통해 자동으로 발급·갱신한다. 별도로 도메인을 사거나 인증서를 직접 관리할 필요가 없다.

요청이 실제로 흘러가는 경로

인터넷 (누구나)
   │  https://k3s-master.taildcdcee.ts.net
   ▼
Tailscale Funnel (k3s-master 노드의 tailscaled)
   │  TLS 종료 후 → http://localhost:80
   ▼
k3s-master의 로컬 80번 포트
   │  Traefik Service가 LoadBalancer 타입이라 k3s 내장 ServiceLB(svclb-traefik)가
   │  클러스터의 모든 노드에서 80/443을 열어둔 → k3s-master도 예외 아님
   ▼
Traefik (kube-system, Ingress Controller)
   │  ingress.yaml 규칙 매칭 (Host *, path /)
   ▼
target-tracking-service ClusterIP Service (8080)
   ▼
target-tracking-service Pod → C4I 지휘통제 대시보드 응답

핵심은 Funnel이 Traefik의 기존 진입점(80번 포트)에 그대로 얹힌다는 것 — 이미 클러스터 전체 노드에 열려 있던 Traefik의 80번 포트를 그대로 인터넷에 재노출한 것일 뿐. Ingress 규칙을 새로 만들 필요도 없었다.

노출 범위와 한계

관련 문서