Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

디스크 장애(오류)는 디스크 스토리지 계층의 물리적 연결 단자의 단선 , 이 외에도 미디어 파손, 배드 섹터, SCSI 오류 등 얘기치 않은 장애로 인해 디스크 I/O 에 오류가 발생하는 상황을 말합니다것 입니다. 이러한 장애 들은 일시적으로 발생했다가 정상화 되기도 하고 영구적 장애로 이어지기도 합니다. bsr 에선 이러한 장애를 일시적 장애와 영구적 장애로 장애 유형으로 구분하고 유형에 따라 오류를 다르게 처리합니다.

일시적 장애는 스토리지 계층에서의 계층에서 어떤 이유로 인해 오류가 잠시 발생 했다가 다시 정상화되는 상황입니다. 이럴 경우에는 디스크 교체가 필요한 정도의 심각한 상황이 아니기 때문에 아니므로 되도록이면 서비스 운영을 지속하면서 기 발생된 에러에 대해서만 별도로 해소하고 복제는 계속 운영되도록 하는게 효율적입니다. 즉 일시적 오류 상황에서는 I/O 에러가 발생한 블록 영역을 out-of-sync 로 기록하고 오류를 상위 계층으로 전달합니다. 상위 파일시스템은 해당 블록으로 I/O 를 재시도 하고 재시도된 I/O 가 성공하면 자연스럽게 OOS 가 해소되도록 합니다. 영구적인 디스크 오류는 이렇게 발생했던 오류가 재시도를 통해 금방 해소되면 일시적 오류로 처리할 수 있지만 재 시도를 계속 해도 I/O 오류가 해소되지 않을 경우엔 이것을 영구적인 오류가 간주하고 디스크 상태를 분리(detach)하여 복제가 중단되도록 합니다.

영구적인 디스크 오류는 디스크 교체 등 디스크 장애에 대한 별도 조치가 필요한 상황으로 전체 재구성의 절차를 통해 복구해야 합니다.

...

Code Block
resource <resource> {
  disk {
    on-io-error <strategy>;
    max-passthrough-count 100;
    ...
  }
  ...
}

해당 옵션을 <common> 섹션에 정의한다면 모든 리소스에 적용됩니다.

...

  • passthrough on-io-error의 기본값으로 하위계층의 I/O 오류를 상위 계층에 보고합니다. I/O 오류는 Primary 노드일 경우 마운트 된 파일시스템으로 보내고, Secondary 노드에서는 Primary 노드로 쓰기 결과를 전달하거나 (복제 연결이 없을 경우)무시 됩니다. 이때 디스크 상태는 현 상태를 유지하며 해당 에러블럭에 대해 OOS로 기록합니다. detach lower-level I/O 에러가 발생하면, 노드는 백업 디바이스를 복제볼륨으로부터 분리(detach)시키고 diskless I/O 오류는 상위에 의해 재시도 되어 정상 처리되거나 다시 오류가 발생될 수 있습니다. 재시도가 되어도 오류가 지속되면 다음의 detach 정책에 의해 처리됩니다.

    • max-passthrough-count 패스스루를 무한정 할 수는 없습니다. 일정 수 이상 패스스루가 반복될 경우 영구적 디스크 장애로 간주해야 하고 여기의 임계점을 지정합니다.

  • detach 하위계층의 I/O 에러가 발생하면, 노드는 장치를 복제볼륨으로부터 분리(detach)시키고 diskless 상태로 전환합니다.

  • call-local-io-error. 로컬 I/O 에러 핸들러로 정의된 명령을 호출합니다. 이 옵션은 local-io-error <cmd> 가 리소스의 <handlers> 섹션에 정의되어 있어야 사용 가능합니다. local-io-error 호출 명령 또는 스크립트를 사용하면  I/O 에러 처리를 전적으로 사용자의 결정에 맡깁니다.

에러처리 정책은 리소스가 운영중이더라도 adjust 명령을 통해 실시간 적용할 수 있습니다.

Info

복제 서비스 운영 경험에 따르면 디스크 장애는 생각보다 자주 발생합니다. 이러한 결과는 하위 디스크 계층에 의존적이며 디스크 계층 즉, 표준 SCSI 계층의 에러는 임의의 시점에 언제든지 발생할 수 있다는 점에 비추어 보면 디스크 계층의 안정성과는 별도로 다루어야 하고, 복제 측면에서도 passthrough 정책의 특징

bsr 은 하위의 SCSI 스토리지 계층에서 발생하는 오류들에 유연하게 대처할 수 있어야 함을 의미합니다합니다.

그동안 디스크 장애 정책으로 제공해 왔던 detach 정책은 서비스 운영관점에선 복제가 특정시점에 특정 시점에 일방적으로 중단되는 정책이었습니다. 이러한 방식은 사후 복구도 어렵고 서비스 운영 지속 측면에서도 불리합니다. 우리는 이러한 문제를 해결하기 위해 passthrough 정책을 고안하였으며 bsr의 기본정책으로 설정하게 되었습니다.

패스스루 정책은 I/O 에러가 발생할 경우 해당 블럭에 대해서 OOS 를 기록하고 실패된 I/O 결과를 파일시스템으로 전달합니다. 이 때 파일시스템이 에러가 발생한 블럭에 대해 쓰기 재시도하여 성공하고 다시 쓰기하여 이를 통해 OOS를 해소한다면 이는 일시적인 디스크 계층의 에러를 파일시스템 스스로 극복하도록 유도하게 됩니다. 비록 파일시스템의 동작 특성에 따라 완전히 OOS가 해소되지 못한다고 하더라도 일부 남겨진 OOS 는 연결 재시도 등을 통해 재동기화 하여 해결할 수도 있습니다.

패스스루 정책은 에러 블럭을 FS가 스스로 해결하거나 동기화를 통해 해소하도록 유도하고, 기본적으로 디스크 I/O에 문제가 있더라도 서비스 운영을 지속하도록 보장합니다.

...

I/O 에러 정책을 패스스루(passthough)로 설정할 경우 I/O 에러의 결과는 파일시스템으로 전달되고 bsr 은 오류가 발생한 I/O 블럭을 OOS로 기록합니다. 이러한 OOS는 I/O 에러가 일시적이었다면 파일시스템에 의해 재 시도 되어 스스로 해소되거나, 그렇지 않다면 복제 재연결을 통해 재동기화를 유도하여 해당 OOS 영역을 해소합니다. 이 때 OOS를 해소하는 동기화의 방향이나 절체 여부 등의 운영은 관리자 또는 HA 운영 로직에 맡깁니다. 

...

디스크 오류 정책을 detach 정책으로 하여 리소스 분리를 자동으로 수행할 수도 있으나 자동분리(detach) 정책 보다는 passthrough 정책으로 설정하는 것을 권장합니다. passthrough 정책이 디스크의 일시적 오류에 능동적으로 대처할 수 있는 만큼 서비스 운영 측면에서 보다 더 합당합니다.

Info

bsr 은 I/O 오류가 일시적인지 또는 영구적인지 판단할 수 없으며 섹터 단위의 I/O 오류 추적 등의 구체적인 오류 통계를 유지하지 않습니다. 오류가 발생한 해당 장치에 대한 I/O 에러 발생 회수 정보만 간직합니다. 구체적인 정보는 알 수 없지만 bsradm status의 I/O 에러 회수를 토대로 에러가 발생한 정도를 파악할 수 있습니다. 만약 일시적 에러가 발생했다면 status에 보여지는 io error 와 oos 는 다소간의 양만 기록되어 있을 것이며 시간이 지나도 그 양은 증가하지 않을 것 입니다.

...

영구적 오류는 다양한 상황에서 발생할 수 있습니다. 디스크에 실제 물리적인 손상(배드블럭)이 발생한 경우 또는 스토리지에 연결된 케이블이 단선되어 볼륨이 제거된 경우 SCSI 컨트롤러에 장애가 발생한 경우 등 실제로 스토리지 계층에 문제가 있는 상황을 포함해, 관리자의 실수 또는 bsr과 호환되지 않는 다른 프로그램의 영향으로 볼륨이 제거되는 복제 외적인 상황 등이 모두 포함됩니다. 이러한 영구적 오류가 발생하면 관리자는 복제를 재구성하거나 디스크를 교체해야 합니다. 영구적 디스크 오류를 조치하기 위해선 먼저 리소스를 down 한 이후 디스크를 복제 상태에서 분리(detach)해야 합니다. 물론 재구성을 해야 하는 복제 리소스에 대해선 메타디스크를 재초기화 해야 합니다.

디스크

...

디스크 교체

...

교체

다음과 같이 메타 데이터 세트를 재생성하고, 리소스를 다시 연결합니다. 필요하다면 명시적으로 동기화 명령을 수행하여 전체동기화를 진행합니다.

...

디스크 읽기 오류, 메타디스크 I/O 오류에 대해선 자동 분리(detach) 정책이 적용되어 복제가 중단되며, 복제 적용되고 복제를 중단합니다. 중단된 리소스는 재구성을 통해서만 복구 될 수 있습니다.

...

만일 Primary 가 이미 동작하고 있다면 연결되면서 자동으로 동기화가 시작되므로 수동으로 동기화를 할 필요는 없습니다.

스플릿 브레인

스플릿 브레인 동작 설정

bsr 에서는 스플릿 브레인을 감지하면 자동으로 운영자에게 알릴 수 있는 방법을 제공합니다.

...

Info

주의 할점

스플릿 브레인 핸들러의 리턴 결과는 bsr 커널 엔진과 동기적으로 연계되기 때문에 핸들러의 실행 결과가 리턴되지 않을 경우 커널 엔진에 영향을 줄 수 있습니다. 복잡하지 않은 단순한 스크립트로 구성할 것을 권장합니다.

리눅스에선 스플릿 브레인 핸들러가 기본적으로 활성화되어 있으나 Windows 에선 기본 비활성화되어 있습니다핸들러는 기본적으로 비활성화 되어있습니다. 다음 명령을 사용하여 핸들러 서비스를 활성화할 수 있습니다.

Code Block
drbdconbsrcon /handler_use 1

수동 복구

복제 연결 단절 후 양 노드가 Primary 역할이었다는 것을 감지했다면 상대 노드와 재 연결하는 시점에 스플릿 브레인(Split-brain)으로 판단하고 즉시 복제 연결을 끊습니다. 그리고 로그에 다음과 같은 메시지를 남깁니다.

Info

Split-Brain detected, dropping connection! 

하나의 노드에서 스플릿 브레인이 감지되면 리소스는 StandAlone 상태가 됩니다. 양 노드가 동시에 스플릿 브레인을 감지했다면 양 노드 모두 StandAlone 상태가 되지만, 한 노드에서 스플릿 브레인을 감지하기 전에 상대 노드가 연결을 먼저 끊게 되면 SB를 감지하지 못한 채 단지 Connecting 상태로 유지합니다.

스플릿 브레인을 복구하기 위해선 스플릿 브레인 자동 복구 구성이 되어 있지 않는 한, 변경사항을 폐기할 노드(victim)를 먼저 선택하고 다음과 같은 절차를 통해 수동으로 복구해야 합니다.

먼저 양 노드에서 다음의 명령을 통해 StandAlone 상태로 만듭니다.

Code Block
bsradm disconnect <resource>

폐기할 노드(victim)에서 아래 명령을 수행합니다. 

Code Block
bsradm secondary <resource>
bsradm connect --discard-my-data <resource>

운영 노드(survivor) 에서 연결합니다. 노드가 이미 Connecting 상태였다면 자동으로 연결되기 때문에 이 단계를 생략할 수 있습니다.

Code Block
bsradm connect <resource>

정상적으로 연결되면 victim의 복제 상태는 즉시 SyncTarget으로 변경되고, 노드 간의 데이터 변경점들이 survivor 노드를 기준으로 동기화 됩니다.

Info

스플릿 브레인의 폐기 노드(victim)의 데이터는 전체 디바이스 차원에서 동기화가 이루어지지 않습니다. 단지 victim의 수정사항을 롤백하고, 모든 수정사항에 대해 스플릿 브레인 survivor에서 victim노드로 전파됩니다. 즉 변경 분에 대해서만 동기화가 이루어 집니다.

재동기화가 완료되면 스플릿 브레인은 해결된 것으로 간주하며, 두 노드는 다시 완전히 일치된 이중화 복제 저장 시스템으로 복구됩니다. 

다중 스플릿 브레인

1:N 복제 환경에선 노드들 간의 스플릿 브레인이 다중으로 발생될 수 있습니다. 

예를 들어 A-B-C 의 1:2 복제 구성의 경우 각 노드의 연결을 단절하고 모든 노드의 리소스를 승격 후 볼륨에 I/O 를 수행합니다. 이 후 각 노드를 강등하여 재 연결하면 각각의 노드간에 스플릿 브레인이 발생됩니다. 이 때 스플릿 브레인은 A-B 노드간, B-C 노드간에 또는 A-C 노드 간의 스플릿 브레인 상황이며 클러스터 내 노드간의 SB가 다중으로 발생된 상황입니다. 이럴 경우 다중 SB의 해결은 노드들 간의 개별 연결 기준으로 다음의 절차에 따라 순차적으로 해결해야 합니다.

  • Survival 노드와 Victim 노드를 결정하고 모든 노드에서 disconnect 하여 StandAlone 상태를 만듭니다.

  • SB가 발생한 노드간에 SB를 해결합니다.

    • Survival 노드는 drbdsetup connect [resource] [victim node-id] 명령을 통해 Connecting 상태로 진입

    • Victim 노드는 drbdsetup connect [resource] [survival node-id] --discard-my-data 명령을 통해 SB 해결

  • SB가 해결되고 나면 연결이 되지 않은 Victim 노드 간의 연결을 복원합니다. drbdsetup connect [resource] [victim node-id]

    • SB 를 해결하여 연결을 복원하는 도중 2차 SB가 발생될 경우도 있습니다. 이럴 경우 위와 동일한 절차로 SB를 해결합니다.

자동 복구

스플릿 브레인이 발생하면 관리자에게는 스플릿 브레인 수동 복구(Manual split brain recovery)가 권장되지만, 경우에 따라서는 그 과정을 자동화하는 것이 좋을 수도 있습니다.

bsr은 스플릿 브레인을 자동 복구할 수 있는 몇 가지 알고리즘을 제공합니다.

  • Younger Primary 노드의 수정분 폐기: 네트워크 연결이 다시 복구 되고 스플릿 브레인이 감지되면, 최근 Primary 역할로 전환한 노드의 수정분을 폐기합니다.

  • Older Primary 노드의 수정분 폐기: 네트워크 연결이 다시 복구 되고 스플릿 브레인이 감지되면, 처음 Primary 역할을 가졌던 노드의 수정분을 폐기합니다.

  • 수정 내용이 적은 Primary 데이터 폐기 - 양쪽 노드에서 수정 내용이 더 적은 쪽 노드를 확인하여 그 노드의 내용을 폐기합니다.

  • 데이터 변경 사항이 없는 호스트로 복구 - 스플릿 브레인 동안 데이터의 수정 이력이 없는 노드가 있다면 해당 노드로 복구시키고 스플릿 브레인 해결을 선언합니다. 하지만 이것은 아주 드문 경우입니다. 양쪽 노드에서 리소스 볼륨을 파일시스템에 마운트(심지어 읽기전용)만 하더라도 볼륨 내용은 수정사항이 발생하기 쉬우며, 그 후에는 이 방식으로 자동 복구될 가능성은 없다고 봐야 합니다.

자동 스플릿 브레인 복구를 사용할 지 여부는 대체로 응용프로그램에 따라 달라집니다. 예를 들어 bsr에서 데이터베이스를 호스팅하는 경우를 생각해보면 사용자 인터페이스와 연관된 데이터 베이스를 사용하는 웹 응용프로그램에서는 폐기 해야할 변경사항이 거의 없어서 자동 복구가 괜찮은 수단이 될 수 있지만 반대로 금융 데이터 처럼 그 어떠한 데이터라도 함부로 폐기가 힘든 성격을 가지고 있는 환경에서는 사람이 직접 수동 복구를 해야 할 것입니다. 자동 스플릿 브레인 복구를 활성화하기 전에 응용프로그램의 요구사항을 신중하게 고려해야 합니다.

자동 복구 정책

자동 split-brain 복구 정책을 구성하기 위해서는 bsr이 제공하는 몇 가지 구성 옵션을 이해해야 합니다. bsr은 SB 감지 시 Primary로 있었던 노드의 수에 따라 복구 정책을 구분하고, 이에 대한 자동 복구 정책은 리소스의 <net> 섹션에 다음과 같은 키워드를 사용하여 구성합니다.

after-sb-0pri. SB가 발생된 시점에, 어떤 노드도 Primary 역할에 있지 않은 상황으로 복구 방법은 다음과 같습니다. 

  • disconnect : 자동으로 복구하지 않습니다. 구성된 SB 핸들러 스크립트가 있다면 이를 호출하고, disconnected 모드를 지속합니다.

  • discard-younger-primary : 마지막으로 Primary 역할을 했다고 추정되는 노드에서 수정사항을 취소하고 되돌립니다. younger primary를 판단할 수 없다면 discard-zero-changes, discard-least-changes 순서로 동작하게 됩니다. 

  • discard-least-changes : 최소의 변경 사항이 발생한 노드에서 수정사항을 취소하고 되돌립니다.

  • discard-zero-changes : 변경 사항이 발생하지 않은 노드가 있다면, 다른 노드의 변경 사항을 적용합니다.

after-sb-1pri. SB가 발생된 시점에, 하나의 노드가 Primary 역할에 있는 상황으로 복구 방법은 다음과 같습니다. 

  • disconnect : 자동으로 복구하지 않습니다. 구성된 SB 핸들러 스크립트가 있다면 이를 호출하고, disconnected 모드를 지속합니다.

  • consensus : SB victim이 선택될 수 있다면 자동으로 해결합니다. 그렇지 않으면, disconnect처럼 동작합니다.

  • call-pri-lost-after-sb : SB victim이 선택될 수 있다면, victim 노드에서 pri-lost-after-sb 핸들러를 호출합니다. 이 핸들러는 <handlers> 섹션에 구성되어야 하고, 클러스터에서 노드가 강제로 제거됩니다.

  • discard-secondary : 현재 Secondary 역할에 있는 노드를 SB victim으로 만듭니다.

after-sb-2pri. SB가 발견된 시점에 양 노드에서 Primary 역할에 있는 상황으로, 복구 방법은 disconnect 를 통한 수동 복구만 사용할 수 있습니다.

구성 파일 작성 예시는 다음과 같습니다.

...

Code Block
resource <resource> {
    handlers {
        split-brain "C:/Tools/script/split-brain.bat";
        ...
    }
    net {
        after-sb-0pri discard-zero-changes;
        after-sb-1pri discard-secondary;
        ...
    }
    ...
}
Info

SB 핸들러의 배치 파일 구성에서 사용하는 파일들은 절대 경로로 기술되어야 합니다.

호환성

타사 제품 또는 모듈과의 호환성 문제에 대해 설명합니다. 호환성 문제는 대부분 다른 프로그램 또는 모듈의 동작이 bsr 의 운영을 방해하는 현상으로 나타납니다.

볼륨 참조

bsr 은 리소스 동작 중에 내부적으로 볼륨에 대한 참조회수를 유지합니다. 만약 down 시점에 볼륨에 대한 참조회수가 0이 아니라면 다음과 같은 유형의 오류 로그가 출력되며 down 은 실패 합니다.

Info

DRBD volume(r0) Secondary failed (error=0: State change failed: (-12) Device is held open by someone

이 문제를 해결하려면 볼륨을 참조하는 프로세스 또는 모듈을 파악하여 해당 모듈의 동작을 중단 시켜서 볼륨에 대한 참조회수를 감소시키는 조치가 필요합니다.

예를 들어, Ubuntu 20.04 이상에서 multipath-tools(0.8.3)는 multipath.conf 에 다음과 같은 예외조치를 통해 bsr 볼륨에 대한 참조가 발생하지 않도록 해야 합니다.

...

스플릿 브레인 상태 확인

스플릿 브레인이 발생했을 때의 상태 출력 결과 입니다.

Code Block
C:\Users\Administrator>bsrsetup status r0 --verbose --statistic
r0 node-id:0 role:Primary suspended:no
    write-ordering:drain req-pending:0
  volume:0 minor:2 disk:UpToDate
      size:10467328 read:29847120 written:3029330 al-writes:260 bm-writes:0 upper-pending:0 lower-pending:0
      al-suspended:no al-pending-changes:0 al-used:0 accelbuf-used:0 blocked:no
  D3W2K22BSRAG-002 node-id:1 connection:StandAlone error:split-brain role:Unknown congested:no
    volume:0 replication:Off peer-disk:DUnknown resync-suspended:no
        received:0 sent:11803912 out-of-sync:329892 pending:0 unacked:0
  D3W2K22BSRAG-003 node-id:2 connection:Connected role:Secondary congested:no
    volume:0 replication:Established peer-disk:UpToDate resync-suspended:no
        received:0 sent:16247308 out-of-sync:0 pending:0 unacked:0

수동 복구

복제 연결 단절 후 양 노드가 Primary 역할이었다는 것을 감지했다면 상대 노드와 재 연결하는 시점에 스플릿 브레인(Split-brain)으로 판단하고 즉시 복제 연결을 끊습니다. 그리고 로그에 다음과 같은 메시지를 남깁니다.

Info

Split-Brain detected, dropping connection! 

하나의 노드에서 스플릿 브레인이 감지되면 리소스는 StandAlone 상태가 됩니다. 양 노드가 동시에 스플릿 브레인을 감지했다면 양 노드 모두 StandAlone 상태가 되지만, 한 노드에서 스플릿 브레인을 감지하기 전에 상대 노드가 연결을 먼저 끊게 되면 SB를 감지하지 못한 채 단지 Connecting 상태로 유지합니다.

스플릿 브레인을 복구하기 위해선 스플릿 브레인 자동 복구 구성이 되어 있지 않는 한, 변경사항을 폐기할 노드(victim)를 먼저 선택하고 다음과 같은 절차를 통해 수동으로 복구해야 합니다.

먼저 양 노드에서 다음의 명령을 통해 StandAlone 상태로 만듭니다.

Code Block
bsradm disconnect <resource>

폐기할 노드(victim)에서 아래 명령을 수행합니다. 

Code Block
bsradm secondary <resource>
bsradm connect --discard-my-data <resource>

운영 노드(survivor) 에서 연결합니다. 노드가 이미 Connecting 상태였다면 자동으로 연결되기 때문에 이 단계를 생략할 수 있습니다.

Code Block
bsradm connect <resource>

정상적으로 연결되면 victim의 복제 상태는 즉시 SyncTarget으로 변경되고, 노드 간의 데이터 변경점들이 survivor 노드를 기준으로 동기화 됩니다.

Info

스플릿 브레인의 폐기 노드(victim)의 데이터는 전체 디바이스 차원에서 동기화가 이루어지지 않습니다. 단지 victim의 수정사항을 롤백하고, 모든 수정사항에 대해 스플릿 브레인 survivor에서 victim노드로 전파됩니다. 즉 변경 분에 대해서만 동기화가 이루어 집니다.

재동기화가 완료되면 스플릿 브레인은 해결된 것으로 간주하며, 두 노드는 다시 완전히 일치된 이중화 복제 저장 시스템으로 복구됩니다. 

다중 스플릿 브레인

1:N 복제 환경에선 노드들 간의 스플릿 브레인이 다중으로 발생될 수 있습니다. 

예를 들어 A-B-C 의 1:2 복제 구성의 경우 각 노드의 연결을 단절하고 모든 노드의 리소스를 승격 후 볼륨에 I/O 를 수행합니다. 이 후 각 노드를 강등하여 재 연결하면 각각의 노드간에 스플릿 브레인이 발생됩니다. 이 때 스플릿 브레인은 A-B 노드간, B-C 노드간에 또는 A-C 노드 간의 스플릿 브레인 상황이며 클러스터 내 노드간의 SB가 다중으로 발생된 상황입니다. 이럴 경우 다중 SB의 해결은 노드들 간의 개별 연결 기준으로 다음의 절차에 따라 순차적으로 해결해야 합니다.

  • Survival 노드와 Victim 노드를 결정하고 모든 노드에서 disconnect 하여 StandAlone 상태를 만듭니다.

  • SB가 발생한 노드간에 SB를 해결합니다.

    • Survival 노드는 bsrsetup connect [resource] [victim node-id] 명령을 통해 Connecting 상태로 진입

    • Victim 노드는 bsrsetup connect [resource] [survival node-id] --discard-my-data 명령을 통해 SB 해결

  • SB가 해결되고 나면 연결이 되지 않은 Victim 노드 간의 연결을 복원합니다. bsrsetup connect [resource] [victim node-id]

    • SB 를 해결하여 연결을 복원하는 도중 2차 SB가 발생될 경우도 있습니다. 이럴 경우 위와 동일한 절차로 SB를 해결합니다.

자동 복구

스플릿 브레인이 발생하면 관리자에게는 스플릿 브레인 수동 복구(Manual split brain recovery)가 권장되지만, 경우에 따라서는 그 과정을 자동화하는 것이 좋을 수도 있습니다.

bsr은 스플릿 브레인을 자동 복구할 수 있는 몇 가지 알고리즘을 제공합니다.

  • Younger Primary 노드의 수정분 폐기: 네트워크 연결이 다시 복구 되고 스플릿 브레인이 감지되면, 최근 Primary 역할로 전환한 노드의 수정분을 폐기합니다.

  • Older Primary 노드의 수정분 폐기: 네트워크 연결이 다시 복구 되고 스플릿 브레인이 감지되면, 처음 Primary 역할을 가졌던 노드의 수정분을 폐기합니다.

  • 수정 내용이 적은 Primary 데이터 폐기 - 양쪽 노드에서 수정 내용이 더 적은 쪽 노드를 확인하여 그 노드의 내용을 폐기합니다.

  • 데이터 변경 사항이 없는 호스트로 복구 - 스플릿 브레인 동안 데이터의 수정 이력이 없는 노드가 있다면 해당 노드로 복구시키고 스플릿 브레인 해결을 선언합니다. 하지만 이것은 아주 드문 경우입니다. 양쪽 노드에서 리소스 볼륨을 파일시스템에 마운트(심지어 읽기전용)만 하더라도 볼륨 내용은 수정사항이 발생하기 쉬우며, 그 후에는 이 방식으로 자동 복구될 가능성은 없다고 봐야 합니다.

자동 스플릿 브레인 복구를 사용할 지 여부는 대체로 응용프로그램에 따라 달라집니다. 예를 들어 bsr에서 데이터베이스를 호스팅하는 경우를 생각해보면 사용자 인터페이스와 연관된 데이터 베이스를 사용하는 웹 응용프로그램에서는 폐기 해야할 변경사항이 거의 없어서 자동 복구가 괜찮은 수단이 될 수 있지만 반대로 금융 데이터 처럼 그 어떠한 데이터라도 함부로 폐기가 힘든 성격을 가지고 있는 환경에서는 사람이 직접 수동 복구를 해야 할 것입니다. 자동 스플릿 브레인 복구를 활성화하기 전에 응용프로그램의 요구사항을 신중하게 고려해야 합니다.

자동 복구 정책

자동 split-brain 복구 정책을 구성하기 위해서는 bsr이 제공하는 몇 가지 구성 옵션을 이해해야 합니다. bsr은 SB 감지 시 Primary로 있었던 노드의 수에 따라 복구 정책을 구분하고, 이에 대한 자동 복구 정책은 리소스의 <net> 섹션에 다음과 같은 키워드를 사용하여 구성합니다.

after-sb-0pri. SB가 발생된 시점에, 어떤 노드도 Primary 역할에 있지 않은 상황으로 복구 방법은 다음과 같습니다. 

  • disconnect : 자동으로 복구하지 않습니다. 구성된 SB 핸들러 스크립트가 있다면 이를 호출하고, disconnected 모드를 지속합니다.

  • discard-younger-primary : 마지막으로 Primary 역할을 했다고 추정되는 노드에서 수정사항을 취소하고 되돌립니다. younger primary를 판단할 수 없다면 discard-zero-changes, discard-least-changes 순서로 동작하게 됩니다. 

  • discard-least-changes : 최소의 변경 사항이 발생한 노드에서 수정사항을 취소하고 되돌립니다.

  • discard-zero-changes : 변경 사항이 발생하지 않은 노드가 있다면, 다른 노드의 변경 사항을 적용합니다.

after-sb-1pri. SB가 발생된 시점에, 하나의 노드가 Primary 역할에 있는 상황으로 복구 방법은 다음과 같습니다. 

  • disconnect : 자동으로 복구하지 않습니다. 구성된 SB 핸들러 스크립트가 있다면 이를 호출하고, disconnected 모드를 지속합니다.

  • consensus : SB victim이 선택될 수 있다면 자동으로 해결합니다. 그렇지 않으면, disconnect처럼 동작합니다.

  • call-pri-lost-after-sb : SB victim이 선택될 수 있다면, victim 노드에서 pri-lost-after-sb 핸들러를 호출합니다. 이 핸들러는 <handlers> 섹션에 구성되어야 하고, 클러스터에서 노드가 강제로 제거됩니다.

  • discard-secondary : 현재 Secondary 역할에 있는 노드를 SB victim으로 만듭니다.

after-sb-2pri. SB가 발견된 시점에 양 노드에서 Primary 역할에 있는 상황으로, 복구 방법은 disconnect 를 통한 수동 복구만 사용할 수 있습니다.

구성 파일 작성 예시는 다음과 같습니다.

Code Block
resource <resource> {
    handlers {
        split-brain "C:/Tools/script/split-brain.bat";
        ...
    }
    net {
        after-sb-0pri discard-zero-changes;
        after-sb-1pri discard-secondary;
        ...
    }
    ...
}
Info

SB 핸들러의 배치 파일 구성에서 사용하는 파일들은 절대 경로로 기술되어야 합니다.

Note

SB 해결(복구) 동기화 중 재 연결이 발생할 경우 다시 SB 발생 상황으로 돌아갑니다. SB 해결이 완료되지 않아서 아직은 양측 노드가 SB 상태이기 때문입니다.

bsr 1.7 이후 부터는 이 부분을 변경하여 한 번 SB 해결이 시도되면 재 연결이 되더라도 이후 SB 해결이 완료될 때 까지 SB 해결을 자동으로 수행하도록 합니다.

장치 참조 오류

bsr 은 내부적으로 백킹 디바이스에 대한 참조 회수를 유지 합니다. 참조 회수는 특정 프로세스가 장치를 열었을 때 증가하고 닫으면 감소되는데 이를 통해 장치에 대한 생명주기를 관리하고 리소스를 정리하는 시점에 특정 프로세스가 장치 볼륨을 더 이상 참조하지 않도록 강제합니다.

bsr 리소스를 구성하는 초기 또는 장치를 umount 하는 과정에서 참조회수가 0 이 아닐 경우에 문제가 발생합니다. 어떤 프로세스가 장치를 열었다가 닫지 않았기 때문에 bsr 은 이를 감지하고 오류로 처리합니다.

  • 리소스 구성 오류

bsr 리소스의 backing device 를 어떤 프로세스가 참조하고 있다면 다음과 같은 오류로 장치 attach에 실패하게 될 것 입니다. 16 오류 코드는 EBUSY 에 해당합니다.

Info

[open_backing_dev] [DRIVER:140] bsr_erro<3> bsr bsr0/0 bsr0: Failed to open("/dev/sdb1") backing device with -16

  • down 오류

리소스 down 시점에 장치에 대한 참조회수가 0이 아니라면 down 은 실패 하고 다음과 같은 로그가 출력 됩니다.

Info

bsr volume(r0) Secondary failed (error=0: State change failed: (-12) Device is held open by someone

이 문제를 해결하려면 bsr 볼륨을 참조하고 있는 프로세스를 파악하여 해당 모듈을 강제 중단(fuser -ck) 시키는 등 볼륨에 대한 참조회수가 감소 되도록 조치 해야 합니다.

예를 들어, Ubuntu 20.04 이상에서 multipath-tools(0.8.3)는 multipath.conf 에 다음과 같은 예외 처리를 통해 bsr 장치에 대한 참조가 발생하지 않도록 해야 합니다. 그렇지 않으면 multipath-tools 로 인해 bsr 볼륨이 지속적으로 참조되어 down 을 할 수 없게 됩니다.

Code Block
blacklist {
        devnode "^(sd)[a-z]"
        devnode "^(bsr)[0-9]"
        }

제품 삭제 실패

제품 삭제가 실패한 경우 다음 순서에 따라 수동으로 삭제할 수 있습니다.

  1. 커널모듈 삭제

    1. bsrvflt.sys 삭제

      1. HKLM, System\CurrentControlSet\Control\Class\{71A27CDD-812A-11D0-BEC7-08002BE2092F}UpperFilters 키의 값 내용 중 bsrvflt 문자열 제거 후 레지스트리 저장

      2. HKLM, System\CurrentControlSet\Services\bsrvflt 키 삭제

    2. bsrfsflt.sys 삭제

      1. HKLM, System\CurrentControlSet\Services\bsrfsflt 키 삭제

  2. 응용 서비스 삭제

    1. sc stop bsr

    2. sc delete bsr

  3. 환경변수 삭제

    1. BSR_PATH, CYGWIN 시스템 환경변수 삭제

  4. Program Files\bsr 경로에 설치된 파일들 삭제

  5. 리부팅