cpflow 6.0.0.rc.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.agents/agent-workflow.yml +16 -38
- data/.agents/bin/README.md +7 -8
- data/.agents/legacy-workflow-policy.yml +11 -0
- data/.agents/shaka.md +20 -0
- data/.agents/trusted-actions.yml +12 -0
- data/.coderabbit.yaml +1 -0
- data/.github/actions/cpflow-build-docker-image/action.yml +153 -22
- data/.github/actions/cpflow-delete-control-plane-app/delete-app.sh +3 -0
- data/.github/actions/cpflow-preview-promotion/action.yml +82 -0
- data/.github/actions/cpflow-preview-promotion/preview-promotion.sh +90 -0
- data/.github/workflows/cpflow-deploy-review-app.yml +13 -1
- data/.github/workflows/cpflow-deploy-staging.yml +12 -1
- data/.github/workflows/cpflow-promote-staging-to-production.yml +128 -9
- data/.github/workflows/rspec.yml +24 -0
- data/AGENTS.md +18 -3
- data/CHANGELOG.md +18 -3
- data/CONTRIBUTING.md +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/docs/ai-github-flow-prompt.md +2 -2
- data/docs/ci-automation.md +178 -14
- data/docs/commands.md +26 -13
- data/docs/postgres-review-apps.md +90 -0
- data/docs/postgres.md +233 -375
- data/docs/secrets-and-env-values.md +42 -0
- data/docs/sidebars.ts +1 -0
- data/lib/command/ai_github_flow_prompt.rb +2 -2
- data/lib/command/apply_template.rb +36 -4
- data/lib/command/base.rb +56 -3
- data/lib/command/delete.rb +174 -4
- data/lib/command/deploy_image.rb +6 -0
- data/lib/command/generate.rb +247 -3
- data/lib/command/generate_github_actions.rb +7 -1
- data/lib/command/setup_app.rb +92 -10
- data/lib/command/update_github_actions.rb +81 -43
- data/lib/core/config.rb +73 -0
- data/lib/core/controlplane.rb +22 -2
- data/lib/core/controlplane_api.rb +28 -2
- data/lib/core/controlplane_api_direct.rb +17 -0
- data/lib/core/disposable_postgres_helpers.rb +167 -0
- data/lib/core/doctor_service.rb +7 -0
- data/lib/core/github_flow_readiness/checks.rb +2 -1
- data/lib/core/github_flow_readiness_service.rb +4 -0
- data/lib/core/repo_introspection.rb +112 -2
- data/lib/cpflow/version.rb +1 -1
- data/lib/generator_templates/.dockerignore +16 -0
- data/lib/generator_templates/Dockerfile +9 -5
- data/lib/generator_templates/entrypoint.sh +2 -0
- data/lib/generator_templates/templates/postgres.yml +9 -0
- data/lib/generator_templates_sqlite/controlplane.yml +2 -1
- data/lib/generator_templates_sqlite/release_script.sh +1 -1
- data/lib/generator_templates_sqlite/templates/rails.yml +2 -1
- data/lib/github_flow_templates/.github/cpflow-help.md +39 -12
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-review-app.yml +1 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-deploy-staging.yml +1 -0
- data/lib/github_flow_templates/.github/workflows/cpflow-promote-staging-to-production.yml +128 -9
- data/lib/github_flow_templates/bin/pin-cpflow-github-ref +37 -13
- data/lib/github_flow_templates/bin/test-cpflow-github-flow +62 -43
- metadata +11 -3
data/docs/postgres.md
CHANGED
|
@@ -1,447 +1,305 @@
|
|
|
1
|
-
# Migrating
|
|
1
|
+
# Migrating PostgreSQL from Heroku to RDS
|
|
2
|
+
|
|
3
|
+
This guide covers a database move from Heroku Postgres to AWS RDS using dump and
|
|
4
|
+
restore or Bucardo replication. Rehearse the chosen method with your database before
|
|
5
|
+
scheduling a production cutover.
|
|
6
|
+
|
|
7
|
+
For other PostgreSQL tasks, use these guides:
|
|
8
|
+
|
|
9
|
+
- [PostgreSQL for disposable review apps](./postgres-review-apps.md): create and
|
|
10
|
+
clean up review-app helpers.
|
|
11
|
+
- [Private RDS/Aurora networking](./rds-private-networking.md): connect Control Plane
|
|
12
|
+
workloads through the Cloud Wormhole agent.
|
|
13
|
+
- [Control Plane PostgreSQL Template Catalog](https://shakadocs.controlplane.com/template-catalog/templates/postgres):
|
|
14
|
+
run PostgreSQL on Control Plane with persistent storage and optional backups.
|
|
15
|
+
|
|
16
|
+
## Choose a migration method
|
|
17
|
+
|
|
18
|
+
| Method | Application downtime | Main tradeoff |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Dump and restore | Writers stay stopped through the final dump and restore | Fewer moving parts; downtime grows with database size |
|
|
21
|
+
| Bucardo replication | Writers stop for the final catch-up and connection switch | More setup; the initial copy runs while the app stays online |
|
|
22
|
+
|
|
23
|
+
Bucardo uses triggers to copy data and replicate later changes. It needs permission
|
|
24
|
+
to install its objects on the source database. Confirm that your Heroku plan and
|
|
25
|
+
target database support the required permissions before choosing it.
|
|
26
|
+
|
|
27
|
+
Do not treat example timings as a downtime guarantee. Measure backup, restore, and
|
|
28
|
+
replication performance during a rehearsal. For background on the trigger-based
|
|
29
|
+
approach, see [AWS's Bucardo migration example](https://aws.amazon.com/blogs/database/migrating-legacy-postgresql-databases-to-amazon-rds-or-aurora-postgresql-using-bucardo/).
|
|
30
|
+
|
|
31
|
+
### Historical large-database timings
|
|
32
|
+
|
|
33
|
+
The original guide recorded these approximate timings for a 1 TB database. It did
|
|
34
|
+
not record enough environment details to reproduce the results. Use them to
|
|
35
|
+
understand the difference between elapsed migration time and downtime, not to
|
|
36
|
+
estimate your migration:
|
|
37
|
+
|
|
38
|
+
| Method | Initial transfer | Application downtime |
|
|
39
|
+
| --- | --- | --- |
|
|
40
|
+
| Dump and restore | 2.5 hours to create a backup, 0.5 hours to download it, and 13 hours to restore with four workers | About 16 hours |
|
|
41
|
+
| Bucardo | About 1.5 days for the initial copy with one worker, while the source application remained online | About 1–2 minutes for the database switch |
|
|
42
|
+
|
|
43
|
+
Copy throughput and the source write rate determine how quickly replication can
|
|
44
|
+
catch up. More instance capacity does not automatically make a single-worker copy
|
|
45
|
+
parallel. Measure the initial copy and final catch-up separately during rehearsal,
|
|
46
|
+
including application shutdown, restart, and readiness checks in the downtime budget.
|
|
47
|
+
|
|
48
|
+
## Prepare the databases and network
|
|
49
|
+
|
|
50
|
+
Before either migration method:
|
|
51
|
+
|
|
52
|
+
1. Inventory database versions, extensions, storage, and every application or job
|
|
53
|
+
that writes to the database.
|
|
54
|
+
2. Create the RDS database with compatible schema support and enough storage for
|
|
55
|
+
the data and expected growth.
|
|
56
|
+
3. Establish connectivity from the migration host and the application's eventual
|
|
57
|
+
deployment location. Prefer private networking; see the
|
|
58
|
+
[RDS/Aurora networking guide](./rds-private-networking.md).
|
|
59
|
+
4. Restrict security groups to the hosts and ports that need access. If temporary
|
|
60
|
+
public access is necessary, restrict it to the migration host and remove it afterward.
|
|
61
|
+
5. Take a source backup and agree on validation, cutover, and rollback criteria.
|
|
62
|
+
|
|
63
|
+
RDS allocated storage cannot be reduced in place. Size it for the initial load,
|
|
64
|
+
indexes, and growth before starting; storage autoscaling may not keep up with a
|
|
65
|
+
large bulk load. Further storage changes must wait for storage optimization to
|
|
66
|
+
finish and are subject to modification limits. See
|
|
67
|
+
[RDS storage autoscaling limitations](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PIOPS.Autoscaling.html#autoscaling-limitations).
|
|
68
|
+
|
|
69
|
+
Choose the target database region based on application latency as well as migration
|
|
70
|
+
throughput. Test the network path while the application still runs on Heroku and
|
|
71
|
+
after its deployment moves. If the application already supports separate read and
|
|
72
|
+
write connections, a temporary read replica near the application may reduce read
|
|
73
|
+
latency. Writes still reach the primary, and reads must tolerate replication lag.
|
|
74
|
+
Rehearse this extra topology before relying on it; see
|
|
75
|
+
[RDS PostgreSQL read replicas](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_PostgreSQL.Replication.ReadReplicas.html).
|
|
76
|
+
|
|
77
|
+
For Bucardo, also check that each replicated table has a primary key. Freeze schema
|
|
78
|
+
changes from the schema copy through cutover. Plan separately for objects Bucardo
|
|
79
|
+
does not replicate, including materialized views.
|
|
80
|
+
|
|
81
|
+
### Set up a migration host
|
|
82
|
+
|
|
83
|
+
Use a temporary host, such as an EC2 instance, that can reach both databases. Choose
|
|
84
|
+
its region, capacity, and disk space based on measured latency and copy requirements.
|
|
85
|
+
Restrict SSH access and protect the private key:
|
|
2
86
|
|
|
3
|
-
> **Networking note.** This guide is written against a *publicly reachable* RDS instance for simplicity of the
|
|
4
|
-
> Bucardo migration steps. For production, you almost certainly want RDS/Aurora in private subnets reached from
|
|
5
|
-
> Control Plane workloads via the Cloud Wormhole agent — see
|
|
6
|
-
> [Connecting Control Plane workloads to a private AWS RDS/Aurora database](./rds-private-networking.md). The
|
|
7
|
-
> Bucardo migration here still works against a private RDS once the network path is set up.
|
|
8
|
-
|
|
9
|
-
If you are replacing Heroku Postgres or another pre-provisioned database service, also review the
|
|
10
|
-
[Control Plane PostgreSQL Template Catalog page](https://shakadocs.controlplane.com/template-catalog/templates/postgres). The
|
|
11
|
-
catalog template covers a single-instance PostgreSQL workload with persistent storage, optional PgBouncer, and optional
|
|
12
|
-
scheduled backups.
|
|
13
|
-
|
|
14
|
-
One of the biggest problems that will appear when moving from Heroku infrastructure is migrating the database. And
|
|
15
|
-
despite it being rather easy if done between Heroku-hosted databases or non-Heroku-hosted databases (as Postgres has
|
|
16
|
-
tools to do that naturally) it is not easily possible between Heroku and anything outside Heroku,
|
|
17
|
-
**as Heroku doesn't allow setting up WAL replication for Postgres**. Period. No... any... replication outside of
|
|
18
|
-
Heroku infrastructure for Postgres.
|
|
19
|
-
|
|
20
|
-
Previously, it was said to be possible to ask Heroku support to manually set up WAL log shipping, but they
|
|
21
|
-
don't want to do that anymore. Which leaves only 2 options:
|
|
22
|
-
|
|
23
|
-
### Option A: dump and restore way
|
|
24
|
-
|
|
25
|
-
Nothing problematic here in general **if you can withstand long application maintenance time**.
|
|
26
|
-
You basically need to:
|
|
27
|
-
|
|
28
|
-
1. enable maintenance
|
|
29
|
-
2. stop the application completely and wait for all the database writes to finish
|
|
30
|
-
3. dump database on Heroku
|
|
31
|
-
4. restore the database on RDS
|
|
32
|
-
5. start the application
|
|
33
|
-
6. disable maintenance
|
|
34
|
-
|
|
35
|
-
And if the database is small or it is a hobby app, this should not be looked any further.
|
|
36
|
-
However, this is not acceptable for 99% of production apps as their databases are huge and maintenance time
|
|
37
|
-
should be as small as possible.
|
|
38
|
-
|
|
39
|
-
Rough timing for a 1Tb database can be (but your mileage may vary):
|
|
40
|
-
|
|
41
|
-
- 2.5h creating Heroku backup
|
|
42
|
-
- 0.5h downloading backup to EC2
|
|
43
|
-
- 13h restoring a backup on RDS (in 4 threads)
|
|
44
|
-
|
|
45
|
-
**~16h total time, equals maintenance downtime**
|
|
46
|
-
|
|
47
|
-
### Option B: logical replication way
|
|
48
|
-
|
|
49
|
-
There are several logical replication solutions exist for Postgres - Slony, Bucardo, Londiste, Mimeo, but... when
|
|
50
|
-
you try to dig deeper, the only viable and up-to-date solution for purpose of migrating from Heroku to RDS is Bucardo.
|
|
51
|
-
|
|
52
|
-
The migration process with Bucardo looks as follows:
|
|
53
|
-
|
|
54
|
-
1. setup Bucardo on the dedicated EC2 instance
|
|
55
|
-
2. dump Heroku database schema and restore it on RDS - rather fast as there is no data
|
|
56
|
-
3. start Bucardo replication - this will install triggers and special schema to your database
|
|
57
|
-
4. wait for replication to catch up - this may take a long time, but the application can continue working as usual
|
|
58
|
-
5. enable maintenance
|
|
59
|
-
6. stop the application completely and wait for replication to finally finish
|
|
60
|
-
7. switch the database connection strings
|
|
61
|
-
8. start the application
|
|
62
|
-
9. disable maintenance
|
|
63
|
-
|
|
64
|
-
Maintenance downtime here can be minutes not hours or days like in p1, but no free lunches - the process is more complex.
|
|
65
|
-
|
|
66
|
-
Rough timing for a 1Tb database can be (but your mileage may vary):
|
|
67
|
-
|
|
68
|
-
- whatever setup time, no hurry
|
|
69
|
-
- 1.5 days for onetimecopy (in 1 thread) - DDL changes not allowed, but no downtime
|
|
70
|
-
- 1-2 min for database switch, maintenance downtime
|
|
71
|
-
|
|
72
|
-
**~2 days total time, ~1-2 min maintenance downtime**
|
|
73
|
-
|
|
74
|
-
### Some considerations:
|
|
75
|
-
|
|
76
|
-
- DDL changes should be "frozen and postponed" while Bucardo replication. There is also a way to stop replication,
|
|
77
|
-
update DDL in both databases, and restart replication, however, as well no-DDL for a day or two seems a
|
|
78
|
-
reasonable restriction for production databases vs potential errors.
|
|
79
|
-
|
|
80
|
-
- there is a "speed up" option to restore dump (with threads) and then run Bucardo to catch up only deltas, but it
|
|
81
|
-
looks unnecessary as speed gain is minimal vs potential errors. It will not speed up things dramatically, but will just
|
|
82
|
-
save a couple of hours of non-maintenance time (which most probably be spent on the command line) so not worth doing.
|
|
83
|
-
|
|
84
|
-
## Before replication
|
|
85
|
-
|
|
86
|
-
### Application code changes
|
|
87
|
-
|
|
88
|
-
Before everything, we need to recheck the database schema and ensure **that every table has a primary key (PK)
|
|
89
|
-
in place** as Bucardo is using PKs for replication.
|
|
90
|
-
|
|
91
|
-
> NOTE: theoretically Bucardo can work with uniq indexes as well, but having a PK on each table is easy and avoids
|
|
92
|
-
unnesessary complications
|
|
93
|
-
|
|
94
|
-
So, please stop, and do whatever is needed for your application.
|
|
95
|
-
|
|
96
|
-
### Choosing database location and EC2 location
|
|
97
|
-
|
|
98
|
-
All Heroku Postgres databases for location US are running in AWS on `us-east-1`. Control Plane, on the other side,
|
|
99
|
-
recommends `us-east-2` as a default. So we need to choose:
|
|
100
|
-
|
|
101
|
-
- either simple setup - main database in `us-east-2`
|
|
102
|
-
- or a bit more complex - main database in `us-east-2`, replica in `us-east-1` (which can be removed later)
|
|
103
|
-
|
|
104
|
-
This makes sense if your application supports working with replicas. Then read-only `SELECT` queries will go to the
|
|
105
|
-
read replica and write `INSERT/UPDATE` queries will go to the main write-enabled database.
|
|
106
|
-
This way we can keep most reading latency to the minimum.
|
|
107
|
-
|
|
108
|
-
Anyway, it is worth to consider developing such a mode in the application if you want to scale in more than 1 region.
|
|
109
|
-
|
|
110
|
-
### Create new EC2 instance which we will use for database replication
|
|
111
|
-
|
|
112
|
-
- better if it will be in the same AWS location where RDS database will be (most probably `us-east-2`)
|
|
113
|
-
- choose Ubuntu as OS
|
|
114
|
-
- use some bigger instance, e.g. `m6i.4xlarge` - price doesn't matter much, as such instance will not run long time
|
|
115
|
-
- if you will be copying backup via this instance, choose sufficient space for both OS and backup and some free space
|
|
116
|
-
- create security group `public-access` with all inbound and outbound traffic allowed. this will be handy as well for
|
|
117
|
-
database setup. if you need tighter access controls, up to you
|
|
118
|
-
- generate a new certificate and save it locally (e.g. `bucardo.pem`), will be used for SSH connection. Do not forget to
|
|
119
|
-
update correct permissions e.g. `chown TODO ~/Dowloads/bucardo.pem`
|
|
120
|
-
|
|
121
|
-
After the instance will be running on AWS, you can connect to it via SSH as follows:
|
|
122
87
|
```sh
|
|
123
|
-
|
|
88
|
+
chmod 600 ~/Downloads/bucardo.pem
|
|
89
|
+
ssh -i ~/Downloads/bucardo.pem ubuntu@MIGRATION_HOST
|
|
124
90
|
```
|
|
125
91
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
- check `public` box
|
|
129
|
-
- pick `public-access` security group (or whatever you need)
|
|
130
|
-
- if you will be restoring from backup, it is possible to choose temporary bigger instance e.g. `db.r6i.4xlarge`, which
|
|
131
|
-
can be downgraded later.
|
|
132
|
-
- if you will be using bucardo onetimecopy, then it is ok to select any instance you may need, as bucardo does copying
|
|
133
|
-
in a single thread
|
|
134
|
-
- it is fairly easy to switch database instance type afterwards and requires only minimal downtime
|
|
135
|
-
- storage space. this needs a good pick, as it is a) not possible to shrink and b) auto-expanding which AWS offers and
|
|
136
|
-
which should be enabled by default can block database modifications for quite long periods (days)
|
|
92
|
+
Run long foreground operations in a detachable session such as `screen`, and save
|
|
93
|
+
logs so you can inspect errors after reconnecting.
|
|
137
94
|
|
|
138
|
-
###
|
|
95
|
+
### Install database tools
|
|
139
96
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
97
|
+
Install PostgreSQL clients compatible with the source and target versions. Follow
|
|
98
|
+
the [PostgreSQL installation instructions](https://www.postgresql.org/download/)
|
|
99
|
+
and [supported-version policy](https://www.postgresql.org/support/versioning/).
|
|
143
100
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
# checking if screen is still running in the background
|
|
149
|
-
ps aux | grep -i screen
|
|
101
|
+
For replication, install Bucardo and its dependencies using the
|
|
102
|
+
[Bucardo installation guide](https://bucardo.org/Bucardo/Installation/) and
|
|
103
|
+
[requirements](https://bucardo.org/Bucardo/installation/requirements). Bucardo needs
|
|
104
|
+
a local PostgreSQL database for its control metadata. Before initializing it, check:
|
|
150
105
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
106
|
+
- Perl and the `DBI`, `DBD::Pg`, and `DBIx::Safe` modules, plus the utility modules
|
|
107
|
+
listed in Bucardo's requirements, are installed for the daemon's Perl runtime.
|
|
108
|
+
- The local control database has `PL/pgSQL` and `PL/PerlU` available. Replicated
|
|
109
|
+
databases need `PL/pgSQL` for the trigger-based sync; they do not need `PL/PerlU`.
|
|
110
|
+
- The installer can authenticate as a PostgreSQL superuser on the local control
|
|
111
|
+
server. This is separate from the source and target database privileges.
|
|
112
|
+
- The configured PID and log directories exist and are writable by the OS user
|
|
113
|
+
running Bucardo. Check the paths chosen by your installation rather than assuming
|
|
114
|
+
a particular distribution's layout.
|
|
154
115
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Now, when RDS is running and EC2 is running we can start installing local Postgres and Bucardo itself. Let's install
|
|
158
|
-
Postgres 13 first. It may be possible to install the latest Postgres, but 13 seems the best choice atm.
|
|
159
|
-
|
|
160
|
-
```sh
|
|
161
|
-
# update all your packages
|
|
162
|
-
sudo apt update
|
|
163
|
-
sudo apt upgrade -y
|
|
164
|
-
|
|
165
|
-
# add postgres repository key
|
|
166
|
-
sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
|
167
|
-
|
|
168
|
-
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
|
169
|
-
|
|
170
|
-
# update again
|
|
171
|
-
sudo apt-get update
|
|
172
|
-
|
|
173
|
-
# install packages
|
|
174
|
-
sudo apt-get -y install make postgresql-13 postgresql-client-13 postgresql-plperl-13 libdbd-pg-perl libdbix-safe-perl
|
|
175
|
-
```
|
|
176
|
-
|
|
177
|
-
Postgres Perl language `plperl` as well as DBD and DBIx packages are needed for Bucardo.
|
|
178
|
-
|
|
179
|
-
Now, as all dependencies are installed, we can install Bucardo from latest tarball.
|
|
116
|
+
Configure authenticated local access to that control database, then initialize it:
|
|
180
117
|
|
|
181
118
|
```sh
|
|
182
|
-
# install Bucardo itself
|
|
183
|
-
wget https://bucardo.org/downloads/Bucardo-5.6.0.tar.gz
|
|
184
|
-
tar xzf Bucardo-5.6.0.tar.gz
|
|
185
|
-
cd Bucardo-5.6.0
|
|
186
|
-
perl Makefile.PL
|
|
187
|
-
sudo make install
|
|
188
|
-
|
|
189
|
-
# create dirs and fix permissions
|
|
190
|
-
sudo mkdir /var/run/bucardo
|
|
191
|
-
sudo mkdir /var/log/bucardo
|
|
192
|
-
sudo chown ubuntu /var/run/bucardo/
|
|
193
|
-
sudo chown ubuntu /var/log/bucardo
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
After that, Bucardo is physically installed as a package and runnable but we need to configure everything.
|
|
197
|
-
Let's start with Postgres. As this is a temporary installation (only for the period of replication),
|
|
198
|
-
it is rather safe to set `trust` localhost connections (or set up another way if you want this).
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
For this, we need to edit `pg_hba.conf` as follows:
|
|
202
|
-
```sh
|
|
203
|
-
# edit pg config to make postgres trusted
|
|
204
|
-
sudo nano /etc/postgresql/13/main/pg_hba.conf
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
in that file change the following lines to `trust`
|
|
208
|
-
```sh
|
|
209
|
-
# in pg_hba.conf
|
|
210
|
-
local all postgres trust
|
|
211
|
-
local all all trust
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
and restart Postgres to pick up changes
|
|
215
|
-
```sh
|
|
216
|
-
# restart postgres
|
|
217
|
-
sudo systemctl restart postgresql
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
And finally-finally we can install Bucardo service database on local Postgres and see if everything runs.
|
|
221
|
-
|
|
222
|
-
```sh
|
|
223
|
-
# this will create local bucardo "service" database
|
|
224
119
|
bucardo install
|
|
225
|
-
|
|
226
|
-
# for option 3 pick `postgres` as a user
|
|
227
|
-
# for option 4 pick `postgres` as a database from where initial connection should be attempted
|
|
228
120
|
```
|
|
229
121
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
### Configuring external (Heroku, RDS) database connections
|
|
122
|
+
Test your chosen versions and authentication settings during rehearsal. The steps
|
|
123
|
+
below describe the replication flow; they do not replace Bucardo's installation guide.
|
|
234
124
|
|
|
235
|
-
|
|
236
|
-
connection properties manually, but for many commands, it is very useful.
|
|
125
|
+
### Configure source and target connections
|
|
237
126
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
touch ~/.pg_service.conf
|
|
241
|
-
nano ~/.pg_service.conf
|
|
242
|
-
```
|
|
127
|
+
Create `~/.pg_service.conf` on the migration host. Replace the placeholders with
|
|
128
|
+
credentials for the source and target databases:
|
|
243
129
|
|
|
244
130
|
```ini
|
|
245
|
-
# ~/.pg_service.conf
|
|
246
|
-
|
|
247
131
|
[heroku]
|
|
248
|
-
host=
|
|
132
|
+
host=HEROKU_HOST
|
|
249
133
|
port=5432
|
|
250
|
-
dbname=
|
|
251
|
-
user=
|
|
252
|
-
password=
|
|
134
|
+
dbname=SOURCE_DATABASE
|
|
135
|
+
user=SOURCE_USER
|
|
136
|
+
password=SOURCE_PASSWORD
|
|
137
|
+
sslmode=require
|
|
253
138
|
|
|
254
139
|
[rds]
|
|
255
|
-
host=
|
|
140
|
+
host=RDS_HOST
|
|
256
141
|
port=5432
|
|
257
|
-
dbname=
|
|
258
|
-
user=
|
|
259
|
-
password=
|
|
142
|
+
dbname=TARGET_DATABASE
|
|
143
|
+
user=TARGET_USER
|
|
144
|
+
password=TARGET_PASSWORD
|
|
145
|
+
sslmode=require
|
|
260
146
|
```
|
|
261
147
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
psql service=heroku -c '\l+'
|
|
265
|
-
psql service=rds -c '\l+'
|
|
266
|
-
```
|
|
148
|
+
Protect this file and confirm that both connections work. Use your provider's
|
|
149
|
+
certificate settings if your environment requires server identity verification.
|
|
267
150
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
my-production-db | xxx | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 821 GB | pg_default |
|
|
273
|
-
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | | 8205 kB | pg_default | default administrative connection database
|
|
274
|
-
rdsadmin | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | rdsadmin=CTc/rdsadmin+| No Access | pg_default |
|
|
275
|
-
| | | | | rdstopmgr=Tc/rdsadmin | | |
|
|
276
|
-
template0 | rdsadmin | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/rdsadmin +| 8033 kB | pg_default | unmodifiable empty database
|
|
277
|
-
| | | | | rdsadmin=CTc/rdsadmin | | |
|
|
278
|
-
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +| 8205 kB | pg_default | default template for new databases
|
|
279
|
-
| | | | | postgres=CTc/postgres | | |
|
|
280
|
-
(5 rows)
|
|
151
|
+
```sh
|
|
152
|
+
chmod 600 ~/.pg_service.conf
|
|
153
|
+
psql service=heroku -c 'SELECT current_database();'
|
|
154
|
+
psql service=rds -c 'SELECT current_database();'
|
|
281
155
|
```
|
|
282
156
|
|
|
283
|
-
|
|
157
|
+
## Option A: dump and restore
|
|
284
158
|
|
|
285
|
-
|
|
159
|
+
For a migration that can tolerate the measured restore time:
|
|
286
160
|
|
|
287
|
-
|
|
161
|
+
1. Enable maintenance mode and stop **all database writers**, including background
|
|
162
|
+
jobs and external services. Maintenance mode alone does not stop writes.
|
|
163
|
+
2. Wait for active writes to finish, then create and download the final source dump.
|
|
164
|
+
3. Restore the dump into RDS and check every restore error.
|
|
165
|
+
4. Validate the target data and application connection.
|
|
166
|
+
5. Follow the [cutover steps](#switch-the-application-to-rds) below.
|
|
288
167
|
|
|
289
|
-
|
|
168
|
+
Keep writers stopped throughout the final dump and restore. The
|
|
169
|
+
[Heroku PGBackups guide](https://devcenter.heroku.com/articles/heroku-postgres-backups)
|
|
170
|
+
covers backup capture and download; choose and rehearse a restore procedure suitable
|
|
171
|
+
for your dump format and database size.
|
|
290
172
|
|
|
291
|
-
|
|
292
|
-
- temporary disable all background jobs or services that are possible to stop. This will help to lessen database
|
|
293
|
-
load and especially, where possible, to decrease database write operations that will decrease replication pipe as well.
|
|
173
|
+
## Option B: Bucardo replication
|
|
294
174
|
|
|
295
|
-
###
|
|
175
|
+
### Copy the schema
|
|
296
176
|
|
|
297
|
-
|
|
298
|
-
|
|
177
|
+
Freeze DDL changes and reduce avoidable write traffic. Copy the source schema into
|
|
178
|
+
the empty target database, retaining logs and checking for errors:
|
|
299
179
|
|
|
300
180
|
```sh
|
|
301
|
-
# save heroku schema to `schema.sql`
|
|
302
181
|
pg_dump service=heroku --schema-only --no-acl --no-owner -v > schema.sql
|
|
303
|
-
|
|
304
|
-
# restore `schema.sql` on RDS
|
|
305
|
-
psql service=rds < schema.sql
|
|
182
|
+
psql --single-transaction -v ON_ERROR_STOP=1 -f schema.sql service=rds
|
|
306
183
|
```
|
|
307
184
|
|
|
308
|
-
|
|
185
|
+
The restore runs in one transaction and rolls back on error. Investigate any
|
|
186
|
+
unsupported extensions or other schema incompatibilities before retrying.
|
|
309
187
|
|
|
310
|
-
|
|
311
|
-
```sh
|
|
312
|
-
# add databases
|
|
313
|
-
bucardo add db from_db dbhost=xxx dbport=5432 dbuser=xxx dbpass=xxx dbname=xxx
|
|
314
|
-
bucardo add db to_db dbhost=xxx dbport=5432 dbuser=postgres dbpass=xxx dbname=xxx
|
|
188
|
+
### Configure the sync
|
|
315
189
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
```
|
|
320
|
-
Here, Bucardo will connect to databases and collect object metadata for replication.
|
|
321
|
-
After that, we can add sync as well:
|
|
190
|
+
Register the source and target with Bucardo. Replace the named placeholders with
|
|
191
|
+
the connection values for each database. These commands contain credentials; protect your terminal
|
|
192
|
+
history and any logs that capture them.
|
|
322
193
|
|
|
323
194
|
```sh
|
|
324
|
-
|
|
325
|
-
bucardo add
|
|
326
|
-
```
|
|
195
|
+
bucardo add db from_db dbhost=HEROKU_HOST dbport=5432 dbuser=SOURCE_USER dbpass=SOURCE_PASSWORD dbname=SOURCE_DATABASE
|
|
196
|
+
bucardo add db to_db dbhost=RDS_HOST dbport=5432 dbuser=TARGET_USER dbpass=TARGET_PASSWORD dbname=TARGET_DATABASE
|
|
327
197
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
-- on heroku
|
|
332
|
-
COPY xxx TO STDOUT
|
|
333
|
-
-- on rds
|
|
334
|
-
COPY xxx FROM STDIN
|
|
198
|
+
bucardo add all tables db=from_db --relgroup=migration
|
|
199
|
+
bucardo add all sequences db=from_db --relgroup=migration
|
|
200
|
+
bucardo add sync mysync relgroup=migration dbs=from_db:source,to_db:target onetimecopy=1
|
|
335
201
|
```
|
|
336
202
|
|
|
337
|
-
|
|
203
|
+
Inspect the registered tables, sequences, and source/target roles before starting.
|
|
204
|
+
See the [Bucardo tutorial](https://bucardo.org/Bucardo/pgbench_example) for its
|
|
205
|
+
registration and inspection commands.
|
|
206
|
+
The `onetimecopy=1` setting requests an initial data copy, followed by replication
|
|
207
|
+
of subsequent changes.
|
|
338
208
|
|
|
339
|
-
|
|
209
|
+
### Start and monitor replication
|
|
340
210
|
|
|
341
211
|
```sh
|
|
342
|
-
# starts Bucardo sync daemon
|
|
343
212
|
bucardo start
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
As well it is ok to disconnect from SSH as Bucardo daemon will continue working in background.
|
|
347
|
-
|
|
348
|
-
### Monitor status
|
|
349
|
-
|
|
350
|
-
To check the progress of sync (from Bucardo perspective):
|
|
351
|
-
```sh
|
|
352
|
-
# overall progress of all syncs
|
|
353
213
|
bucardo status
|
|
354
|
-
|
|
355
|
-
# single sync progress
|
|
356
214
|
bucardo status mysync
|
|
357
215
|
```
|
|
358
216
|
|
|
359
|
-
|
|
217
|
+
Bucardo runs as a daemon. You can disconnect from SSH and reconnect to inspect its
|
|
218
|
+
status and logs. To inspect its database activity:
|
|
219
|
+
|
|
360
220
|
```sh
|
|
361
|
-
|
|
362
|
-
psql service=
|
|
363
|
-
psql service=rds -c 'select * from pg_stat_activity' | grep -i bucardo
|
|
221
|
+
psql service=heroku -c 'SELECT * FROM pg_stat_activity' | grep -i bucardo
|
|
222
|
+
psql service=rds -c 'SELECT * FROM pg_stat_activity' | grep -i bucardo
|
|
364
223
|
```
|
|
365
224
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
1. Please do a sanity check of data in tables. E.g. check:
|
|
369
|
-
|
|
370
|
-
- table `COUNT`
|
|
371
|
-
- min/max of PK ids where applicable
|
|
372
|
-
- min/max of `created_at/updated_at` where applicable
|
|
225
|
+
Wait for the initial copy to finish and investigate replication errors. Keep schema
|
|
226
|
+
changes frozen until cutover completes.
|
|
373
227
|
|
|
374
|
-
|
|
228
|
+
### Validate before cutover
|
|
375
229
|
|
|
376
|
-
|
|
377
|
-
Just go to `psql` and `REFRESH MATERIALIZED VIEW ...`
|
|
230
|
+
Compare source and target data with checks suited to the application:
|
|
378
231
|
|
|
379
|
-
|
|
232
|
+
- Row counts and representative records.
|
|
233
|
+
- Minimum and maximum primary keys or timestamps, where meaningful.
|
|
234
|
+
- Sequence values and application-specific invariants.
|
|
235
|
+
- Objects outside replication, including refreshed materialized views.
|
|
380
236
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
afther this switch it is not possible (at least easily).
|
|
237
|
+
Checks taken while writes continue can differ. Repeat the final validation after
|
|
238
|
+
stopping writers and waiting for replication to catch up.
|
|
384
239
|
|
|
385
|
-
|
|
240
|
+
## Switch the application to RDS
|
|
386
241
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
4. detach heroku postgres from DATABASE_URL
|
|
391
|
-
5. set `DATABASE_URL` to RDS url (plaintext now)
|
|
392
|
-
6. start dynos
|
|
393
|
-
7. wait for their readiness with `heroku ps:wait`
|
|
394
|
-
8. stop maintenance with `heroku maintenance:off`
|
|
395
|
-
9. :fire: **Now we are fully on RDS, so DDL changes are allowed** :fire:
|
|
396
|
-
10. you could gradually enable all background jobs and services which were temporary stopped
|
|
242
|
+
Rehearse these steps with the application's deployment process. If you are also
|
|
243
|
+
moving the app to Control Plane, prepare its database secret and workloads before
|
|
244
|
+
the cutover window.
|
|
397
245
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
As we now running on RDS, there is only single task left to do on Heroku - make a final backup of database and save it.
|
|
246
|
+
For classic Heroku Postgres, retain a second source attachment before detaching
|
|
247
|
+
`DATABASE`. Replace `SOURCE_ADDON` with the existing add-on identifier:
|
|
401
248
|
|
|
402
249
|
```sh
|
|
403
|
-
|
|
404
|
-
heroku pg:backups:capture -a example-app
|
|
405
|
-
|
|
406
|
-
# to get url of backup
|
|
407
|
-
heroku pg:backups:url bXXXX -a example-app
|
|
250
|
+
heroku addons:attach SOURCE_ADDON --as MIGRATION_SOURCE -a APP
|
|
408
251
|
```
|
|
409
252
|
|
|
410
|
-
|
|
253
|
+
Confirm that `MIGRATION_SOURCE_URL` refers to the source database. Leave this
|
|
254
|
+
attachment in place for backup and recovery; the cutover detaches only `DATABASE`.
|
|
255
|
+
For Advanced databases, establish the equivalent retained attachment using that
|
|
256
|
+
plan's commands during rehearsal.
|
|
257
|
+
|
|
258
|
+
1. Enable maintenance mode. For a Heroku-hosted app, use `heroku maintenance:on -a APP`.
|
|
259
|
+
2. Stop all writers: web dynos, workers, scheduled jobs, and external services.
|
|
260
|
+
3. Wait for active writes to finish. With Bucardo, wait for the final replication
|
|
261
|
+
catch-up and verify the target again.
|
|
262
|
+
4. Save the old connection configuration and add-on attachment details for recovery.
|
|
263
|
+
For a Heroku-hosted app, detach the attachment that owns `DATABASE_URL` before
|
|
264
|
+
setting the RDS connection. For classic Heroku Postgres, this is typically
|
|
265
|
+
`heroku addons:detach DATABASE -a APP`; confirm the attachment name first.
|
|
266
|
+
Advanced databases use a different attachment command. See the
|
|
267
|
+
[Heroku CLI attachment reference](https://devcenter.heroku.com/articles/heroku-cli-commands#heroku-addons-detach-attachment_name)
|
|
268
|
+
and [database-type-specific credential instructions](https://devcenter.heroku.com/articles/heroku-postgresql-credentials#detach-a-credential).
|
|
269
|
+
Keep the source database itself; do not destroy the add-on.
|
|
270
|
+
5. With Bucardo, stop replication with `bucardo stop` after the final catch-up,
|
|
271
|
+
before any application writes reach RDS. Confirm that the sync has stopped and
|
|
272
|
+
keep source writers disabled.
|
|
273
|
+
6. Update the app's database connection to RDS using its deployment secret/configuration
|
|
274
|
+
mechanism.
|
|
275
|
+
7. Start the application and check readiness, database connectivity, and key operations.
|
|
276
|
+
For Heroku dynos, `heroku ps:wait -a APP` can check process readiness.
|
|
277
|
+
8. End maintenance only after those checks pass. On Heroku, use `heroku maintenance:off -a APP`.
|
|
278
|
+
9. Resume background jobs and scheduled writers. Lift the schema freeze once
|
|
279
|
+
replication is no longer needed.
|
|
280
|
+
|
|
281
|
+
**Rollback boundary:** before RDS accepts new application writes, the source can
|
|
282
|
+
remain the authoritative database. After new writes reach RDS, switching back to
|
|
283
|
+
Heroku requires a data reconciliation plan; changing the connection string alone
|
|
284
|
+
would lose those writes.
|
|
285
|
+
|
|
286
|
+
## Finish the migration
|
|
287
|
+
|
|
288
|
+
1. Retain a final Heroku backup according to your recovery policy. Keep the source
|
|
289
|
+
available until the agreed recovery window closes.
|
|
290
|
+
2. Verify RDS backups, monitoring, storage, and application performance.
|
|
291
|
+
3. Remove Bucardo's temporary replication objects when they are no longer needed,
|
|
292
|
+
following its cleanup procedure. Do not restart the old sync against the live target.
|
|
293
|
+
4. Remove temporary network access, migration credentials, and the migration host.
|
|
294
|
+
|
|
295
|
+
To capture and locate a final Heroku backup, use a remaining source attachment or
|
|
296
|
+
add-on identifier for `SOURCE_ADDON`:
|
|
411
297
|
|
|
412
298
|
```sh
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
# install aws cli (in a way reccomended by Amazon)
|
|
417
|
-
# ...TODO...
|
|
418
|
-
|
|
419
|
-
# configure aws credentials
|
|
420
|
-
aws configure
|
|
421
|
-
|
|
422
|
-
# check S3 access
|
|
423
|
-
aws s3 ls
|
|
424
|
-
|
|
425
|
-
# upload to S3
|
|
426
|
-
screen -dmL time aws s3 cp latest.dump s3://my-dumps-bucket/ --region us-east-1
|
|
299
|
+
heroku pg:backups:capture SOURCE_ADDON -a APP
|
|
300
|
+
heroku pg:backups:url BACKUP_ID -a APP
|
|
427
301
|
```
|
|
428
302
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
https://stackoverflow.com/questions/22264753/linux-how-to-install-dbdpg-module
|
|
434
|
-
|
|
435
|
-
https://gist.github.com/luizomf/1a7994cf4263e10dce416a75b9180f01
|
|
436
|
-
|
|
437
|
-
https://www.waytoeasylearn.com/learn/bucardo-installation/
|
|
438
|
-
|
|
439
|
-
https://gist.github.com/knasyrov/97301801733a31c60521
|
|
440
|
-
|
|
441
|
-
https://www.cloudnation.nl/inspiratie/blogs/migrating-heroku-postgresql-to-aurora-rds-with-almost-minimal-downtime
|
|
442
|
-
|
|
443
|
-
https://blog.porter.run/migrating-postgres-from-heroku-to-rds/
|
|
444
|
-
|
|
445
|
-
https://www.endpointdev.com/blog/2017/06/amazon-aws-upgrades-to-postgres-with/
|
|
446
|
-
|
|
447
|
-
https://aws.amazon.com/blogs/database/migrating-legacy-postgresql-databases-to-amazon-rds-or-aurora-postgresql-using-bucardo/
|
|
303
|
+
Download it to protected storage. If your retention destination is S3, use your
|
|
304
|
+
normal AWS credentials and bucket policy to upload the dump. Verify the stored
|
|
305
|
+
backup before removing the source database.
|