본문 바로가기
ElasticSearch & OpenSearch

[OpenSearch] 수동 Snapshot

by yonikim 2023. 5. 16.
728x90

AWS OpenSearch 의 경우 인스턴스 유형 별로 최대 스토리지가 정해져 있다. 

로그 남기는 용도로 사용하고 있는 경우에는 그렇게 좋은 사양을 사용할 필요도 없고, 노드 수를 많이 만들 필요도 없다고 본다. 

 

그러나 스토리지의 한도는 점점 다가오고, OpenSearch 는 Low Disk Space 알림을 내뱉기 시작할텐데...

과거 로그 쿨하게 삭제...⭐️ 를 하고 싶으나, 검색 로그의 경우 다양한 지표에서 쓰일 수 있기 때문에 쿨하게 삭제할 수도 없는 노릇이다. 

 


 

OpenSearch 의 경우 자동 스냅샷을 생성해주긴 하나 14일 동안만 보관하고 클러스터 복구 전용으로 다른 클러스터로 데이터 이동이 안된다. 그렇기 때문에 수동 스냅샷 생성하는 방법에 대해 알아보도록 하자. 

 

 

사전 준비

1. S3 Bucket 생성

수동 스냅샷을 저장할 S3 버킷을 생성한다. 이 때 S3 Glacier 수명 주기 규칙을 적용하면 안된다. 

 

2. IAM Role 생성

OpenSearch 스냅샷을 생성할 수 있는 IAM 역할을 생성한다. 이 역할을 production_opensearch_snapshot_role 이라고 지칭하겠다.

  • 1번에서 생성한 S3 버킷 액세스 정책 연결
{
  "Version": "2012-10-17",
  "Statement": [{
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-bucket-name"
      ]
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::s3-bucket-name/*"
      ]
    }
  ]
}

 

  • OpenSearch 액세스 정책 연결 
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/production_opensearch_snapshot_role"
    },
    {
      "Effect": "Allow",
      "Action": "es:ESHttpPut",
      "Resource": "arn:aws:es:region:123456789012:domain/domain-name/*"
    }
  ]
}

 

  • 신뢰관계
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "es.amazonaws.com",
                    "lambda.amazonaws.com"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

 

 

스냅샷 레포지토리 등록

아래와 같이 PUT 요청을 OpenSearch 도메인 엔드포인트로 보내면 되는데,

PUT {{OPENSEARCH_LOG_DOMAIN_NAME}}/_snapshot/snapshot-repository
{
  "type": "s3",
  "settings": {
    "bucket": "s3-bucket-name",
    "region": "ap-northeast-2",
    "role_arn": "arn:aws:iam::123456789012:role/production_opensearch_snapshot_role"
  }
}

 

 

VPC 이슈로 인하여 Lambda 에 배포해서 만들었다. AWS Document 에서는 Python 을 사용했으나 나의 경우 Node.js 를 사용했으니 참고 바란다.

 

▷ handler.js

  • Lambda Role 은 위에서 만든 IAM Role 로 기재해준다.
const { HttpRequest } = require("@aws-sdk/protocol-http");
const { SignatureV4 } = require("@aws-sdk/signature-v4");
const { defaultProvider } = require("@aws-sdk/credential-provider-node");
const { Sha256 } = require("@aws-crypto/sha256-browser");
const { NodeHttpHandler } = require("@aws-sdk/node-http-handler");

const { REGION = "ap-northeast-2" } = process.env;

module.exports.main = async () => {
  try {
    const method = "PUT";
    const requestParams = {
      method,
      hostname: process.env.OPENSEARCH_LOG_DOMAIN_NAME,
      headers: {
        "Content-Type": "application/json",
        host: process.env.OPENSEARCH_LOG_DOMAIN_NAME,
      },
      path: `/_snapshot/snapshot-repository`,
      body: JSON.stringify({
        type: "s3",
        settings: {
          bucket: "s3-bucket-name",
          region: REGION,
          role_arn: "arn:aws:iam::123456789012:role/production_opensearch_snapshot_role",
        },
      }),
    };
    const response = await promiseRequest({ requestParams });
    console.log(response);
    return {
      statusCode: 200,
    };
  } catch (err) {
    console.log(err);
    return {
      statusCode: 500,
      body: JSON.stringify(err),
    };
  }
};

const promiseRequest = async ({ requestParams }) => {
  const signatureParams = {
    credentials: defaultProvider(),
    region: REGION,
    service: "es",
    sha256: Sha256,
  };

  const request = new HttpRequest(requestParams);
  const signer = new SignatureV4(signatureParams);

  const signedRequest = await signer.sign(request);
  const client = new NodeHttpHandler();

  let responseBody = "";
  return await new Promise((resolve, reject) => {
    client
      .handle(signedRequest)
      .then(({ response }) => {
        response.body.on("data", (chunk) => {
          responseBody += chunk;
        });
        response.body.on("end", () => {
          resolve(JSON.parse(responseBody));
        });
      })
      .catch((err) => {
        reject(err);
        throw err;
      });
  });
};

 

 



 

 🎉 403 에러 발생  🎉 

no permissions for [cluster:admin/repository/put] and User [name=arn:aws:iam::012345678912:user/username, backend_roles=[], requestedTenant=null]

세분화된 액세스 제어를 활성화한 경우 위와 같은 에러가 발생할 수 있다고 한다.

 

 

OpenSearch Dashboards 에서 스냅샷 역할 매핑

1. OpenSearch Dashboards 로그인 > Security 선택

 

2. Roles > manage_snapshots 선택

 

3. Mapped users > [Manage mapping] 클릭 > Users 에 위에서 만든 IAM Role ARN 추가

 

 

스냅샷 생성 및 복구

1. 레포지토리 등록 확인

GET /_snapshot

 

2. 스냅샷 생성

PUT /_snapshot/snapshot-repository/snapshot-name

 

3. 스냅샷 확인

GET /_snapshot/snapshot-repository/_all?pretty

 

4. 스냅샷 복구

POST _snapshot/snapshot-repository/snapshot-name/_restore 
{
    "indices": ["es-log-202201", "es-log-202202"],
    "include_global_state" : false,
    "ignore_unavailable": true
}

 

 

 

 

(참조: https://docs.aws.amazon.com/ko_kr/opensearch-service/latest/developerguide/managedomains-snapshots.html)

728x90