본문 바로가기
WIKI 기술 지식 베이스

Cross-cluster search

원문 보기 위키 갱신

출처: 문서

본문

크로스 클러스터 검색

OpenSearch에서 크로스 클러스터 검색(CCS)을 사용하면 여러 클러스터에 걸쳐 데이터를 검색하고 분석할 수 있어서, 분산된 데이터 소스에서 인사이트를 얻을 수 있어요. 크로스 클러스터 검색은 Security 플러그인에서 기본적으로 사용할 수 있지만, 다른 클러스터의 원격 연결을 허용하도록 각 클러스터를 구성해야 해요. 여기에는 원격 클러스터 연결 설정과 접근 권한 구성이 포함돼요.


목차

  1. TOC {:toc}

사전 요구 사항

크로스 클러스터 검색을 구성하기 전에 다음 사전 요구 사항이 충족되었는지 확인하세요:

  • 크로스 클러스터 검색에 참여하는 클러스터의 노드에서 opensearch.yml의 node.roles를 재정의했다면, node.roles 설정에 remote_cluster_client 역할이 포함되어 있는지 확인하세요:

    node.roles: [<other_roles>, remote_cluster_client]
    

    {% include copy.html %}

인증 흐름

다음 순서는 코디네이팅 클러스터에서 원격 클러스터에 접근할 때 크로스 클러스터 검색의 인증 흐름을 설명해요. 원격 클러스터와 코디네이팅 클러스터에서 서로 다른 인증 및 권한 부여 구성을 사용할 수 있지만, 양쪽 모두에서 같은 설정을 사용하는 것을 권장해요.

  1. Security 플러그인이 코디네이팅 클러스터에서 사용자를 인증해요.
  2. Security 플러그인이 코디네이팅 클러스터에서 사용자의 백엔드 역할을 가져와요.
  3. 인증된 사용자를 포함한 호출이 원격 클러스터로 전달돼요.
  4. 원격 클러스터에서 사용자의 권한이 평가돼요.

원격 클러스터 역할 평가

3.9에 도입됨 {: .label .label-purple }

기본적으로 원격 클러스터는 코디네이팅 클러스터에서 전파된 보안 역할과 자체 역할 매핑을 조합하여 권한을 평가해요. 그 결과 코디네이팅 클러스터에서 넓은 권한(예: all_access)을 가진 사용자는 원격 클러스터에서도 동일한 권한을 받게 돼요.

CCS 사용자가 받는 권한을 원격 클러스터가 독립적으로 제어할 수 있게 하려면, 원격 클러스터에서 다음 클러스터 설정을 지정하세요:

PUT /_cluster/settings
{
  "persistent": {
    "plugins.security.ccs.ignore_source_security_roles": true
  }
}

{% include copy-curl.html %}

plugins.security.ccs.ignore_source_security_roles가 true이면, 원격 클러스터는 코디네이팅 클러스터에서 전파된 보안 역할을 제거하고 자체 roles_mapping.yml 구성만으로 접근을 평가해요. 그러면 각 클러스터에서 CCS 사용자 권한을 독립적으로 정의할 수 있어요. 이 설정의 기본값은 false이므로 기존 CCS 배포에는 영향을 주지 않아요.

제한 사항

이 설정에는 다음과 같은 제한 사항이 있어요:

  • 원격 클러스터는 CCS 사용자를 다시 인증하지 않기 때문에 internal_users.yml의 역할 할당을 참조하지 않아요. 이 설정이 활성화되어 있으면 roles_mapping.yml을 사용해 CCS 사용자에게 원격 클러스터 접근 권한을 부여해야 해요. internal_users.yml에서 opendistro_security_roles로 수행된 역할 할당은 CCS 사용자 권한 부여에 아무런 영향을 주지 않아요.
  • 이 설정은 크로스 클러스터 검색 요청에만 적용돼요. 다른 크로스 클러스터 작업은 영향을 받지 않아요.

권한 설정

원격 클러스터의 인덱스를 쿼리하려면 사용자에게 READ 또는 SEARCH 권한이 있어야 해요. 또한 검색 요청에 원격 클러스터로 나가고 들어오는 요청을 최소화하지 않도록 OpenSearch에 지시하는 쿼리 파라미터 ccs_minimize_roundtrips=false가 포함되어 있다면, 사용자에게 다음과 같은 추가 인덱스 권한이 필요해요:

indices:admin/shards/search_shards

ccs_minimize_roundtrips 파라미터에 대한 자세한 내용은 Search API의 파라미터 목록을 참조하세요.

roles.yml 구성 예시

humanresources:
  cluster:
    - CLUSTER_COMPOSITE_OPS_RO
  indices:
    'humanresources':
      '*':
        - READ
        - indices:admin/shards/search_shards # needed when the search request includes parameter setting 'ccs_minimize_roundtrips=false'.

OpenSearch Dashboards에서의 역할 예시

크로스 클러스터 검색 역할을 생성하는 OpenSearch Dashboards 패널

Docker 설정 예제

Docker 권한을 정의하려면 다음 샘플 파일을 docker-compose.yml로 저장하고 docker compose up을 실행하여 같은 네트워크에서 두 개의 단일 노드 클러스터를 시작하세요:

version: '3'
services:
  opensearch-ccs-node1:
    image: opensearchproject/opensearch:{{site.opensearch_version}}
    container_name: opensearch-ccs-node1
    environment:
      - cluster.name=opensearch-ccs-cluster1
      - discovery.type=single-node
      - bootstrap.memory_lock=true # along with the memlock settings below, disables swapping
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
      - "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" # The initial admin password used by the demo configuration
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - opensearch-data1:/usr/share/opensearch/data
    ports:
      - 9200:9200
      - 9600:9600 # required for Performance Analyzer
    networks:
      - opensearch-net

  opensearch-ccs-node2:
    image: opensearchproject/opensearch:{{site.opensearch_version}}
    container_name: opensearch-ccs-node2
    environment:
      - cluster.name=opensearch-ccs-cluster2
      - discovery.type=single-node
      - bootstrap.memory_lock=true # along with the memlock settings below, disables swapping
      - "OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m" # minimum and maximum Java heap size, recommend setting both to 50% of system RAM
      - "OPENSEARCH_INITIAL_ADMIN_PASSWORD=<custom-admin-password>" # The initial admin password used by the demo configuration
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - opensearch-data2:/usr/share/opensearch/data
    ports:
      - 9250:9200
      - 9700:9600 # required for Performance Analyzer
    networks:
      - opensearch-net

volumes:
  opensearch-data1:
  opensearch-data2:

networks:
  opensearch-net:

클러스터가 시작된 후 다음 명령어로 각 클러스터의 이름을 확인하세요:

curl -XGET -u 'admin:<custom-admin-password>' -k 'https://localhost:9200'
{
  "cluster_name" : "opensearch-ccs-cluster1",
  ...
}

curl -XGET -u 'admin:<custom-admin-password>' -k 'https://localhost:9250'
{
  "cluster_name" : "opensearch-ccs-cluster2",
  ...
}

두 클러스터 모두 localhost에서 실행되므로 중요한 식별자는 포트 번호예요. 이 경우 포트 9200(opensearch-ccs-node1)을 원격 클러스터로, 포트 9250(opensearch-ccs-node2)을 코디네이팅 클러스터로 사용하세요.

원격 클러스터의 IP 주소를 얻으려면 먼저 컨테이너 ID를 확인하세요:

docker ps
CONTAINER ID    IMAGE                                       PORTS                                                      NAMES
6fe89ebc5a8e    opensearchproject/opensearch:{{site.opensearch_version}}   0.0.0.0:9200->9200/tcp, 0.0.0.0:9600->9600/tcp, 9300/tcp   opensearch-ccs-node1
2da08b6c54d8    opensearchproject/opensearch:{{site.opensearch_version}}   9300/tcp, 0.0.0.0:9250->9200/tcp, 0.0.0.0:9700->9600/tcp   opensearch-ccs-node2

그다음 해당 컨테이너의 IP 주소를 가져오세요:

docker inspect --format='{% raw %}{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}{% endraw %}' 6fe89ebc5a8e
172.31.0.3

코디네이팅 클러스터에서 각 "시드 노드"에 대해 원격 클러스터 이름과 IP 주소(포트 9300 포함)를 추가하세요. 이 경우 시드 노드는 하나뿐이에요:

curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:<custom-admin-password>' 'https://localhost:9250/_cluster/settings' -d '
{
  "persistent": {
    "cluster.remote": {
      "opensearch-ccs-cluster1": {
        "seeds": ["172.31.0.3:9300"]
      }
    }
  }
}'

모든 cURL 요청은 OpenSearch Dashboards Dev Tools로도 보낼 수 있어요. {: .tip } 다음 이미지는 Dev Tools를 사용한 cURL 요청의 예시를 보여줘요. 크로스 클러스터 검색을 위해 원격 클러스터를 구성하는 OpenSearch Dashboards Dev Tools 요청

원격 클러스터에서 문서를 인덱싱하세요:

curl -XPUT -k -H 'Content-Type: application/json' -u 'admin:<custom-admin-password>' 'https://localhost:9200/books/_doc/1' -d '{"Dracula": "Bram Stoker"}'

이 시점에서 크로스 클러스터 검색이 동작해요. admin 사용자로 테스트할 수 있어요:

curl -XGET -k -u 'admin:<custom-admin-password>' 'https://localhost:9250/opensearch-ccs-cluster1:books/_search?pretty'
{
  ...
  "hits": [{
    "_index": "opensearch-ccs-cluster1:books",
    "_id": "1",
    "_score": 1.0,
    "_source": {
      "Dracula": "Bram Stoker"
    }
  }]
}

테스트를 계속하려면 두 클러스터 모두에서 새 사용자를 생성하세요:

curl -XPUT -k -u 'admin:<custom-admin-password>' 'https://localhost:9200/_plugins/_security/api/internalusers/booksuser' -H 'Content-Type: application/json' -d '{"password":"password"}'
curl -XPUT -k -u 'admin:<custom-admin-password>' 'https://localhost:9250/_plugins/_security/api/internalusers/booksuser' -H 'Content-Type: application/json' -d '{"password":"password"}'

그다음 booksuser로 이전과 동일한 검색을 실행하세요:

curl -XGET -k -u booksuser:password 'https://localhost:9250/opensearch-ccs-cluster1:books/_search?pretty'
{
  "error" : {
    "root_cause" : [
      {
        "type" : "security_exception",
        "reason" : "no permissions for [indices:admin/shards/search_shards, indices:data/read/search] and User [name=booksuser, roles=[], requestedTenant=null]"
      }
    ],
    "type" : "security_exception",
    "reason" : "no permissions for [indices:admin/shards/search_shards, indices:data/read/search] and User [name=booksuser, roles=[], requestedTenant=null]"
  },
  "status" : 403
}

권한 오류가 발생하는 점에 유의하세요. 원격 클러스터에서 적절한 권한을 가진 역할을 생성하고 booksuser를 해당 역할에 매핑하세요:

curl -XPUT -k -u 'admin:<custom-admin-password>' -H 'Content-Type: application/json' 'https://localhost:9200/_plugins/_security/api/roles/booksrole' -d '{"index_permissions":[{"index_patterns":["books"],"allowed_actions":["indices:admin/shards/search_shards","indices:data/read/search"]}]}'
curl -XPUT -k -u 'admin:<custom-admin-password>' -H 'Content-Type: application/json' 'https://localhost:9200/_plugins/_security/api/rolesmapping/booksrole' -d '{"users" : ["booksuser"]}'

두 클러스터 모두 사용자 역할을 가져야 하지만, 역할과 매핑을 모두 필요로 하는 것은 원격 클러스터뿐이에요. 이 경우 코디네이팅 클러스터는 인증(즉, "이 요청에 유효한 사용자 자격 증명이 포함되어 있나요?")을 처리하고, 원격 클러스터는 권한 부여(즉, "이 사용자가 이 데이터에 접근할 수 있나요?")를 처리해요. {: .tip }

마지막으로 검색을 다시 실행하세요:

curl -XGET -k -u booksuser:password 'https://localhost:9250/opensearch-ccs-cluster1:books/_search?pretty'
{
  ...
  "hits": [{
    "_index": "opensearch-ccs-cluster1:books",
    "_id": "1",
    "_score": 1.0,
    "_source": {
      "Dracula": "Bram Stoker"
    }
  }]
}

베어 메탈/가상 머신 설정 예제

베어 메탈 서버나 가상 머신에서 OpenSearch를 실행하고 있다면, OpenSearch 클러스터의 IP(또는 도메인)를 지정하여 동일한 명령어를 실행할 수 있어요. 예를 들어 크로스 클러스터 검색을 위해 원격 클러스터를 구성하려면 원격 노드의 IP 또는 원격 클러스터의 도메인을 찾은 후 다음 명령어를 실행하세요:

curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:<custom-admin-password>' 'https://opensearch-domain-1:9200/_cluster/settings' -d '
{
  "persistent": {
    "cluster.remote": {
      "opensearch-ccs-cluster2": {
        "seeds": ["opensearch-domain-2:9300"]
      }
    }
  }
}'

노드 디스커버리 과정의 일부로 클러스터의 모든 노드가 쿼리되기 때문에, 원격 클러스터의 노드 IP 중 하나만 가리키면 충분해요. {: .tip }

이제 두 클러스터에 걸쳐 쿼리를 실행할 수 있어요:

curl -XGET -k -u 'admin:<custom-admin-password>' 'https://opensearch-domain-1:9200/opensearch-ccs-cluster2:books/_search?pretty'
{
  ...
  "hits": [{
    "_index": "opensearch-ccs-cluster2:books",
    "_id": "1",
    "_score": 1.0,
    "_source": {
      "Dracula": "Bram Stoker"
    }
  }]
}

Kubernetes/Helm 설정 예제

Kubernetes 클러스터로 OpenSearch를 배포하는 경우 LoadBalancer 또는 Ingress를 사용하여 원격 클러스터를 구성해야 해요. 다음 Helm 예제로 생성된 Kubernetes 서비스는 ClusterIP 타입이라 클러스터 내부에서만 접근할 수 있으므로, 외부에서 접근 가능한 엔드포인트를 사용해야 해요:

curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:<custom-admin-password>' 'https://opensearch-domain-1:9200/_cluster/settings' -d '
{
  "persistent": {
    "cluster.remote": {
      "opensearch-ccs-cluster2": {
        "seeds": ["ingress:9300"]
      }
    }
  }
}'

프록시 설정

프록시 뒤에서 실행되는 클러스터에 크로스 클러스터 검색을 구성할 수 있어요. 리버스 프록시를 구성하는 방법은 다양하고, 선택할 수 있는 프록시도 여러 가지예요. 다음 예제는 TLS 종료 없이 기본적인 NGINX 리버스 프록시 구성을 보여주지만, 선택할 수 있는 프록시와 리버스 프록시는 많아요. 이 예제가 동작하려면 OpenSearch에 transport와 HTTP TLS 암호화가 모두 활성화되어 있어야 해요. TLS 암호화 구성에 대한 자세한 내용은 TLS 인증서 구성을 참조하세요.

사전 요구 사항

프록시 모드를 사용하려면 다음 사전 요구 사항을 충족해야 해요:

  • 소스 클러스터의 노드가 구성된 proxy_address에 연결할 수 있는지 확인하세요.
  • 프록시가 원격 클러스터 노드로 연결을 라우팅할 수 있는지 확인하세요.

프록시 구성

다음은 HTTP와 transport 통신을 위한 기본 NGINX 구성이에요:

stream {
    upstream opensearch-transport {
        server <opensearch>:9300;
    }
    upstream opensearch-http {
        server <opensearch>:9200;
    }
    server {
        listen 8300;
        ssl_certificate /.../{{site.opensearch_version}}/config/esnode.pem;
        ssl_certificate_key /.../{{site.opensearch_version}}/config/esnode-key.pem;
        ssl_trusted_certificate /.../{{site.opensearch_version}}/config/root-ca.pem;
        proxy_pass opensearch-transport;
        ssl_preread on;
    }
    server {
        listen 443;
        listen [::]:443;
        ssl_certificate /.../{{site.opensearch_version}}/config/esnode.pem;
        ssl_certificate_key /.../{{site.opensearch_version}}/config/esnode-key.pem;
        ssl_trusted_certificate /.../{{site.opensearch_version}}/config/root-ca.pem;
        proxy_pass opensearch-http;
        ssl_preread on;
    }
}

HTTP와 transport 통신의 리스닝 포트는 각각 443과 8300으로 설정돼요.

OpenSearch 구성

다음 명령어를 사용하여 원격 클러스터가 proxy를 가리키도록 구성할 수 있어요:

curl -k -XPUT -H 'Content-Type: application/json' -u 'admin:<custom-admin-password>' 'https://opensearch:9200/_cluster/settings' -d '
{
  "persistent": {
    "cluster.remote": {
      "opensearch-remote-cluster": {
        "mode": "proxy",
        "proxy_address": "<remote-cluster-proxy>:8300"
      }
    }
  }
}'

프록시 구성 섹션에서 앞서 구성한 포트 8300에 유의하세요.

더 알아보기 (Learn more)