一、配置
orcherstrator的配置涉及到很多的内容,详细可查看官方文档1,官方文档2,下面所说的一些状态的详细解释也可以查看官网
1.后端配置
让orchestrator知道在哪里可以找到后端数据库。在此设置中,orchestrator将在3000端口上提供HTTP。
{
"Debug": false,
"ListenAddress": ":3000",
}
以MySQl为后端的配置
{
"MySQLOrchestratorHost": "orchestrator.backend.master.com",
"MySQLOrchestratorPort": 3306,
"MySQLOrchestratorDatabase": "orchestrator",
"MySQLOrchestratorCredentialsConfigFile": "/etc/mysql/orchestrator-backend.cnf",
}
MySQLOrchestratorCredentialsConfigFile的配置内容
[client]
user=orchestrator_srv
password=${ORCHESTRATOR_PASSWORD}
其中用户或密码可以是明文形式,也可以从环境中获取其值。
或者,您可以选择在配置文件中使用纯文本凭据:
{
"MySQLOrchestratorUser": "orchestrator_srv",
"MySQLOrchestratorPassword": "orc_server_password",
}
以MySQL为后端数据库所需的用户权限
CREATE USER 'orchestrator_srv'@'orc_host' IDENTIFIED BY 'orc_server_password';
GRANT ALL ON orchestrator.* TO 'orchestrator_srv'@'orc_host';
SQLite为后端的配置
{
"BackendDB": "sqlite",
"SQLite3DataFile": "/var/lib/orchestrator/orchestrator.db",
}
如果 SQLite3DataFile 指示的文件不存在,orchestrator 将创建它。 它将需要给定路径/文件的写权限。
2.基础发现
配置让orchestrator知道如何查询MySQL拓扑,提取什么信息
{
"MySQLTopologyCredentialsConfigFile": "/etc/mysql/orchestrator-topology.cnf",
"InstancePollSeconds": 5, # Orchestrator 将每 InstancePollSeconds 秒探测一次每个服务器。
"DiscoverByShowSlaveHosts": false,
}
MySQLTopologyCredentialsConfigFile 遵循与 MySQLOrchestratorCredentialsConfigFile 类似的规则。 您可以选择使用明文凭据:
[client]
user=orchestrator
password=orc_topology_password
或者,您可以选择使用纯文本凭据:
{
"MySQLTopologyUser": "orchestrator",
"MySQLTopologyPassword": "orc_topology_password",
}
所有的MySQL拓扑需要的权限
CREATE USER 'orchestrator'@'orc_host' IDENTIFIED BY 'orc_topology_password';
GRANT SUPER, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT, RELOAD ON *.* TO 'orchestrator'@'orc_host';
GRANT SELECT ON meta.* TO 'orchestrator'@'orc_host';
GRANT SELECT ON ndbinfo.processes TO 'orchestrator'@'orc_host'; -- Only for NDB Cluster
GRANT SELECT ON performance_schema.replication_group_members TO 'orchestrator'@'orc_host'; -- Only for Group Replication / InnoDB cluster
3.域名解析配置
{
"HostnameResolveMethod": "default",
"MySQLHostnameResolveMethod": "@@hostname",
}
主机可以通过 IP 地址、和/或短名称、和/或 FQDN 和/或 VIP 相互引用。 Orchestrator 需要唯一且一致地标识主机。 它通过解析目标主机名来实现这一点。
许多人发现“MySQLHostnameResolveMethod”:“@@hostname”是最简单的。 您的选择是:
- “HostnameResolveMethod”: “cname”: 对主机名进行 CNAME 解析
- “HostnameResolveMethod”: “default”: 没有通过网络协议进行特殊解析
- “MySQLHostnameResolveMethod”: “@@hostname”: 发出 select @@hostname
- “MySQLHostnameResolveMethod”: “@@report_host”: 发出 select @@report_host,需要配置report_host
- “HostnameResolveMethod”: “none” 和 “MySQLHostnameResolveMethod”: “”: 不执行任何操作。 决不解析。 这可能会吸引一切始终使用 IP 地址的设置。
4.配置:发现、分类服务器:
Orchestrator 将找出集群、数据中心等的名称。
{
"ReplicationLagQuery": "select absolute_lag from meta.heartbeat_view",
"DetectClusterAliasQuery": "select ifnull(max(cluster_name), '') as cluster_alias from meta.cluster where anchor=1",
"DetectClusterDomainQuery": "select ifnull(max(cluster_domain), '') as cluster_domain from meta.cluster where anchor=1",
"DataCenterPattern": "",
"DetectDataCenterQuery": "select substring_index(substring_index(@@hostname, '-',3), '-', -1) as dc",
"PhysicalEnvironmentPattern": "",
"DetectSemiSyncEnforcedQuery": ""
}
Replication lag
默认情况下,orchestrator 使用 SHOW SLAVE STATUS 并采用 1 秒的延迟粒度值。 但是,此延迟并未考虑链式复制情况下的级联延迟。 许多使用自定义心跳机制,例如 pt-heartbeat。 这提供了主设备的“绝对”延迟以及亚秒分辨率。
ReplicationLagQuery 允许您设置自己的查询。
Cluster alias
不同的集群有共同的名称。 “Main”、“Analytics”、“Shard031”等。但是 MySQL 集群本身并不知道这些名称。
DetectClusterAliasQuery 是一个查询,您可以通过它让 Orchestrator 了解集群的名称。
名字很重要。 您可能会使用它来告诉orchestrator诸如:“请自动恢复此集群”或“此集群中所有参与的实例是什么”之类的信息。
为了使此类数据可以通过查询访问,一个技巧是在原数据库中创建一个表:
CREATE TABLE IF NOT EXISTS cluster (
anchor TINYINT NOT NULL,
cluster_name VARCHAR(128) CHARSET ascii NOT NULL DEFAULT '',
cluster_domain VARCHAR(128) CHARSET ascii NOT NULL DEFAULT '',
PRIMARY KEY (anchor)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
mysql meta -e "INSERT INTO cluster (anchor, cluster_name, cluster_domain) \
VALUES (1, '${cluster_name}', '${cluster_domain}') \
ON DUPLICATE KEY UPDATE \
cluster_name=VALUES(cluster_name), cluster_domain=VALUES(cluster_domain)"
也许您的主机命名约定会披露集群名称,而您只需要对@@hostname进行简单的查询。
Data center
Orchestrator 具有数据中心意识。 它不仅可以在网络界面上为它们提供漂亮的颜色; 也会在运行故障转移时会考虑 DC(数据中心)。
您将通过以下两种方法之一配置数据中心感知:
DataCenterPattern:要在 FQDN 上使用的正则表达式。 例如:“db-.?-.?.[.].myservice[.]com”
DetectDataCenterQuery:返回数据中心名称的查询
Cluster domain
对于不太重要的部分,主要是为了可见性,DetectClusterDomainQuery 应返回 VIP 或 CNAME,或者以其他方式返回集群主节点的地址
Semi-sync topology
在某些环境中,不仅控制半同步副本的数量,而且控制副本是半同步副本还是异步副本也很重要。 Orchestrator 可以检测不需要的半同步配置,并切换半同步标志 rpl_semi_sync_slave_enabled 和 rpl_semi_sync_master_enabled 以纠正这种情况
Semi-sync master (rpl_semi_sync_master_enabled)
如果 DetectSemiSyncEnforcedQuery 返回新主设备的值 > 0,则 Orchestrator 在主设备故障转移期间启用半同步主设备标志(例如 DeadMaster)。 如果主标志发生更改或设置不正确,orchestrator 不会触发任何恢复。
半同步主服务器可以进入两种故障场景:LockedSemiSyncMaster 和 MasterWithTooManySemiSyncReplicas。 在这两种情况之一的恢复期间,orchestrator 会禁用半同步副本上的半同步主标志。
Semi-sync replicas (rpl_semi_sync_slave_enabled)
Orchestrator 可以检测拓扑中是否存在错误数量的半同步副本(LockedSemiSyncMaster 和 MasterWithTooManySemiSyncReplicas),然后可以通过相应地启用/禁用半同步副本标志来纠正这种情况。
此行为可以通过以下选项控制:
- DetectSemiSyncEnforcedQuery:返回半同步优先级的查询(零表示异步副本;数字越大表示优先级越高)
- EnforceExactSemiSyncReplicas:决定是否强制执行严格的半同步副本拓扑的标志。 如果启用,LockedSemiSyncMaster 和 MasterWithTooManyReplicas 的恢复将启用和禁用副本上的半同步,以根据优先级顺序完全匹配所需的拓扑。
- RecoverLockedSemiSyncMaster:决定是否从 LockedSemiSyncMaster 场景中恢复的标志。 如果启用,LockedSemiSyncMaster 的恢复将按照优先级顺序在副本上启用(但绝不禁用)半同步,以匹配主服务器等待计数。 如果设置了 EnforceExactSemiSyncReplicas,则此选项无效。 如果您只想处理半同步副本太少的情况,那么它很有用
- ReasonableLockedSemiSyncMasterSeconds:触发 LockedSemiSyncMaster 条件之前的秒数; 如果未设置,则回退到 ReasonableReplicationLagSeconds
优先级顺序由 DetectSemiSyncEnforcedQuery(零表示异步副本;数字越大优先级越高)、升级规则 (DetectPromotionRuleQuery) 和主机名(后备)定义。
示例 1:强制执行严格的半同步副本拓扑,其中 rpl_semi_sync_master_wait_for_slave_count=1:
"DetectSemiSyncEnforcedQuery": "select priority from meta.semi_sync where cluster_member = @@hostname",
"EnforceExactSemiSyncReplicas": true
假设这个拓扑,
,- replica1 (priority = 10, rpl_semi_sync_slave_enabled = 1)
master
`- replica2 (priority = 20, rpl_semi_sync_slave_enabled = 1)
Orchestrator 将检测 MasterWithTooManySemiSyncReplicas 场景并禁用副本 1 上的半同步(优先级较低)。
示例 2:使用 rpl_semi_sync_master_wait_for_slave_count 强制执行弱半同步副本拓扑
"DetectSemiSyncEnforcedQuery": "select 2586",
"DetectPromotionRuleQuery": "select promotion_rule from meta.promotion_rules where cluster_member = @@hostname",
"RecoverLockedSemiSyncMaster": true
假设这个拓扑,
,- replica1 (priority = 2586, promotion rule = prefer, rpl_semi_sync_slave_enabled = 0)
master
`- replica2 (priority = 2586, promotion rule = neutral, rpl_semi_sync_slave_enabled = 0)
Orchestrator 将检测 LockedSemiSyncMaster 场景并在副本 1 上启用半同步(更可取的升级规则)。
5.Pseudo GTID
Orchestrator 将识别二进制日志中的魔法提示,使其能够像具有 GTID 一样操作非 GTID 拓扑,包括副本的重新定位、智能故障转移等。
Automated Pseudo-GTID injection
Orchestrator 可以为您注入伪 GTID
{
"AutoPseudoGTID": true,
}
并且可以忽略任何其他 Pseudo-GTID 相关配置(它们都将被 Orchestrator 隐式覆盖)。需要在 MySQL 服务器上授予以下权限
GRANT DROP ON _pseudo_gtid_.* to 'orchestrator'@'orch_host';
注意:pseudo_gtid 库不需要存在。 无需创建它。 Orchestrator 将运行以下形式的查询:
drop view if exists `_pseudo_gtid_`.`_asc:5a64a70e:00000001:c7b8154ff5c3c6d8`
这些语句不会执行任何操作,只会充当二进制日志中的魔术标记。
Orchestrator 只会在允许的情况下尝试注入 Pseudo-GTID。 如果您想将Pseudo-GTID注入限制到特定集群,则可以通过仅向希望注入Pseudo-GTID的那些集群授予权限来实现。 可以通过以下方式在特定集群上禁用伪 GTID 注入:
REVOKE DROP ON _pseudo_gtid_.* FROM 'orchestrator'@'orch_host';
自动 pseudo-GTID 注入是一项较新的开发,它取代了运行自己的pseudo-GTID注入的需要。
在运行手动pseudo-GTID 注入后启用自动pseudo-GTID 注入:
- 将不再需要管理伪 GTID 服务/事件调度程序。
- 特别是,在主节点故障转移时,不需要在旧的/升级的主节点上禁用/启用pseudo-GTID。
Manual Pseudo-GTID injection
如果您想自己注入Pseudo-GTID,我们建议您配置如下:
{
"PseudoGTIDPattern": "drop view if exists `meta`.`_pseudo_gtid_hint__asc:",
"PseudoGTIDPatternIsFixedSubstring": true,
"PseudoGTIDMonotonicHint": "asc:",
"DetectPseudoGTIDQuery": "select count(*) as pseudo_gtid_exists from meta.pseudo_gtid_status where anchor = 1 and time_generated > now() - interval 2 hour",
}
上述假设:
- 你有一个元数据库
- 您将通过此示例脚本注入Pseudo-GTID 条目
6.topology control
以下配置会影响 Orchestrator 如何将更改应用到拓扑服务器:
Orchestrator 将找出集群、数据中心等的名称。
{
"UseSuperReadOnly": false,
}
UseSuperReadOnly
默认为 false。 如果为 true,则每当要求 Orchestrator 设置/清除 read_only 时,它也会将更改应用于 super_read_only。 super_read_only 仅在特定版本的 Oracle MySQL 和 Percona Server 上可用。
7.failure detection
Orchestrator 将始终检测拓扑故障。 作为配置问题,可以设置轮询频率和Orchestrator通知此类检测的特定方式。
恢复被讨论在 配置:恢复
{
"FailureDetectionPeriodBlockMinutes": 60,
}
Orchestrator 每秒运行一次检测。
FailureDetectionPeriodBlockMinutes 是一种反垃圾邮件机制,可阻止Orchestrator一次又一次地通知相同的检测。
Hooks
配置 Orchestrator 以在发现时采取操作:
{
"OnFailureDetectionProcesses": [
"echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countReplicas}' >> /tmp/recovery.log"
],
}
您可以将许多神奇变量(如上面的 {failureCluster})发送到外部挂钩。 查看拓扑恢复中的完整列表
MySQL configuration
由于故障检测使用 MySQL 拓扑本身作为信息源,因此建议如下设置 MySQL 复制,以便清楚地指示或快速缓解错误。
- 设置全局slave_net_timeout = 4,请参阅文档。 这会在副本与其主服务器之间设置较短(2秒)的心跳间隔,并使副本快速识别故障。 如果没有此设置,某些情况可能需要一分钟才能检测到。
- 将主设备更改为 MASTER_CONNECT_RETRY=1,MASTER_RETRY_COUNT=86400。 如果复制失败,副本将每 1 秒尝试重新连接一次(默认为 60 秒)。 对于短暂的网络问题,此设置会尝试快速复制恢复,如果成功,将避免Orchestrator进行一般故障/恢复操作。
8.recovery
Orchestrator 将恢复\拓扑的故障。 指示 Orchestrator 哪些集群要自动恢复以及哪些集群需要人工恢复。 您将为 Orchestrator 配置hooks以移动 VIP、更新服务发现等。
还要考虑 MySQL 拓扑本身需要遵循一些规则,请参阅 MySQL 配置
{
"RecoveryPeriodBlockSeconds": 3600,
"RecoveryIgnoreHostnameFilters": [],
"RecoverMasterClusterFilters": [
"thiscluster",
"thatcluster"
],
"RecoverIntermediateMasterClusterFilters": [
"*"
],
}
上文中:
- Orchestrator 将自动恢复所有集群的中间主故障
- Orchestrator 将自动恢复两个指定集群的主故障; 其他集群的master不会自动恢复。 由人工来处理恢复
- 一旦集群经历了恢复,orchestrator 将在接下来的 3600 秒(1 小时)内阻止自动恢复。 这是一种防扑动机制。
再次注意,自动恢复是可选的。
Promotion actions
不同的环境需要采取不同的恢复/提升行动
{
"ApplyMySQLPromotionAfterMasterFailover": true,
"PreventCrossDataCenterMasterFailover": false,
"PreventCrossRegionMasterFailover": false,
"FailMasterPromotionOnLagMinutes": 0,
"FailMasterPromotionIfSQLThreadNotUpToDate": true,
"DelayMasterPromotionIfSQLThreadNotUpToDate": false,
"MasterFailoverLostInstancesDowntimeMinutes": 10,
"DetachLostReplicasAfterMasterFailover": true,
"MasterFailoverDetachReplicaMasterHost": false,
"MasterFailoverLostInstancesDowntimeMinutes": 0,
"PostponeReplicaRecoveryOnLagMinutes": 0,
}
- ApplyMySQLPromotionAfterMasterFailover:当为 true 时,orchestrator 将重置所有从属设备并在升级的主设备上设置 read_only=0。 默认值:true。 如果为 true,则覆盖 MasterFailoverDetachSlaveMasterHost。
- PreventCrossDataCenterMasterFailover:默认为 false。 如果为 true,orchestrator 将仅使用同一 DC 中的服务器替换发生故障的主服务器。 它将尽力从同一 DC 中找到替代者,如果找不到,将中止(失败)故障转移。 另请参见 DetectDataCenterQuery 和 DataCenterPattern 配置变量。
- PreventCrossRegionMasterFailover:默认为 false。 如果为 true,orchestrator 将仅使用来自同一区域的服务器替换出现故障的主服务器。 它将尽力从同一区域找到替代者,如果找不到,将中止(失败)故障转移。 另请参阅 DetectRegionQuery 和 RegionPattern 配置变量。
- FailMasterPromotionOnLagMinutes:默认为 0(升级不会失败)。 如果候选副本落后太多,可用于使升级失败。 示例:副本损坏了 5 小时,然后主服务器发生故障。 人们可能希望阻止故障转移,以便恢复丢失 5 小时的二进制日志/中继日志。 要使用此标志,您必须设置 ReplicationLagQuery 并使用心跳机制,例如 pt-heartbeat。 当复制中断时,MySQL 内置的 SHOW SLAVE STATUS(8.0 之前)的 Seconds_behind_master 输出不会报告复制延迟。
- FailMasterPromotionIfSQLThreadNotUpToDate:如果所有副本在故障时都滞后,则即使是最新的升级副本也可能具有未应用的中继日志。 在此类服务器上发出reset slave all将丢失中继日志数据。
- DelayMasterPromotionIfSQLThreadNotUpToDate:如果所有副本在故障时都滞后,则即使是最新的升级副本也可能具有未应用的中继日志。 当为 true 时,“orchestrator”将等待 SQL 线程赶上,然后再升级新的 master。 FailMasterPromotionIfSQLThreadNotUpToDate 和 DelayMasterPromotionIfSQLThreadNotUpToDate 是互斥的。
- DetachLostReplicasAfterMasterFailover:某些副本可能在恢复过程中丢失。 如果为 true,orchestrator 将通过 detach-replica 命令强制中断其复制,以确保没有人认为它们完全正常工作。
- MasterFailoverDetachReplicaMasterHost :当为 true 时,orchestrator 将在升级的 master 上发出 detach-replica-master-host (这确保新的 master 不会尝试复制旧的 master,如果它恢复了)。 默认值:false。 如果ApplyMySQLPromotionAfterMasterFailover 为true,则毫无意义。 MasterFailoverDetachSlaveMasterHost 是它的别名。
- MasterFailoverLostInstancesDowntimeMinutes:主故障转移后丢失的任何服务器(包括失败的主服务器和丢失的副本)停机的分钟数。 设置为 0 以禁用。 默认值:0。
- PostponeReplicaRecoveryOnLagMinutes:在崩溃恢复时,滞后超过给定分钟数的副本仅在恢复过程的后期、在选择 master/IM 并执行进程之后复活。 值为 0 会禁用此功能。 默认值:0。PostponeSlaveRecoveryOnLagMinutes 是它的别名。
Hooks
这些hooks可用于恢复:
- PreGracefulTakeoverProcesses:在计划的、优雅的主节点上执行,在主节点变为只读之前立即执行。
- PreFailoverProcesses:在 Orchestrator 采取恢复操作之前立即执行。 这些进程中的任何一个失败(非零退出代码)都会中止恢复。 提示:这使您有机会根据系统的某些内部状态中止恢复。
- PostMasterFailoverProcesses:在成功主恢复结束时执行。
- PostIntermediateMasterFailoverProcesses:在具有副本恢复功能的成功中间主节点或复制组成员结束时执行。
- PostFailoverProcesses:在任何成功恢复结束时执行(包括并添加到上述两者)。
- PostUnsuccessfulFailoverProcesses:在任何不成功的恢复结束时执行。
-PostGracefulTakeoverProcesses:在旧主服务器位于新升级主服务器之下之后,在计划的、优雅的主服务器接管中执行。
任何以“&”结尾的进程命令都将异步执行,并且此类进程的失败将被忽略。
以上所有内容都是 Orchestrator 按定义顺序顺序执行的命令列表。
一个简单的例子
{
"PreGracefulTakeoverProcesses": [
"echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [
"echo 'Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PostFailoverProcesses": [
"echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostUnsuccessfulFailoverProcesses": [],
"PostMasterFailoverProcesses": [
"echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:
{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostIntermediateMasterFailoverProcesses": [],
"PostGracefulTakeoverProcesses": [
"echo 'Planned takeover complete' >> /tmp/recovery.log"
],
}{
"PreGracefulTakeoverProcesses": [
"echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [
"echo 'Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
],
"PostFailoverProcesses": [
"echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostUnsuccessfulFailoverProcesses": [],
"PostMasterFailoverProcesses": [
"echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:
{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log"
],
"PostIntermediateMasterFailoverProcesses": [],
"PostGracefulTakeoverProcesses": [
"echo 'Planned takeover complete' >> /tmp/recovery.log"
],
}
Hooks arguments and environment
Orchestrator 为所有hooks提供与故障/恢复相关的信息,例如故障实例的身份、升级实例的身份、受影响的副本、故障类型、集群名称等。
该信息通过两种方式独立传递,您可以选择使用一种或两种方式
- 1.环境变量:orchestrator 将设置以下内容,hooks可以检索这些内容:
ORC_FAILURE_TYPE
ORC_INSTANCE_TYPE (“master”, “co-master”, “intermediate-master”)
ORC_IS_MASTER (true/false)
ORC_IS_CO_MASTER (true/false)
ORC_FAILURE_DESCRIPTION
ORC_FAILED_HOST
ORC_FAILED_PORT
ORC_FAILURE_CLUSTER
ORC_FAILURE_CLUSTER_ALIAS
ORC_FAILURE_CLUSTER_DOMAIN
ORC_COUNT_REPLICAS
ORC_IS_DOWNTIMED
ORC_AUTO_MASTER_RECOVERY
ORC_AUTO_INTERMEDIATE_MASTER_RECOVERY
ORC_ORCHESTRATOR_HOST
ORC_IS_SUCCESSFUL
ORC_LOST_REPLICAS
ORC_REPLICA_HOSTS
ORC_COMMAND (“force-master-failover”, “force-master-takeover”, “graceful-master-takeover” if applicable)
并且,如果恢复成功
ORC_SUCCESSOR_HOST
ORC_SUCCESSOR_PORT
ORC_SUCCESSOR_BINLOG_COORDINATES
ORC_SUCCESSOR_ALIAS - 2.命令行文本替换。 Orchestrator 会替换您的 *Proccesses 命令中的以下魔法标记:
{failureType}
{instanceType} (“master”, “co-master”, “intermediate-master”)
{isMaster} (true/false)
{isCoMaster} (true/false)
{failureDescription}
{failedHost}
{failedPort}
{failureCluster}
{failureClusterAlias}
{failureClusterDomain}
{countReplicas} (replaces {countSlaves})
{isDowntimed}
{autoMasterRecovery}
{autoIntermediateMasterRecovery}
{orchestratorHost}
{lostReplicas} (replaces {lostSlaves})
{countLostReplicas}
{replicaHosts} (replaces {slaveHosts})
{isSuccessful}
{command} (“force-master-failover”, “force-master-takeover”, “graceful-master-takeover” if applicable)
并且,如果恢复成功
{successorHost}
{successorPort}
{successorBinlogCoordinates}
{successorAlias}
MySQL Configuration
您的 MySQL 拓扑必须满足一些要求才能支持故障转移。 这些要求很大程度上取决于您使用的拓扑/配置的类型。
- 具有 GTID 的 Oracle/Percona:可升级服务必须启用 log_bin 和 log_slave_updates。 副本必须使用 AUTO_POSITION=1(通过 CHANGE MASTER TO MASTER_AUTO_POSITION=1)。
- MariaDB GTID:可升级服务必须启用 log_bin 和 log_slave_updates。
- Pseudo GTID:可升级服务必须启用 log_bin 和 log_slave_updates。 如果使用5.7/8.0并行复制,请设置slave_preserve_commit_order=1。
- BinlogServers:可升级服务必须启用 log_bin。
还可以考虑通过 MySQL 配置改进故障检测
9.Configuration: raft
设置 Orchestrator/raft 集群以实现高可用性。
在 3 节点设置上运行 Orchestrator/raft,在每个节点上进行配置:
"RaftEnabled": true,
"RaftDataDir": "<path.to.orchestrator.data.directory>",
"RaftBind": "<ip.or.fqdn.of.this.orchestrator.node>",
"DefaultRaftPort": 10008,
"RaftNodes": [
"<ip.or.fqdn.of.orchestrator.node1>",
"<ip.or.fqdn.of.orchestrator.node2>",
"<ip.or.fqdn.of.orchestrator.node3>"
],
具体含义:
- RaftEnabled 必须设置为 true,否则 Orchestrator 以共享后端模式运行。
- RaftDataDir 必须设置为 Orchestrator 可写入的目录。 如果该目录不存在,orchestrator 将尝试创建该目录。
- RaftBind 必须设置,使用本地主机的 IP 地址或完整主机名。 该 IP 或主机名也将被列为 RaftNodes 变量之一。
- DefaultRaftPort 可以设置为任何端口,但在所有部署中必须保持一致。
- RaftNodes 应列出 raft 集群的所有节点。 该列表将包含 IP 地址或主机名,并将包括 RaftBind 中显示的该主机本身的值。
例子:
"RaftEnabled": true,
"RaftDataDir": "/var/lib/orchestrator",
"RaftBind": "10.0.0.2",
"DefaultRaftPort": 10008,
"RaftNodes": [
"10.0.0.1",
"10.0.0.2",
"10.0.0.3"
],
# 或
"RaftEnabled": true,
"RaftDataDir": "/var/lib/orchestrator",
"RaftBind": "node-full-hostname-2.here.com",
"DefaultRaftPort": 10008,
"RaftNodes": [
"node-full-hostname-1.here.com",
"node-full-hostname-2.here.com",
"node-full-hostname-3.here.com"
],
网络、防火墙、路由
如果您的 Orchestrator/raft 节点需要通过 NAT 网关进行通信,您还可以设置:
"RaftAdvertise": "<ip.or.fqdn.visible.to.other.nodes>"
其他节点应联系的 IP 或主机名。 否则其他节点将尝试与“RaftBind”地址通信并失败。
Raft 节点将代理 HTTP 请求反向发送给leader。 Orchestrator 将尝试启发式计算leader的重定向请求的 URL。 如果位于 NAT、重新路由端口等之后,orchestrator 可能无法计算该 URL。 您可以配置:
"HTTPAdvertise": "scheme://hostname:port"
显式指定节点(假设它是leader)将通过 HTTP API 访问的位置。 例如,您可以:
"HTTPAdvertise": "http://my.public.hostname:3000"
Backend DB
raft 设置支持 MySQL 或 SQLite 后端数据库。
单节点的raft设置
在生产中,需要使用多个 raft 节点,例如 3 或 5 个。
在测试环境中,可以运行由单个节点组成的 Orchestrator/raft 设置。 该节点将隐式成为leader,并将向自身通告 raft 消息。
要运行单节点 Orchestrator/raft,请配置一个空的 RaftNode:
"RaftNodes": [],
或者,指定单个节点,与 RaftBind 或 RaftAdvertise 相同:
"RaftEnabled": true,
"RaftBind": "127.0.0.1",
"DefaultRaftPort": 10008,
"RaftNodes": [
"127.0.0.1"
],
10.安全
当在 HTTP 模式(API 或 Web)下运行时,对 Orchestrator 的访问可能会通过以下任一方式受到限制:
- 基本身份验证
将以下内容添加到 Orchestrator 的配置文件中:
"AuthenticationMethod": "basic",
"HTTPAuthUser": "dba_team",
"HTTPAuthPassword": "time_for_dinner"
使用basic验证时,只有一个凭证,并且没有角色。
Orchestrator 的配置文件包含 MySQL 服务器的凭据以及上面指定的基本身份验证凭据。 确保其安全(例如 chmod 600)。
- 基本身份验证,扩展
将以下内容添加到 Orchestrator 的配置文件中:
"AuthenticationMethod": "multi",
"HTTPAuthUser": "dba_team",
"HTTPAuthPassword": "time_for_dinner"
multi的工作方式与basic类似,但也接受具有任何密码的只读用户。 只读用户可以查看所有内容,但无法通过 API 执行写入操作(例如停止副本、重新指向副本、发现新实例等)
- Headers authentication
通过反向代理转发的标头进行身份验证(例如 Apache2 将请求中继到 Orchestrator)。 要求:
"AuthenticationMethod": "proxy",
"AuthUserHeader": "X-Forwarded-User",
需要配置反向代理以通过 HTTP 标头发送经过身份验证的用户的名称,并使用与 AuthUserHeader 配置相同的标头名称。
例如,Apache2 设置可能如下所示:
RequestHeader unset X-Forwarded-User
RewriteEngine On
RewriteCond %{LA-U:REMOTE_USER} (.+)
RewriteRule .* - [E=RU:%1,NS]
RequestHeader set X-Forwarded-User %{RU}e
代理身份验证允许角色。 一些用户是高级用户,其余的只是普通用户。 高级用户可以更改拓扑,而普通用户则处于只读模式。 要指定已知 DBA 的列表,请使用:
"PowerAuthUsers": [
"wallace", "gromit", "shaun"
],
或者,无论如何,您可以通过以下方式将整个Orchestrator进程设置为只读:
"ReadOnly": "true",
可以将 ReadOnly 与任何喜欢的身份验证方法结合起来。
11.Key-Value stores
Orchestrator 支持这些键值存储:
- 基于关系表的内部存储
- consul
- zookeeper
Orchestrator 通过将集群的 master 存储在 KV 中来支持 master 发现。
"KVClusterMasterPrefix": "mysql/master",
"ConsulAddress": "127.0.0.1:8500",
"ZkAddress": "srv-a,srv-b:12181,srv-c",
"ConsulCrossDataCenterDistribution": true,
KVClusterMasterPrefix 是用于主发现条目的前缀。 例如,集群别名是 mycluster,主机名是 some.host-17.com,那么期望一行信息为,其中:
- key: mysql/master/mycluster
- value: some.host-17.com:3306
note: 在zookeeper上,如果前缀没有“ / ” 将会自动添加
Breakdown entries
除了上述内容之外,orchestrator 还分解了主条目并添加了以下内容(通过上面的示例进行说明):
- mysql/master/mycluster/hostname,value为 some.host-17.com
- mysql/master/mycluster/port,value为 3306
- mysql/master/mycluster/ipv4,value为 192.168.0.1
- mysql/master/mycluster/ipv6,value为
任何主条目都会自动添加 /hostname、/port、/ipv4 和 /ipv6 扩展名。
Stores
如果指定,ConsulAddress 表示 Consul HTTP 服务可用的地址。 如果未指定,则不会尝试进行 Consul 访问。
如果指定,ZkAddress 指示要连接的一台或多台 ZooKeeper 服务器。 每个服务器的默认端口为 2181。以下所有内容都是等效的:
- srv-a,srv-b:12181,srv-c
- srv-a,srv-b:12181,srv-c:2181
- srv-a:2181,srv-b:12181,srv-c:2181
Consul specific
有关 Consul 特定设置,请参阅 kv 文档。
12.大型环境中的 Orchestrator 配置
如果监控大量服务器,后端数据库可能会成为瓶颈。 以下注释涉及使用 MySQL 作为 Orchestrator 后端。
某些配置选项允许您控制吞吐量。 这些设置是:
- BufferInstanceWrites
- InstanceWriteBufferSize
- InstanceFlushIntervalMilliseconds
- DiscoveryMaxConcurrency
使用 DiscoveryMaxConcurrency 限制 Orchestrator 进行的并发发现数量,并确保后端服务器的 max_connections 设置足够高,以允许 Orchestrator 建立所需数量的连接。
通过在 Orchestrator 中设置 BufferInstanceWrites: True,当轮询完成时,结果将被缓冲,直到 InstanceFlushIntervalMilliseconds 已过或 InstanceWriteBufferSize 缓冲写入已完成。
缓冲的写入使用单个insert … on duplicate key update … 调用按写入时间排序。 如果同一主机出现两次,则只有最后一次写入才会写入该主机的数据库。
InstanceFlushIntervalMilliseconds 应远低于 InstancePollSeconds,因为将此值设置得太高将意味着数据不会写入 Orchestrator 数据库后端。 这可能会导致最近未检查的问题。 此外,不同的运行状况检查是针对后端数据库状态运行的,因此更新频率不够可能会导致 Orchestrator 无法正确检测不同的故障场景。
对于较大的 Orchestrator 环境,建议的起始值可能是:
"BufferInstanceWrites": true,
"InstanceWriteBufferSize": 1000,
"InstanceFlushIntervalMilliseconds": 50,
"DiscoveryMaxConcurrency": 1000,
13.简单配置示例
{
"Debug": true,
"EnableSyslog": false,
"ListenAddress": ":3000",
"MySQLTopologyCredentialsConfigFile": "/etc/mysql/orchestrator.cnf",
"MySQLTopologySSLPrivateKeyFile": "",
"MySQLTopologySSLCertFile": "",
"MySQLTopologySSLCAFile": "",
"MySQLTopologySSLSkipVerify": true,
"MySQLTopologyUseMutualTLS": false,
"MySQLTopologyMaxPoolConnections": 3,
"MySQLOrchestratorHost": "127.0.0.1",
"MySQLOrchestratorPort": 3306,
"MySQLOrchestratorDatabase": "orchestrator",
"MySQLOrchestratorCredentialsConfigFile": "/etc/mysql/orchestrator_srv.cnf",
"MySQLOrchestratorSSLPrivateKeyFile": "",
"MySQLOrchestratorSSLCertFile": "",
"MySQLOrchestratorSSLCAFile": "",
"MySQLOrchestratorSSLSkipVerify": true,
"MySQLOrchestratorUseMutualTLS": false,
"MySQLConnectTimeoutSeconds": 1,
"DefaultInstancePort": 3306,
"ReplicationLagQuery": "select round(absolute_lag) from meta.heartbeat_view",
"SlaveStartPostWaitMilliseconds": 1000,
"DiscoverByShowSlaveHosts": false,
"InstancePollSeconds": 5,
"DiscoveryIgnoreReplicaHostnameFilters": [
"a_host_i_want_to_ignore[.]example[.]com",
".*[.]ignore_all_hosts_from_this_domain[.]example[.]com",
"a_host_with_extra_port_i_want_to_ignore[.]example[.]com:3307"
],
"ReadLongRunningQueries": false,
"SkipMaxScaleCheck": true,
"BinlogFileHistoryDays": 10,
"UnseenInstanceForgetHours": 240,
"SnapshotTopologiesIntervalHours": 0,
"InstanceBulkOperationsWaitTimeoutSeconds": 10,
"ActiveNodeExpireSeconds": 5,
"HostnameResolveMethod": "default",
"MySQLHostnameResolveMethod": "@@hostname",
"SkipBinlogServerUnresolveCheck": true,
"ExpiryHostnameResolvesMinutes": 60,
"RejectHostnameResolvePattern": "",
"ReasonableReplicationLagSeconds": 10,
"ProblemIgnoreHostnameFilters": [
],
"VerifyReplicationFilters": false,
"MaintenanceOwner": "orchestrator",
"ReasonableMaintenanceReplicationLagSeconds": 20,
"MaintenanceExpireMinutes": 10,
"MaintenancePurgeDays": 365,
"CandidateInstanceExpireMinutes": 60,
"AuditLogFile": "",
"AuditToSyslog": false,
"AuditPageSize": 20,
"AuditPurgeDays": 365,
"RemoveTextFromHostnameDisplay": ":3306",
"ReadOnly": false,
"AuthenticationMethod": "",
"HTTPAuthUser": "",
"HTTPAuthPassword": "",
"AuthUserHeader": "",
"PowerAuthUsers": [
"*"
],
"ClusterNameToAlias": {
"127.0.0.1": "test suite"
},
"AccessTokenUseExpirySeconds": 60,
"AccessTokenExpiryMinutes": 1440,
"DetectClusterAliasQuery": "select ifnull(max(cluster_name), '') as cluster_alias from meta.cluster where anchor=1",
"DetectClusterDomainQuery": "",
"DataCenterPattern": "",
"DetectDataCenterQuery": "select 'redacted'",
"PhysicalEnvironmentPattern": "",
"PromotionIgnoreHostnameFilters": [
],
"ServeAgentsHttp": false,
"UseSSL": false,
"UseMutualTLS": false,
"SSLSkipVerify": false,
"SSLPrivateKeyFile": "",
"SSLCertFile": "",
"SSLCAFile": "",
"SSLValidOUs": [
],
"StatusEndpoint": "/api/status",
"StatusSimpleHealth": true,
"StatusOUVerify": false,
"HttpTimeoutSeconds": 60,
"StaleSeedFailMinutes": 60,
"SeedAcceptableBytesDiff": 8192,
"SeedWaitSecondsBeforeSend": 2,
"PseudoGTIDPattern": "drop view if exists `meta`.`_pseudo_gtid_hint__asc:",
"PseudoGTIDPatternIsFixedSubstring": true,
"PseudoGTIDMonotonicHint": "asc:",
"DetectPseudoGTIDQuery": "select count(*) as pseudo_gtid_exists from meta.pseudo_gtid_status where anchor = 1 and time_generated > now() - interval 1 day",
"BinlogEventsChunkSize": 10000,
"BufferBinlogEvents": true,
"SkipBinlogEventsContaining": [
"@@SESSION.GTID_NEXT= 'ANONYMOUS'"
],
"ReduceReplicationAnalysisCount": false,
"FailureDetectionPeriodBlockMinutes": 60,
"RecoveryPeriodBlockSeconds": 600,
"RecoveryIgnoreHostnameFilters": [
],
"RecoverMasterClusterFilters": [
"*"
],
"RecoverIntermediateMasterClusterFilters": [
"*"
],
"OnFailureDetectionProcesses": [
"/redacted/our-orchestrator-recovery-handler -t 'detection' -f '{failureType}' -h '{failedHost}' -C '{failureCluster}' -A '{failureClusterAlias}' -n '{countReplicas}'"
],
"PreGracefulTakeoverProcesses": [
"echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
],
"PreFailoverProcesses": [
"/redacted/our-orchestrator-recovery-handler -t 'pre-failover' -f '{failureType}' -h '{failedHost}' -C '{failureCluster}' -A '{failureClusterAlias}' -n '{countReplicas}'"
],
"PostFailoverProcesses": [
"/redacted/our-orchestrator-recovery-handler -t 'post-failover' -f '{failureType}' -h '{failedHost}' -H '{successorHost}' -C '{failureCluster}' -A '{failureClusterAlias}' -n '{countReplicas}' -u '{recoveryUID}'"
],
"PostUnsuccessfulFailoverProcesses": [
"/redacted/our-orchestrator-recovery-handler -t 'post-unsuccessful-failover' -f '{failureType}' -h '{failedHost}' -C '{failureCluster}' -A '{failureClusterAlias}' -n '{countReplicas}' -u '{recoveryUID}'"
],
"PostMasterFailoverProcesses": [
"/redacted/do-something # e.g. kick pt-heartbeat on promoted master"
],
"PostIntermediateMasterFailoverProcesses": [
],
"PostGracefulTakeoverProcesses": [
"echo 'Planned takeover complete' >> /tmp/recovery.log"
],
"CoMasterRecoveryMustPromoteOtherCoMaster": true,
"DetachLostSlavesAfterMasterFailover": true,
"ApplyMySQLPromotionAfterMasterFailover": true,
"PreventCrossDataCenterMasterFailover": false,
"PreventCrossRegionMasterFailover": false,
"MasterFailoverLostInstancesDowntimeMinutes": 60,
"PostponeReplicaRecoveryOnLagMinutes": 10,
"OSCIgnoreHostnameFilters": [
],
"GraphitePollSeconds": 60,
"GraphiteAddr": "",
"GraphitePath": "",
"GraphiteConvertHostnameDotsToUnderscores": true,
"BackendDB": "mysql",
"MySQLTopologyReadTimeoutSeconds": 3,
"MySQLDiscoveryReadTimeoutSeconds": 3,
"SQLite3DataFile": "/var/lib/orchestrator/orchestrator-sqlite.db",
"RaftEnabled": false,
"RaftBind": "redacted",
"RaftDataDir": "/var/lib/orchestrator",
"DefaultRaftPort": 10008,
"ConsulAddress": "redacted:8500",
"RaftNodes": [
"redacted",
"redacted",
"redacted"
]
}