무인 업데이트는 자체 VPN으로 접근하는 서버에 합리적인 정책이며, 동시에 스스로 만들어 내는 단일 실패 지점이다. 패키지 작업이 서비스를 재시작하고, 터널이 끊기며, 쓰고 있던 관리 경로가 그것과 함께 사라진다. 복구 모델은 두 가지이고, 둘 중 무엇을 고를지는 한 가지 조건에 달려 있다. 업데이트되는 대상을 거치지 않는 접근 경로가 있는가.

두 가지 복구 모델, 하나의 결정적 조건

첫 모델은 업데이트를 신뢰하고 나중에 다시 연결할 수 있다고 가정한다. VPN이 호스트에 이르는 여러 방법 중 하나이고 터널의 실패가 진단 능력을 없애지 않을 때 작동한다. 둘째 모델은 미리 독립적인 경로, 보통 호스팅 사업자의 콘솔을 마련하고 터널을 유지보수로 가장 잘 끊길 대상으로 취급한다. 두 모델 모두 변호할 수 있고, 사전 작업이 필요한 것은 하나뿐이다.

결정적 조건은 말하기 쉽고 건너뛰기도 쉽다. 기계로 가는 모든 관리 경로가 업데이트되는 서비스를 지난다면 복구 모델은 아예 없고 기대만 있을 뿐이다. 변경 검토에서 그것을 소리 내어 말하라.

그 조건을 시험하는 데는 십 분이 걸리고, 첫 무인 업데이트 전에 해야 하며 장애 중이 아니다. 모든 것이 작동할 때 콘솔을 열고 자격 증명이 유효한지 확인한 뒤 다시 닫아라. 콘솔이 생각하는 호스트로 열리는지 확인하라. 그다음 새벽 3시에 실제로 쓸 로그인이 아직 작동하는지 확인하라.

마지막 부분은 들리는 것보다 중요하다. 육 개월 전에 비밀번호를 바꾸고 한 번도 검증하지 않은 콘솔 계정은 복구 경로가 아니다. 그것은 경로를 설명한 문서일 뿐이다.

백업이 복원하지 않는 것

구성 아카이브는 파일의 기록이고, 업데이트는 파일보다 많은 것을 바꾼다. 패키지 상태, 커널 모듈, 활성화된 유닛 링크, 별도 도구로 적용한 방화벽 규칙은 모두 구성 디렉터리 밖에 있으며, 그것을 무시하는 복원은 구성된 것처럼 보이지만 전달하지 않는 기계를 만든다.

What changedRestored by a configuration backupNeeds its own action
Service unit or startup orderingPartly, if the unit file was includedPackage state and enabled links
Kernel module or interface supportNoKernel or module rollback, or a boot-time decision
Peer or device authorizationOnly if the backup predates the revocationA deliberate decision about which peers return
Firewall rules applied outside the configOnly if they were capturedReplaying and verifying each rule

권한 부여는 자기 줄을 가질 자격이 있다. 침해된 장치를 제거하기 전에 찍은 백업은 그 장치의 접근을 기꺼이 복원한다. 장애 중에 그리로 되돌리는 것이 한 사건을 두 사건으로 만드는 길이며, 복원 결정은 파일에 대해 그랬던 만큼 명시적으로 피어에 대해서도 내려야 한다.

되돌리기의 메커니즘도 중요하다. 패키지가 관리하는 파일 위에 더 오래된 실행 파일을 복사하는 것은 패키지 변경의 지원되는 되돌리기가 아니며, 패키지 데이터베이스가 파일 시스템과 맞지 않는 상태를 설명하도록 남긴다. 패키지 관리자 자체의 다운그레이드 경로나 사업자가 제공하는 스냅숏을 써라. 패키지 데이터베이스가 기록하는 다운그레이드라야 반복할 수 있다.

이 중 어느 것도 백업에 반대하지 않는다. 부분 복원의 실패 방식이 원래 장애보다 혼란스럽기 때문에 각 산출물이 어느 계층을 덮는지 알아야 한다는 쪽이다. 런북에서 각 백업 옆에 계층을 적어라.

체크포인트, 업데이트, 그다음 외부에서 검증

변경 전 상태를 나중에 비교할 수 있는 형태로 기록하라. 설치된 버전, 관련 서비스 유닛, 수신 중인 소켓, 현재 피어 목록이다. 리눅스 호스트에서는 네 개의 명령으로 그 대부분을 덮는다.

systemctl list-units --type=service | grep -E 'openvpn|wg-quick'
ss -lunp | grep -E ':51820|:1194'
journalctl -u wg-quick@wg0 --since '-10 min'

첫째는 어떤 유닛이 있고 실행 중인지 보여 주고, 둘째는 수신기가 실제로 결속되었는지 확인하며, 셋째는 지난 몇 분에 대한 서비스 자체의 설명을 준다. 어느 것도 클라이언트가 연결할 수 있음을 증명하지 않으므로 다음 단계는 호스트 밖에서 이뤄진다. 그 판독값을 비교 기준으로 남겨 두라.

터널을 쓰지 않는 네트워크에서 검증하라. 승인된 클라이언트 하나를 인증하고, 이름을 해석하고, 의도한 애플리케이션 하나에 도달하라. 인터페이스가 올라와 있다는 로컬 상태 줄은 인터페이스에 대한 진술이며, 라우팅이나 키, 피어를 허용하는 정책에 대한 것이 아니다.

그다음 재연결 경로를 의도적으로 시험하라. 서비스를 한 번 재시작하고 수동 개입 없이 터널이 돌아오는지 확인하라. 부팅 때만 제대로 시작하는 서비스는 최악의 순간에 놀라게 할 서비스이기 때문이다.

실패하면 시험한 경로를 써라

복구 순서는 화려하지 않고 작동한다. 독립 경로로 호스트에 도달하고, 서비스 자체의 로그를 읽고, 장애에 해당하는 특정 체크포인트를 복원하라. 시도마다 한 가지만 바꿔야 다음 로그 판독이 의미를 갖는다.

연결을 되찾으려고 기록하지 않은 변경을 여러 개 하려는 충동을 물리쳐라. 다섯 개를 동시에 고쳐 되살린 기계는 나중에 설명할 수 없고, 다음 업데이트는 실제로 하중을 지탱하던 변경을 다시 들여올 것이다.

그다음 증거를 갖고 영구 정책을 정하라. 업데이트가 아무도 문서화하지 않은 의존성을 드러냈다면 고칠 것은 문서와 테스트이지 업데이트를 끄는 것이 아니다. 깨끗하게 재시작할 수 없는 서비스를 드러냈다면 고칠 것은 유닛이지 일정이 아니다.

조건에 이름이 붙는 순간 비교는 깔끔하게 정리된다. 독립 경로가 있으면 무인 업데이트는 관리 가능한 위험이 된다. 그것이 없으면 같은 정책은 복구 시간을 알 수 없는 계획된 중단이 되고, 어떤 자동화도 그 산수를 바꾸지 않는다.

관련 글