콘텐츠로 이동

Tenax로 복원하기

모든 복원은 Restore 리소스입니다. 콘솔, CLI, API 모두 이 리소스를 생성합니다. 제자리 복원을 요청하고 대상 이름을 입력하지 않는 한, 복원은 기존 데이터베이스에 절대 쓰지 않습니다. 모드를 고르세요.

필요한 것 모드 역할
데이터 확인, 수정 사항 점검, 보고서 실행 sandbox (기본값) operator
테이블 하나나 몇 개의 행 되찾기 sandbox 후 필요한 것을 복사 operator
프로덕션 옆의 사본(새 데이터베이스 이름) new restorer
클러스터 외부의 누군가를 위한 덤프 파일 download (사전 서명 URL, 1시간) restorer
대상 전체를 되돌리기 in place (안전 백업 후) restorer-admin

1. 시점 찾기

tenax targets                                   # PITR windows and last backups
tenax backups team/app                          # versions (ids, times, sizes, verified, pinned)
tenax changes team/app --since 6h               # what changed when: per-table counts and DDL per segment
tenax diff <backup-a> <backup-b>                # schema and row changes between two versions

콘솔에서 대상을 연 뒤 변경을 여세요. 각 세그먼트 행에 시각을 채워 주는 "이전 시점 샌드박스"와 "이후 시점 샌드박스" 링크가 있습니다.

PITR이 있으면 기간 안의 어떤 초든 사용할 수 있습니다(UTC, RFC3339): --at 2026-01-02T03:04:05Z. PITR이 없으면 백업 ID를 고르세요: --at 20260102T020000Z-1a2b3c. 복원할 수 없는 시각이면 Tenax가 이유를 알려 주고 복원 가능 기간을 출력합니다.

2. 샌드박스로 복원(안전한 기본값)

tenax restore team/app --at 2026-01-02T03:04:05Z --ttl 6h --wait
tenax sandbox show <sandbox>                    # connection info, expiry
tenax query <sandbox> -e "select count(*) from orders where created_at > now() - interval '1 day'"
tenax query <sandbox> -e "select * from orders where id = 42" -o csv > order42.csv
  • 샌드박스는 전용 네임스페이스 tenax-sbx-<name>, 무작위 자격 증명, TTL을 받습니다(기본값 24시간, tenax sandbox extend <sandbox> --by 24h로 정책 최대값까지 연장 가능).
  • 쿼리 콘솔은 기본적으로 읽기 전용이며, 30초 타임아웃과 1,000행 제한이 있습니다. 대상의 mask 패턴과 일치하는 열은 마스킹됩니다. 모든 쿼리는 감사 로그에 기록됩니다.
  • 다른 파드에서: 파드에 tenax.run/sandbox-client: <sandbox> 레이블을 붙이고 sandbox show가 출력하는 클러스터 내부 주소로 연결하세요.
  • 노트북에서, 샌드박스를 --expose로 만든 경우: tenax sandbox connect <sandbox> --port 15432. Cloudflare Access를 통해 터널을 열고 연결 문자열을 출력합니다.
  • 다 쓰면 tenax sandbox delete <sandbox>. 만료된 샌드박스는 자동으로 삭제됩니다.

3. 새 데이터베이스로 복원

tenax restore team/app --at 2026-01-02T03:04:05Z --to new \
  --host postgres.team.svc --database app_restored --credentials-secret tenax-admin --wait

Tenax는 먼저 스테이징 샌드박스로 복원하고 검사를 실행한 뒤, 논리 덤프와 불러오기로 결과를 새 데이터베이스에 복사합니다(ADR 0007). 기존 데이터베이스는 절대 덮어쓰지 않습니다. 관리자 Secret(tenax- 접두사)은 대상의 네임스페이스에 있어야 하며 CREATE DATABASE 권한이 필요합니다.

4. 다운로드

tenax restore team/app --at <backup-id> --to download --wait

--wait는 복호화되고 다시 압축된 덤프의 사전 서명 URL을 출력합니다. 1시간 동안 유효합니다. 이 URL은 비밀 정보이므로 비밀 정보처럼 공유하세요.

5. 제자리 복원(최후의 수단)

tenax restore team/app --at 2026-01-02T03:04:05Z --to in-place --confirm app --credentials-secret tenax-admin --wait
  1. 먼저 쓰기 작업을 멈추세요. Tenax는 애플리케이션을 멈추지 않습니다. 스케일을 줄이거나 유지 보수 모드로 전환하세요.
  2. Tenax가 현재 상태의 안전 백업을 만듭니다(사유 safety). 이를 건너뛰려면 --skip-safety-backup이 필요합니다.
  3. 스테이징 샌드박스로 복원하고 결과를 검사한 뒤 대상의 데이터베이스를 교체합니다.
  4. 애플리케이션을 다시 시작하고 확인하세요.

문제가 생기면 안전 백업은 대상의 일반 버전이므로 같은 방법으로 복원하면 됩니다.

CLI 없이

Restore 리소스 자체가 API입니다.

apiVersion: tenax.run/v1alpha1
kind: Restore
metadata: { name: app-incident-42, namespace: team }
spec:
  target: app
  source: { time: "2026-01-02T03:04:05Z" }     # or backupID: ..., or latest: true
  destination:
    mode: sandbox
    sandbox: { ttl: 6h }

kubectl -n team get restore app-incident-42 -w로 진행 상황을 볼 수 있습니다: 계획, 기준 백업 가져오기, 재생, 검사, Succeeded.

Tenax 자체가 다운되었을 때

스토어가 기준이 되는 원본이며, 백업 형식은 단순합니다. - manifest.json에는 모든 오브젝트가 크기와 SHA-256과 함께 나열되어 있습니다. - 오브젝트는 zstd로 압축되고 age로 암호화되어 있습니다: age -d -i key.txt obj.zst.age | zstd -d. - Postgres 물리 백업은 pg_basebackup tar 스트림과 WAL 세그먼트입니다. - Postgres 논리 백업은 데이터베이스마다 하나씩인 pg_dump -Fc 파일입니다. - MySQL 백업은 mysqldump 출력과 binlog 파일입니다.

클러스터를 잃었거나 다시 만든 뒤

복구는 자동입니다. Tenax는 자체 데이터베이스를 두지 않습니다. 스토어가 모든 백업을 보관하고(중요한 유일한 사본입니다), Git이 BackupStore, 정책, 대상을 보관하며(GitOps), age ID는 다른 Secret처럼 복원하면 됩니다. 새 클러스터에 같은 스토어와 같은 ID로 Tenax를 설치하고 같은 대상을 적용하세요. 그러면 다음이 진행됩니다.

  1. 컨트롤러가 시작할 때 각 스토어를 확인합니다(BackupStore.status.lastImportTime). 대상마다 가장 최근 keepBackupObjects개(기본값 20) 백업의 Backup 오브젝트를 고정된 것을 포함해 다시 만듭니다. 스토어에는 아무것도 쓰지 않습니다. 더 오래된 백업은 보존 정책에 따라 스토어와 콘솔의 카탈로그에 그대로 남습니다.
  2. 복원, PITR 복원 가능 기간, 콘솔이 이전처럼 동작합니다. streamer는 새 전체 백업에서 새 체인을 시작합니다.

가져오기는 대상이 바뀔 때와 controller.autoImport.interval(1시간)마다 실행됩니다. 끄려면 controller.autoImport.enabled: false를 설정하세요. tenax catalog import [--dry-run]은 kubeconfig를 사용해 같은 작업을 수동으로 수행합니다.