etcd 분산 키-값 저장소의 원리와 운영

etcd란?

etcd는 고가용성과 일관성을 보장하는 분산 키-값 저장 시스템으로, 주로 분산 환경에서 구성 데이터 공유 및 서비스 디스커버리에 활용된다. Kubernetes와 같은 오케스트레이션 플랫폼의 핵심 구성 요소로 작동하며, 클러스터 상태 정보를 안정적으로 유지한다. 유사한 기능을 제공하는 시스템으로 ZooKeeper가 있으나, etcd는 더 간결한 아키텍처와 높은 성능으로 널리 채택되고 있다.

보안 기반 etcd 클러스터 구축

실제 운영 환경에서는 인증서 기반의 암호화 통신이 필수적이다. 다음은 TLS를 적용한 3노드 etcd 클러스터 구성 예시이다.

기반 도구 설치: CFSSL

Certificate Authority(CA) 및 TLS 인증서 생성을 위해 CFSSL 도구를 설치한다. 아래 명령어는 첫 번째 마스터 노드에서 실행한다.

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

CA 인증서 생성

모든 노드에서 인증서 저장 경로를 생성한다.

mkdir -p /etc/kubernetes/pki

CA 구성 파일 작성:

{
  "signing": {
    "default": { "expiry": "87600h" },
    "profiles": {
      "secure-etcd": {
        "usages": ["signing", "key encipherment", "server auth", "client auth"],
        "expiry": "87600h"
      }
    }
  }
}

CA 요청 파일:

{
  "CN": "etcd-ca",
  "key": { "algo": "rsa", "size": 2048 },
  "names": [{ "C": "KR", "ST": "Seoul", "L": "Jongno", "O": "infra", "OU": "control" }]
}

인증서 생성:

cfssl gencert -initca ca-csr.json | cfssljson -bare ca

etcd 전용 인증서 발급

etcd 노드들 간의 상호 인증을 위한 인증서를 생성한다. 모든 etcd 서버의 IP를 SANs에 포함해야 한다.

{
  "CN": "etcd-server",
  "hosts": [
    "127.0.0.1",
    "172.16.1.188",
    "172.16.1.189",
    "172.16.1.190"
  ],
  "key": { "algo": "rsa", "size": 2048 }
}

인증서 발급:

cfssl gencert \
  -ca=ca.pem \
  -ca-key=ca-key.pem \
  -config=ca-config.json \
  -profile=secure-etcd etcd-csr.json | cfssljson -bare etcd

생성된 etcd.pem, etcd-key.pem을 각 노드의 /etc/kubernetes/pki 디렉터리에 복사한다.

etcd 클러스터 배포

최신 안정 버전을 다운로드하고 바이너리를 설치한다.

wget https://github.com/etcd-io/etcd/releases/download/v3.5.4/etcd-v3.5.4-linux-amd64.tar.gz
tar xzf etcd-v3.5.4-linux-amd64.tar.gz
cp etcd-v3.5.4-linux-amd64/etcd* /usr/bin/

모든 노드에서 데이터 디렉터리를 생성한다.

mkdir -p /var/lib/etcd

systemd 서비스 설정

첫 번째 노드의 /usr/lib/systemd/system/etcd.service 설정 예시:

[Unit]
Description=etcd distributed key-value store
After=network.target

[Service]
Type=notify
ExecStart=/usr/bin/etcd \
  --name infra1 \
  --data-dir=/var/lib/etcd \
  --listen-client-urls https://172.16.1.188:2379,http://127.0.0.1:2379 \
  --advertise-client-urls https://172.16.1.188:2379 \
  --listen-peer-urls https://172.16.1.188:2380 \
  --initial-advertise-peer-urls https://172.16.1.188:2380 \
  --cert-file=/etc/kubernetes/pki/etcd.pem \
  --key-file=/etc/kubernetes/pki/etcd-key.pem \
  --trusted-ca-file=/etc/kubernetes/pki/ca.pem \
  --peer-cert-file=/etc/kubernetes/pki/etcd.pem \
  --peer-key-file=/etc/kubernetes/pki/etcd-key.pem \
  --peer-trusted-ca-file=/etc/kubernetes/pki/ca.pem \
  --initial-cluster-token etcd-cluster-1 \
  --initial-cluster infra1=https://172.16.1.188:2380,infra2=https://172.16.1.189:2380,infra3=https://172.16.1.190:2380 \
  --initial-cluster-state new
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target

두 번째 및 세 번째 노드에서는 --name, --initial-advertise-peer-urls 등의 IP를 해당 노드의 주소로 수정한다.

클러스터 시작 및 상태 확인

모든 노드에서 서비스를 활성화하고 시작한다.

systemctl daemon-reload
systemctl enable etcd
systemctl start etcd

클러스터 정상 동작 확인:

export ETCDCTL_API=3
etcdctl --cacert=/etc/kubernetes/pki/ca.pem \
        --cert=/etc/kubernetes/pki/etcd.pem \
        --key=/etc/kubernetes/pki/etcd-key.pem \
        --endpoints=https://172.16.1.188:2379 \
        endpoint health

내부 데이터 저장 구조

etcd는 지정된 데이터 디렉터리(/var/lib/etcd) 내부에 두 가지 핵심 컴포넌트를 유지한다.

  • WAL (Write-Ahead Log): 모든 상태 변경 이력을 순차적으로 기록한다. 장애 발생 시 WAL을 기반으로 상태를 재구성할 수 있으며, 데이터 무결성을 보장한다.
  • Snapshots: 특정 시점의 전체 상태를 저장한다. WAL 파일의 급격한 증가를 방지하기 위해 주기적으로 스냅샷을 생성하고, 이전의 WAL 세그먼트를 정리한다.

이러한 메커니즘은 빠른 복구, 로그 기반 리플레이, 과거 상태로의 롤백을 가능하게 한다.

Raft 합의 알고리즘

etcd는 Raft 프로토콜을 사용하여 멀티 노드 간의 데이터 일관성을 유지한다. Raft는 다음과 같은 특징을 가진다.

  • 각 노드는 Leader, Follower, Candidate 중 하나의 상태를 가진다.
  • 클러스터 내 단일 Leader만이 클라이언트 요청을 처리하고, 모든 변경 사항을 Follower들에게 복제한다.
  • Leader 장애 시 자동으로 새로운 선출 절차(Term 기반)가 시작되어 서비스 중단 없이 복구된다.
  • Paxos보다 이해와 구현이 용이하도록 설계되었다.

서비스 디스커버리 활용

etcd는 서비스 등록 및 검색을 위한 이상적인 백엔드 저장소이다. 주요 구성 요소는 다음과 같다.

  • 중앙 집중형 저장소: Raft 기반의 강한 일관성을 제공하므로 신뢰할 수 있는 서비스 목록 유지가 가능하다.
  • 레지스트리 및 하트비트: 서비스는 고유 키를 통해 etcd에 등록하고, TTL(시간 제한)을 설정한 후 주기적으로 갱신함으로써 활성 상태를 유지한다.
  • 검색 및 연결: 클라이언트는 etcd에서 대상 서비스의 엔드포인트를 조회하여 직접 연결하거나, 로드 밸런서를 통해 접근할 수 있다.

장애 복구 전략

etcd 클러스터는 (N-1)/2개의 노드 장애까지 견딜 수 있다. 이를 초과하면 Quorum 손실로 인해 클러스터가 완전히 중단되며 수동 복구가 필요하다.

백업

실행 중인 클러스터에서 스냅샷을 생성한다.

ETCDCTL_API=3 etcdctl --endpoints=127.0.0.1:2379 \
  snapshot save backup_$(date +%Y%m%d).db \
  --cacert=/etc/kubernetes/pki/ca.pem \
  --cert=/etc/kubernetes/pki/etcd.pem \
  --key=/etc/kubernetes/pki/etcd-key.pem

복원

손상된 클러스터를 복구하기 위한 절차:

  1. 모든 etcd 노드에서 서비스 중지
  2. 기존 데이터 디렉터리 삭제: rm -rf /var/lib/etcd
  3. 각 노드에서 스냅샷 복원 명령 실행 (노드별 이름 및 주소 지정)
  4. 복원된 데이터로 서비스 재시작

복원 작업은 논리적으로 새로운 클러스터를 구성하므로 기존 구성과 동일한 초기 클러스터 파라미터를 지정해야 한다.

태그: etcd Raft Distributed Systems Service Discovery TLS

7월 21일 07:15에 게시됨