-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstd-replication-setup.sh
More file actions
executable file
·323 lines (292 loc) · 13.1 KB
/
std-replication-setup.sh
File metadata and controls
executable file
·323 lines (292 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
#!/usr/bin/env bash
env | sort | grep "POD\|HOST\|NAME\|SSL"
args=$@
NAMESPACE="$POD_NAMESPACE"
USER="$MYSQL_ROOT_USERNAME"
PASSWORD="$MYSQL_ROOT_PASSWORD"
function timestamp() {
date +"%Y/%m/%d %T"
}
function log() {
local type="$1"
local msg="$2"
echo "$(timestamp) [$script_name] [$type] $msg"
}
function retry {
local retries="$1"
shift
local count=0
local wait=1
until "$@"; do
exit="$?"
if [ $count -lt $retries ]; then
log "INFO" "Attempt $count/$retries. Command exited with exit_code: $exit. Retrying after $wait seconds..."
sleep $wait
else
log "INFO" "Command failed in all $retries attempts with exit_code: $exit. Stopping trying any further...."
return $exit
fi
count=$(($count + 1))
done
return 0
}
report_host="$HOSTNAME.$GOVERNING_SERVICE_NAME.$POD_NAMESPACE.svc"
echo "report_host = $report_host"
localhost="127.0.0.1"
# wait for mysql daemon be running (alive)
function wait_for_mysqld_running() {
local mysql="$mysql_header --host=$localhost"
for i in {900..0}; do
out=$(${mysql} -N -e "select 1;" 2>/dev/null)
log "INFO" "Attempt $i: Pinging '$report_host' has returned: '$out'...................................."
if [[ "$out" == "1" ]]; then
break
fi
echo -n .
sleep 1
done
if [[ "$i" == "0" ]]; then
echo ""
log "ERROR" "Server ${report_host} failed to start in 900 seconds............."
exit 1
fi
log "INFO" "mysql daemon is ready to use......."
}
joining_for_first_time=1
function alter_user() {
local mysql="$mysql_header --host=$localhost"
local ssl_require=""
local user="$1"
if [[ "${REQUIRE_SSL:-}" == "TRUE" ]]; then
ssl_require="REQUIRE SSL"
else
ssl_require="REQUIRE NONE"
fi
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;ALTER USER '$user'@'%' $ssl_require;"
}
function create_replication_user() {
# https://mariadb.com/kb/en/setting-up-replication/
log "INFO" "Checking whether replication user exist or not......"
local mysql="$mysql_header --host=$localhost"
# At first, ensure that the command executes without any error. Then, run the command again and extract the output.
retry 120 ${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='repl';" | awk '{print$1}'
out=$(${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='repl';" | awk '{print$1}')
# if the user doesn't exist, crete new one.
if [[ "$out" -eq "0" ]]; then
joining_for_first_time=0
log "INFO" "Replication user not found. Creating new replication user........"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;CREATE USER 'repl'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;FLUSH PRIVILEGES;"
else
log "INFO" "Replication user exists. Skipping creating new one......."
fi
alter_user "repl"
}
function create_maxscale_user() {
log "INFO" "Checking whether maxscale user exist or not......"
local mysql="$mysql_header --host=$localhost"
# At first, ensure that the command executes without any error. Then, run the command again and extract the output.
retry 120 ${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='maxscale';" | awk '{print$1}'
out=$(${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='maxscale';" | awk '{print$1}')
# if the user doesn't exist, crete new one.
if [[ "$out" -eq "0" ]]; then
log "INFO" "Maxscale user not found. Creating new maxscale user........"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;CREATE USER 'maxscale'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.user TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.db TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.tables_priv TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.columns_priv TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.procs_priv TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.proxies_priv TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT ON mysql.roles_mapping TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SHOW DATABASES ON *.* TO 'maxscale'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;FLUSH PRIVILEGES;"
else
log "INFO" "Maxscale user exists. Skipping creating new one......."
fi
alter_user "maxscale"
}
#//TODO:
#function create_maxscale_confsync_user() {
# log "INFO" "Checking whether maxscale user exist or not......"
# local mysql="$mysql_header --host=$localhost"
# # At first, ensure that the command executes without any error. Then, run the command again and extract the output.
# retry 120 ${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='maxscale_confsync';" | awk '{print$1}'
# out=$(${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='maxscale_confsync';" | awk '{print$1}')
# # if the user doesn't exist, crete new one.
# if [[ "$out" -eq "0" ]]; then
# log "INFO" "maxscale_confsync user not found. Creating new maxscale_confsync user........"
# retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;CREATE USER 'maxscale_confsync'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';"
# retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SELECT, INSERT, UPDATE, CREATE ON mysql.maxscale_config TO maxscale_confsync@'%';"
# retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;FLUSH PRIVILEGES;"
# else
# log "INFO" "maxscale_confsync user exists. Skipping creating new one......."
# fi
#}
function create_monitor_user() {
log "INFO" "Checking whether monitor user exist or not......"
local mysql="$mysql_header --host=$localhost"
# At first, ensure that the command executes without any error. Then, run the command again and extract the output.
retry 120 ${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='monitor_user';" | awk '{print$1}'
out=$(${mysql} -N -e "select count(host) from mysql.user where mysql.user.user='monitor_user';" | awk '{print$1}')
# if the user doesn't exist, crete new one.
if [[ "$out" -eq "0" ]]; then
log "INFO" "Monitor user not found. Creating new monitor user........"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;CREATE USER 'monitor_user'@'%' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD';"
#mariadb 10.6+ change SUPER-> READ_ONLY ADMIN, REPLICATION CLIENT> SLAVE MONITOR
if [[ "$(echo -e "1:10.7\n$MARIADB_VERSION" | sort -V | tail -n1)" == "$MARIADB_VERSION" ]]; then
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT READ_ONLY ADMIN, RELOAD on *.* to 'monitor_user'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SLAVE MONITOR ON *.* TO 'monitor_user'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT BINLOG ADMIN, REPLICATION MASTER ADMIN, REPLICATION SLAVE ADMIN ON *.* TO 'monitor_user'@'%';"
else
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT SUPER, RELOAD on *.* to 'monitor_user'@'%';"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;GRANT REPLICATION CLIENT on *.* to 'monitor_user'@'%';"
fi
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=0;FLUSH PRIVILEGES;"
else
log "INFO" "Monitor user exists. Skipping creating new one......."
fi
alter_user "monitor_user"
}
function bootstrap_cluster() {
echo "this is master node"
local mysql="$mysql_header --host=$localhost"
retry 120 ${mysql} -N -e "SET SQL_LOG_BIN=1;"
}
function join_to_master_by_current_pos() {
# member try to join into the existing group as fresh install, datadir is clean and no backup is restored
log "INFO" "The replica, ${report_host} is joining to master node ${master}..."
local mysql="$mysql_header --host=$localhost"
log "INFO" "Joining to master with gtid current_pos.."
retry 20 ${mysql} -N -e "STOP SLAVE;"
retry 20 ${mysql} -N -e "RESET SLAVE ALL;"
local ssl_options=""
if [[ "${REQUIRE_SSL:-}" == "TRUE" ]]; then
ssl_options=", MASTER_SSL=1, MASTER_SSL_CA='/etc/mysql/certs/server/ca.crt'"
log "INFO" "Configuring replication with TLS enabled"
else
log "INFO" "Configuring replication without TLS"
fi
retry 20 ${mysql} -N -e "CHANGE MASTER TO MASTER_HOST='$master', MASTER_USER='repl', MASTER_PASSWORD='$MYSQL_ROOT_PASSWORD' $ssl_options, MASTER_USE_GTID=current_pos;"
retry 20 ${mysql} -N -e "START SLAVE;"
joining_for_first_time=0
echo "end join to master node by gtid current_pos"
}
function join_to_master_by_slave_pos() {
# member try to join into the existing group as old instance
log "INFO" "The replica, ${report_host} is joining to master node ${master} by slave_pos..."
local mysql="$mysql_header --host=$localhost"
log "INFO" "Resetting binlog,gtid and set gtid_slave_pos.."
retry 20 ${mysql} -N -e "STOP SLAVE;"
retry 20 ${mysql} -N -e "RESET SLAVE ALL;"
if [ $joining_for_first_time -eq 1 ]; then
retry 20 ${mysql} -N -e "SET GLOBAL gtid_slave_pos = '$gtid';"
fi
if [[ "${REQUIRE_SSL:-}" == "TRUE" ]]; then
ssl_options=", MASTER_SSL=1, MASTER_SSL_CA='/etc/mysql/certs/server/ca.crt'"
log "INFO" "Configuring replication with TLS enabled"
else
log "INFO" "Configuring replication without TLS"
fi
retry 20 ${mysql} -N -e "CHANGE MASTER TO MASTER_HOST='$master', MASTER_USER='repl', MASTER_PASSWORD='$MYSQL_ROOT_PASSWORD' $ssl_options, MASTER_USE_GTID=slave_pos;"
retry 20 ${mysql} -N -e "START SLAVE;"
joining_for_first_time=0
echo "end join to master node by gtid slave_pos"
}
export pid
function start_mysqld_in_background() {
log "INFO" "Starting MySQL server with docker-entrypoint.sh mysqld $args..."
process=""
if [[ $MARIADB_VERSION == "1:11"* ]]; then
docker-entrypoint.sh mariadbd $args &
process="mariadbd"
else
docker-entrypoint.sh mysqld $args &
process="mysqld"
fi
pid=$!
log "INFO" "The process ID of $process is '$pid'"
}
backup_restored=0
if [ -f "/scripts/receive_backup.txt" ]; then
echo "Waiting for the master to start streaming backup data..."
echo "$POD_IP" >/scripts/backup_receive_started.txt
while true; do
socat -u TCP-LISTEN:3307 STDOUT | mbstream -x -C /var/lib/mysql
if [ $? -eq 0 ]; then
log "INFO" "Data restore successful."
break
else
log "INFO" "Data restore failed."
rm -rf /var/lib/mysql
fi
done
mariabackup --prepare --target-dir=/var/lib/mysql
rm /scripts/backup_receive_started.txt
backup_restored=1
rm /scripts/receive_backup.txt
fi
start_mysqld_in_background
if [[ "${REQUIRE_SSL:-}" == "TRUE" ]]; then
export mysql_header="mariadb -u ${USER} --port=3306 --ssl-ca=/etc/mysql/certs/server/ca.crt --ssl-cert=/etc/mysql/certs/server/tls.crt --ssl-key=/etc/mysql/certs/server/tls.key"
else
export mysql_header="mariadb -u ${USER} --port=3306"
fi
export MYSQL_PWD=${PASSWORD}
# wait for mysqld to be ready
wait_for_mysqld_running
# ensure replication user
create_replication_user
# ensure maxscale user
create_maxscale_user
# ensure monitor user
create_monitor_user
#TODO:
# ensure maxscale_confsync user
#create_maxscale_confsync_user
while true; do
kill -0 $pid
exit="$?"
if [[ "$exit" == "0" ]]; then
echo "mysqld process is running"
else
echo "need start mysqld and wait_for_mysqld_running"
start_mysqld_in_background
wait_for_mysqld_running
fi
# wait for the script copied by coordinator
while [ ! -f "/scripts/signal.txt" ]; do
log "WARNING" "signal is not present yet!"
sleep 1
done
desired_func=$(cat /scripts/signal.txt)
rm -rf /scripts/signal.txt
log "INFO" "going to execute $desired_func"
if [[ $desired_func == "create_cluster" ]]; then
bootstrap_cluster
fi
if [[ $desired_func == "join_to_master" ]]; then
# wait for the script copied by coordinator
while [ ! -f "/scripts/master.txt" ]; do
log "WARNING" "master detector file isn't present yet!"
sleep 1
done
master=$(cat /scripts/master.txt)
rm -rf /scripts/master.txt
if [[ $backup_restored -eq 0 ]]; then
join_to_master_by_current_pos
else
while [ ! -f "/scripts/gtid.txt" ]; do
log "WARNING" "gtid detector file isn't present yet!"
sleep 1
done
gtid=$(cat /scripts/gtid.txt)
echo "master replica's current gtid position is $gtid"
rm -rf /scripts/gtid.txt
join_to_master_by_slave_pos
fi
fi
log "INFO" "waiting for mysql process id = $pid"
wait $pid
done