Elasticsearchのバックアップ/リストア



Page content

バックアップでなくsnapshotと呼ぶのが通例らしい。

requestsを使っても出来ますが、PythonのElasticsearch clientを使います。

ちなみにAWS Elasticsearch Searviceを使ってます。レポジトリはS3を使います。


基本

IAM Role作成

snaoshotを作成するため、以下のポリシーを付与したロールSnapshotRoleを作成。

{
  "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/s3_bucket_path*"
      ]
    }
  ]
}

snapshot repository登録

import boto3
from elasticsearch import Elasticsearch, RequestsHttpConnection
from requests_aws4auth import AWS4Auth

region = 'ap-northeast-1'
credentials = boto3.Session().get_credentials()
awsauth = AWS4Auth(
    credentials.access_key,
    credentials.secret_key,
    region,
    'es',
    session_token=credentials.token)

es = Elasticsearch(
    hosts = [{'host': 'elasticsearch_host', 'port': 443}],
    http_auth = awsauth,
    use_ssl = True,
    verify_certs = True,
    connection_class = RequestsHttpConnection
)

body = {
    "type": "s3",
    "settings": {
        "bucket": "s3_bucket_name",
        "base_path": "s3_bucket_path",
        "region": region,
        "role_arn": "arn:aws:iam::123456789012:role/SnapshotRole"
    }
es.snapshot.create_repository(repository='repository-name', body=body)

snapshot取得

es.snapshot.create(
    repository='repository_name',
    snapshot='snapshot_name',
    request_timeout=30)

request_timeoutはデフォルトの10秒だと度々タイムアウトしたので追加。

indexを指定して取得する場合、bodyを指定する。asterisk使用可能。

body = {
  "indices": "my_index_pattern_*"
}
es.snapshot.create(
    repository='repository_name',
    snapshot='snapshot_name',
    body=body,
    request_timeout=30)

restore

es.snapshot.restore(
    repository='repository_name',
    snapshot='snapshot_name',
    request_timeout=30)

snapshot作成時と同様、bodyでindicesも指定可能。


データ移行

ログの送信を止めずに別のElasticsearchサーバにデータを移行したい時。

新/旧サーバでsnapshot repository登録

共通のS3をsnapshot repositoryに登録するとデータコピーが不要。


旧サーバでsnapshot取得

上と同じ。


新サーバでrestore

1. ログをpublishしてElasticsearchに送信する場合

リアルタイムにログを送るので、先にpublish先を新サーバに切り替える。

新サーバとsnapshotに共通のindexが存在する場合リストアが失敗するため、indexをリネームする。

body = {
  "rename_pattern": "*",
  "rename_replacement": "$1-restored"
}
es.snapshot.restore(
    repository='repository_name',
    snapshot='snapshot_name',
    body=body,
    request_timeout=30)

2. ログをpollingしてElasticsearchに送信する場合

この場合、先にpollingを切り替えてからリネームしてリストアすると、重複したログを保持してしまう。

なので、先にリストアしてからpollingを切り替える。

logstash等がindexとidが重複するログは弾いてくれる。


参考