보안 강화와 Tailscale VPN으로 외부 접근 설정하기 (홈랩 k8s 구축기 6편)

munilive
munilive
보안 강화와 Tailscale VPN으로 외부 접근 설정하기 (홈랩 k8s 구축기 6편)

지난 편에서 모니터링 스택을 올렸다. 이번 편은 마지막으로, 보안 강화와 외부 접근 설정이다.

보안을 신경 쓰는 이유

홈랩이라고 해도 실제 서비스를 운영하려면 보안을 무시할 수 없다. DB에는 실제 데이터가 들어가고, CI/CD 파이프라인에는 GitHub 토큰 같은 시크릿이 오간다. 클러스터 내부라고 해서 아무 Pod이나 아무 곳에나 접근할 수 있게 두는 것은 좋지 않다.

세 가지를 구성했다. Kyverno로 정책을 적용하고, Network Policy로 네임스페이스 간 트래픽을 격리하고, kube-bench로 현재 보안 상태를 정기적으로 점검한다.

Kyverno

Kyverno는 Kubernetes 네이티브 정책 엔진이다. Pod이 생성될 때 정책을 검사해서 위반하면 차단(Enforce)하거나 기록(Audit)할 수 있다.

홈랩에서는 Audit 모드로만 적용했다. Enforce 모드로 걸어두면 기존에 돌고 있는 시스템 컴포넌트들이 정책에 걸려서 재배포가 안 되는 상황이 생길 수 있기 때문이다. 일단 어떤 것들이 위반하는지 기록으로 남겨두고, 나중에 상황을 보면서 Enforce로 전환할 생각이다.

적용한 정책은 세 가지다.

정책내용
disallow-privileged-containersprivileged 컨테이너 감사
require-resource-limitsCPU/Memory limits 미설정 감사
disallow-latest-tag:latest 이미지 태그 사용 감사

세 번째 정책이 실제로 가장 유용하다고 느꼈다. :latest 태그를 쓰면 이미지가 언제 바뀌었는지 추적하기 어렵고, 의도치 않게 다른 버전이 배포될 수 있다. Audit 기록을 보면서 어떤 것들이 걸리는지 확인해두었다.

Network Policy

DB, 캐시, 메시지 브로커가 들어있는 네임스페이스는 기본적으로 격리하고, 허용할 트래픽만 명시적으로 열어두었다.

databases, queues, caches 네임스페이스에 default-deny 정책을 적용하면 기본적으로 모든 트래픽이 차단된다. 그 위에 허용 규칙을 추가하는 방식이다.

  • apps 네임스페이스 → DB, 캐시 접근 허용
  • apps, console 네임스페이스 → Kafka 접근 허용
  • DNS(53) egress는 모든 네임스페이스에서 허용 (DNS가 막히면 아무것도 안 된다)

이렇게 해두면 default 네임스페이스에서 아무 Pod이나 띄워서 내부 DB에 접근하는 것이 불가능해진다.

kube-bench

kube-bench는 CIS Kubernetes Benchmark를 기준으로 클러스터 보안 설정을 점검해주는 도구다. CronJob으로 매주 일요일에 자동 실행되도록 설정했다.

처음 실행 결과는 이랬다.

결과
PASS69
FAIL12
WARN41
INFO8

FAIL 12개를 보고 처음엔 당황했는데, 내용을 보니 대부분 프로덕션 환경 전용 설정들이었다. 감사 로그 활성화, etcd 암호화, API 서버 고급 인증 설정 같은 것들인데, 홈랩에서 당장 필요한 항목들은 아니었다. WARN 항목들도 비슷한 맥락이었다.

그래도 kube-bench 결과를 주기적으로 확인해두면, 설정 변경 후 의도치 않게 보안 수준이 낮아지는 것을 감지할 수 있다.

결과를 확인하는 방법도 조금 다듬었다. 처음에는 CronJob이 실행된 후 kubectl logs로 직접 들어가서 봐야 했는데, 어차피 Jenkins도 올라와 있으니 Jenkins Pipeline으로 연결해두면 더 편할 것 같았다. kube-bench CronJob을 실행하고 완료를 기다린 뒤 결과를 Console Output으로 출력하는 파이프라인을 만들었다. Jenkins에서 수동으로 실행하거나 매주 자동으로 실행되는데, 결과를 보려고 일부러 터미널을 열 필요가 없어졌다.

Tailscale — 외부에서 내부 서비스에 접근하기

ArgoCD, Grafana, Jenkins는 내부 네트워크에서만 접근 가능하도록 구성했다. 집 밖에서 이 서비스들에 접근하려면 VPN이 필요하다.

Tailscale을 선택했다. 설치가 간단하고, Subnet Router 기능이 있어서 클러스터 내부 IP 대역 전체를 VPN을 통해 접근 가능하게 만들 수 있다. 각 서비스마다 포트를 열거나 복잡한 설정을 할 필요 없이, k8s 클러스터 안의 Tailscale Pod이 게이트웨이 역할을 해준다.

로컬 Mac (Tailscale 클라이언트)
    ↓ VPN
k8s-homelab (Tailscale Subnet Router)

k8s 내부 네트워크
    ├── Service CIDR: 10.96.0.0/12
    └── Pod CIDR: 10.244.0.0/16

Tailscale k8s 배포는 StatefulSet으로 구성했고, Auth Key는 Sealed Secret으로 관리한다.

Split DNS

VPN 연결만으로는 충분하지 않다. ArgoCD, Grafana 같은 서비스들은 내부 도메인으로 접근하도록 되어있는데, 그 도메인이 외부 DNS에는 등록되어 있지 않다.

Tailscale의 Split DNS 기능을 활용했다. 내부 도메인에 대한 DNS 요청을 k8s CoreDNS로 보내도록 설정해두면, VPN 연결 상태에서는 내부 도메인이 정상적으로 해석된다.

Tailscale 대시보드에서 두 가지를 설정했다.

도메인DNS 서버역할
cluster.localCoreDNS IPk8s 내부 서비스
내부 도메인CoreDNS IPArgoCD, Grafana 등

이 설정 후 집 밖에서 Tailscale을 켜면 ArgoCD나 Grafana에 도메인으로 바로 접근할 수 있게 됐다.

마무리

6편에 걸쳐 홈랩 Kubernetes 클러스터 구축 과정을 기록했다. VM 3개로 시작해서 CI/CD, 모니터링, 보안, VPN 접근까지 꽤 많은 것이 올라왔다.

아직 남아있는 것들도 있다. Cloudflare Tunnel을 통해 실제 서비스를 외부에 노출하는 것, 추가 노드를 붙이는 것, 실제 서비스 앱을 올려서 운영해보는 것. 인프라 기반은 갖춰졌으니, 이제 그 위에서 실제로 무언가를 만들어볼 차례다.

이 기록이 비슷한 고민을 하고 있는 누군가에게 조금이라도 도움이 되었으면 좋겠다.

munilive

munilive

Backend Application Developer

Share

Comments

Related Posts

Prometheus, Grafana, Loki로 모니터링 구성하기 (홈랩 k8s 구축기 5편)

Prometheus, Grafana, Loki로 모니터링 구성하기 (홈랩 k8s 구축기 5편)

지난 편에서 CI/CD 파이프라인을 구성했다. 이번 편은 모니터링이다. 클러스터가 잘 돌아가고 있는지, 어디서 문제가 생겼는지 파악하려면 메트릭과 로그를 봐야 한다. 그리고 이번…

munilive munilive ·
Jenkins, ArgoCD, Harbor로 CI/CD 파이프라인 구성하기 (홈랩 k8s 구축기 4편)

Jenkins, ArgoCD, Harbor로 CI/CD 파이프라인 구성하기 (홈랩 k8s 구축기 4편)

지난 편에서 네트워크와 스토리지를 구성했다. 이번에는 코드를 빌드하고 클러스터에 배포하는 파이프라인을 만드는 차례다. CI/CD를 왜 직접 구성하는가 GitHub Actions를…

munilive munilive ·
MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

MetalLB, ingress-nginx, Longhorn으로 네트워크와 스토리지 구성하기 (홈랩 k8s 구축기 3편)

지난 편에서 Ansible로 Kubernetes 클러스터를 구성했다. 클러스터는 올라왔지만, 이 상태로는 아무것도 할 수 없다. 외부에서 트래픽을 받는 방법도 없고, 데이터를 저장…

munilive munilive ·