본문 바로가기
Service Mesh/Consul

Consul Peering 환경에서 데이터 센터 간 Failover 구성

by wlsdn3004 2024. 2. 7.
728x90
반응형

 

본 글은 이전에 작성된 [Consul Cluster Peering을 통한 데이터 센터 간 통신] 글에서 구성한 환경 기반으로 작성하는 글로 본 글의 실습을 진행하려면 이전 글의 환경 구성을 완료해야 한다.

 

Failover란?


Failover는 주요 서비스의 장애 발생 시, 자동으로 대체 서비스로 전환하는 과정을 의미한다. 이는 예기치 못한 데이터 센터 장애에 서비스의 중단 시간을 최소화하고, 서비스의 지속 가능성을 보장하기 위해 중요한 기능이다.

 

본 글에서 진행할 Failover 실습 시나리오는 아래와 같다.

 

위 시나리오를 구성하기 위한 Failover 방법으로는 두 가지가 있는데, ServiceResolver와 SamenessGroup방식이 있다.

  • ServiceResolver: 서비스에서 upstreams 요청에 대해 설정한 조건이 부합할 때 트래픽 동작을 조작할 수 있는 기능
  • SamenessGroup: Cluster Peering 연결을 통해 remote 파티션에 등록된 서비스의 이름과 Consul namespace가 같을 때 동일한 서비스로 인식하게 할 수 있는 기능

 

구성 환경

  • 3개의 Amazon EKS 클러스터 v1.27.7
  • Consul version v1.17-ent
  • Consul Enterprise license
  • Consul Helm Chart 버전 1.3.1
  • Helm Cli v3.8.2

 

1. ServiceResolver Failover


cluster-01(dc2)에 배포할 static-client 및 static-server 서비스 yaml파일을 작성한다.

# static-client.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: static-client
spec:
  protocol: 'http'
---
apiVersion: v1
kind: Service
metadata:
  name: static-client
spec:
  selector:
    app: static-client
  ports:
    - port: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: static-client
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: static-client
spec:
  replicas: 1
  selector:
    matchLabels:
      app: static-client
  template:
    metadata:
      name: static-client
      labels:
        app: static-client
      annotations:
        'consul.hashicorp.com/connect-inject': 'true'
    spec:
      containers:
        - name: static-client
          image: curlimages/curl:latest
          command: ['/bin/sh', '-c', '--']
          args: ['while true; do sleep 30; done;']
      serviceAccountName: static-client

 

# static-server.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceDefaults
metadata:
  name: static-server
spec:
  protocol: 'http'
---
apiVersion: v1
kind: Service
metadata:
  name: static-server
spec:
  selector:
    app: static-server
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: static-server
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: static-server
spec:
  replicas: 1
  selector:
    matchLabels:
      app: static-server
  template:
    metadata:
      name: static-server
      labels:
        app: static-server
      annotations:
        consul.hashicorp.com/connect-inject: "true"
    spec:
      containers:
        - name: static-server
          image: hashicorp/http-echo:latest
          args:
            - -text="i'm peer cluster-01"
            - -listen=:8080
          ports:
            - containerPort: 8080
              name: http
      serviceAccountName: static-server

 

작성한 파일을 적용하여 static-client, static-server 서비스를 배포한다.

$ kubectl apply -f static-client.yaml -f static-server.yaml

 

서비스 통신 허용을 위해 serviceintentions를 설정한다.

# intentions.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceIntentions
metadata:
  name: static-server-intention
spec:
  destination:
    name: static-server
  sources:
   - name: "*"
     action: deny
   - name: static-client
     action: allow

 

위 serviceintentions 설정을 반영한다.

$ kubectl apply -f intentions.yaml

 

failover 동작을 위한 serviceresolver를 설정한다.

  • 아래 설정은 같은 dc2의 서비스 static-server로 호출하다 실패하면 피어링 된 cluster-02의 static-server로 호출하고, cluster-02의 static-server도 실패하면 cluster-03의 static-server로 failover 하라는 내용이다.
# resolver.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: ServiceResolver
metadata:
  name: static-server
spec:
  connectTimeout: 1s
  failover:
    '*':
      targets:
        - peer: 'cluster-02'
          service: 'static-server'
          namespace: 'default'
        - peer: 'cluster-03'
          service: 'static-server'
          namespace: 'default'

 

위 serviceresolver 설정을 반영한다.

$ kubectl apply -f resolver.yaml

 

static-client 서비스에 접근하여 static-server가 정상인지 호출 테스트한다.

$ kubectl exec -it deploy/static-client -c static-client -- /bin/sh
$ while true; do curl static-server ; sleep 1 ; done
"i'm peer cluster-01"
"i'm peer cluster-01"
"i'm peer cluster-01"

 

1초마다 호출하는 상황에서 static-server 장애 유발을 위해 static-server를 삭제한다.

$ kubectl delete deploy static-server

 

아래는 cluster-01의 static-client에 접근하여 호출 상황을 캡처한 사진이다.

 

cluster-01의 static-server 서비스를 삭제하니 cluster-02의 static-server로 failover 되는 걸 확인할 수 있다.

그럼, cluster-02의 static-server도 삭제해서 동작을 확인해 보자.

$ kubectl delete deploy static-server

 

cluster-01의 static-client에서 호출 상황을 캡처한 결과이다.

 cluster-02의 static-server도 삭제되니 cluster-03 static-server로 failover 되는 걸 확인할 수 있다.

 

아래는 맨 처음 cluster-01에 있던 static-server를 다시 생성 후 static-client에서 호출 상황을 캡처한 결과이다.

다시 복구된 cluster-01의 static-server를 호출하는 걸 확인할 수 있다.

 

 

2. SamenessGroup Failover


먼저, 위에서 설정한 serviceresolver 설정을 삭제한다.

$ kubectl delete -f resolver.yaml

 

Failover 동작을 위해 SamenessGroups 설정파일을 작성한다.

  • 아래 설정에서 failover 대상 우선순위가 spec.members의 순서에 영향을 받는데, 위에 선언한 순서부터 우선순위가 적용된다.
    • 예) default 파티션(자신의 클러스터 서비스)의 서비스가 죽으면 다음으로는 cluster-03의 서비스로 failover 되고, cluster-03 서비스가 죽으면 cluster-02 서비스로 failover 된다.
# samenessgroup.yaml
apiVersion: consul.hashicorp.com/v1alpha1
kind: SamenessGroup
metadata:
  name: example-sg
spec:
  defaultForFailover: true
  members:
    - partition: default
    - peer: cluster-03
    - peer: cluster-02

 

작성한 SamenessGroups 설정파일을 반영한다.

$ kubectl apply -f samenessgroup.yaml

 

static-client 서비스에 접근하여 static-server가 정상인지 호출 테스트한다.

$ kubectl exec -it deploy/static-client -c static-client -- /bin/sh
$ while true; do curl static-server ; sleep 1 ; done
"i'm peer cluster-01"
"i'm peer cluster-01"
"i'm peer cluster-01"

 

1초마다 호출하는 상황에서 static-server 장애 유발을 위해 static-server를 삭제한다.

$ kubectl delete deploy static-server

 

static-client에 접근하여 호출 상황을 보면 다음과 같다.

cluster-01의 static-server가 죽어 cluster-03의 static-server를 호출하는 걸 확인할 수 있다.

 

이어서 cluster-03의 static-server도 삭제한 뒤 확인해 보자.

cluster-03의 static-server가 죽어 cluster-02의 static-server를 호출하는 걸 확인할 수 있다.

 

 

반응형

댓글