Installing the pgEdge Control Plane
This guide contains instructions for deploying the Control Plane on a set of Linux hosts, such as virtual machines or bare metal servers.
Control Plan excels at managing Postgres in a highly-available configuration. To review a list of best practices for Control Plane deployment in a high-availability environment, visit here.
Initializing Docker Swarm
After creating hosts that meet the prerequisites, you're ready to provision a Docker Swarm cluster. Docker Swarm is first used to deploy the Control Plane server on each host, and is then used by the Control Plane to deploy Postgres instances across hosts when requested.
To initialize a new Docker Swarm cluster, run the following command on one of your hosts. This host will become the first manager in the swarm. Use the command:
docker swarm init
Swarm initialized: current node (dxn1zf6l61qsb1josjja83ngz) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join \
--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \
192.168.99.100:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
This command will output a docker swarm join command with a token. Invoke the provided docker swarm join command on each of the other hosts to join them to the cluster. After all hosts have joined the cluster, you can verify the cluster status by running:
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
vzou89zyd4n3xz6p6jvoohqxx * host-1 Ready Active Leader 28.3.3
5sa7m11ub62t1n22feuhg0mbp host-2 Ready Active Reachable 28.3.3
our0m7sn7gjops9klp7j1nvu7 host-3 Ready Active Reachable 28.3.3
Promoting Swarm Managers
Swarm manager nodes are responsible for orchestrating and maintaining the state of the Docker Swarm cluster. To conform to high availability best practices, we recommend using an odd number of managers based on your cluster size to ensure consensus.
Hint
We recommend running 3 manager nodes for clusters with up to 7 nodes, and at most 5 managers for clusters with more than 7 nodes.
To promote a node to manager, connect to a node that is already a manager, and invoke the following command:
docker node promote <node_name>
You can find a list of nodes and their status with the following command:
docker node ls
Nodes with the Leader or Reachable status under the MANAGER STATUS column are managers:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
vzou89zyd4n3xz6p6jvoohqxx * host-1 Ready Active Leader 28.3.3
5sa7m11ub62t1n22feuhg0mbp host-2 Ready Active Reachable 28.3.3
our0m7sn7gjops9klp7j1nvu7 host-3 Ready Active Reachable 28.3.3
Creating the Stack Definition File
After creating your Swarm, create a stack definition file and deploy the Control Plane server on every node in your Docker Swarm cluster.
Hint
Save your stack definition file to a convenient location; when referring to the file in your API input, include the complete path to the file.
Example: Creating a Stack Definition File
You can run the following command on a Swarm node to get the node ID for each node in the Docker Swarm cluster. The node with an asterisk (*) next to its ID is the node on which you're running the command.
docker node ls
The output will look like this:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
vzou89zyd4n3xz6p6jvoohqxx * host-1 Ready Active Leader 28.3.3
5sa7m11ub62t1n22feuhg0mbp host-2 Ready Active Reachable 28.3.3
our0m7sn7gjops9klp7j1nvu7 host-3 Ready Active Reachable 28.3.3
Given that output, the following stack definition file will deploy a single Control Plane server to each node, where each host is named sequentally (host-1, host-2, and host-3).
services:
host-1:
image: ghcr.io/pgedge/control-plane:v0.5.1
command: run
environment:
- PGEDGE_HOST_ID=host-1
- PGEDGE_DATA_DIR=/data/pgedge/control-plane
volumes:
- /data/pgedge/control-plane:/data/pgedge/control-plane
- /var/run/docker.sock:/var/run/docker.sock
networks:
- host
deploy:
placement:
constraints:
- node.id==vzou89zyd4n3xz6p6jvoohqxx
host-2:
image: ghcr.io/pgedge/control-plane:v0.5.1
command: run
environment:
- PGEDGE_HOST_ID=host-2
- PGEDGE_DATA_DIR=/data/pgedge/control-plane
volumes:
- /data/pgedge/control-plane:/data/pgedge/control-plane
- /var/run/docker.sock:/var/run/docker.sock
networks:
- host
deploy:
placement:
constraints:
- node.id==5sa7m11ub62t1n22feuhg0mbp
host-3:
image: ghcr.io/pgedge/control-plane:v0.5.1
command: run
environment:
- PGEDGE_HOST_ID=host-3
- PGEDGE_DATA_DIR=/data/pgedge/control-plane
volumes:
- /data/pgedge/control-plane:/data/pgedge/control-plane
- /var/run/docker.sock:/var/run/docker.sock
networks:
- host
deploy:
placement:
constraints:
- node.id==our0m7sn7gjops9klp7j1nvu7
networks:
host:
name: host
external: true
Include the deploy: placement: constraints: property in your stack definition to ensure that the Control Plane server is deployed onto a specific Swarm node. Placement constraints in Docker Swarm are used to control where services run within your cluster. In the configuration above, each service defined under the deploy property specifies a placement constraint:
deploy:
placement:
constraints:
- node.id==our0m7sn7gjops9klp7j1nvu7
This tells Docker Swarm to run the service only on the node with the matching node.id. By setting constraints like this, you ensure that each Control Plane container is deployed to a specific host in your cluster.
Note
This configuration uses the host network to attach each Control Plane container to the host's network interface. This automatically publishes all ports used by the container, and is required for the Control Plane to function.
Note
The path to the data volume must be the same inside the container as it is outside the container. The Control Plane provides this path to Docker when it runs database containers, so it needs to be accessible on the host and inside the container.
Etcd Server vs Client Mode
By default, each Control Plane server also acts as an Etcd server. However, in larger clusters or in clusters with an even number of nodes, some Control Plane servers should run in client mode.
Similar to the Docker Swarm configuration, you should configure your Control Plane cluster with three Etcd servers for clusters with up to seven hosts. For clusters with more than seven hosts, you should have no more than five Etcd servers.
We recommend mirroring your Docker Swarm configuration so that the Control Plane serves Etcd on each Swarm manager node and is a client on each Swarm worker node. Add this environment variable to a Control Plane server's service definition to configure the client mode:
- PGEDGE_ETCD_MODE=client
For example:
host-4:
image: ghcr.io/pgedge/control-plane:v0.5.1
command: run
environment:
- PGEDGE_HOST_ID=host-4
- PGEDGE_DATA_DIR=/data/pgedge/control-plane
- PGEDGE_ETCD_MODE=client
volumes:
- /data/pgedge/control-plane:/data/pgedge/control-plane
- /var/run/docker.sock:/var/run/docker.sock
networks:
- host
deploy:
placement:
constraints:
- node.id==g0nw8mhfox4hox1ny2fgk4x6h
Tip
The Stack Definition Generator below can produce this configuration for you.
Stack Definition Generator
To make it easier to generate the stack definition file, you can use the generator below to create a stack definition file based on the nodes in your Docker Swarm.
First, run the following command from any node within the swarm to list the Node IDs:
docker node ls --format '{{ .ID }} {{ .ManagerStatus }}'
Paste the output below and click "Generate Stack." This generator is fully local to this page, and doesn't transmit any data.
# Once submitted, the generated stack will appear here.
Deploying the Stack
To deploy the stack definition file, run the following command, specifying the path to the control-plane.yaml file:
docker stack deploy -c control-plane.yaml control-plane
This command creates the services and networks defined in the stack definition file.
Once the stack is deployed, the pgEdge Control Plane server will be running on each node. From there, you can proceed with initializing the Control Plane before beginning to deploy databases.
Initializing the Control Plane
Once the Control Plane server is deployed on all hosts, you can initialize the Control Plane.
Each Control Plane server starts in an uninitialized state until it's added to a Control Plane cluster. In a typical configuration, you will submit a request to one Control Plane server to initialize the new cluster, then submit requests to all other servers to join them in the new cluster.
For example, to initialize a cluster with three hosts, you would:
- Initialize the cluster on
host-1. - Join
host-2tohost-1's cluster. - Join
host-3tohost-1's cluster.
To initialize a cluster, make a GET request to the /v1/cluster/init
endpoint. The response will contain a "join token", which can be provided to
other instances via a POST request to the /v1/cluster/join endpoint. Using
the example from above, the initialization steps would be:
-
Initialize the cluster on
host-1:curl http://node_ip_address:3000/v1/cluster/initWhere
node_ip_addressspecifies the IP address ofhost-1. Control Plane returns a response like:{ "token": "PGEDGE-0c470f2eac35bb25135654a8dd9c812fc4aca4be8c8e34483c0e279ab79a7d30-907336deda459ebc79079babf08036fc", "server_url": "http://198.19.249.2:3000" }We'll submit these details to the other Control Plane server instances to join them to the new cluster.
-
Join
host-2tohost-1's cluster:curl -i -X POST http://node_ip_address:3000/v1/cluster/join \ -H 'Content-Type:application/json' \ --data '{ "token":"PGEDGE-0c470f2eac35bb25135654a8dd9c812fc4aca4be8c8e34483c0e279ab79a7d30-907336deda459ebc79079babf08036fc", "server_url":"http://198.19.249.2:3000" }'Where
node_ip_addressspecifies the IP address ofhost-2. Control Plane returns a204response on success. -
Join
host-3tohost-1's cluster:curl -i -X POST http://node_ip_address:3000/v1/cluster/join \ -H 'Content-Type:application/json' \ --data '{ "token":"PGEDGE-0c470f2eac35bb25135654a8dd9c812fc4aca4be8c8e34483c0e279ab79a7d30-907336deda459ebc79079babf08036fc", "server_url":"http://198.19.249.2:3000" }'Where
node_ip_addressspecifies the IP address ofhost-3. Control Plane returns a204response on success.The
join tokencan also be fetched from any host in the cluster with aGETrequest to the/v1/cluster/join-tokenendpoint:curl http://node_ip_address:3000/v1/cluster/join-tokenAfter initializing the cluster, you can submit requests to any host in the cluster.