5.12. 리더 선택 방식 구성
Operator의 라이프사이클 동안, 예를 들어 Operator에 대한 업그레이드를 롤아웃할 때 언제든지 여러 개의 인스턴스를 실행할 수 있습니다. 이러한 시나리오에서는 리더를 선택하여 여러 Operator 인스턴스 간 경합을 방지해야 합니다. 그러면 하나의 리더 인스턴스에서만 조정을 처리하고 다른 인스턴스는 비활성화되지만 리더가 아래로 내려가면 이어서 작업을 수행할 수 있습니다.
두 가지 리더 선택 구현 방법 중 선택할 수 있으며 각각 고유한 장단점이 있습니다.
- Leader-for-life
-
리더 Pod는 삭제되는 경우에만 가비지 컬렉션을 사용하여 리더십을 포기합니다. 이 구현에서는 실수로 두 개의 인스턴스가 리더로 실행될 가능성을 방지합니다. 이러한 상태를 스플릿 브레인이라고 합니다. 그러나 이 방법을 사용하면 새 리더 선택이 지연될 수 있습니다. 예를 들어 리더 Pod가 응답하지 않거나 분할된 노드에 있는 경우
pod-eviction-timeout
은 리더 Pod가 노드에서 삭제되고 아래로 내려가는 데 걸리는 시간을 지정하는데 기본값은5m
입니다. 자세한 내용은 leader-for-life Go 설명서를 참조하십시오. - Leader-with-lease
- 리더 Pod는 주기적으로 리더 리스를 갱신하고 리스를 갱신할 수 없는 경우 리더십을 포기합니다. 이 구현에서는 기존 리더가 격리되었을 때 새 리더로 더 빠르게 전환할 수 있지만 특정 상황에서 스플릿 브레인이 발생할 가능성이 있습니다. 자세한 내용은 Leader-with-lease Go 설명서를 참조하십시오.
Operator SDK에서는 기본적으로 Leader-for-life 구현을 사용합니다. 두 가지 접근 방식에 대한 관련 Go 설명서를 참조하여 사용 사례에 적합한 장단점을 고려하도록 합니다.
5.12.1. Operator 리더 선택 예
다음 예제에서는 Operator에 대한 두 개의 리더 선택 옵션인 Leader-for-life 및 Leader-with-lease를 사용하는 방법을 보여줍니다.
5.12.1.1. Leader-for-life 선택
Leader-for-life 선택 방식을 구현하면 leader.Become()
호출 시 memcached-operator-lock
이라는 구성 맵을 생성하여 Operator에서 리더가 될 때까지 재시도하지 못하도록 합니다.
import ( ... "github.com/operator-framework/operator-sdk/pkg/leader" ) func main() { ... err = leader.Become(context.TODO(), "memcached-operator-lock") if err != nil { log.Error(err, "Failed to retry for leader lock") os.Exit(1) } ... }
Operator가 클러스터 내에서 실행되지 않는 경우 leader.Become()
은 Operator의 이름을 탐지할 수 없기 때문에 리더 선택을 건너뛰기 위해 오류 없이 단순히 반환됩니다.
5.12.1.2. Leader-with-lease 선택
리더 선택을 위해 Manager 옵션을 사용하여 Leader-with-lease 구현을 활성화할 수 있습니다.
import ( ... "sigs.k8s.io/controller-runtime/pkg/manager" ) func main() { ... opts := manager.Options{ ... LeaderElection: true, LeaderElectionID: "memcached-operator-lock" } mgr, err := manager.New(cfg, opts) ... }
Operator가 클러스터에서 실행되지 않으면 Manager에서 리더 선택을 위한 구성 맵을 생성하기 위해 Operator의 네임스페이스를 탐지할 수 없기 때문에 시작 시 오류를 반환합니다. Manager에 LeaderElectionNamespace
옵션을 설정하여 이 네임스페이스를 덮어쓸 수 있습니다.