亚马逊AWS官方博客

无需订阅费! 手把手教你如何在Amazon OpenSearch Service中使用跨集群复制功能(Cross-Cluster Replication)

背景

OpenSearch 1.1.0开源版本开始,跨集群复制(Cross-Cluster Replication,简称CCR)插件正式发布。同样地,在2021年10月,Amazon OpenSearch Service也正式支持了跨集群复制功能,从而使用户能够自动地复制索引,甚至可以通过低延迟将索引从一个域同步到另一个跨账号或者跨区域的域中。跨集群复制采用的是active-passive模型,follower(数据被复制到的目标端)索引从leader(远程数据复制的源端)索引中提取数据。此外,从2022年4月开始,Amazon OpenSearch Service 还支持在已经创建的域上进行跨集群复制。

借助CCR功能,用户可以实现众多任务关键型应用程序的高可用性以及顺序一致性,其中一些可能需要使用到跨集群复制的场景包括:

  • 通过复制索引,可以确保服务在源索引意外故障时继续处理搜索请求;
  • 防止在搜索(读请求)增加的情况下影响索引(写请求)的吞吐,做到读写分离;
  • 跨区域复制数据可以最小化数据与应用程序服务器之间的距离,以减少了访问延迟;
  • 将数据从多个分散的集群复制到一个集中的报表集群,提升查询效率。

除此之外,CCR功能还支持auto-follow自动跟随功能,用户可以针对单个leader域定义一组复制规则,这些规则会自动复制匹配指定模式的索引。当leader域上的索引匹配其中一个模式(例如,books*表示匹配books开头的索引)时,follower域上会自动创建出一个匹配的索引。CCR支持复制任何与该模式匹配的已经创建好的索引,同时也会支持用户新创建的索引。接下来,本文将会演示在Amazon OpenSearch Service使用跨集群复制功能的详细过程。

架构介绍

本文演示中使用的是同账号同区域中的跨集群复制,主要内容是从follower domain向leader domain发起连接请求,建立连接后follower domain从leader domain拉取对应的索引内容,如下图所示。

演示中我们是往leader domain中发送数据,实际上其数据可能来自于其他数据源或者数据流水线,跨集群复制的架构保持不变。例如,通过Amazon Kinesis Data Analytics中的Flink程序通过CDC的方式获取Amazon RDS MySQL中的数据,然后实时地将数据推送到OpenSearch集群中,其中leader domain可以作为读写集群,然后follower domain作为读集群,如下图所示。

近实时数据收集也可能是采用Kinesis Agent收集EC2服务器上的数据,并通过Amazon Kinesis Firehose自动直接打到OpenSearch集群中,如下图所示。

此外,如上所述用户会有跨区域复制的需求,以满足本地数据访问的延迟,如下图所示。

解决方案

接下来我们来看配置的具体步骤,内容如下:

  1. 创建leader domain;
  2. 创建follower domain;
  3. 创建跨集群的连接connection;
  4. 创建复制用户和角色;
  5. 开启CCR复制;
  6. 验证CCR复制;
  7. 配置auto-follow规则。

以下演示是在美东1区域(us-east-1)进行。

① 创建leader domain

首先,进入到Amazon OpenSearch Service控制台,选择Create domain。

设置domain 名称,示例中为my-leader-domain,部署类型选择Custom。

部署类型选择Custom,并使用默认最新的OpenSearch 1.2版本。

节点配置示例中使用1-AZ,实际线上生产环境建议使用2-AZ或者3-AZ。节点类型保持默认的r6g.large.search。

示例中为了演示禁用了Dedicated master nodes功能,实际线上生产环境建议开启。

网络设置部分建议使用VPC,配置对应的VPC、Subnet和Security Group。然后,集群需要开启Fine-grained access control,这里使用Internal master user,根据实际情况配置对应的用户名和密码。

Access Policy设置需要添加es:ESCrossClusterGet权限,对应的资源需要设置为域,这里是/leader-domain,注意不是/leader-domain/*。

策略可以参考以下内容,主要替换账户、区域和OpenSearch域信息:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "*"
        ]
      },
      "Action": [
        "es:*"
      ],
      "Resource": "arn:aws:es:us-east-1:<your account number>:domain/my-leader-domain/*"
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:ESCrossClusterGet",
      "Resource": "arn:aws:es:us-east-1:<your account number>:domain/my-leader-domain"
    }
  ]
}

其他设置保持默认,然后点击创建。

② 创建follower domain

创建过程和leader domain类似,只需要修改下access policy部分,可以参考以下内容:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:us-east-1:<your account number>:domain/my-follower-domain/*"
    }
  ]
}

③ 创建connection

使用CCR将索引从一个域复制到另一个域,需要在两个域之间建立跨集群连接。由于CCR采取的是pull模式,所以需要从follower domain侧发起请求,因此连接需要在follower domain这里创建。有关两个域的连接信息,也可以参考之前已经支持的Cross-cluster search功能

因为后面的操作涉及到leader和follower两个域的操作,容易混淆,这里会在操作前标注需要在哪里执行。

follower操作」进入到follower domain的界面,选择Connections,点击请求。

填写对应的Connection alias,注意这里的alias会用在后面的CCR连接的请求中。选择对应的leader domain,这里是my-leader-domain,然后发起请求。

之后可以看到连接出现在Outbound connections中。

leader操作」接下来需要接受这个请求,回到leader域名中点击Connection选项,可以看到请求的连接出现在Inbound connections中,选中连接并点击Appove接受。

之后,两边的连接状态都会变成Active,然后可以开始后续的工作。

④ 创建复制用户和角色

CCR在复制的过程中会用到leader和follower的用户和角色信息,通常在实际使用中不建议使用all_access的管理员权限,而是单独配置复制的用户和角色,这里演示将在两个域中进行创建。

此外,在OpenSearch的开源版本中,其安全插件配置有两个内置的角色:cross_cluster_replication_leader_full_access和cross_cluster_replication_follower_full_access,关于更多OpenSearch内置角色的信息,可以参考这个链接。目前,这两个角色在Amazon OpenSearch Service中暂未提供,因此我们参考OpenSearch中的内容进行创建。

*注:由于在Amazon OpenSearch Service中,对应的权限暂时没有办法从下来菜单中选取,所以这里需要使用API的方式进行角色的创建(创建后可以到安全界面中查看),之后角色和用户之间的映射可以选择使用API或者是界面操作。关于映射的更多说明,可以参考这个链接

follower操作」在管理控制台中查看Dashboard URL,使用master用户和密码登录到follower domain的Dashboard界面,并从侧边栏选择Dev Tools。

通过以下API创建角色,角色名称可以参考使用cross_cluster_replication_follower_full_access,或者根据实际情况进行调整。

PUT _plugins/_security/api/roles/cross_cluster_replication_follower_full_access
{
  "cluster_permissions": [
    "cluster:admin/plugins/replication/autofollow/update"
  ],
  "index_permissions": [
    {
      "index_patterns": [
        "*"
      ],
      "fls": [],
      "masked_fields": [],
      "allowed_actions": [
        "indices:admin/plugins/replication/index/setup/validate",
        "indices:data/write/plugins/replication/changes",
        "indices:admin/plugins/replication/index/start",
        "indices:admin/plugins/replication/index/pause",
        "indices:admin/plugins/replication/index/resume",
        "indices:admin/plugins/replication/index/stop",
        "indices:admin/plugins/replication/index/update",
        "indices:admin/plugins/replication/index/status_check"
      ]
    }
  ],
  "tenant_permissions": []
}

再通过以下API创建用户,角色名称可以参考使用replication_user,或者根据实际情况进行调整。

PUT _plugins/_security/api/internalusers/replication_user 
{
  "password": "<your password>",
  "opendistro_security_roles": [],
  "backend_roles": []
}

接下来需要将角色和用户映射起来,可以通过以下API实现。

PUT _plugins/_security/api/rolesmapping/cross_cluster_replication_follower_full_access
{
  "backend_roles" : [],
  "hosts" : [],
  "users" : ["replication_user"]
}

leader操作」步骤和上述内容类似,在管理控制台中查看Dashboard URL,使用master用户和密码登录到follower domain的Dashboard界面,并从侧边栏选择Dev Tools。

通过以下API创建角色,角色名称可以参考使用cross_cluster_replication_leader_full_access,或者根据实际情况进行调整。

PUT _plugins/_security/api/roles/cross_cluster_replication_leader_full_access
{
  "cluster_permissions": [],
  "index_permissions": [
    {
      "index_patterns": [
        "*"
      ],
      "fls": [],
      "masked_fields": [],
      "allowed_actions": [
        "indices:admin/plugins/replication/index/setup/validate",
        "indices:data/read/plugins/replication/changes",
        "indices:data/read/plugins/replication/file_chunk"
      ]
    }
  ],
  "tenant_permissions": []
}

这里我们使用界面操作来演示创建用户的过程,首先从侧边栏切换到Security界面。

接下来选择Internal users,然后创建用户。

设置用户名和密码,注意这里的用户名需使用和follower domain相同的用户名,例如replication_user。

*注:如果没有设置相同的用户名,在开始复制的时候会报以下错误。

{
        "type" : "security_exception",
        "reason" : "no permissions for [indices:admin/plugins/replication/index/setup/validate] and User [name=replication_user, backend_roles=[], requestedTenant=__user__]"
      }

接下来需要将角色和用户映射起来,切换到角色页面,选择创建好的cross_cluster_replication_leader_full_access角色,点击进入详情。

点击Mapped users界面,并准备进行映射。

选择用户replication_user,进行角色和用户的映射。

⑤ 开启复制

leader操作」保持管理员账号登录状态(因为replication_user用户并没有创建索引的权限),在leader domain上创建待复制的索引,切换到Dev Tools界面,执行以下API创建示例索引leader-01。

  PUT leader-01

follower操作」从管理员账号登出,然后通过replication_user。在follower domain上开始复制索引,切换到Dev Tools界面,执行以下API开始复制。

PUT _plugins/_replication/follower-01/_start
{
   "leader_alias": "my-ccr",
   "leader_index": "leader-01",
   "use_roles":{
      "leader_cluster_role": "cross_cluster_replication_leader_full_access",
      "follower_cluster_role": "cross_cluster_replication_follower_full_access"
   }
}

其中,follower-01为follower侧的索引名称,my-ccr为之前创建的connection名称, leader-01为待复制的索引,角色cross_cluster_replication_leader_full_access和cross_cluster_replication_follower_full_access为之前创建的角色,并且已经映射到用户replication_user。

⑥ 查看复制

follower操作」保持replication_user账号登录状态,继续在Dev Tools界面操作,执行以下API查看复制状态。

GET _plugins/_replication/follower-01/_status

执行后会得到以下结果:

{
  "status" : "SYNCING",
  "reason" : "User initiated",
  "leader_alias" : "my-ccr",
  "leader_index" : "leader-01",
  "follower_index" : "follower-01",
  "syncing_details" : {
    "leader_checkpoint" : -5,
    "follower_checkpoint" : -5,
    "seq_no" : -2
  }
}

可以看到目前的状态是SYNCING,表示正常进行复制中,其他可能的状态还有BOOTSTRAPPING,PAUSED和REPLICATION NOT IN PROGRESS(如果leader索引删除后,再查看复制状态会出现此状态)。

查看syncing_details 复制细节可以看到leader_checkpoint 和follower_checkpoint 两个检查点的值都是-5,这里反映的是分片计数的情况(-1表示1个分片,-5表示5个分片,以此类推),并且值会随着每次更改而增加,从中也可以看出follower对leader索引的复制情况。如果索引是完全同步的,则值相同。seq_no是按照相同的顺序对leader和follower索引执行相同的操作,也会随着,保障顺序一致性。

接下来,我们再写入一些数据查看复制情况。

leader操作」保持管理员账号登录状态,在leader domain切换到Dev Tools界面,执行以下API创建示例数据。

POST leader-01/_bulk
{ "index" : { "_id" : "1" } }
{"director": "Frankenheimer, John", "genre": ["Drama", "Mystery", "Thriller", "Crime"], "year": 1962, "actor": ["Lansbury, Angela", "Sinatra, Frank", "Leigh, Janet", "Harvey, Laurence", "Silva, Henry", "Frees, Paul", "Gregory, James", "Bissell, Whit", "McGiver, John", "Parrish, Leslie", "Edwards, James", "Flowers, Bess", "Dhiegh, Khigh", "Payne, Julie", "Kleeb, Helen", "Gray, Joe", "Nalder, Reggie", "Stevens, Bert", "Masters, Michael", "Lowell, Tom"], "title": "The Manchurian Candidate"}
{ "index" : { "_id" : "2" } }
{"director": "Baird, Stuart", "genre": ["Action", "Crime", "Thriller"], "year": 1998, "actor": ["Downey Jr., Robert", "Jones, Tommy Lee", "Snipes, Wesley", "Pantoliano, Joe", "Jacob, Ir\u00e8ne", "Nelligan, Kate", "Roebuck, Daniel", "Malahide, Patrick", "Richardson, LaTanya", "Wood, Tom", "Kosik, Thomas", "Stellate, Nick", "Minkoff, Robert", "Brown, Spitfire", "Foster, Reese", "Spielbauer, Bruce", "Mukherji, Kevin", "Cray, Ed", "Fordham, David", "Jett, Charlie"], "title": "U.S. Marshals"}
{ "index" : { "_id" : "3" } }
{"director": "Ray, Nicholas", "genre": ["Drama", "Romance"], "year": 1955, "actor": ["Hopper, Dennis", "Wood, Natalie", "Dean, James", "Mineo, Sal", "Backus, Jim", "Platt, Edward", "Ray, Nicholas", "Hopper, William", "Allen, Corey", "Birch, Paul", "Hudson, Rochelle", "Doran, Ann", "Hicks, Chuck", "Leigh, Nelson", "Williams, Robert", "Wessel, Dick", "Bryar, Paul", "Sessions, Almira", "McMahon, David", "Peters Jr., House"], "title": "Rebel Without a Cause"}

follower操作」保持replication_user账号登录状态,继续在Dev Tools界面操作,再次执行以下API查看复制状态。

GET _plugins/_replication/follower-01/_status

执行后会得到以下结果:

{
  "status" : "SYNCING",
  "reason" : "User initiated",
  "leader_alias" : "my-ccr",
  "leader_index" : "leader-01",
  "follower_index" : "follower-01",
  "syncing_details" : {
    "leader_checkpoint" : -2,
    "follower_checkpoint" : -2,
    "seq_no" : 1
  }
}

查看syncing_details ,可以看到leader_checkpoint ,follower_checkpoint 和seq_no都相应地增加了计数,并且leader_checkpoint 和follower_checkpoint相同,表示数据已经追平。

如果想查询follower-01的数据,可以切换到管理员用户进行查看(因为replication_user用户并没有创建索引的权限)。通过以下API可以搜索到follower-01最新的数据。

GET follower-01/_search

这里需要注意的是follower-01为只读索引,如果尝试向follower-01索引中添加数据,会提示以下错误信息:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "cluster_block_exception",
        "reason" : "index [follower-01] blocked by: [FORBIDDEN/1000/index read-only(cross-cluster-replication)];"
      }
    ],
    "type" : "cluster_block_exception",
    "reason" : "index [follower-01] blocked by: [FORBIDDEN/1000/index read-only(cross-cluster-replication)];"
  },
  "status" : 403
}

⑦ 设置复制规则

以上演示是针对单个索引需要跨集群复制的情况,如果想要大规模地、自动化地完成复制,可以通过CCR的Auto-follow功能来完成,借助复制规则的方式实现。

follower操作」保持replication_user账号登录状态,继续在Dev Tools界面操作,执行以下API设置Auto-follow的规则。

POST _plugins/_replication/_autofollow
{
   "leader_alias" : "my-ccr",
   "name": "my-rule",
   "pattern": "leader-*",
   "use_roles":{
      "leader_cluster_role": "cross_cluster_replication_leader_full_access",
      "follower_cluster_role": "cross_cluster_replication_follower_full_access"
   }
}

leader操作」保持管理员账号登录状态,在leader domain切换到Dev Tools界面,执行以下API创建新索引。

PUT leader-02

follower操作」保持replication_user账号登录状态,继续在Dev Tools界面操作,执行以下API设置Auto-follow的规则。

POST _plugins/_replication/_autofollow
{
   "leader_alias" : "my-ccr",
   "name": "my-rule",
   "pattern": "leader-*",
   "use_roles":{
      "leader_cluster_role": "cross_cluster_replication_leader_full_access",
      "follower_cluster_role": "cross_cluster_replication_follower_full_access"
   }
}

查看leader-02的复制情况:

GET _plugins/_replication/leader-02/_status

可以看到索引已经自动被复制过来了。

{
  "status" : "SYNCING",
  "reason" : "User initiated",
  "leader_alias" : "my-ccr",
  "leader_index" : "leader-02",
  "follower_index" : "leader-02",
  "syncing_details" : {
    "leader_checkpoint" : -5,
    "follower_checkpoint" : -5,
    "seq_no" : -3
  }
}

OpenSearch以及Amazaon OpenSearch Service也提供了Auto-follow统计信息的API,可以通过以下命令查看:

GET /_plugins/_replication/autofollow_stats

从以下结果可以看到已经有2个索引(leader-01和leader-02)已经成功复制。

{
  "num_success_start_replication" : 2,
  "num_failed_start_replication" : 0,
  "num_failed_leader_calls" : 0,
  "failed_indices" : [ ],
  "autofollow_stats" : [
    {
      "name" : "my-rule",
      "pattern" : "leader-*",
      "num_success_start_replication" : 2,
      "num_failed_start_replication" : 0,
      "num_failed_leader_calls" : 0,
      "failed_indices" : [ ]
    }
  ]
}

以上就是关于Amazon OpenSearch Service CCR功能的操作流程演示,如果用户想要停止复制,可以通过Stop replication(对应单独的复制)和Delete replication rule(对应Auto-follow的复制)动作来实现。

小结

本文介绍了Amazon OpenSearch Service提供的跨集群复制CCR功能,通过CCR用户可以轻松快速地将数据索引的复制,以实现对集群读写分离、故障转移、跨区域同步、集中式管理等应用场景的支持。目前,跨集群复制可在全球 26 个区域内的 Amazon OpenSearch Service服务中使用,快来开启吧!

参考资料

https://aws.amazon.com/about-aws/whats-new/2022/04/cross-cluster-replication-amazon-opensearch-domains/

https://docs.aws.amazon.com/opensearch-service/latest/developerguide/replication.html

https://opensearch.org/docs/latest/replication-plugin/index/

https://opensearch.org/docs/latest/replication-plugin/api/

本篇作者

史天

史天,亚马逊云科技资深解决方案架构师。拥有丰富的云计算、数据分析和机器学习经验,目前致力于数据科学、机器学习、无服务器等领域的研究和实践。译有《机器学习即服务》《基于Kubernetes的DevOps实践》《Kubernetes微服务实战》《Prometheus监控实战》《云原生时代的CoreDNS学习指南》等。