Skip to content

Commit 79423c5

Browse files
committed
feat: use Docker containers in create snapshot script (postgres-ai#70)
1 parent 01871fd commit 79423c5

File tree

1 file changed

+39
-15
lines changed

1 file changed

+39
-15
lines changed

scripts/create_zfs_snapshot.sh

+39-15
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,12 @@ clone_full_name="${zfs_pool}/${clone_name}"
2828
clone_dir="${mount_dir}/${clone_name}"
2929
# Directory of PGDATA in the clone mount.
3030
clone_pgdata_dir="${clone_dir}${pgdata_subdir}"
31+
# Directory of PGDATA in the promote container.
32+
container_pgdata_dir="/var/lib/postgresql/pgdata"
3133

3234
# Postgres configuration.
3335
# Port on which Postgres will be started using clone's PGDATA.
34-
clone_port=${CLONE_PORT:-6999}
35-
pg_bin_dir=${PG_BIN_DIR:-"/usr/lib/postgresql/12/bin"}
36+
clone_port=${CLONE_PORT:-5432}
3637
pg_sock_dir=${PG_SOCK_DIR:-"/var/run/postgresql"}
3738
pg_username=${PGUSERNAME:-"postgres"}
3839
# Set password with PGPASSWORD env.
@@ -108,11 +109,24 @@ echo "host all all 0.0.0.0/0 md5" >> ${clone_pgdata_dir}/pg_hba.conf
108109
echo "" > ${clone_pgdata_dir}/pg_ident.conf
109110
SH
110111

111-
${sudo_cmd} ${pg_bin_dir}/pg_ctl \
112-
-D "${clone_pgdata_dir}" \
113-
-o "-p ${clone_port} -c 'shared_buffers=4096'" \
114-
-W \
115-
start
112+
echo >&2 "Run container"
113+
114+
# Make sure that PGDATA has correct permissions.
115+
user_owner=$(sudo ls -ld ${clone_pgdata_dir}/PG_VERSION | awk '{print $3}')
116+
group_owner=$(sudo ls -ld ${clone_pgdata_dir}/PG_VERSION | awk '{print $4}')
117+
sudo chown -R ${user_owner}:${group_owner} ${clone_pgdata_dir}
118+
119+
container_name="dblab_promote"
120+
sudo docker run \
121+
--name ${container_name} \
122+
--label dblab_control \
123+
--restart on-failure \
124+
--volume ${clone_pgdata_dir}:${container_pgdata_dir} \
125+
--env PGDATA=${container_pgdata_dir} \
126+
--user postgres \
127+
--detach \
128+
postgres:${pg_ver}-alpine
129+
116130

117131
# Now we are going to wait until we can connect to the server.
118132
# If it was a replica, it may take a while..
@@ -121,7 +135,7 @@ ${sudo_cmd} ${pg_bin_dir}/pg_ctl \
121135

122136
failed=true
123137
for i in {1..1000}; do
124-
if [[ $(${pg_bin_dir}/psql -p $clone_port -U ${pg_username} -d ${pg_db} -h ${pg_sock_dir} -XAtc 'select pg_is_in_recovery()') == "t" ]]; then
138+
if [[ $(sudo docker exec ${container_name} psql -p ${clone_port} -U ${pg_username} -d ${pg_db} -h ${pg_sock_dir} -XAtc 'select 1') == "1" ]]; then
125139
failed=false
126140
break
127141
fi
@@ -130,19 +144,24 @@ for i in {1..1000}; do
130144
done
131145

132146
if $failed; then
133-
>&2 echo "Failed to start Postgres (in standby mode)"
147+
echo >&2 "Failed to start Postgres (in standby mode)"
148+
sudo docker rm --force ${container_name}
134149
exit 1
135150
fi
136151

152+
should_be_promoted=$(sudo docker exec ${container_name} psql -p ${clone_port} -U ${pg_username} -d ${pg_db} -h ${pg_sock_dir} -XAtc 'select pg_is_in_recovery()')
153+
137154
# Save data state timestamp.
138155
# - if we had a replica, we can use `pg_last_xact_replay_timestamp()`,
139156
# - if it is a master initially, the DB state timestamp must be provided by user in unix time format.
140157
if [[ ! -z ${DATA_STATE_AT+x} ]]; then
141158
# For testing, use:
142159
# DATA_STATE_AT=$(TZ=UTC date '+%Y%m%d%H%M%S')
143160
data_state_at="${DATA_STATE_AT}"
161+
elif [[ $should_be_promoted != "t" ]]; then
162+
data_state_at=$(TZ=UTC date '+%Y%m%d%H%M%S')
144163
else
145-
data_state_at=$(${pg_bin_dir}/psql \
164+
data_state_at=$(sudo docker exec ${container_name} psql \
146165
--set ON_ERROR_STOP=on \
147166
-p ${clone_port} \
148167
-U ${pg_username} \
@@ -153,11 +172,14 @@ else
153172
fi
154173

155174
# Promote to the master. Again, it may take a while.
156-
${sudo_cmd} ${pg_bin_dir}/pg_ctl -D ${clone_pgdata_dir} -W promote
175+
if [[ $should_be_promoted == "t" ]]; then
176+
echo >&2 "Promote"
177+
sudo docker exec ${container_name} pg_ctl -D ${container_pgdata_dir} -W promote
178+
fi
157179

158180
failed=true
159181
for i in {1..1000}; do
160-
if [[ $(${pg_bin_dir}/psql -p ${clone_port} -U ${pg_username} -d ${pg_db} -h ${pg_sock_dir} -XAtc 'select pg_is_in_recovery()') == "f" ]]; then
182+
if [[ $(sudo docker exec ${container_name} psql -p ${clone_port} -U ${pg_username} -d ${pg_db} -h ${pg_sock_dir} -XAtc 'select pg_is_in_recovery()') == "f" ]]; then
161183
failed=false
162184
break
163185
fi
@@ -166,7 +188,8 @@ for i in {1..1000}; do
166188
done
167189

168190
if $failed; then
169-
>&2 echo "Failed to promote Postgres to master"
191+
echo >&2 "Failed to promote Postgres to master"
192+
sudo docker rm --force ${container_name}
170193
exit 1
171194
fi
172195

@@ -181,8 +204,7 @@ fi
181204
################################################################################
182205

183206
# Finally, stop Postgres and create the base snapshot ready to be used for thin provisioning
184-
${sudo_cmd} ${pg_bin_dir}/pg_ctl -D ${clone_pgdata_dir} -w stop
185-
# todo: check that it's stopped, similiraly as above
207+
sudo docker stop ${container_name}
186208

187209
${sudo_cmd} rm -rf ${clone_pgdata_dir}/pg_log
188210

@@ -193,5 +215,7 @@ sudo zfs set dblab:datastateat="${data_state_at}" ${clone_full_name}@${snapshot_
193215

194216
${sudo_cmd} rm -rf /tmp/trigger_${clone_port}
195217

218+
sudo docker rm ${container_name}
219+
196220
# Return to previous working directory.
197221
cd -

0 commit comments

Comments
 (0)