여러 대륙에 걸친 Kubernetes: 전 세계 데이터센터에서 k3s와 k8s를 고가용성으로 운영하기

게시일 읽는 시간 27분

미국, 유럽, 아시아에 걸쳐 대륙 하나가 통째로 멈춰도 버티는 Kubernetes: etcd가 장거리 연결을 견디지 못하는 이유, 리전별 k3s 클러스터, Flux를 이용한 GitOps, Geo-DNS 페일오버, 리전 간 데이터, kubeadm과의 차이를 다룹니다.

애플리케이션을 장애에 강하고 자동으로 확장되는 형태로 운영하고 싶다면 표준은 Kubernetes입니다. 그런데 미국, 유럽, 아시아의 서버를 묶어 Kubernetes 클러스터 하나로 구성하자는, 얼핏 자연스러워 보이는 발상은 한 가지 세부 사항에서 막힙니다. 바로 Kubernetes가 모든 상태를 저장하는 데이터베이스인 etcd입니다. 이 글에서는 그럼에도 여러 대륙에 걸친 Kubernetes를 동작하게 만드는 방법을, 그것도 대륙 하나가 통째로 장애를 겪어도 버틸 수 있는 방식으로 보여 드립니다. 리전마다 클러스터를 하나씩 두고, GitOps로 함께 배포하며, 사용자를 가장 가까운 정상 리전으로 보내는 Geo-DNS를 쓰는 방식입니다.

아키텍처는 몇 분이면 설치할 수 있는 가볍고 완전히 인증된 Kubernetes 배포판인 k3s로 구성하고, 마지막에는 kubeadm으로 구축하는 전통적인 Kubernetes에서는 무엇이 달라지는지 보여 드립니다. 여러 위치에 걸친 가용성, 쿼럼, 페일오버의 기초는 세 대륙에 걸친 Docker Swarm 글에서 자세히 다룹니다. 이 글은 Kubernetes에서 달라지는 점에 집중합니다.

모든 대륙에 걸친 클러스터 하나, 아니면 리전마다 클러스터 하나?

여러 대륙에 걸친 Kubernetes에는 모든 대륙을 아우르는 단일 클러스터가 아니라 리전마다 클러스터를 하나씩 두는 구조가 올바른 아키텍처입니다. 각 클러스터는 독립적으로 동작하고, 모든 클러스터가 같은 Git 저장소에서 배포되며, 헬스 체크를 갖춘 Geo-DNS가 사용자를 나눠 보냅니다. 한 리전에 장애가 나면 나머지 리전이 이어받으며, 이때 공유 클러스터 상태를 바다 건너로 조율할 필요가 없습니다.

etcd가 장거리 연결을 견디지 못하는 이유

Kubernetes는 모든 상태와 설정, 모든 변경 사항을 Raft 합의를 쓰는 키-값 저장소인 etcd에 저장합니다. 쓰기 작업은 하나하나 전체 etcd 멤버 중 과반수의 확인을 받아야 합니다. etcd의 기본값은 하트비트 간격 100밀리초, 선출 타임아웃 1초인데, 유럽, 북미, 아시아 사이의 패킷 지연 시간은 80~250밀리초에 이릅니다. 이 값들을 높일 수는 있지만, 그러면 파드 스케줄링부터 시크릿 저장까지 클러스터의 모든 쓰기 작업이 느려집니다. k3s 문서는 이 점을 분명히 밝힙니다. 내장 etcd는 여러 네트워크에 걸쳐 분산된 클러스터에서는 지원되지 않으며, 모든 서버는 같은 위치에 있어야 합니다. Kubernetes 자체도 클러스터 하나가 여러 대륙이 아니라 한 리전 안의 여러 영역을 담당하도록 설계되어 있습니다.

세 가지 패턴 비교

패턴동작 방식평가
모든 대륙에 걸친 단일 클러스터컨트롤 플레인과 etcd를 여러 대륙에 분산권장하지 않음: 쓰기 작업이 느리고 etcd가 불안정하며, 내장 etcd를 쓰는 k3s에서는 지원되지 않음
컨트롤 플레인은 한 리전에, 워커는 전 세계에서버는 한 위치에, 에이전트는 다른 대륙에기술적으로는 동작하지만, 컨트롤 플레인이 있는 리전에 장애가 나면 전 세계 어디에서도 더 이상 새로 스케줄링할 수 없음
리전별 클러스터독립된 클러스터 세 개를 GitOps로 함께 배포하고 앞단에 Geo-DNS를 둠권장: 각 리전이 다른 리전의 장애를 견디고, 오류는 한 리전 안에 머묾

“리전별 클러스터” 방식에는 흔히 과소평가되는 두 번째 장점이 있습니다. 컨트롤 플레인의 오류, 클러스터에 대한 잘못된 변경, 실패한 업그레이드가 언제나 한 리전에만 영향을 준다는 점입니다. 다른 리전의 사용자는 아무것도 알아채지 못합니다.

k3s와 k8s 중 무엇을 쓸까요?

둘 다 같은 API, 같은 매니페스트, 같은 도구를 쓰는 진짜 Kubernetes입니다. 차이는 구성 방식과 드는 수고에 있습니다.

항목k3skubeadm으로 구성한 k8s
설치명령 하나, 바이너리 파일 하나컨테이너 런타임, kubeadm, kubelet, 네트워크 플러그인을 각각 설정
서버 노드 하나에 필요한 리소스최소 2코어, 2 GB RAM구성 요소에 따라 훨씬 더 많이 필요
기본 포함Ingress 컨트롤러(Traefik), 네트워크(Flannel), 스토리지 프로비저너, 서비스 로드 밸런서핵심 구성 요소만 포함되며, 나머지는 모두 직접 선택
고가용성서버 세 대로 구성한 내장 etcdAPI 앞에 로드 밸런서를 둔 컨트롤 플레인 노드 세 대
적합한 경우대부분의 애플리케이션, 소규모 팀, 리전마다 단일 노드모든 구성 요소를 직접 정하고 싶은 팀

리전별 클러스터 아키텍처에는 k3s를 권장합니다. 클러스터 세 개를 운영하는 일은 각 클러스터가 단순할 때만 수월하기 때문입니다. 이미 kubeadm을 다뤄 보셨다면 아키텍처는 그대로 가져가시면 되고, 차이점은 아래의 kubeadm 섹션에서 설명합니다.

아키텍처: 리전 세 곳, 클러스터 세 개, 진입점 하나

구성 요소역할대비하는 장애
리전별 k3s 클러스터사용자와 가까운 곳에서 애플리케이션을 실행리전 전체의 장애
리전마다 서버 세 대(확장 단계)리전 안에서 etcd와 컨트롤 플레인의 고가용성을 유지한 리전 안의 개별 서버 장애
Git 저장소와 클러스터별 Flux각 클러스터가 원하는 상태를 Git에서 직접 가져옴장애 지점이 될 중앙 배포 서버가 없음
DNS 챌린지로 발급한 인증서를 쓰는 Ingress사용자의 요청을 받음DNS 전환과 관계없이 인증서가 동작함
헬스 체크를 갖춘 Geo-DNS사용자를 가장 가까운 정상 리전으로 보냄접속할 수 없게 된 리전
복제되는 데이터 저장소와 백업여러 리전에 데이터를 보관리전 장애 시 데이터 손실

시작 단계와 확장 단계

시작 단계는 미국, 유럽, 아시아에 한 대씩 둔 서버 세 대이며, 각 서버가 독립된 단일 노드 클러스터로 동작합니다. 서버 한 대에 장애가 나면 그 서버의 리전이 멈추고, Geo-DNS가 그 리전의 사용자를 인접 리전으로 보냅니다. 이 단계만으로도 이미 대륙 하나 전체의 장애에 대비하도록 설계되어 있습니다. 확장 단계에서는 리전마다 같은 위치에 서버 세 대를 둡니다. 그러면 각 리전이 사용자를 다른 리전으로 돌리지 않고도 서버 한 대의 장애를 자체적으로 견딥니다.

적합한 KernelHost 위치

KernelHost는 프랑크푸르트암마인의 maincubes 데이터센터에서 서버를 운영하며, 유럽, 북미, 아시아 태평양의 다른 위치에서도 가상 서버를 제공합니다. 미국 내 세 곳, 캐나다, 런던, 스트라스부르, 바르샤바, 헬싱키, 싱가포르, 일본, 시드니, 뭄바이가 여기에 포함됩니다. 전체 목록은 서버 위치 페이지에 있습니다. 이 글의 예시는 유럽에는 프랑크푸르트암마인, 북미에는 미국 동부 해안, 아시아에는 싱가포르를 사용합니다.

가이드: 세 리전에 k3s로 Kubernetes 구축하기

예시에서는 Debian 12 또는 13이 설치된 서버 세 대(k3s-eu, k3s-us, k3s-asia)를 사용합니다. 공인 주소는 문서화용 네트워크 203.0.113.0/24에서 가져왔고, 도메인은 example.com입니다. 둘 다 실제 값으로 바꾸세요.

1단계: 세 리전에 서버 준비하기

세 리전에 서버 세 대를 주문하세요. k3s 외에 애플리케이션이 쓸 여유도 있도록 사양은 최소 2 vCPU와 4 GB RAM으로 잡습니다. 새 루트 서버 체크리스트에 따라 기본 보안 강화를 적용하고, 역할이 드러나는 호스트 이름을 붙이세요. etcd는 빠른 SSD의 덕을 확실히 보며, KernelHost 서버의 NVMe 스토리지는 이 조건을 충족합니다.

2단계: k3s 설치하기

세 서버 각각에 명령 하나로 k3s를 설치합니다. 그러면 각 서버가 노드 하나로 이뤄진 완전한 Kubernetes 클러스터가 됩니다.

curl -sfL https://get.k3s.io | sh -
kubectl get nodes

약 1분 뒤 kubectl get nodes가 노드를 Ready로 표시합니다. Ingress 컨트롤러인 Traefik, 네트워크를 맡는 Flannel, 로컬 볼륨용 프로비저너가 기본으로 포함되어 있습니다.

3단계: 리전마다 서버 세 대로 확장하기

리전 자체도 고가용성을 갖추게 하려면 같은 위치에 서버 세 대를 두세요. 첫 번째 서버가 내장 etcd를 시작하고, 나머지 두 대는 공유 토큰으로 합류합니다. etcd에는 홀수 대의 서버가 필요하며, 서버가 세 대면 리전은 서버 한 대의 장애를 견딜 수 있습니다.

curl -sfL https://get.k3s.io | K3S_TOKEN=비밀_토큰 sh -s - server \
    --cluster-init \
    --tls-san=api.eu.example.com
curl -sfL https://get.k3s.io | K3S_TOKEN=비밀_토큰 sh -s - server \
    --server https://203.0.113.21:6443 \
    --tls-san=api.eu.example.com

한 리전의 모든 서버는 네트워크 대역과 기능에 관해 같은 설정을 써야 합니다. 서버 사이에는 etcd용 2379~2380/TCP, API용 6443/TCP, Kubelet용 10250/TCP, Flannel 네트워크용 8472/UDP 포트가 열려 있어야 하고, 외부에는 계속 닫아 둡니다. 토큰은 비밀 정보입니다. 토큰을 아는 사람은 누구든 자기 서버를 클러스터에 들여놓을 수 있습니다.

4단계: 세 클러스터 모두에 대한 접근 설정하기

k3s는 접속 정보를 /etc/rancher/k3s/k3s.yaml에 저장합니다. 각 클러스터의 이 파일을 작업용 PC로 복사하고, 파일 안의 127.0.0.1을 서버 주소로 바꾼 뒤, 컨텍스트 이름을 리전에 맞춰 바꾸세요.

kubectl config rename-context default eu
kubectl config use-context eu
kubectl --context us get nodes

6443 포트의 API는 클러스터로 들어가는 가장 강력한 통로입니다. 방화벽에서는 본인의 주소나 VPN에서 오는 접속만 허용하고, 인터넷 전체에 여는 일은 절대 없어야 합니다. k3s.yaml 파일에는 관리자 인증서가 들어 있으므로 root 비밀번호만큼 신중하게 보관해야 합니다.

5단계: 모든 클러스터에 Flux로 GitOps 적용하기

세 리전 모두 같은 애플리케이션을 같은 버전으로 운영하도록, 원하는 상태는 Git 저장소에 두고 각 클러스터에서는 그 상태를 스스로 맞춰 가는 Flux를 실행합니다. 즉 각 클러스터가 자기 설정을 직접 가져오므로, 장애를 일으킬 수 있는 중앙 배포 서버가 없습니다. 검증된 저장소 구조는 다음과 같습니다.

apps/
  web/            애플리케이션 공통 매니페스트
clusters/
  eu/             유럽용 설정과 버전
  us/             북미용 설정과 버전
  asia/           아시아용 설정과 버전
flux bootstrap git --url=ssh://git@git.example.com/infra/fleet.git --branch=main --path=clusters/eu

같은 명령을 각 컨텍스트에서 --path=clusters/us와 --path=clusters/asia로 실행합니다. 리전마다 디렉터리가 따로 있으므로 새 버전을 먼저 한 리전에 배포하고, 그다음에 나머지 리전에 배포할 수 있습니다.

6단계: 장애에 강한 애플리케이션 정의하기

한 리전 안에서 애플리케이션이 유지보수와 서버 장애를 견디게 해 주는 것은 세 가지입니다. 여러 노드에 나뉘어 배치되는 여러 레플리카, 비정상 파드를 가려내는 프로브, 그리고 유지보수 때문에 모든 파드가 한꺼번에 제거되지 않도록 막는 중단 예산입니다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: kubernetes.io/hostname
          whenUnsatisfiable: ScheduleAnyway
          labelSelector:
            matchLabels:
              app: web
      containers:
        - name: web
          image: registry.example.com/web:1.0
          ports:
            - containerPort: 8080
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            periodSeconds: 10
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web
spec:
  minAvailable: 1
  selector:
    matchLabels:
      app: web

Readiness 프로브는 파드가 응답하지 않는 동안 그 파드를 트래픽에서 제외하고, Liveness 프로브는 파드가 멈춰 있으면 재시작합니다. 단일 노드 클러스터에서는 여러 노드로 분산하는 설정이 아직 효과가 없으며, 리전에 서버가 세 대가 되면 자동으로 적용됩니다.

7단계: Ingress와 인증서

들어오는 트래픽은 기본 포함된 Traefik이 받습니다. 세 리전 모두 같은 도메인을 서비스하므로, TLS 인증서는 cert-manager로 DNS 챌린지를 거쳐 발급받으세요. DNS 챌린지는 DNS 레코드가 지금 어디를 가리키든 모든 리전에서 동작합니다. 반면 HTTP 챌린지는 레코드가 현재 가리키지 않는 리전에서는 모두 실패합니다. Kubernetes Ingress 없이 작업하신다면 nginx를 리버스 프록시로 설정하기 글에서 기초를 확인하실 수 있습니다.

8단계: 페일오버를 갖춘 Geo-DNS 설정하기

지리 기반 라우팅과 헬스 체크를 지원하는 DNS 서비스는 유럽 사용자를 프랑크푸르트암마인으로, 아메리카 대륙의 사용자를 미국 동부 해안으로, 아시아 사용자를 싱가포르로 보내고, 30~60초마다 각 리전의 진입점이 응답하는지 확인합니다. 한 리전에 장애가 나면 그 리전의 주소는 더 이상 내주지 않습니다. 레코드의 TTL을 60초로 설정하면 전환은 대개 1~2분 안에 끝납니다. 레코드를 클러스터 안에서 관리하고 싶다면 external-dns를 쓸 수 있습니다.

9단계: 리전별로 차례차례 배포하고 장애 테스트하기

새 버전은 먼저 한 리전의 디렉터리에 반영하고, 그 리전을 몇 분 동안 지켜본 뒤 나머지 리전에도 적용합니다. 이렇게 하면 어떤 점검에도 걸리지 않은 오류가 있더라도 기껏해야 한 리전에만 영향을 줍니다. 리전 장애는 그 리전 서버의 k3s를 중지하는 방식으로 연습하고, 이때 Geo-DNS가 그 리전을 응답에서 빼는지, 인접 리전이 부하를 감당하는지 확인합니다.

systemctl stop k3s
systemctl start k3s

서버가 세 대인 리전에서는 서버 한 대의 유지보수도 추가로 연습합니다. kubectl drain은 6단계의 중단 예산을 지키면서 파드를 옮기고, kubectl uncordon은 서버를 다시 운영에 투입합니다.

kubectl drain k3s-eu-2 --ignore-daemonsets --delete-emptydir-data
kubectl uncordon k3s-eu-2

리전 간 데이터

Kubernetes가 분산하는 것은 파드이지 데이터가 아닙니다. 기본 포함된 프로비저너가 만든 PersistentVolume은 정확히 노드 한 대에만 존재하고, 클러스터 사이에는 기본적으로 공유 데이터 저장소가 전혀 없습니다. 따라서 데이터가 걸린 모든 것에는 여러 위치에 걸친 다른 모든 클러스터와 같은 원칙이 적용됩니다.

  • 데이터베이스는 자체적으로 복제합니다. 한 리전에 프라이머리 인스턴스를 두고 나머지 리전에 복제본을 두는 방식이 검증되어 있으며, PostgreSQL용 CloudNativePG 같은 데이터베이스 오퍼레이터는 이런 복제본을 클러스터 경계를 넘어서도 지원합니다. 대륙 간 복제는 비동기로 이뤄지므로, 비상시에는 마지막 몇 초 동안의 쓰기 작업이 빠질 수 있습니다. 전 세계에서 손실 없이 쓰기가 필요하다면 CockroachDB나 YugabyteDB 같은 멀티 리전 데이터베이스가 있습니다.
  • 파일과 업로드는 두 번째 리전으로 복제되는 S3 호환 오브젝트 스토리지에 둡니다.
  • 세션은 복제되는 데이터베이스나 복제되는 캐시에 저장하거나, 애플리케이션이 서명된 토큰을 쓰게 합니다.
  • 백업은 여전히 필수입니다. 복제는 정상 데이터와 똑같이 오류도 퍼뜨리기 때문입니다. Kubernetes 오브젝트와 볼륨에는 Velero가 적합하며, 기초는 서버 백업 전략을 참고하세요.

k3s 대신 kubeadm으로 구축하는 Kubernetes

kubeadm을 써도 아키텍처는 같습니다. 리전별 클러스터, GitOps, Geo-DNS입니다. 달라지는 것은 각 클러스터를 구성하는 방식입니다. 모든 노드에 containerd 같은 컨테이너 런타임과 kubeadm, kubelet, kubectl을 설치하고, 리전의 API 앞에 로드 밸런서나 kube-vip 등으로 만든 가상 주소를 둔 다음, 첫 번째 컨트롤 플레인 노드를 초기화합니다.

kubeadm init --control-plane-endpoint "api.eu.example.com:6443" --upload-certs

출력에는 합류 명령이 두 개 들어 있습니다. 하나는 나머지 두 컨트롤 플레인 노드를 위한 --control-plane --certificate-key가 붙은 명령이고, 다른 하나는 워커용입니다. 그다음 Calico나 Cilium 같은 네트워크 플러그인과, k3s에는 이미 들어 있는 Ingress 컨트롤러를 설치합니다. 이런 추가 수고는 개별 구성 요소를 직접 골라야 하거나 업스트림 버전에 가깝게 머물러야 할 때 그만한 가치가 있습니다.

여러 대륙에 걸친 Kubernetes에 KernelHost를 쓰는 이유

요구 사항중요한 이유KernelHost에서는
여러 대륙에 있는 위치리전별 클러스터에는 리전마다 서버가 필요함프랑크푸르트암마인과 유럽, 북미, 아시아 태평양의 위치를 한 업체에서 모두 제공
무제한 트래픽이미지 다운로드, 데이터베이스 복제, 백업이 지속적으로 트래픽을 만듦전송량 제한이 없는 무제한 트래픽 VPS
빠른 스토리지etcd는 느린 디스크에 민감함RAID로 구성한 NVMe SSD
DDoS 방어모든 Ingress는 공개적으로 접근할 수 있음모든 위치에 기본 포함, 핵심 위치인 프랑크푸르트암마인에서는 3.2 Tbps Arbor 실시간 필터링 제공, null-routing 없음
완전한 루트 권한k3s, 방화벽, 커널 설정에는 완전한 제어 권한이 필요함모든 KVM 루트 서버와 전용 서버에서 제공
약정 없음노드와 테스트 클러스터는 수시로 생겼다 사라짐PrePaid, 최소 이용 기간 없음, 설치비 없음
자동화새 노드를 스크립트로 만들 수 있어야 함KernelHost API를 통한 주문과 제어

모든 클라우드 요금제의 개요와 대형 클라우드 제공업체와의 비용 비교는 클라우드 서버 임대 페이지에서 확인하실 수 있습니다.

흔한 실수와 피하는 방법

  • 여러 대륙에 걸쳐 구성한 etcd. 그 결과 쓰기 작업이 느려지고 리더 선출이 불안정해지며, 내장 etcd를 쓰는 k3s에서는 지원되지도 않습니다. 해결책: 리전별 클러스터.
  • 한 리전에 서버 두 대. etcd에는 과반수가 필요하므로 서버 두 대로는 장애를 한 건도 견디지 못합니다. 해결책: 한 대 또는 세 대.
  • 인터넷 전체에 열린 API. 6443 포트는 클러스터의 마스터 키입니다. 해결책: 본인의 주소나 VPN에서만 허용.
  • 중앙 배포 서버. 이 서버에 장애가 나면 더 이상 아무것도 배포할 수 없습니다. 해결책: 각 클러스터에서 Git으로부터 직접 가져오는 Flux.
  • 모든 리전에서 동시에 하는 업데이트. 그러면 오류 하나가 모든 사용자에게 영향을 줍니다. 해결책: 저장소의 디렉터리를 이용해 리전별로 차례차례 업데이트.
  • HTTP 챌린지로 받는 인증서. DNS 레코드가 현재 가리키지 않는 리전에서는 갱신이 실패합니다. 해결책: DNS 챌린지.
  • 복제 없이 로컬 볼륨에 둔 데이터베이스. 노드에 장애가 나면 데이터에 접근할 수 없습니다. 해결책: 데이터베이스 오퍼레이터를 이용한 복제.
  • 프로브도 중단 예산도 없음. 비정상 파드가 계속 트래픽을 받고, 유지보수 때 모든 파드가 한꺼번에 내려갑니다. 해결책: Readiness 프로브와 Liveness 프로브, 그리고 PodDisruptionBudget.

핵심 요약

  • 여러 대륙에 걸친 Kubernetes에는 리전별 클러스터가 맞습니다. 모든 대륙에 걸친 단일 클러스터는 etcd의 지연 시간 때문에 실패합니다.
  • 시작 단계는 미국, 유럽, 아시아에 한 대씩 둔 서버 세 대이며, 이 단계만으로도 대륙 하나 전체의 장애를 견딥니다.
  • 확장 단계에서는 리전마다 같은 위치에 서버 세 대를 두며, 그러면 각 리전이 개별 서버의 장애도 견딥니다.
  • 각 클러스터의 Flux가 같은 Git 저장소에서 애플리케이션을 리전별로 차례차례 배포합니다.
  • 헬스 체크와 짧은 TTL을 갖춘 Geo-DNS가 사용자를 가장 가까운 정상 리전으로 보내고, 인증서는 DNS 챌린지로 발급받습니다.
  • Kubernetes가 분산하는 것은 파드이지 데이터가 아닙니다. 데이터베이스에는 자체 복제가 필요하고, 백업은 여전히 필수입니다.
  • 이 아키텍처에는 대개 kubeadm보다 k3s가 더 나은 선택입니다. 단순한 클러스터 세 개가 복잡한 클러스터 세 개보다 운영하기 쉽기 때문입니다.

자주 묻는 질문

Kubernetes 클러스터 하나를 여러 대륙에 걸쳐 운영할 수 있나요?
기술적으로는 컨트롤 플레인을 분산할 수 있지만 권장하지 않습니다. Kubernetes는 상태를 etcd에 저장하며, 모든 쓰기 작업은 전체 etcd 멤버 중 과반수의 확인을 받아야 합니다. 대륙 사이의 지연 시간은 80~250밀리초인데, etcd는 기본적으로 100밀리초의 하트비트 간격으로 동작합니다. k3s 문서에 따르면 내장 etcd는 분산된 네트워크에 걸친 구성을 지원하지 않습니다. 올바른 방법은 리전별 클러스터입니다.
여러 리전에 걸쳐 Kubernetes를 고가용성으로 구축하려면 어떻게 해야 하나요?
리전마다 독립된 클러스터를 둡니다. 예를 들어 미국, 유럽, 아시아에 k3s 클러스터를 하나씩 둡니다. 모든 클러스터는 각 클러스터의 Flux 등을 이용해 GitOps 방식으로 같은 Git 저장소에서 배포되고, 헬스 체크를 갖춘 Geo-DNS가 사용자를 가장 가까운 정상 리전으로 보냅니다. 한 리전에 장애가 나면 나머지 리전이 이어받으며, 공유 상태를 바다 건너로 조율할 필요가 없습니다.
k3s와 k8s는 어떻게 다른가요?
둘 다 같은 API와 같은 매니페스트를 쓰는 완전한 Kubernetes입니다. k3s는 바이너리 파일 하나로 된 가볍고 인증된 배포판으로, 명령 하나로 설치되며 Ingress 컨트롤러, 네트워크, 스토리지 프로비저너를 기본으로 포함합니다. 서버 한 대에는 최소 2코어와 2 GB RAM이 필요합니다. kubeadm으로 구성하는 k8s 클러스터는 개별 구성 요소를 조합해 만들며, 선택의 폭이 더 넓은 대신 수고도 더 많이 듭니다.
고가용성 k3s 클러스터에는 서버가 몇 대 필요한가요?
같은 위치에 둔, 내장 etcd를 쓰는 서버 노드 세 대입니다. etcd에는 과반수가 필요하므로 서버 세 대면 한 대의 장애를 견딜 수 있습니다. 서버 두 대는 얻는 것이 없습니다. 둘 중 한 대만 장애가 나도 과반수를 잃기 때문입니다. 여러 대륙에 걸친 Kubernetes라면 시작 단계에서는 리전마다 하나씩, 단일 노드 클러스터 세 개로 충분합니다. 리전 전체의 장애는 Geo-DNS가 받아 내기 때문입니다.
k3s에는 어떤 포트가 필요한가요?
Kubernetes API와 k3s 슈퍼바이저는 6443/TCP 포트에서, Kubelet은 10250/TCP에서, Flannel 네트워크는 VXLAN을 쓸 때 8472/UDP에서, WireGuard를 쓸 때 51820/UDP에서 동작합니다. 내장 etcd를 쓰는 서버가 여러 대라면 서버 사이에 2379~2380/TCP 포트가 추가로 필요합니다. 이 포트들은 어느 것도 인터넷에 열어 두어서는 안 되며, API는 본인의 주소나 VPN에서 오는 접속만 허용하세요.
애플리케이션을 여러 Kubernetes 클러스터에 어떻게 배포하나요?
GitOps로 배포합니다. 모든 클러스터의 원하는 상태를 Git 저장소 하나에 두고, 각 클러스터에서는 그 상태를 스스로 맞춰 가는 Flux 같은 도구를 실행합니다. 리전마다 디렉터리가 따로 있으므로 새 버전을 먼저 한 리전에 배포하고, 일정 시간 지켜본 뒤 나머지 리전에 배포할 수 있습니다. 이 방식에는 장애를 일으킬 수 있는 중앙 배포 서버가 없습니다.
Kubernetes 리전 간 페일오버는 어떻게 동작하나요?
지리 기반 라우팅과 헬스 체크를 지원하는 DNS 서비스로 동작합니다. 이 서비스는 사용자를 가장 가까운 리전으로 보내고, 30~60초마다 그 리전의 Ingress가 응답하는지 확인합니다. 한 리전에 장애가 나면 그 리전의 주소를 더 이상 내주지 않고 사용자를 가장 가까운 정상 리전으로 보냅니다. TTL을 60초로 두면 전환은 대개 1~2분 안에 끝납니다.
리전에 장애가 나도 데이터는 어떻게 보존되나요?
Kubernetes가 분산하는 것은 파드이지 데이터가 아닙니다. 그래서 데이터베이스는 스스로 복제합니다. 예를 들어 PostgreSQL이라면 클러스터 경계를 넘어서도 복제본을 운영하는 CloudNativePG 오퍼레이터를 씁니다. 대륙 간 복제는 비동기로 이뤄지므로 비상시에는 마지막 몇 초 동안의 쓰기 작업이 빠질 수 있습니다. 파일은 복제되는 오브젝트 스토리지에 두고, Velero 등을 이용한 정기 백업은 여전히 필수입니다.
여러 대륙에 걸친 구성에는 Kubernetes와 Docker Swarm 중 무엇이 맞나요?
Docker Swarm은 세 대륙에 걸친 단일 클러스터로 구성할 수 있고, 운영도 훨씬 간단합니다. Kubernetes는 자동화 기능이 더 많고 생태계도 더 크지만, 여러 대륙에 걸칠 때는 리전별 클러스터로 운영하고 GitOps로 하나로 묶습니다. 애플리케이션 규모가 크지 않은 소규모 팀에는 Swarm이 실용적인 선택인 경우가 많고, 복잡한 플랫폼에는 Kubernetes가 맞습니다.
여러 대륙에 걸친 Kubernetes에는 어떤 KernelHost 위치가 적합한가요?
KernelHost는 프랑크푸르트암마인과 함께 유럽, 북미, 아시아 태평양의 다른 위치에서도 서버를 제공합니다. 미국 내 세 곳, 캐나다, 런던, 스트라스부르, 바르샤바, 헬싱키, 싱가포르, 일본, 시드니, 뭄바이가 여기에 포함됩니다. 검증된 조합은 프랑크푸르트암마인, 미국 동부 해안, 싱가포르이며, 리전마다 같은 위치에 서버를 한 대 또는 세 대 둡니다.
세 대륙에 걸친 Kubernetes에는 비용이 얼마나 드나요?
시작 단계에서는 리전마다 한 대씩 서버 세 대, 확장 단계에서는 아홉 대가 필요하고, 여기에 헬스 체크를 지원하는 DNS 서비스가 더해집니다. k3s 자체는 무료입니다. 복제, 백업, 이미지 다운로드가 꾸준히 트래픽을 만들기 때문에 무제한 트래픽 요금제가 결정적입니다. KernelHost의 무제한 트래픽 VPS는 전송량 제한 없이 PrePaid 방식으로 운영되며, 최소 이용 기간도 설치비도 없어 필요에 따라 클러스터를 늘리거나 줄일 수 있습니다.

Kubernetes k3s k8s kubeadm 고가용성 멀티 리전 GitOps Flux Geo-DNS 클라우드