ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • aws elasticsearch snapshot 으로 데이터 백업 with java
    개발/Elasticsearch 2021. 2. 9. 19:00

     지금 서비스하고 있는 aws elasitcsearch 버전이 6.8인데 7.7에서 힙 메모리 사용이 확 개선되어, 가장 최신 버전인 7.9 버전으로 마이그레이션 하려고 한다.

     

    1. s3 bucket 생성

    -snapshot 저장할 s3 bucket 생성한다.

     

    2. IAM - 역할 생성

    iam - 역할 - 역할 만들기 

    ec2 선택해서 다음 - 다음 - 다음 역할이름 입력하여 역할 만들기 완료

     

    3. 역할에 신뢰관계 설정

    생성한 역할에 신뢰 관계 - 신뢰 관계 편집 

     

    ec2 대신 es로 변경

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Sid": "",
          "Effect": "Allow",
          "Principal": {
            "Service": "es.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }

    신뢰 정책 업데이트

     

    4. 해당 역할에 정책 연결

    정책 연결 - 정책생성을 통해 정책을 정의해도 되고, 인라인 정책에 추가해도 된다.

    인라인 정책 추가 - json

    사용 bucket명은 testsnapshot-bucket

    {
      "Version": "2012-10-17",
      "Statement": [{
          "Action": [
            "s3:ListBucket"
          ],
          "Effect": "Allow",
          "Resource": [
            "arn:aws:s3:::testsnapshot-bucket"
          ]
        },
        {
          "Action": [
            "s3:GetObject",
            "s3:PutObject",
            "s3:DeleteObject"
          ],
          "Effect": "Allow",
          "Resource": [
            "arn:aws:s3:::testsnapshot-bucket/*"
          ]
        }
      ]
    }

     

    이제 iam 작업은 다 끝났다.

     

     

    5. snapshot repository 생성

     

    현 프로젝트에 gradle에  추가되어있는 관련 디펜던시

    'org.springframework.boot' version '2.2.8.RELEASE' 환경
    
    implementation group: 'org.springframework.cloud', name: 'spring-cloud-starter-aws', version: '2.2.1.RELEASE'
    implementation 'org.springframework.data:spring-data-elasticsearch:3.2.8.RELEASE'
    implementation 'software.amazon.awssdk:auth:2.13.42'

     

    a.kibana

    PUT _snapshot/my-snapshot-repo-name
    {
      "type": "s3",
      "settings": {
        "bucket": "s3-bucket-name",
        "base_path": "es-snapshot/test",
        "region": "region",
        "role_arn": "arn:aws:iam::123456789012:role/TheSnapshotRole",
        "compress" : "true"
      }
    }

     

    와같이 입력하여 생성 할 수 있다곤 하는데 되지 않아 java로 작업 하였다.

     

    {
      "Message": "User: anonymous is not authorized to perform: iam:PassRole on resource: "
    }​

    와 같은 에러 메세지 발생

     

    b. java

     

      private static String region = "ap-northeast-2";
        private static String serviceName = "es";
        private static String aesEndpoint = "old 엔드포인트"
        private static String newAesEndpoint = "new 엔드포인트"
        private static String snapshotRepository = "/_snapshot/whitelabel_backup";
        private static String snapshotSettings = "{ \"type\": \"s3\", \"settings\": { \"bucket\": \"testsnapshot-bucket\", \"region\": \"ap-northeast-2\", \"base_path\": \"es-snapshot/test\", \"compress\":\"true\", \"role_arn\": \"위에서 생성한 역할"\ } }";
    
        static final AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain();
    
        public String doSnapshot() throws IOException {
            RestClient esClient = esClient(serviceName, region);
    
            // Register a snapshot repository
            HttpEntity entity = new NStringEntity(snapshotSettings, ContentType.APPLICATION_JSON);
            Request request = new Request("PUT", snapshotRepository);
            request.setEntity(entity);
            // request.addParameter(name, value); // optional parameters
            Response response = esClient.performRequest(request);
            System.out.println(response.getStatusLine().getStatusCode());
            System.out.println(response.toString());
            return response.toString();
        }
    
        public static RestClient esClient(String serviceName, String region) {
            AWS4Signer signer = new AWS4Signer();
            signer.setServiceName(serviceName);
            signer.setRegionName(region);
            HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider);
            return RestClient.builder(HttpHost.create(aesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)).build();
        }
    
        public static RestClient newEsClient(String serviceName, String region) {
            AWS4Signer signer = new AWS4Signer();
            signer.setServiceName(serviceName);
            signer.setRegionName(region);
            HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider);
            return RestClient.builder(HttpHost.create(newAesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)).build();
        }
    

    status code 200이 나오면 정상 처리

     

    kibana에서 

    GET _snapshot 

    으로 

    {
      "cs-automated" : {
        "type" : "s3"
      },
      "whitelabel_backup" : {
        "type" : "s3",
        "settings" : {
          "bucket" : "testsnapshot-bucket",
          "base_path" : "es-snapshot/test",
          "region" : "ap-northeast-2",
          "role_arn" : "생성한 역할",
          "compress" : "true"
        }
      }
    }

    확인 가능

     

    6. elasticsearch snapshot 해당 s3에 저장

        public void moveToS3() throws IOException {
    
            RestClient esClient = esClient(serviceName, region);
    
            // Save indexes into S3 repository
            String takeSnapShot = "{\n  \"indices\": \"*\",\n  \"ignore_unavailable\": true,\n  \"include_global_state\": false\n}";
            HttpEntity entity = new NStringEntity(takeSnapShot, ContentType.APPLICATION_JSON);
            Request request = new Request("PUT", snapshotRepository + "/snapshot-all");
            request.setEntity(entity);
    
            Response response = esClient.performRequest(request);
    
            System.out.println(response.toString());
        }

     

     

    7.  5.b와 같은 방법으로 새 elasticsearch server snpashot repository 생성

     

    8. 새 서버에 백업 데이터 복구

     

        public void EsRestore() throws IOException {
    
            RestClient esClient = newEsClient(serviceName, region);
    
            // Restoring snapshot as ES indices
            String takeSnapShot = "{\n  \"indices\": \"test-index\",\n  \"ignore_unavailable\": true,\n  \"include_global_state\": false\n}";
            HttpEntity entity = new NStringEntity(takeSnapShot, ContentType.APPLICATION_JSON);
            Request request = new Request("POST", snapshotRepository + "/snapshot-all/_restore");
            request.setEntity(entity);
    
            Response response = esClient.performRequest(request);
    
            System.out.println(response.toString());
        }
    

     

     

     

     

     

     

    댓글

Designed by Tistory.