-
[HomeLab] Tailscale 을 쿠버네티스에 배포하기DevOps, 클라우드/Container 2024. 7. 5. 00:52
서론
인터넷에서 내 클러스터로 들어오는 인바운드는 모두 허용할 수 없었다.
외부에 노출시킬 서비스를 제외하고는 VPN 등을 통해서 접근하게 해야했다.
기존에는 Tailscale을 통해 각 노드에 직접 접근했으나 Calico와의 충돌 문제가 있었다.Tailscale은 쿠버네티스에 배포할 수 있다.
이게 무슨 소리냐면 VPN 대역에서만 접근할 수 있는 Tailscale 서비스를 클러스터에 배포할 수 있다는 뜻이다.
내 사설망에 일종의 VPN Ingress-Controller가 생기는 셈이다.배포 유형은 3가지를 지원한다고 한다.
- 프록시
- Tailscale 프록시를 통해서 쿠버네티스 서비스와 통신할 수 있도록 해준다.
- 다만, 통신하려는 '서비스' 외에 다른 쿠버네티스 리소스에 접근하거나 제어할 수 없다.
- 사이드카
- 특정 파드에 사이드카 형태로 배포한다.
- VPN 대역에서 파드를 토출할 수 있다.
- 서브넷 라우터
- 쿠버네티스 클러스터 네트워크 전체를 VPN 대역에 노출한다.
- 쿠버네티스 네트워크 정책이나 Tailscale의 접근 제어가 허용한다면 클러스터의 모든 포드 또는 서비스에 연결할 수 있다.
위와 같은 배포 유형 중 어떤 배포 방식을 선택할지 고민했다.
우선 (2.) 사이드카 방식의 경우, 작은 규모의 클러스터에 불필요한 부하를 더 줄 것이라 판단했다.
(1.) 프록시 방식은 내가 가진 규모의 클러스터에서 좀 더 모범 사례에 가까울 것 같았다.
다만, 아직 설정할 것이 많고 이미 구축된 서비스 외에 외부에서 접근할 일이 있다면 (3.) 서브넷 라우터가 좀 더 적합한 방식일 것이라 판단했다.Tailscale를 쿠버네티스 클러스터에 배포하기
우선 Tailscale에서 인증키를 발급받자.
관리자 콘솔에서Settings
탭을 누르면 좌측의Key
메뉴에서 인증키를 발급 받을 수 있다.우리의 클러스터에는 외부에 노출되지 않은 서비스가 있다고 가정한다.
apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:latest ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginxapp spec: selector: app: nginx ports: - port: 80 targetPort: 80
생성한 키를 쿠버네티스의 시크릿 리소스로 생성한다.
apiVersion: v1 kind: Secret metadata: name: ts_key type: Opaque data: TAILSCALE_KEY: <YOUR_BASE64_ENCODED_TAILSCALE_KEY> # 평문 키를 사용할 경우 # stringData: # TAILSCALE_KEY: <YOUR_PLAIN_TAILSCALE_KEY>
앞서 등록한 시크릿 키를 활용하는 서비스 어카운트를 생성한다.
Tailscale 파드는 서비스 어카운트에 접근해 인증할 때 시크릿 키를 사용한다.이 서비스 어카운트로 Tailscale 파드를 동작시키며 RBAC에서 허용된 권한으로 클러스터에 접근할 수 있다.
현재의 Role을 살펴보면...
ts_key
시크릿 리소스에 대한 일부 read/write 권한을 허용한다.- 이 Role은
tailscale
서비스 어카운트에 붙어있다.
apiVersion: v1 kind: ServiceAccount metadata: name: tailscale --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: tailscale rules: - apiGroups: [""] resourceNames: ["ts_key"] resources: ["secrets"] verbs: ["get", "update", "patch"] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: tailscale subjects: - kind: ServiceAccount name: tailscale roleRef: kind: Role name: tailscale apiGroup: rbac.authorization.k8s.io
이제는 Tailscale 파드를 배포하자.
앞서 말한 것처럼 서브넷 라우터 방식으로 배포할 것이다.apiVersion: v1 kind: Pod metadata: name: tailscale-subnet spec: serviceAccountName: tailscale containers: - name: tailscale image: ghcr.io/tailscale/tailscale:v1.68.1 env: - name: TS_KUBE_SECRET value: ts_key - name: TAILSCALE_KEY valueFrom: secretKeyRef: name: ts_key key: TAILSCALE_KEY - name: TS_ROUTES value: "<POD_CIDR>,<SERVICE_CIDR>" - name: TS_USERSPACE value: "true" securityContext: runAsUser: 1000 runAsGroup: 1000 resources: limits: memory: 512Mi cpu: "1" requests: memory: 256Mi cpu: "0.2"
여기서 각 env를 살펴보면 다음과 같다.
TAILSCALE_KEY
: 먼저 등록한 tailscale 시크릿이다.TS_ROUTES
: CNI가 지원하는 Pod 대역, 서비스 대역을 콤마로 구분한 문자열이다.TS_USERSPACE
: tailscale이 유저공간 네트워킹을 사용하도록 한다.
위와 같이 파드를 배포하고 확인해보면 다음과 같이
tailscale-subnet
파드가 생성된 것을 확인할 수 있다.
지금은 namespace를 설정하지 않아서 default ns에 생성되었다.kubectl apply -f tailscale.deployment.yaml pod/tailscale-subnet created kubectl get pods NAME READY STATUS RESTARTS AGE tailscale-subnet 1/1 Running 1 (68s ago) 2m21s
Tailscale 콘솔에서 라우팅 설정하기
이제 Tailscale 관리자 콘솔에서 Machine 목록을 확인하면 서브넷 라우터로 배포한 `tailscale-subnet` 파드가 등록된 것을 확인할 수 있다.
이제 라우팅 설정을 하기 위해 해당 머신(파드)의 라우팅 설정에 들어간다.
라우팅 설정에는 앞서 `TSROUTE` 로 설정한 파드 CIDR 대역과 서비스 CIDR 대역이 있다.
이 대역으로 라우팅을 허용하자.
Cluster-IP로 배포된 Internal 서비스 접근하기
라우팅 설정까지 완료하면 우린 서비스의 Cluster-IP로 접근할 수 있다.
물론 Tailscale VPN을 켜야한다.
내부에서만 접근할 ArgoCD 서비스를 VPN를 통해서만 접근할 수 있도록 설정했다.
VPN 자체도 구축해보고 싶었는데 우선 편의성과 내 시간을 지키기 위해서 이 방법을 선택했다.
참고
https://tailscale.com/learn/managing-access-to-kubernetes-with-tailscale
'DevOps, 클라우드 > Container' 카테고리의 다른 글
[CNI] 처음 열어보는 CNI 스펙 (0) 2024.10.11 [HomeLab] K8S 노드에 Label 추가하기 (0) 2024.07.21 [HomeLab] Calico와 Tailscale 충돌 문제 (0) 2024.06.22 라즈베리파이를 이용한 멀티 노드 클러스터링 (4) - Spring Boot (0) 2022.04.06 라즈베리파이를 이용한 멀티 노드 클러스터링 (3) - MySQL (0) 2022.04.05 - 프록시