ํšŒ์‚ฌ์—์„œ AWS Elasticsearch๋ฅผ ์ด์šฉํ•˜์—ฌ ์ƒ์šฉ์„œ๋น„์Šค์˜ ๋กœ๊ทธ๋ฅผ ๊ธฐ๋กํ•˜๊ณ  ์žˆ๋Š”๋ฐ ๊ทธ ์šฉ๋Ÿ‰์ด ์ข€ ๋งŽ์•„ 10TB์šฉ๋Ÿ‰์œผ๋กœ 1๋‹ฌ ์ •๋„๋ฐ–์— ๋ฒ„ํ‹ฐ๊ณ  ์žˆ์ง€ ๋ชปํ•ด ์ด๋Ÿฐ ์ €๋Ÿฐ ๋ฆฌ์„œ์น˜๋ฅผ ์ข€ ํ•˜๋‹ค๊ฐ€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฅผ S3๋กœ ๋ฐฑ์—…ํ•ด๋ณด๊ธฐ๋กœ ํ•˜์˜€๊ณ  ๊ทธ ๊ณผ์ •์„ ๊ธฐ๋กํ•ด๋ณธ๋‹ค.

 

 

์ฐธ๊ณ ๋กœ AWS SDK๋Š” 1.11.483 ์‚ฌ์šฉ์ค‘์ด๋ฉฐ, role ๊ธฐ๋ฐ˜์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์–ด access_key, secret_key๋“ฑ์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค.

 

์šฐ์„  ์•„๋ž˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ๋‹ค.

// ES snapshot S3 ์ €์žฅ์„ ์œ„ํ•œ ๋””ํŽœ๋˜์‹œ ์ถ”๊ฐ€
compile 'org.elasticsearch:elasticsearch:7.1.1'
compile 'org.elasticsearch.client:elasticsearch-rest-high-level-client:7.1.1'

 

1. ์Šค๋ƒ…์ƒท ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋“ฑ๋ก

a. Kibana์—์„œ ์ง์ ‘ ๋“ฑ๋ก

PUT _snapshot/my-snapshot-repo
{
  "type": "s3",
  "settings": {
    "bucket": "๋ฒ„ํ‚ท๋ช…, ์˜ˆ์ œ์—์„œ๋Š” my-bucket ์‚ฌ์šฉ",
    "base_path": "/๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š๋Š” ํด๋”๊ฒฝ๋กœ, ๋ฒ„ํ‚ท ๋‚ด ํด๋” ๊ฒฝ๋กœ์ž„, ์˜ˆ์ œ์—์„œ๋Š” base/path/to/save/backup/data ์‚ฌ์šฉ",
    "readonly" : "true",
    "region": "us-west-1",
    "role_arn": "arn:aws:iam::4234:my-role",
    "compress" : "true"
  }
}

๋งŒ์•ฝ ์œ„ ๋ช…๋ น์–ด ์‹คํ–‰์‹œ ์•„๋ž˜์™€ ๊ฐ™์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค๋ฉด role ์„ค์ •์— ์ถ”๊ฐ€ํ•ด์•ผํ•  ์‚ฌํ•ญ์ด ์žˆ๋Š”๋ฐ, ํ•ด๋‹น ํฌ์ŠคํŠธ ์ตœํ•˜๋‹จ์˜ ์ฐธ๊ณ ๋ฌธํ—Œ๋“ค์„ ์ฝ์–ด๋ณด๋ฉฐ ํ•ด๊ฒฐํ•ด๋ณด์‹œ๊ธธ ๋ฐ”๋ž€๋‹ค. 

{
  "Message": "User: anonymous is not authorized to perform: iam:PassRole on resource: arn:aws:iam::4234:my-role"
}

 

๋‚˜๋Š” ์•„๋ž˜ ์„ค๋ช…ํ•  Java ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๋“ฑ๋กํ–ˆ๋‹ค.

 

b. Java ์ฝ”๋“œ (1๊ณผ ๋™์ผํ•œ ๋‚ด์šฉ์„ ์ž๋ฐ”์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ ๊ฒƒ์ด๋‹ค)

    import com.amazonaws.auth.AWS4Signer;
    import com.amazonaws.auth.AWSCredentialsProvider;
    import com.amazonaws.auth.DefaultAWSCredentialsProviderChain;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpHost;
    import org.apache.http.HttpRequestInterceptor;
    import org.apache.http.entity.ContentType;
    import org.apache.http.nio.entity.NStringEntity;
    import org.elasticsearch.action.get.GetRequest;
    import org.elasticsearch.action.get.GetResponse;
    import org.elasticsearch.client.*;
    import org.junit.Ignore;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.ActiveProfiles;
    import org.springframework.test.context.junit4.SpringRunner;

    import javax.ws.rs.HttpMethod;
    import java.io.IOException;

    @Slf4j
    @ActiveProfiles("${SPRING_PROFILES_ACTIVE:local}")
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class AWSESSnapshotTest {

        private String region = "us-west-1";
        private static String serviceName = "es";
        private static String aesEndpoint = "VPC Endpoint๋ฅผ ๋„ฃ์–ด์ฃผ์„ธ์š”";
        private static String snapshotRepository = "/_snapshot/๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ช…์„ ์จ์ฃผ์„ธ์š”";
        private static String snapshotSettings = "{ \"type\": \"s3\", \"settings\": { \"bucket\": \"๋ฒ„ํ‚ท๋ช…์„ ์จ์ฃผ์„ธ์š”\", \"region\": \"๋ฆฌ์ „์„ ๋ช…์‹œํ•ด์ฃผ์„ธ์š”, ์˜ˆ: us-west-1\", \"base_path\": \"์Šค๋ƒ…์ƒท์„ ์ €์žฅํ•  ๋ฒ„ํ‚ท๋‚ด ํด๋” ๊ฒฝ๋กœ\", "compress":"true", "readonly":"true", \"role_arn\": \"IAM Role์„ ์ ์–ด์ฃผ์„ธ์š”\" } }";

        private static final AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain();

        @Test
        public void AWS_ES_์ˆ˜๋™์Šค๋ƒ…์ƒท_๋ฆฌํฌ์ง€ํ† ๋ฆฌ_๋“ฑ๋ก() throws IOException {
            RestClient esClient = esClient(serviceName, region);

            // Register a snapshot repository
            HttpEntity entity = new NStringEntity(snapshotSettings, ContentType.APPLICATION_JSON);
            Request request = new Request(HttpMethod.PUT, snapshotRepository);
            request.setEntity(entity);
            // request.addParameter(name, value); // optional parameters
            Response response = esClient.performRequest(request);
            System.out.println(response.toString());
        }

        // Adds the interceptor to the ES REST client
        public static RestHighLevelClient esClient2(String serviceName, String region) {
            AWS4Signer signer = new AWS4Signer();
            signer.setServiceName(serviceName);
            signer.setRegionName(region);

            // java.lang.NoClassDefFoundError: org/elasticsearch/common/xcontent/DeprecationHandler
            HttpRequestInterceptor interceptor = new AWSRequestSigningApacheInterceptor(serviceName, signer, credentialsProvider);

            return new RestHighLevelClient(RestClient.builder(HttpHost.create(aesEndpoint)).setHttpClientConfigCallback(hacb -> hacb.addInterceptorLast(interceptor)));
        }

    }

 

์ž๋ฐ”์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด ES์—์„œ ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ์„ค์ •์ด ์ž˜ ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•ด๋ณด์ž.

GET _snapshot

"my-repo" : {
  "type" : "s3",
  "settings" : {
    "bucket" : "my-bucket",
    "base_path" : "base/path/to/save/backup/data",
    "readonly" : "false",
    "region" : "us-west-1",
    "role_arn" : "arn:aws:iam::4234:my-role",
    "compress" : "true"
  }
}

 

์ด๋ ‡๊ฒŒ ์ž˜ ๋‚˜์™”๋‹ค๋ฉด ์ด์ œ ์ธ๋ฑ์Šค ๋ฐฑ์—…์œผ๋กœ ๋„˜์–ด๊ฐ€์ž.

 

2. ES ์ธ๋ฑ์Šค๋ฅผ S3๋กœ ๋ฐฑ์—…

ES ์ธ๋ฑ์Šค๋ฅผ S3๋กœ ๋ฐฑ์—…ํ•  ๋•Œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ•  ์ˆ˜ ์žˆ๋‹ค.

    public void AWS_ES_์ˆ˜๋™์Šค๋ƒ…์ƒท_S3_์ €์žฅ() throws IOException {

        RestClient esClient = esClient(serviceName, region);

        // Save indexes into S3 repository
        String takeSnapShot = "{\n  \"indices\": \"index-2020-04-*\",\n  \"ignore_unavailable\": true,\n  \"include_global_state\": false\n}";
        HttpEntity entity = new NStringEntity(takeSnapShot, ContentType.APPLICATION_JSON);
        Request request = new Request(HttpMethod.PUT, snapshotRepository + "/snapshot-test-2020-04");
        request.setEntity(entity);
        
        Response response = esClient.performRequest(request);
        
        System.out.println(response.toString());
    }
    
    
    ์ถœ๋ ฅ๊ฒฐ๊ณผ : 
    Response{requestLine=PUT /_snapshot/my-repo/snapshot-test-2020-04 HTTP/1.1, host=${VPC Endpoint}, response=HTTP/1.1 200 OK}

 

์œ„ ์ฝ”๋“œ๋Š” ์ธ๋ฑ์Šค๋ช…์ด "index-2020-04-"๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ชจ๋“  ์ธ๋ฑ์Šค๋ฅผ "snapshot-test-2020-04"๋ผ๋Š” ์ด๋ฆ„์˜ ์Šค๋ƒ…์ƒท์œผ๋กœ S3์— ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์‹ค์ œ๋กœ S3์˜ ํ•ด๋‹น ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ๊ฐ€์„œ ํ™•์ธํ•ด๋ณด๋ฉด indices ๋””ํ…ํ† ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜์–ด์žˆ๊ณ , ๊ทธ ์•ˆ์—๋Š” ๋ฐฑ์—…ํ•˜๋ คํ–ˆ๋˜ ์ธ๋ฑ์Šค์˜ ๊ฐœ์ˆ˜๋งŒํผ uuid๊ฐ™์€ ์ด๋ฆ„์˜ ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์žˆ๊ณ  ๊ทธ ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์—๋Š” ๋˜ uuid๊ฐ™์€ ์ด๋ฆ„์˜ ํŒŒ์ผ๋“ค์ด ์ž”๋œฉ ์ƒ์„ฑ๋˜์–ด์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋”ฐ๋ผ์„œ S3 ํŒŒ์ผ๋ช…๋งŒ ๋ณด๊ณ ์„œ๋Š” ์ด๊ฒŒ ์–ด๋Š ์Šค๋ƒ…์ƒท์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐํŒŒ์ผ์ธ์ง€ ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค ์•„๋†” ใ…œใ…œ ์ถ”ํ›„ S3์—์„œ ํ•ด๋‹น ์Šค๋ƒ…์ƒท์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์‚ญ์ œํ•˜๊ณ  ์‹ถ์–ด๋„ ์—ฌ๊ธฐ์„œ(S3์—์„œ) ํŒŒ์ผ๋ช…๋งŒ ๋ณด๊ณ ๋Š” ์ฒ˜๋ฆฌํ•  ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ๋œป์ด๋‹ค. 

 

์šฐ์„  ๋ฐฑ์—…๋œ ์ˆ˜๋™ ์Šค๋ƒ…์ƒท์„ ๋‹ค์‹œ ES๋กœ ๋ณต์›ํ•ด์„œ ์ž˜ ์กฐํšŒํ•ด์˜ฌ ์ˆ˜ ์žˆ๋Š”์ง€๋ถ€ํ„ฐ ํ™•์ธํ•ด๋ณด์ž.

 

3. S3์— ๋ฐฑ์—…๋œ ์Šค๋ƒ…์ƒท์„ ES๋กœ ๋ณต์›ํ•˜๊ธฐ

๋ณต์›์‹œ์—๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ ํ•  ์ˆ˜ ์žˆ๋‹ค.

    public void AWS_ES_์ˆ˜๋™์Šค๋ƒ…์ƒท_S3_๋ณต์›_ํ…Œ์ŠคํŠธ() throws IOException {

        RestClient esClient = esClient(serviceName, region);

        // Restoring snapshot as ES indices
        String takeSnapShot = "{\n  \"indices\": \"index-2020-04-28\",\n  \"ignore_unavailable\": true,\n  \"include_global_state\": false\n}";
        HttpEntity entity = new NStringEntity(takeSnapShot, ContentType.APPLICATION_JSON);
        Request request = new Request(HttpMethod.POST, snapshotRepository + "/snapshot-test-2020-04/_restore");
        request.setEntity(entity);
        
        Response response = esClient.performRequest(request);
        
        System.out.println(response.toString());
    }
    
    ์ถœ๋ ฅ๊ฒฐ๊ณผ:
    Response{requestLine=POST /_snapshot/my-repo/snapshot-test-2020-04/_restore HTTP/1.1, host=${VPC Endpoint}, response=HTTP/1.1 200 OK}

์œ„ ์ฝ”๋“œ๋Š” 4์›”๋‹ฌ ๋กœ๊ทธ์— ๋Œ€ํ•ด์„œ ์ €์žฅํ–ˆ๋˜ ์Šค๋ƒ…์ƒท์—์„œ ํŠน์ •์ผ์ž์˜ ์ธ๋ฑ์Šค ์ฆ‰, index-2020-04-28 ์— ๋Œ€ํ•ด์„œ๋งŒ ๋ณต์›์„ ์ง„ํ–‰ํ•œ๋‹ค.

์œ„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด ES์— ํ•ด๋‹น ์ธ๋ฑ์Šค๊ฐ€ ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งŒ์•ฝ ๋ณต์›ํ•˜๋ ค๋Š” ์ธ๋ฑ์Šค ๋ช…์ด ์กด์žฌํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

org.elasticsearch.client.ResponseException: method [POST], host [https://vpc-endpoint.amazonaws.com], URI [/_snapshot/my-repo/snapshot-test-2020-04/_restore], status line [HTTP/1.1 500 Server Error]
{"error":{"root_cause":[{"type":"snapshot_restore_exception","reason":"[my-repo:snapshot-test-2020-04/ECzLylZnTsGn8KfBqCvSEw] cannot restore index [index-2020-04-27] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name"}],"type":"snapshot_restore_exception","reason":"[my-repo:snapshot-test-2020-04/ECzLylZnTsGn8KfBqCvSEw] cannot restore index [index-2020-04-27] because an open index with same name already exists in the cluster. Either close or delete the existing index or restore the index under a different name by providing a rename pattern and replacement name"},"status":500}

 

์ด๋Ÿด ๊ฒฝ์šฐ ์•„๋ž˜ 3๊ฐ€์ง€ ๊ฒฝ์šฐ๋กœ ๋ณต์›์ ˆ์ฐจ๋ฅผ ์ง„ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

 

์ฒซ์งธ, ํ˜„์žฌ ์กด์žฌํ•˜๋Š” ๋™์ผํ•œ ์ด๋ฆ„์˜ ์ธ๋ฑ์Šค๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๋ณต์›ํ•œ๋‹ค.

๋‘˜์งธ, ๋ณต์›ํ•  ๋•Œ ์ธ๋ฑ์Šค๋ช…์„ renameํ•ด์„œ ๋ณต์›ํ•œ๋‹ค.

์…‹์งธ, ๋‹ค๋ฅธ ES๋„๋ฉ”์ธ์œผ๋กœ ๋ณต์›ํ•œ๋‹ค -> ์ด๊ฑด ์ˆ˜๋™์œผ๋กœ ์Šค๋ƒ…์ƒท์„ ์ƒ์„ฑํ•œ ๊ฒฝ์šฐ์—๋งŒ ๊ฐ€๋Šฅํ•œ ๋ฐฉ๋ฒ•์ด๋‹ค.

 

๋‚˜๋Š” ํ…Œ์ŠคํŠธ ์ค‘์ด๋ฏ€๋กœ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฒซ๋ฒˆ์งธ๋ฅผ ์„ ํƒํ–ˆ๋‹ค.

 

๋งŒ์•ฝ ์Šค๋ƒ…์ƒท์— ์—ฌ๋Ÿฌ ์ธ๋ฑ์Šค์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ๋‹ด๊ฒจ์žˆ๊ณ  ๋ชจ๋“  ์ •๋ณด๋ฅผ ๋ณต์›ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋‹จ ํ•˜๋‚˜์˜ ์ธ๋ฑ์Šค๋ผ๋„ ์ด๋ฆ„์ด ๊ฒน์นœ๋‹ค๋ฉด ์œ„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

์œ„ ์ฝ”๋“œ๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด ES์—์„œ ํ•ด๋‹น ์ธ๋ฑ์Šค์˜ ์ •๋ณด๋ฅผ ์กฐํšŒํ•ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

 

๊ทธ๋ฆฌ๊ณ  ํŠน์ • ์ธ๋ฑ์Šค๊ฐ€ ์•„๋‹Œ ์—ฌ๋Ÿฌ ์ธ๋ฑ์Šค๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๋ณต์›ํ•˜๊ณ ์ž ํ•  ๋•Œ๋Š” takeSnapShot์˜ indices ํ•ญ๋ชฉ์— ์ธ๋ฑ์Šค๋ช…์„ ๋‚˜์—ดํ•ด์ฃผ๋ฉด ๋œ๋‹ค. *๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑด ES ์œ ์ €๋ผ๋ฉด ๋‹น์—ฐํžˆ ์•„์‹คํ…Œ๊ณ ..

"indices":"index-2020-04-*,index-2020-05-0*"

์œ„์ฒ˜๋Ÿผ ํ•ด์ฃผ๋ฉด 4์›”๋‹ฌ ๋ชจ๋“  ์ธ๋ฑ์Šค์™€ 5์›” 1์ผ~5์›” 9์ผ๊นŒ์ง€์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ณต์›ํ•˜๊ฒŒ ๋  ๊ฒƒ์ด๋‹ค.

 

์ž, ๊ทธ๋Ÿผ ๋ณต์›์— ๋Œ€ํ•ด์„œ๋Š” ์ด์ •๋„๋กœ ํ•˜๊ณ , ์Šค๋ƒ…์ƒท๋„ ๋„ˆ๋ฌด ์˜ค๋ž˜ ๋ณด๊ด€ํ•˜๋ฉด ์šฉ๋Ÿ‰๋งŒ ์žก์•„๋จน์„ํ…Œ๋‹ˆ ์‚ญ์ œ๋Š” ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„์ง€ ๋ณด์ž.

 

4. S3์— ๋ฐฑ์—…ํ•œ ES ์Šค๋ƒ…์ƒท ์‚ญ์ œํ•˜๊ธฐ

์Šค๋ƒ…์ƒท์„ ์‚ญ์ œํ•  ๋•Œ๋Š” ์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด๋œ๋‹ค.

    public void AWS_ES_์ˆ˜๋™์Šค๋ƒ…์ƒท_์‚ญ์ œ_ํ…Œ์ŠคํŠธ() throws IOException {

        RestClient esClient = esClient(serviceName, region);

        Request request = new Request(HttpMethod.DELETE, snapshotRepository + "/snapshot-test-2020-04");

        Response response = esClient.performRequest(request);

        System.out.println(response.toString());
    }

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด S3์— ์ƒ์„ฑ๋˜์—ˆ๋˜ ํŒŒ์ผ๋“ค์ด ์‚ญ์ œ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, indices ๋””๋ ‰ํ† ๋ฆฌ๋Š” ์™„์ „ํžˆ ์‚ญ์ œ๋˜๊ณ  ์Šค๋ƒ…์ƒท ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋กœ ์ง€์ •๋œ root ๊ฒฝ๋กœ์—๋Š” ๋ช‡๋ช‡ ์“ฐ๋ ˆ๊ธฐ(??) ํŒŒ์ผ๋“ค์ด ๋‚จ์•„์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋งŒ์•ฝ 2๊ฐœ ์ด์ƒ์˜ ์Šค๋ƒ…์ƒท์„ ์ €์žฅํ–ˆ๋‹ค๋ฉด indices ๋””๋ ‰ํ† ๋ฆฌ๋Š” ๋ชจ๋“  ์Šค๋ƒ…์ƒท์— ๋Œ€ํ•œ ์‚ญ์ œ์š”์ฒญ์„ ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ์‚ญ์ œ๋˜์ง€ ์•Š๋Š”๋‹ค. ๋˜ํ•œ, ์Šค๋ƒ…์ƒท์„ ์‚ญ์ œํ•  ๋•Œ๋Š” ์‹œ๊ฐ„์ด ์˜ค๋ž˜๊ฑธ๋ฆฐ๋‹ค. sync ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ์—๋Š” ๋„ˆ๋ฌด๋„ˆ๋ฌด๋„ˆ๋ฌด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์šฉ์—์„œ ์‚ญ์ œ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด async ๋ฐฉ์‹์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธธ ๊ถŒ์žฅํ•œ๋‹ค. ์œ„ ์ฝ”๋“œ๋Œ€๋กœ ์ž‘์„ฑํ–ˆ๋‹ค๋ฉด ๋ฌด์กฐ๊ฑด ์•„๋ž˜ ์†Œ์ผ“ํƒ€์ž„์•„์›ƒ ์˜ˆ์™ธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.

java.net.SocketTimeoutException: 30,000 milliseconds timeout on connection http-outgoing-0 [ACTIVE]

 

๋งŒ์•ฝ ์Šค๋ƒ…์ƒท ์ด๋ฆ„์ด ๊ธฐ์–ต์ด ๋‚˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ? S3์—์„œ ์กฐํšŒํ•ด๋ด์•ผ ํŒŒ์ผ๋ช…์ด ์–ด๋–ค ์Šค๋ƒ…์ƒท์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋„๋ก ์ƒ์„ฑ๋˜์–ด์žˆ์œผ๋‹ˆ ์•Œ ๊ธธ์ด ์—†๋‹ค. ํ‚ค๋ฐ”๋‚˜ dev tool์—์„œ ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์–ด๋–ค ์Šค๋ƒ…์ƒท์ด ์žˆ๋Š”์ง€ ๊ทธ ์Šค๋ƒ…์ƒท์— ์–ด๋–ค ์ธ๋ฑ์Šค๋“ค์ด ์ €์žฅ๋˜์–ด์žˆ๋Š”์ง€๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

GET _snapshot/my-repo/_all 	<- my-repo์˜ ๋ชจ๋“  ์Šค๋ƒ…์ƒท ์กฐํšŒํ•˜๊ธฐ



{
  "snapshots" : [ {
    "snapshot" : "snapshot-test-2020-04",
    "uuid" : "VPMGlnLTQlqIT7SxPaqCOg",
    "version_id" : 7016199,
    "version" : "7.1.1",
    "indices" : [ "index-2020-04-29", "index-2020-04-26", "index-2020-04-27", "index-2020-04-28" ],
    "include_global_state" : false,
    "state" : "SUCCESS",
    "start_time" : "2020-05-25T07:34:09.804Z",
    "start_time_in_millis" : 1590392049804,
    "end_time" : "2020-05-25T07:34:32.145Z",
    "end_time_in_millis" : 1590392072145,
    "duration_in_millis" : 22341,
    "failures" : [ ],
    "shards" : {
      "total" : 20,
      "failed" : 0,
      "successful" : 20
    }
  } ]
}

 

ํŠน์ • ์Šค๋ƒ…์ƒท์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ํ™•์ธํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์•„๋ž˜ ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜๋ฉด ๋œ๋‹ค.

GET _snapshot/my-repo/snapshot-test-*

 

 

์ฐธ๊ณ ๋กœ ํ๋ ˆ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ES์˜ ๋ฐ์ดํ„ฐ๋ฅผ rotate ์‹œํ‚ฌ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ด€๋ จ ๋งํฌ๋Š” ์ฐธ๊ณ ๋ฌธ์„œ์— ๋„ฃ์–ด๋†“์•˜์œผ๋‹ˆ ๊ด€์‹ฌ์žˆ์œผ์‹œ๋ฉด ์ฝ์–ด๋ณด์„ธ์š”.

 

๊ทธ๋ฆฌ๊ณ  ์‹ค์ œ๋กœ๋Š” ์ด ์Šค๋ƒ…์ƒท ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ES 7 ์ด์ƒ์—์„œ ์ง€์›ํ•˜๋Š” UltraWarm ์„ค์ •์„ ์ด์šฉํ•˜๊ธฐ๋กœ ํ–ˆ์Šต๋‹ˆ๋‹ค. ES์ธ์Šคํ„ด์Šค ์‚ฌ์ด์ฆˆ๋„ warm ๋…ธ๋“œ์˜ ๊ฒฝ์šฐ ํ•ซ๋…ธ๋“œ์™€๋Š” ๋ณ„๊ฐœ๋กœ S3๋ฅผ ์ด์šฉํ•จ์œผ๋กœ์จ ๋น„์šฉ์„ ๋งŽ์ด ์ค„์ผ ์ˆ˜ ์žˆ๊ณ  ์ €์žฅ๊ธฐ๊ฐ„ ์—ญ์‹œ ์›ํ•˜๋Š” ๋งŒํผ ๋Š˜๋ฆด ์ˆ˜ ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ์ƒํ™ฉ์—์„œ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์„ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. UltraWarm์ด ๋ญ”์ง€์— ๋Œ€ํ•ด์„œ๋Š” ์ฐธ๊ณ ๋ฌธ์„œ์˜ ๋งํฌ๋ฅผ ํ™•์ธํ•ด๋ณด์„ธ์š”. ์ฐธ๊ณ ๋กœ ES ๋ฒ„์ „ 6.8์ด์ƒ์—์„œ๋งŒ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

UltraWarm ์œผ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํ•  ๋•Œ๋Š” ์•„๋ž˜ ๋ช…๋ น์–ด๋“ค์„ ์ฐธ๊ณ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

// ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—… ์š”์ฒญ
POST _ultrawarm/migration/index-2020-02-09/_warm

 

// ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—… ์ค‘์ธ ์ธ๋ฑ์Šค์˜ ์ƒํƒœ ํ™•์ธ
GET _ultrawarm/migration/index-2020-02-09/_status

-> ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—…์ค‘์ด ์•„๋‹Œ๊ฒฝ์šฐ ์ฆ‰, ๋๋‚ฌ๊ฑฐ๋‚˜ ์‹œ์ž‘๋„ ์•ˆํ•œ ์ƒํƒœ๋ฉด ์˜ค๋ฅ˜๋ฉ”์‹œ์ง€๊ฐ€ ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.

 

// ์ธ๋ฑ์Šค ํŒจํ„ด ๋ชฉ๋ก ์กฐํšŒ
GET _cat/indices/index-2020-02-0*?v&s=index


-> ์ด ๋ช…๋ น์€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—… ์ง„ํ–‰ ์ค‘์— ์ธ๋ฑ์Šค์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ–ˆ์—ˆ๋‹ค. ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—…์ด ์‹œ์ž‘๋˜๋ฉด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋ ค๋Š” ์ธ๋ฑ์Šค์˜ ์›๋ž˜ ์‚ฌ์ด์ฆˆ๋ณด๋‹ค 2๋ฐฐ๊นŒ์ง€ hot data node์˜ ์šฉ๋Ÿ‰์„ ์ฐจ์ง€ํ•˜๊ฒŒ๋œ๋‹ค. ์—ฌ์œ ๋ถ„์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์—†๋‹ค๋ฉด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์ž‘์—… ์ž์ฒด๊ฐ€ ์‹œ์ž‘๋˜์ง€ ์•Š๋Š”๋‹ค. (free size๋ฅผ ๊ฒ€์‚ฌํ•œ ๋’ค ์‹œ์ž‘ํ•˜๋„๋ก ๋˜์–ด์žˆ๋‹ค)

 

// ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์™„๋ฃŒ๋œ ์ธ๋ฑ์Šค ์ƒํƒœ ์กฐํšŒ
GET index-2020-02-09/_settings


-> Ultrawarm ๋…ธ๋“œ๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜์ด ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด ์œ„ ๋ช…๋ น์–ด๋กœ ์กฐํšŒ ์‹œ box_type์ด warm ์œผ๋กœ ๋ฐ”๋€Œ์–ด ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์ฐธ๊ณ ๋ฌธ์„œ

https://www.elastic.co/guide/en/elasticsearch/plugins/current/repository-s3-repository.html

https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-managedomains-snapshots.html#es-managedomains-snapshot-prerequisites

https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-request-signing.html#es-request-signing-java

https://aws.amazon.com/ko/blogs/database/use-amazon-s3-to-store-a-single-amazon-elasticsearch-service-index/

https://www.elastic.co/guide/en/elasticsearch/reference/7.1/modules-snapshots.html

AWS ํ๋ ˆ์ดํ„ฐ ์ด์šฉํ•˜๊ธฐ

AWS ES Ultrawarm