Tailscale Kubernetes Operator 설정 가이드
개요
이 가이드는 Tailscale Kubernetes Operator를 설정하여 웹 앱(myapp.example.com)을 Tailscale 네트워크에만 노출하는 방법을 설명합니다. 설정 완료 후 Tailscale VPN에 연결된 사용자만 앱에 접근할 수 있습니다.
아키텍처
현재 구성:
인터넷 → Cloudflare → NGINX Ingress → K8s 서비스 (NextJS, FastAPI, RQ Dashboard)
Tailscale 설정 후:
Tailscale 네트워크 → K8s 서비스 (Tailscale Operator 경유)
도메인 옵션
커스텀 도메인(myapp.example.com)을 Tailscale과 함께 사용할 수 있나요?
짧은 답변: 네, 하지만 CNAME으로는 안 됩니다.
CNAME이 안 되는 이유:
- MagicDNS 이름(예:
myapp.your-tailnet.ts.net)은 Tailscale 네트워크 내에서만 해석됨 - 공개 DNS에 존재하지 않음
- 공개 CNAME
myapp.example.com→myapp.your-tailnet.ts.net은 해석 실패
선택지:
| 옵션 | 접근 URL | 공개 접근 | Tailscale 플랜 | 난이도 |
|---|---|---|---|---|
| MagicDNS만 | myapp.your-tailnet.ts.net | 없음 | 무료 | 쉬움 |
| Split-Horizon DNS (추천) | myapp.example.com | 차단 또는 “VPN 필요” 페이지 | 무료 | 보통 |
| Tailscale 커스텀 도메인 | myapp.example.com | 없음 | Business/Enterprise | 쉬움 |
| Exit Node + IP 화이트리스트 | myapp.example.com | Exit node 경유만 | 무료 | 보통 |
추천: Split-Horizon DNS
이 가이드는 Split-Horizon DNS에 초점을 맞춥니다:
- ✅
myapp.example.com계속 사용 가능 - ✅ 무료 Tailscale 플랜으로 가능
- ✅ 진정한 VPN 전용 접근 제공
- ✅ Exit node나 추가 인프라 불필요
자세한 설정은 Step 8.5를 참조하세요.
사전 준비
- Tailscale 계정 (무료 등급 가능)
- GKE 클러스터 관리자 권한
- 클러스터에 설정된
kubectl - 로컬에 Helm 설치
- Tailscale 인증 키 (Step 1에서 생성)
Step 1: Tailscale 인증 키 생성
-
Tailscale 관리 콘솔로 이동
-
Generate auth key 클릭
-
키 설정:
- 설명:
my-app-k8s-operator - 재사용 가능: ✅ 활성화 (operator가 여러 노드 생성 가능)
- 임시: ❌ 비활성화 (네트워크에 노드를 영구적으로 유지)
- 사전 승인: ✅ 활성화 (디바이스 자동 승인)
- 태그:
tag:k8s추가 (없으면 생성) - 만료: 90일 또는 만료 없음으로 설정
- 설명:
-
생성된 키 복사 (
tskey-auth-...로 시작) -
임시 저장 - Step 3에서 필요
Step 2: Tailscale Kubernetes Operator 설치
옵션 A: Helm 사용 (추천)
# Tailscale Helm 저장소 추가
helm repo add tailscale https://pkgs.tailscale.com/helmcharts
helm repo update
# Operator 설치
helm upgrade --install \
tailscale-operator \
tailscale/tailscale-operator \
--namespace=tailscale \
--create-namespace \
--set-string oauth.clientId="<YOUR_OAUTH_CLIENT_ID>" \
--set-string oauth.clientSecret="<YOUR_OAUTH_CLIENT_SECRET>" \
--wait
참고: OAuth 자격 증명은 Tailscale OAuth Clients에서 다음 스코프로 새 OAuth 클라이언트를 생성하세요:
devices:write
옵션 B: kubectl 사용 (대안)
# Operator 매니페스트 다운로드 및 적용
kubectl apply -f https://github.com/tailscale/tailscale/raw/main/cmd/k8s-operator/deploy/manifests/operator.yaml
# 설치 확인
kubectl get pods -n tailscale-system
Step 3: Tailscale OAuth 클라이언트 생성 (Operator용)
Operator는 사용자 대신 디바이스를 관리하기 위해 OAuth 자격 증명이 필요합니다.
-
Generate OAuth client 클릭
-
설정:
- 설명:
k8s-operator-my-app - 스코프:
devices:write(필수)routes:write(선택, 서브넷 라우팅용)dns:write(선택, MagicDNS용)
- 태그:
tag:k8s
- 설명:
-
Client ID와 Client Secret 복사
-
Kubernetes 시크릿 생성:
kubectl create secret generic operator-oauth \
--namespace=tailscale \
--from-literal=client-id="<YOUR_OAUTH_CLIENT_ID>" \
--from-literal=client-secret="<YOUR_OAUTH_CLIENT_SECRET>"
Step 4: Operator가 OAuth 시크릿을 사용하도록 설정
Operator를 위한 values 파일 생성:
cat > tailscale-operator-values.yaml <<EOF
oauth:
clientId: "<YOUR_OAUTH_CLIENT_ID>"
clientSecret: "<YOUR_OAUTH_CLIENT_SECRET>"
apiServerProxyConfig:
mode: "true"
EOF
Operator 설치 업데이트:
helm upgrade --install \
tailscale-operator \
tailscale/tailscale-operator \
--namespace=tailscale \
--create-namespace \
-f tailscale-operator-values.yaml \
--wait
Step 5: 서비스를 Tailscale에 노출
두 가지 접근 방법이 있습니다:
접근법 A: 서비스 레벨 노출 (추천)
각 서비스에 어노테이션을 추가하여 개별 서비스를 노출합니다.
NextJS 서비스:
apiVersion: v1
kind: Service
metadata:
name: app-nextjs
namespace: { { .Release.Namespace } }
annotations:
tailscale.com/expose: "true"
tailscale.com/hostname: "app-nextjs"
spec:
type: LoadBalancer
loadBalancerClass: tailscale
ports:
- name: http
port: 3000
targetPort: 3000
selector:
app: app-nextjs
FastAPI 서비스:
apiVersion: v1
kind: Service
metadata:
name: app-fastapi
namespace: { { .Release.Namespace } }
annotations:
tailscale.com/expose: "true"
tailscale.com/hostname: "app-fastapi"
spec:
type: LoadBalancer
loadBalancerClass: tailscale
ports:
- name: http
port: 8000
targetPort: 8000
selector:
app: app-fastapi
접근법 B: Ingress 레벨 노출
모든 서비스로 라우팅하는 단일 Tailscale 인그레스 프록시를 생성합니다. values.yaml에 추가:
tailscale:
enabled: false # 준비되면 true로 설정
hostname: "myapp" # myapp.your-tailnet.ts.net으로 접근 가능
Step 6: 업데이트된 설정 배포
helm upgrade my-app ./k8s/charts/my-app \
-f path/to/values-orbit.yaml \
--namespace my-app
Step 7: Tailscale 디바이스 확인
- Tailscale 관리 콘솔 → Machines로 이동
- 새 디바이스 확인
- 각 디바이스는 Tailscale IP(100.x.x.x)와 MagicDNS 이름을 가짐
Step 8: Tailscale로 앱 접근
- 디바이스에서 Tailscale 연결
- MagicDNS로 앱 접근:
- NextJS:
http://app-nextjs.your-tailnet.ts.net:3000 - FastAPI:
http://app-fastapi.your-tailnet.ts.net:8000
- NextJS:
- 접근 테스트 - Tailscale 연결 시에만 접근 가능한지 확인
Step 9: Tailscale ACL 설정 (선택 사항)
Tailscale ACL로 접근 제어:
{
"acls": [
{
"action": "accept",
"src": ["autogroup:members"],
"dst": ["tag:k8s:*"]
}
],
"tagOwners": {
"tag:k8s": ["autogroup:admin"]
}
}
트러블슈팅
Operator 파드가 시작되지 않음
kubectl logs -n tailscale -l app=operator
kubectl describe deployment -n tailscale tailscale-operator
서비스에 Tailscale IP가 할당되지 않음
kubectl get svc -n my-app
kubectl describe svc app-nextjs -n my-app
kubectl logs -n tailscale -l app=operator --tail=100