Posted on:February 4, 2026 at 12:00 AM

Tailscale Kubernetes Operator 설정 가이드

Tailscale Kubernetes Operator 설정 가이드

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.commyapp.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.comExit 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 인증 키 생성

  1. Tailscale 관리 콘솔로 이동

  2. Generate auth key 클릭

  3. 키 설정:

    • 설명: my-app-k8s-operator
    • 재사용 가능: ✅ 활성화 (operator가 여러 노드 생성 가능)
    • 임시: ❌ 비활성화 (네트워크에 노드를 영구적으로 유지)
    • 사전 승인: ✅ 활성화 (디바이스 자동 승인)
    • 태그: tag:k8s 추가 (없으면 생성)
    • 만료: 90일 또는 만료 없음으로 설정
  4. 생성된 키 복사 (tskey-auth-...로 시작)

  5. 임시 저장 - 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 자격 증명이 필요합니다.

  1. Tailscale 관리 콘솔 → Settings → OAuth Clients로 이동

  2. Generate OAuth client 클릭

  3. 설정:

    • 설명: k8s-operator-my-app
    • 스코프:
      • devices:write (필수)
      • routes:write (선택, 서브넷 라우팅용)
      • dns:write (선택, MagicDNS용)
    • 태그: tag:k8s
  4. Client IDClient Secret 복사

  5. 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 디바이스 확인

  1. Tailscale 관리 콘솔 → Machines로 이동
  2. 새 디바이스 확인
  3. 각 디바이스는 Tailscale IP(100.x.x.x)와 MagicDNS 이름을 가짐

Step 8: Tailscale로 앱 접근

  1. 디바이스에서 Tailscale 연결
  2. MagicDNS로 앱 접근:
    • NextJS: http://app-nextjs.your-tailnet.ts.net:3000
    • FastAPI: http://app-fastapi.your-tailnet.ts.net:8000
  3. 접근 테스트 - 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

참고 문서