API Gateway와 Consul을 통합하는 방법

Fei Han

February 25, 2022

Ecosystem

배경 정보

Consul은 서비스 메시 솔루션입니다. 그 핵심 중 하나인 Consul KV는 분산 키-값 데이터베이스로, 주로 구성 매개변수와 메타데이터를 저장하는 데 사용되며, 사용자가 인덱싱된 객체를 저장할 수도 있습니다.

마이크로서비스 아키텍처 모델에서, 업스트림 서비스가 확장이나 하드웨어 장애 등으로 인해 변경될 때, 수동으로 구성을 작성하여 업스트림 서비스 정보를 유지하는 방식은 유지 관리 비용이 급격히 증가할 수 있습니다. 이를 해결하기 위해 Apache APISIX는 서비스 디스커버리 레지스트리를 제공하여 최신 서비스 인스턴스 정보를 동적으로 가져와 사용자의 유지 관리 비용을 줄입니다.

현재 Apache APISIX는 커뮤니티에서 기여한 consul_kv 모듈을 통해 Consul KV 기반의 서비스 디스커버리 레지스트리를 지원합니다.

작동 원리

Apache APISIX는 Consul KV의 분산 키-값 저장 기능을 활용하여 서비스 제공자와 소비자를 분리하고, 서비스 디스커버리 레지스트리의 두 가지 핵심 기능을 구현합니다.

  1. 서비스 등록: 서비스 제공자가 레지스트리에 서비스를 등록합니다.
  2. 서비스 디스커버리: 서비스 소비자가 레지스트리를 통해 서비스 제공자의 라우팅 정보를 찾습니다.

이를 기반으로 Apache APISIX는 기존 마이크로서비스 아키텍처에 더 유연하게 적응하여 사용자 요구를 더 잘 충족할 수 있습니다.

consul architectures

Apache APISIX에서 Consul 활성화 방법

이 문서의 테스트 환경은 docker-compose를 사용하여 Docker에서 구축되었습니다.

  1. Apache APISIX를 다운로드합니다.

    # apisix-docker Git 저장소를 가져옵니다.
    git clone https://github.com/apache/apisix-docker.git
    
  2. Consul 폴더와 구성 파일을 생성합니다.

    # Consul 폴더 생성
    mkdir -p ~/docker-things/consul/ && cd $_
    # 구성 파일 생성
    touch docker-compose.yml server1.json
    
  3. docker-compose.yml 파일을 편집합니다.

    version: '3.8'
    
    services:
    consul-server1:
    image: consul:1.9.3
    container_name: consul-server1
    restart: always
    volumes:
      - ./server1.json:/consul/config/server1.json:ro
    networks:
      - apisix
    ports:
      - '8500:8500'
    command: 'agent -bootstrap-expect=1'
    
    networks:
    apisix:
    external: true
    name: example_apisix
    
  4. server1.json 파일을 편집합니다.

    {
    node_name: consul-server1,
    server: true,
    addresses: {
    http: 0.0.0.0
    }
    }
    
  5. Apache APISIX 구성 파일 apisix_conf/config.yaml에 Consul 관련 구성 정보를 추가합니다.

    # config.yml
    # ...기타 구성
    discovery:
    consul_kv:
    servers:
      - http://consul-server1:8500
    prefix: upstreams
    
  6. Apache APISIX와 Consul을 시작합니다.

    # example, consul 폴더로 이동하여 APISIX와 Consul을 시작합니다.
    docker-compose up -d
    
  7. 테스트 서비스를 Consul에 등록합니다. 예제에는 두 개의 웹 서비스가 포함되어 있으며, 이를 직접 테스트에 사용할 수 있습니다.

    # 예제의 docker-compose.yml을 확인합니다.
    # 두 개의 웹 서비스를 볼 수 있습니다.
    $ cat docker-compose.yml | grep web
    # 출력
    web1:
    - ./upstream/web1.conf:/etc/nginx/nginx.conf
    web2:
    - ./upstream/web2.conf:/etc/nginx/nginx.conf
    
  8. 이러한 웹 서비스의 IP 주소를 확인합니다.

    $ sudo docker inspect -f='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(sudo docker ps -aq) | grep web
    # 출력
    /example-web1-1 - 172.26.0.7
    /example-web2-1 - 172.26.0.2
    
  9. 터미널에서 Consul의 HTTP API에 요청하여 테스트 서비스를 등록합니다.

    # 해당 IP로 등록합니다.
    curl \
    -X PUT \
    -d ' {weight: 1, max_fails: 2, fail_timeout: 1}' \
    http://127.0.0.1:8500/v1/kv/upstreams/webpages/172.26.0.7:80
    
    curl \
    -X PUT \
    -d ' {weight: 1, max_fails: 2, fail_timeout: 1}' \
    http://127.0.0.1:8500/v1/kv/upstreams/webpages/172.26.0.2:80
    

    /v1/kv/ 이후의 경로는 {Prefix}/{Service Name}/{IP}:{Port} 형식을 따릅니다.

    {Prefix}는 APISIX에서 Consul을 구성할 때 작성한 접두사이며, {Service Name}{IP}:{Port}는 사용자가 업스트림 서비스에 따라 결정해야 합니다.

    데이터 형식은 {"weight": , "max_fails": , "fail_timeout": }입니다.

  10. 테스트 서비스가 성공적으로 등록되었는지 확인합니다.

    curl http://127.0.0.1:8500/v1/kv/upstreams/webpages?keys
    

    다음 반환 메시지는 성공적인 등록을 나타냅니다.

    [upstreams/webpages/172.26.0.2:80,upstreams/webpages/172.26.0.7:80]%
    

라우트 생성 및 Consul 활성화

Apache APISIX에서 제공하는 Admin API를 사용하여 라우트에 Consul을 추가합니다.

X-API-KEYupstream.service_name을 추가하기 전에 결정해야 합니다.

  • X-API-KEY: Admin API 접근 토큰으로, 이 예제에서는 기본값인 edd1c9f034335f136f87ad84b625c8f1을 사용합니다.
  • upstream.service_name: 업스트림 서비스의 이름으로, 라우트에 바인딩될 레지스트리의 서비스를 지정하며, Consul을 사용할 때 테스트 서비스를 등록하는 데 사용된 URL로 설정해야 하며, 끝에 {IP}:{Port} 부분을 제거해야 합니다. 또한 Apache APISIX에서 제공하는 Memory Dump API를 사용하여 서비스의 URL을 가져오고 업스트림 서비스가 올바르게 발견되었는지 확인할 수 있습니다.
$ curl http://127.0.0.1:9092/v1/discovery/consul_kv/dump | jq
# 출력
{
  "services": {
    # 이 키는 필요한 URL입니다.
    "http://consul-server1:8500/v1/kv/upstreams/webpages/": [
      {
        "port": 80,
        "host": "172.26.0.7",
        "weight": 1
      },
      {
        "port": 80,
        "host": "172.26.0.2",
        "weight": 1
      }
    ]
  },
  "config": {
    # ...구성
  }
}

라우트 추가

여기서 URL /consul/*에 대한 요청은 http://consul-server1:8500/v1/kv/upstreams/webpages/로 라우팅됩니다. 또한 discovery_typeconsul_kv로 설정하여 해당 모듈을 시작해야 합니다.

curl http://127.0.0.1:9080/apisix/admin/routes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X POST -d '
{
    "uri": "/consul/*",
    "upstream": {
        "service_name": "http://consul-server1:8500/v1/kv/upstreams/webpages/",
        "type": "roundrobin",
        "discovery_type": "consul_kv"
    }
}'

테스트 및 결과 확인

요청 결과는 Apache APISIX의 새 라우트가 Consul을 통해 올바른 서비스 주소를 찾아 로드 밸런싱 정책에 따라 두 노드에 요청할 수 있음을 보여줍니다.

# 첫 번째 요청
curl -s http://127.0.0.1:9080/consul/
# 출력
hello web1%

# 두 번째 요청
curl -s http://127.0.0.1:9080/consul/
# 출력
hello web2%

# 참고: 두 요청 모두 web1 또는 web2와 같은 결과를 반환할 수도 있습니다.
#       이는 로드 밸런싱의 특성으로 인해 발생하며, 더 많은 요청을 시도해 볼 수 있습니다.

요약

이 문서의 전반부에서는 Apache APISIX가 Consul과 함께 Consul KV 기반의 서비스 디스커버리 레지스트리를 구현하여 서비스 정보 관리 및 유지 관리 문제를 해결하는 방법을 설명했습니다. 후반부에서는 Docker에서 Consul과 함께 Apache APISIX를 사용하는 방법에 중점을 두었습니다. 물론 실제 시나리오에서의 적용은 비즈니스 시나리오와 기존 시스템 아키텍처에 따라 분석해야 합니다.

Apache APISIX에서 Consul 레지스트리를 사용하는 방법에 대한 더 많은 지침은 공식 문서에서 확인할 수 있습니다.

Apache APISIX는 현재 추가 서비스와의 통합을 지원하기 위해 추가 플러그인을 개발 중이므로, 관심이 있다면 GitHub Discussion에서 논의를 시작하거나 메일링 리스트를 통해 소통할 수 있습니다.

Tags: