ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Etcd] WAL Log (Write Ahead Log) 알아보기
    Etcd 2024. 6. 17. 05:59
    728x90
    반응형

    - 목차

     

    들어가며.

    Etcd 는 데이터의 영속성 (Persistence) 를 구현하기 위해서 여러가지 데이터 저장 요소들이 존재합니다.

    크게 세가지 구성 요소를 통해서 Etcd 는 데이터의 영속성을 구현하는데요.

    1. WAL Log
    2. Snapshot
    3. BoltDB

    와 같이 3개의 Disk 내의 File 들이 존재합니다.

     

    먼저 각각의 파일의 역할들에 대해서 간단히 알아보도록 하겠습니다.

     

    WAL Log.

    WAL LogWrite Ahead Log 의 줄임말입니다.

    이는 수 많은 서비스에서 여러가지 이름으로 사용되는 기능으로 데이터베이스에 추가되는 모든 데이터 변경사항들이 기록되는 영역입니다.

    MySQLRedo Log 는 데이터를 생성, 수정, 삭제하는 모든 DML 쿼리들이 Redo Log 에 추가됩니다.

    Hadoop 에서도 Edit Log 라는 데이터 변경 로그가 NameNode 내부 Edit Log 에 차곡차곡 기록되죠.

    그리고 여러 LSM Tree 기반의 데이터베이스 ( RocksDB, LevelDB ) 등 에서도 사용됩니다.

    이렇게 WAL Log 는 모든 데이터의 수정 사항들이 기록되게 되죠.

    Etcd 같은 경우에도 마찬가지로 "etcdctl put KEY VALUE", "etcdctl del KEY" 와 같은 데이터 생성/수정/삭제 요청이 WAL Log 에 쌓입니다.

     

    그럼 WAL Log 의 쓰임새는 무엇일까요 ?

    WAL LogCrash Recovery 상황에서 사용됩니다.

    Etcd 는 실질적으로 BoltDB 에 저장된 데이터를 통해서 사용자에게 데이터를 제공합니다.

    즉, "etcdctl get KEY" 와 같이 특정 KEY 에 해당하는 데이터의 조회가 요청될 때에 BoltDB 에 있는 특정 KEY 의 데이터를 반환합니다.

    하지만, BoltDB 는 최종적인 저장소이기 때문에 데이터가 최종적으로 BoltDB 에 저장 완료되기 전에 Etcd 가 Crash 된다면,

    해당 데이터는 손실될 수 있습니다.

    따라서 모든 데이터 변경 요청은 WAL Log 에 먼저 저장되고, Crash 상황이 발생한다면 WAL Log 의 기록을 통해서 정상적인 Recovery 를 수행합니다.

     

    특히 이번 글의 주제인 WAL Log 는 이어지는 내용에서 상세히 다루어보겠습니다.

     

    Snapshot.

    SnapshotWAL Log 를 사용하는 서비스라면 Snapshot 은 한쌍으로 따라오는 또 다른 개념입니다.

    WAL Log 의 기록은 Snapshot 으로 저장되어, 언제든지 데이터 복구를 시도할 수 있습니다.

    Snapshot 은 주기적으로 또는 WAL Log 가 일정 크기를 초과하게 되면 WAL Log 의 기록으로부터 Snapshot 이 생성됩니다.

     

    아래의 이미지는 Etcd 파일 시스템 내부에서 Snapshot 에 해당하는 파일들을 보여줍니다.

    아래 이미지는 WAL Log 로부터 4개의 Snapshot 파일들이 생성된 모습입니다.

    Snapshot 또한 WAL Log 와 함께 Crash Recovery 의 목적으로 사용됩니다.

    Snapshot 이라는 이름처럼 특정 시점의 데이터 상태를 저장하고 있습니다.

    그래서 특정 시점의 데이터 상태를 복구할 수 있습니다.

     

     

     

    BoltDB.

    BoltDB 는 RocksDB 나 LevelDB 처럼 데이터 저장소에서 흔히 사용되는 임베디드 데이터베이스입니다.

    단독으로 동작하는 데이터베이스처럼 TCP Connection 지원하거나 자체적인 데몬 프로세스로 동작하진 않습니다.

    대신 Etcd 내부에서 데이터를 저장하는 최종적인 저장소의 역할을 수행합니다.

    실질적으로 etcdctl get KEY 와 같은 요청을 통해서 BoltDB 에 저장된 데이터를 직접 조회하게 됩니다.

     

    이번 글에서느 BoltDB 의 내용은 여기까지만 다루고 다른 블로그 글에서 자세히 설명해보도록 하겠습니다.

     

     

    WAL Log 의 여러가지 설정들 알아보기.

    앞서 말씀드린대로 WAL Log 는 Etcd 에 발생하는 모든 데이터 변경 기록들이 저장됩니다.

    WAL Log 는 "quay.io/coreos/etcd" 도커 이미지를 기준으로 /var/etcd 디렉토리 내부에 존재합니다.

    아래의 이미지처럼 /var/etcd/member/wal 디렉토리 하위에 .wal 이라는 확장자를 가지는 파일이 보이는데요.

    .wal 확장자를 가지는 파일이 바로 WAL Log 파일입니다.

     

     

    --data-dir.

    etcd 실행파일을 통해서 etcd 프로세스를 실행할 때에 --data-dir Flag 가 제공됩니다.

    이는 WAL Log 파일의 저장 위치를 지정하는 Flag 입니다.

    활용 예시는 아래와 같습니다.

     

    docker network create etcd
    docker volume create etcd1
    
    docker run --platform linux/amd64 -d --network etcd \
    --name etcd1 --hostname etcd1 \
    -v etcd1:/var/etcd \
    -p 12380:2380 \
    -p 12379:2379 \
    quay.io/coreos/etcd:v3.5.17 \
    /usr/local/bin/etcd \
        --data-dir=/var/etcd \
        --listen-client-urls=http://0.0.0.0:2379 \
        --advertise-client-urls="http://host.docker.internal:12379" \
        --listen-peer-urls=http://0.0.0.0:2380 \
        --initial-advertise-peer-urls=http://etcd1:2380 \
        --initial-cluster="node1=http://etcd1:2380" \
        --initial-cluster-state=new \
        --initial-cluster-token=etcd \
        --snapshot-count=5 \
        --name=node1

     

    저는 습관적으로 Docker Network 와 Volume 을 활용하는 편이라 위와 같이 Network, Volume 을 생성하여 Etcd Container 에 적용하였습니다.

    위의 도커 명령어를 간단히 설명드리면, /usr/local/bin/etcd 실행파일을 실행하며 --data-dir Flag 를 통해서 WAL Log 의 저장 위치를 지정합니다.

    실행 결과는 아래의 이미지와 같이 /var/etcd 내부에 wal 디렉토리와 .wal 파일이 존재하게 됩니다.

     

     

     

    --snapshot-count.

    Etcd 는 --snapshot-count Flag 를 제공합니다.

    이는 WAL Log 에 기록되는 Raft Log 의 갯수가 --snapshot-count 이 도달하면 Snapshot 생성을 트리거하는 Threshold 값입니다.

    예를 들어, --snapshot-count 가 5 로 설정되어 있고, Etcd 에 5번의 데이터 변경 요청이 발생하면 1개의 Snapshot 이 생성됩니다.

     

    아래의 명령어는 총 20번의 etcdctl put KEY VALUE 명렁을 수행하는 예시입니다.

    --snapshot-count 를 5로 설정하였기 때문에 총 4개의 Snapshot 이 생성되게 됩니다.

     

    for i in {0..20}; 
        do sleep 3; 
        docker run --platform linux/amd64 --network etcd -e ETCDCTL_API=3 --rm quay.io/coreos/etcd:v3.5.17 \
        etcdctl --endpoints=http://etcd1:2379 put key value; 
    done

     

    아래의 이미지는 총 4개의 Snapshot 이 생성된 결과입니다.

     

     

     

    --max-wals.

    --max-wals 설정은 최대로 생성 가능한 .wal 파일의 갯수를 의미합니다.

    Etcd 는 Snapshot 을 생성하기 이전까지 .wal 파일 내부에 Raft Log 들을 누적하여 기록합니다.

    그리고 Snapshot 이 생성되는 시점에 WAL Log 내부의 Raft Log 들이 정리되게 됩니다.

    만약 --snapshot-count 값이 매우 크거나 Raft Log 의 크기가 큰 경우에 .wal 파일에 Raft Log 들이 꽉차게 될 수도 있습니다.

    이런 경우에 Etcd 는 새로운 WAL Log 파일을 만들어 대처하게 됩니다.

     

    아래의 명령어는 --max-wals 의 값을 5로 설정한 Etcd 를 실행하는 도커 명령어입니다.

    그리고 --snapshot-count 를 50000으로 설정하여 WAL Log 를 최대 5개까지 생성해보는 예시를 구현하려고 합니다.

     

    docker run --platform linux/amd64 -d --network etcd \
    --name etcd1 --hostname etcd1 \
    -v etcd1:/var/etcd \
    -p 12380:2380 \
    -p 12379:2379 \
    quay.io/coreos/etcd:v3.5.17 \
    /usr/local/bin/etcd \
        --data-dir=/var/etcd \
        --listen-client-urls=http://0.0.0.0:2379 \
        --advertise-client-urls="http://host.docker.internal:12379" \
        --listen-peer-urls=http://0.0.0.0:2380 \
        --initial-advertise-peer-urls=http://etcd1:2380 \
        --initial-cluster="node1=http://etcd1:2380" \
        --initial-cluster-state=new \
        --initial-cluster-token=etcd \
        --snapshot-count=50000 \
        --max-wals=5 \
        --name=node1

     

     

    그리고 아래의 명령어를 통해서 많은 수의 Raft Log 를 생성하려고 합니다.

    총 9999회의 반복문을 돌면서 etcdctl 를 수행합니다.

     

    docker run --platform linux/amd64 --network etcd -e ETCDCTL_API=3 --rm bitnami/etcd:3.5.17 \
        bash -c 'for i in {0..9999}; do etcdctl --endpoints=http://etcd1:2379 put key_$i "$(head -c 20240 </dev/urandom | base64)"; done'

     

    그 결과는 아래와 같이 총 5개의 .wal 파일 생성됩니다.

    그리고 아직까지 Snapshot 은 생성되지 않았습니다.

     

    ./member/snap:
    total 350M
    drwx------ 2 root root 4.0K Jun  17 21:08 .
    drwx------ 4 root root 4.0K Jun  17 21:08 ..
    -rw------- 1 root root 354M Jun  17 21:22 db
    
    ./member/wal:
    total 367M
    drwx------ 2 root root 4.0K Jun  17 21:19 .
    drwx------ 4 root root 4.0K Jun  17 21:08 ..
    -rw------- 1 root root  62M Jun  17 21:19 0.tmp
    -rw------- 1 root root  62M Jun  17 21:11 0000000000000000-0000000000000000.wal
    -rw------- 1 root root  62M Jun  17 21:13 0000000000000001-0000000000000969.wal
    -rw------- 1 root root  62M Jun  17 21:16 0000000000000002-00000000000012cc.wal
    -rw------- 1 root root  62M Jun  17 21:19 0000000000000003-0000000000001c2f.wal
    -rw------- 1 root root  62M Jun  17 21:22 0000000000000004-0000000000002592.wal

     

     

    그리고 추가적으로 Raft Log 을 생성하게 되면 아래와 같이 --max-wals 를 초과하는 WAL Log 파일들이 생성될 수도 있습니다.

    이는 아직까지 Snapshot 이 생성되지 않았기 때문에 모든 WAL Log 파일들을 유지하는 중입니다.

     

    ./member/snap:
    total 1.1G
    drwx------ 2 root root 4.0K Jun  17 00:08 .
    drwx------ 4 root root 4.0K Jun  17 00:08 ..
    -rw------- 1 root root 1.1G Jun  17 00:59 db
    
    ./member/wal:
    total 978M
    drwx------ 2 root root 4.0K Jun  17 00:57 .
    drwx------ 4 root root 4.0K Jun  17 00:08 ..
    -rw------- 1 root root  62M Jun  17 00:57 0.tmp
    -rw------- 1 root root  62M Jun  17 00:11 0000000000000000-0000000000000000.wal
    -rw------- 1 root root  62M Jun  17 00:13 0000000000000001-0000000000000969.wal
    -rw------- 1 root root  62M Jun  17 00:16 0000000000000002-00000000000012cc.wal
    -rw------- 1 root root  62M Jun  17 00:19 0000000000000003-0000000000001c2f.wal
    -rw------- 1 root root  62M Jun  17 00:22 0000000000000004-0000000000002592.wal
    -rw------- 1 root root  62M Jun  17 00:24 0000000000000005-0000000000002ef3.wal
    -rw------- 1 root root  62M Jun  17 00:25 0000000000000006-0000000000003840.wal
    -rw------- 1 root root  62M Jun  17 00:27 0000000000000007-000000000000418d.wal
    -rw------- 1 root root  62M Jun  17 00:29 0000000000000008-0000000000004ada.wal
    -rw------- 1 root root  62M Jun  17 00:32 0000000000000009-000000000000542a.wal
    -rw------- 1 root root  62M Jun  17 00:36 000000000000000a-0000000000005d8e.wal
    -rw------- 1 root root  62M Jun  17 00:40 000000000000000b-0000000000006701.wal
    -rw------- 1 root root  62M Jun  17 00:45 000000000000000c-0000000000007099.wal
    -rw------- 1 root root  62M Jun  17 00:57 000000000000000d-0000000000007a33.wal
    -rw------- 1 root root  62M Jun  17 00:59 000000000000000e-0000000000008465.wal

     

    이러한 경우에는 Etcd 의 --snapshot-count 설정을 변경하는 조치가 필요합니다.

    아래의 결과는 Etcd --snapshot-count 값을 줄이고, 재실행한 결과입니다.

     

    ./member/snap:
    total 1.3G
    drwx------ 2 root root 4.0K Jun  17 01:09 .
    drwx------ 4 root root 4.0K Jun  17 01:09 ..
    -rw-r--r-- 1 root root 7.0K Jun  17 01:09 0000000000000002-00000000000096c0.snap
    -rw-r--r-- 1 root root 7.0K Jun  17 01:09 0000000000000002-0000000000009ab6.snap
    -rw-r--r-- 1 root root 7.0K Jun  17 01:09 0000000000000002-0000000000009eac.snap
    -rw-r--r-- 1 root root 7.0K Jun  17 01:09 0000000000000002-000000000000a2a2.snap
    -rw-r--r-- 1 root root 7.4K Jun  17 01:09 0000000000000003-000000000000a69a.snap
    -rw------- 1 root root 1.3G Jun  17 01:09 db
    
    ./member/wal:
    total 367M
    drwx------ 2 root root 4.0K Jun  17 01:09 .
    drwx------ 4 root root 4.0K Jun  17 01:09 ..
    -rw------- 1 root root  62M Jun  17 01:09 0.tmp
    -rw------- 1 root root  62M Jun  17 00:57 000000000000000d-0000000000007a33.wal
    -rw------- 1 root root  62M Jun  17 01:00 000000000000000e-0000000000008465.wal
    -rw------- 1 root root  62M Jun  17 01:02 000000000000000f-0000000000008dcb.wal
    -rw------- 1 root root  62M Jun  17 01:05 0000000000000010-0000000000009730.wal
    -rw------- 1 root root  62M Jun  17 01:09 0000000000000011-000000000000a095.wal

     

     

    반응형
Designed by Tistory.