Fly.io에서 LiteFS 시작하기
LiteFS는 SQLite를 위한 분산 파일 시스템으로, 여러 Machine에 걸쳐 데이터베이스를 복제하고 쓰기는 단일 프라이머리(primary) 노드에서만 처리해요. 이 가이드는 Fly.io에서 LiteFS 클러스터를 구성하고 실행하는 전체 과정을 안내해요. 완전한 작동 예시는 litefs-example 저장소에서 볼 수 있어요.
출처: 문서
본문
개요 (Overview)
이 가이드는 Fly.io에서 LiteFS 클러스터를 구성하고 실행하는 단계를 안내해요. 완전한 작동 예시는 litefs-example 저장소를 참고하세요.
LiteFS 설치
의존성
litefs 바이너리는 자체 완결형(self-contained)이지만, LiteFS가 로컬 파일 시스템을 마운트할 수 있도록 fuse3 라이브러리를 설치해야 해요. 또한 Consul에 연결한다면 ca-certificates도 필요하고, 거의 확실히 sqlite 설치도 필요할 거예요. 설치는 패키지 매니저에 따라 달라지지만, alpine 기반이나 debian 기반 이미지의 Dockerfile에 추가할 수 있는 줄은 다음과 같아요:
# for alpine-based images
RUN apk add ca-certificates fuse3 sqlite
# for debian/ubuntu-based images
RUN apt-get update -y && apt-get install -y ca-certificates fuse3 sqlite3
LiteFS 설치
LiteFS는 애플리케이션과 함께 컨테이너 안에서 실행되도록 만들어졌어요. 공식 Docker 이미지에서 litefs 바이너리를 복사해 가져올 수 있어요:
COPY --from=flyio/litefs:0.5 /usr/local/bin/litefs /usr/local/bin/litefs
Docker에서 USER 명령으로 사용자를 바꾸는 대신, LiteFS는 root로 실행하는 것을 권장해요. 애플리케이션을 다른 사용자로 실행해야 한다면 su 명령으로 애플리케이션을 비-root 사용자로 실행하세요.
예시는 litefs-example 저장소의 예시 Dockerfile을 참고하세요.
LiteFS 구성
LiteFS의 대부분의 설정 옵션은 litefs.yml이라는 YAML 설정 파일로 지정해요. 이 파일은 보통 /etc/litefs.yml에 두지만, -config 플래그로 경로를 변경할 수 있어요.
litefs-example 저장소의 litefs.yml 파일에서 전체 예시를 보거나, 이 섹션의 나머지를 따라가며 더 자세한 설명을 확인할 수 있어요!
파일 시스템
먼저 LiteFS가 파일 시스템을 마운트할 위치와 내부 데이터를 저장할 위치를 알려주는 필드 두 개를 설정해요.
# This directory is where your application will access the database.
fuse:
dir: "/litefs"
# This directory is where LiteFS will store internal data.
# You must place this directory on a persistent volume.
data:
dir: "/var/lib/litefs"
Fly.io에서 실행한다면 볼륨을 만들어야 해요:
fly volumes create litefs --size 10
그런 다음 fly.toml에서 마운트로 지정하세요:
[mounts]
source = "litefs"
destination = "/var/lib/litefs"
리스 구성 (Lease configuration)
LiteFS는 특정 시점에 단일 노드만 *프라이머리(primary)*가 될 수 있어요. 프라이머리 노드만 데이터베이스에 데이터를 쓸 수 있어요. 다른 노드는 *레플리카(replica)*라고 하며 읽기 전용 복사본을 제공해요.
프라이머리는 분산 리스(distributed lease)로 결정돼요. 이 가이드에서는 높은 쓰기 가용성을 위해 프라이머리가 자동으로 장애 조치할 수 있게 해주는 Consul 리스를 사용할 거예요. 다음으로 앱에 Consul URL을 추가할 수 있어요:
fly consul attach
그러면 앱에 FLY_CONSUL_URL 시크릿이 설정되고, 여기에 클러스터 URL이 담겨요.
그런 다음 litefs.yml에 lease 섹션을 설정하세요:
lease:
type: "consul"
# Specifies if this node can become primary. The expression below evaluates
# to true on nodes that are run in the primary region. Nodes in other regions
# act as non-candidate, read-only replicas.
candidate: ${FLY_REGION == PRIMARY_REGION}
# If true, then the node will automatically become primary after it has
# connected with the cluster and sync'd up. This makes it easier to run
# migrations on start up.
promote: true
# The API URL that other nodes will use to connect to this node.
advertise-url: "http://${FLY_ALLOC_ID}.vm.${FLY_APP_NAME}.internal:20202"
consul:
# The URL of the Consul cluster.
url: "${FLY_CONSUL_URL}"
# A unique key shared by all nodes in the LiteFS cluster.
# Change this if you are running multiple clusters in a single app!
key: "${FLY_APP_NAME}/primary"
자세한 내용은 설정 가이드의 [리스 관리][] 섹션에서 확인할 수 있어요.
프록시 구성 (Configuring the proxy)
LiteFS는 모든 쓰기가 프라이머리 노드에서 발생해야 해요. 즉 애플리케이션이 쓰기 요청을 현재 프라이머리로 리다이렉트해야 합니다. 또한 프라이머리에 쓰기를 하고 변경 사항이 그 레플리카로 전파되기 전에 레플리카에서 읽는 것도 가능해요.
대부분의 웹 애플리케이션은 LiteFS 내장의 얇은 프록시를 활용할 수 있는데, 이 프록시가 쓰기 리다이렉션과 레플리카 일관성 문제를 자동으로 처리해요. 이 프록시를 사용하려면 애플리케이션이 다음 규칙을 따라야 해요:
-
GET요청은 절대 쓰기 작업(예:INSERT,UPDATE등)을 수행하지 않아야 해요. -
클라이언트는 쿠키가 활성화되어 있어야 해요.
프록시를 구성하려면 설정 파일에 proxy 섹션을 설정해야 해요:
proxy:
# Bind address for the proxy to listen on.
addr: ":8080"
# Hostport of your application - replace 8081 with whatever port
# your application is listening on!
target: "localhost:8081"
# Filename of the SQLite database you want to use for TXID tracking.
db: "my.db"
자세한 내용은 [프록시 구성 가이드][]에서 확인할 수 있어요.
LiteFS 실행
LiteFS를 시작하는 데 사용하는 주요 명령은 litefs mount예요. 이 명령은 FUSE 파일 시스템을 마운트한 다음 LiteFS 노드들이 서로 통신할 수 있는 API 서버를 시작해요. Dockerfile의 ENTRYPOINT로 사용할 수 있어요:
ENTRYPOINT litefs mount
슈퍼바이저로 실행하기
LiteFS는 단독으로 실행되거나 애플리케이션의 간단한 슈퍼바이저 프로세스 역할을 할 수 있어요. 슈퍼바이저로 실행하면 LiteFS가 클러스터에 연결된 후에 애플리케이션을 시작하도록 기다릴 수 있어요.
구성의 exec 섹션에 하나 이상의 명령을 지정할 수 있어요. lease.promote를 true로 설정하면 마이그레이션 스크립트를 후보(candidate) 노드에서만 실행하도록 지정할 수 있어요. 이는 후보 노드가 자동으로 프라이머리로 승격되어 마이그레이션을 실행한다는 뜻이에요.
exec:
# Only run migrations on candidate nodes.
- cmd: "rails db:migrate"
if-candidate: true
# Then run the application server on all nodes.
- cmd: "rails server"
LiteFS 인스턴스 테스트
LiteFS가 마운트되면 SQLite 클라이언트나 sqlite3 CLI를 사용해 마운트 디렉터리의 데이터베이스와 상호작용할 수 있어요:
sqlite3 /litefs/my.db
LiteFS는 마운트의 루트에 있는 파일만 허용하며, 현재 서브디렉터리는 지원하지 않아요.
데이터베이스 가져오기
기존 데이터베이스가 있다면 litefs import 명령으로 가져올 수 있어요.
litefs import -name my.db /path/to/database
자세한 내용은 litefs import 문서를 참고하세요.
경고: LiteFS의 SQLite 데이터베이스는 SQLite 클라이언트를 통해서만, 아니면
litefs도구를 통해서만 상호작용해야 해요.데이터베이스를 복사해 넣기 위해
cp를 사용하지 마세요.