Skip to content

Commit f2ced3c

Browse files
authored
Add support for Read replica 8.0.x (#17)
Signed-off-by: Mehedi Hasan <[email protected]>
1 parent 76dadb7 commit f2ced3c

File tree

2 files changed

+186
-5
lines changed

2 files changed

+186
-5
lines changed

scripts/run_innodb.sh

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ function log() {
1515
args=$@
1616
report_host="$HOSTNAME.$GOV_SVC.$POD_NAMESPACE.svc"
1717
log "INFO" "report_host = $report_host"
18-
1918
# wait for the peer-list file created by coordinator
2019
while [ ! -f "/scripts/peer-list" ]; do
2120
log "WARNING" "peer-list is not created yet"
@@ -37,6 +36,7 @@ if [ -z "$whitelist" ]; then
3736
fi
3837

3938
cat >>/etc/my.cnf <<EOL
39+
#!includedir /etc/mysql/conf.d
4040
default_authentication_plugin=mysql_native_password
4141
#loose-group_replication_ip_whitelist = "${whitelist}"
4242
loose-group_replication_ip_allowlist = "${whitelist}"
@@ -184,9 +184,8 @@ function join_in_cluster() {
184184
}
185185

186186
joined_in_cluster=0
187-
function make_sure_instance_join_in_cluster() {
187+
check_instance_joined_in_cluster() {
188188
local mysqlshell="mysqlsh -u${replication_user} -p${MYSQL_ROOT_PASSWORD} -h${primary}"
189-
retry 10 ${mysqlshell} -e "cluster = dba.getCluster(); cluster.rescan({addInstances:['${report_host}:3306'],interactive:false})"
190189
out=($(${mysqlshell} --sql -e "SELECT member_host FROM performance_schema.replication_group_members;"))
191190

192191
for host in "${out[@]}"; do
@@ -197,6 +196,11 @@ function make_sure_instance_join_in_cluster() {
197196
done
198197
}
199198

199+
function make_sure_instance_join_in_cluster() {
200+
local mysqlshell="mysqlsh -u${replication_user} -p${MYSQL_ROOT_PASSWORD} -h${primary}"
201+
retry 10 ${mysqlshell} -e "cluster = dba.getCluster(); cluster.rescan({addInstances:['${report_host}:3306'],interactive:false})"
202+
}
203+
200204
function rejoin_in_cluster() {
201205
local mysqlshell="mysqlsh -u${replication_user} -p${MYSQL_ROOT_PASSWORD} -h${primary}"
202206
${mysqlshell} -e "cluster=dba.getCluster(); cluster.rejoinInstance('${replication_user}@${report_host}',{password:'${MYSQL_ROOT_PASSWORD}'})"
@@ -225,6 +229,7 @@ function start_mysqld_in_background() {
225229
pid=$!
226230
log "INFO" "The process id of mysqld is '$pid'"
227231
}
232+
228233
replication_user=repl
229234

230235
start_mysqld_in_background
@@ -275,13 +280,20 @@ while true; do
275280
if [[ $desired_func == "join_in_cluster" ]]; then
276281
select_primary
277282
join_in_cluster
278-
make_sure_instance_join_in_cluster
283+
check_instance_joined_in_cluster
284+
if [[ "$joined_in_cluster" == "0" ]]; then
285+
make_sure_instance_join_in_cluster
286+
fi
279287
fi
280288

281289
if [[ $desired_func == "rejoin_in_cluster" ]]; then
282290
select_primary
283291
rejoin_in_cluster
284-
make_sure_instance_join_in_cluster
292+
check_instance_joined_in_cluster
293+
if [[ "$joined_in_cluster" == "0" ]]; then
294+
make_sure_instance_join_in_cluster
295+
fi
296+
check_instance_joined_in_cluster
285297
if [[ "$joined_in_cluster" == "0" ]]; then
286298
join_in_cluster
287299
fi

scripts/run_read_only.sh

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
#!/usr/bin/env bash
2+
3+
# BASE_NAME = name of the StatefulSet (same as the name of CRD)
4+
# HOSTNAME = name of the host | name of the pod (set by k8s)
5+
# primaryHost = primary dns of the source
6+
# hostToConnect = source dns
7+
8+
env | sort | grep "POD\|HOST\|NAME"
9+
10+
args=$@
11+
12+
USER="$MYSQL_ROOT_USERNAME"
13+
PASSWORD="$MYSQL_ROOT_PASSWORD"
14+
localhost=127.0.0.1
15+
16+
function timestamp() {
17+
date +"%Y/%m/%d %T"
18+
}
19+
20+
function log() {
21+
local type="$1"
22+
local msg="$2"
23+
echo "$(timestamp) [$script_name] [$type] $msg"
24+
}
25+
26+
function retry {
27+
local retries="$1"
28+
shift
29+
30+
local count=0
31+
local wait=1
32+
until "$@"; do
33+
exit="$?"
34+
if [ $count -lt $retries ]; then
35+
log "INFO" "Attempt $count/$retries. Command exited with exit_code: $exit. Retrying after $wait seconds..."
36+
sleep $wait
37+
else
38+
log "INFO" "Command failed in all $retries attempts with exit_code: $exit. Stopping trying any further...."
39+
return $exit
40+
fi
41+
count=$(($count + 1))
42+
done
43+
return 0
44+
}
45+
46+
echo $BASE_NAME
47+
svr_id=$(($(echo -n "${HOSTNAME}" | sed -e "s/${BASE_NAME}-//g") + 11))
48+
log "INFO" "server_id = $svr_id"
49+
50+
log "INFO" "Storing default mysqld config into /etc/mysql/my.cnf"
51+
52+
mkdir -p /etc/mysql/read_only.conf.d/
53+
echo "!includedir /etc/mysql/read_only.conf.d/" >>/etc/mysql/my.cnf
54+
55+
cat >>/etc/mysql/read_only.conf.d/read.cnf <<EOL
56+
[mysqld]
57+
#default-authentication-plugin=mysql_native_password
58+
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
59+
# General replication settings
60+
gtid_mode = ON
61+
enforce_gtid_consistency = ON
62+
# Host specific replication configuration
63+
server_id = ${svr_id}
64+
bind-address = "0.0.0.0"
65+
EOL
66+
67+
export pid
68+
69+
function start_mysqld_in_background() {
70+
log "INFO" "Starting mysql server with 'docker-entrypoint.sh mysqld ${args[@]}'..."
71+
docker-entrypoint.sh mysqld $args &
72+
pid=$!
73+
log "INFO" "The process id of mysqld is '$pid'"
74+
}
75+
76+
reading_first_time=0
77+
function install_clone_plugin() {
78+
log "INFO" "Checking whether clone plugin on host $1 is installed or not...."
79+
local mysql="$mysql_header --host=$1"
80+
81+
# At first, ensure that the command executes without any error. Then, run the command again and extract the output.
82+
retry 120 ${mysql} -N -e 'SHOW PLUGINS;' | grep clone
83+
out=$(${mysql} -N -e 'SHOW PLUGINS;' | grep clone)
84+
if [[ -z "$out" ]]; then
85+
log "INFO" "Clone plugin is not installed. Installing the plugin..."
86+
retry 120 ${mysql} -e "INSTALL PLUGIN clone SONAME 'mysql_clone.so';"
87+
reading_first_time=1
88+
log "INFO" "Clone plugin successfully installed"
89+
else
90+
log "INFO" "Already clone plugin is installed"
91+
fi
92+
}
93+
94+
# wait for mysql daemon be running (alive)
95+
function wait_for_mysqld_running() {
96+
local mysql="$mysql_header --host=$localhost"
97+
98+
for i in {900..0}; do
99+
out=$(mysql -N -e "select 1;" 2>/dev/null)
100+
log "INFO" "Attempt $i: Pinging '$report_host' has returned: '$out'...................................."
101+
if [[ "$out" == "1" ]]; then
102+
break
103+
fi
104+
105+
echo -n .
106+
sleep 1
107+
done
108+
109+
if [[ "$i" == "0" ]]; then
110+
echo ""
111+
log "ERROR" "Server ${report_host} failed to start in 900 seconds............."
112+
exit 1
113+
fi
114+
log "INFO" "mysql daemon is ready to use......."
115+
}
116+
117+
function start_read_replica() {
118+
#stop_slave
119+
local mysql="$mysql_header --host=$localhost"
120+
121+
if [[ "$source_ssl" == "true" ]]; then
122+
ssl_config=",SOURCE_SSL=1,SOURCE_SSL_CA = '/etc/mysql/server/certs/ca.crt'"
123+
require_SSL="REQUIRE SSL"
124+
fi
125+
echo $ssl_config
126+
out=$($mysql_header -e "CHANGE MASTER TO MASTER_HOST = '$hostToConnect',MASTER_PORT = 3306,MASTER_USER = '$USER',MASTER_PASSWORD = '$PASSWORD',MASTER_AUTO_POSITION = 1 $ssl_config;")
127+
echo $out
128+
sleep 1
129+
out=$($mysql_header -e "start slave;")
130+
echo $out
131+
}
132+
133+
# create mysql client with user exported in mysql_header and export password
134+
# this is to bypass the warning message for using password
135+
start_mysqld_in_background
136+
137+
export mysql_header="mysql -u ${USER} --port=3306"
138+
export MYSQL_PWD=${PASSWORD}
139+
140+
wait_for_mysqld_running
141+
142+
install_clone_plugin "localhost"
143+
144+
install_clone_plugin "$primaryHost"
145+
146+
while true; do
147+
kill -0 $pid
148+
exit="$?"
149+
if [[ "$exit" == "0" ]]; then
150+
echo "mysqld process is running"
151+
else
152+
echo "need to start mysqld and wait_for_mysqld_running"
153+
start_mysqld_in_background
154+
wait_for_mysqld_running
155+
fi
156+
157+
if [[ "$reading_first_time" == "1" ]]; then
158+
159+
$mysql_header -e "SET GLOBAL clone_valid_donor_list='$primaryHost:3306';"
160+
error_message=$(${mysql_header} -e "CLONE INSTANCE FROM 'root'@'$primaryHost':3306 IDENTIFIED BY '$PASSWORD' $require_SSL;" 2>&1)
161+
# https://dev.mysql.com/doc/refman/8.0/en/clone-plugin-remote.html#:~:text=ERROR%203707%20(HY000)%3A%20Restart,not%20managed%20by%20supervisor%20process).&text=It%20means%20that%20the%20recipient,after%20the%20data%20is%20cloned.
162+
log "INFO" "Clone error message: $error_message"
163+
fi
164+
165+
start_read_replica
166+
log "INFO" "waiting for mysql process id = $pid"
167+
reading_first_time=0
168+
wait $pid
169+
done

0 commit comments

Comments
 (0)