This documents how freno
achieves high availability and consistent state with a MySQL
backend. As an alternative, see Raft.
You may use any number of freno
nodes, which will all connect to same MySQL backend. The nodes will pick leader by synching on the MySQL backend, and will not directly communicate with each other.
The following depicts a possible setup to provide with freno
high availability:
- A highly available MySQL setup: the HA of MySQL is outside
freno
's scope. Consider orchestrator. 2
or morefreno
nodes configured- Configure all to use the same
BackendMySQLHost
. - HAProxy in front of
freno
nodes.- HAProxy only directs traffic to the leader.
freno
has specialized/leader-check
. - Sample HAProxy configuration can be found in haproxy.cfg
- HAProxy only directs traffic to the leader.
- Clients to talk to HAProxy
- Implicitly, all clients only talk to the leader
Let's dissect the general section of the sample config file:
{
"BackendMySQLHost": "mysql.example.com",
"BackendMySQLPort": 3306,
"BackendMySQLSchema": "freno_backend",
"BackendMySQLUser": "freno_daemon",
"BackendMySQLPassword": "123456",
"Domain": "us-east-1/production",
"ShareDomain": "production",
}
BackendMySQLHost
: MySQL master hostnameBackendMySQLPort
: MySQL master portBackendMySQLSchema
: schema wherefreno
will read/write state (see below)BackendMySQLUser
: user with read+write privileges on backend schemaBackendMySQLPassword
: passwordDomain
: the same MySQL backend can serve multiple, unrelatedfreno
clusters. Nodes within the same cluster should have the sameDomain
value and will compete for leadership.ShareDomain
: it is possible for clusters to collaborate. Clusters with sameShareDomain
will consul with each other's metric health reports. A cluster may reject acheck
request if another cluster considers thecheck
metrics unhealthy.
You may exchange the above for environment variables:
{
"BackendMySQLHost": "${MYSQL_BACKEND_HOST}",
"BackendMySQLPort": 3306,
"BackendMySQLSchema": "${MYSQL_BACKEND_SCHEMA}",
"BackendMySQLUser": "${MYSQL_BACKEND_RW_USER}",
"BackendMySQLPassword": "${MYSQL_BACKEND_RW_PASSWORD}",
"Domain": "us-east-1/production",
"ShareDomain": "production",
}
and export such variables to the freno
daemon.
The backend schema should have these tables:
CREATE TABLE service_election (
domain varchar(32) NOT NULL,
share_domain varchar(32) NOT NULL,
service_id varchar(128) NOT NULL,
last_seen_active timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (domain),
KEY share_domain_idx (share_domain,last_seen_active)
);
CREATE TABLE throttled_apps (
app_name varchar(128) NOT NULL,
throttled_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP,
ratio DOUBLE,
PRIMARY KEY (app_name)
);
CREATE TABLE skipped_hosts (
host_name varchar(128) NOT NULL,
skipped_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
expires_at TIMESTAMP NOT NULL,
PRIMARY KEY (host_name)
);
The BackendMySQLUser
account must have SELECT, INSERT, DELETE, UPDATE
privileges on those tables.