Setting up the Snowflake Connector for PostgreSQL Agent container¶
Note
The Snowflake Connector for PostgreSQL is subject to the Connector Terms.
This topic describes the procedure to set up the Snowflake Connector for PostgreSQL agent container. A database connector agent is a containerized application that runs inside your infrastructure, connecting directly to your databases and to Snowflake.
The process of configuring the Snowflake Connector for PostgreSQL agent includes the following steps:
[Optionally] Configure orchestration using Kubernetes
Review prerequisites and choose an orchestration system¶
Review and complete all prerequisites and proceed to Configure and run the agent.
Choose a container orchestration system¶
The agent is packaged as a standard Docker container image, and can be run on any orchestration system that supports the standard. This can be a stand-alone Docker (https://www.docker.com/) instance, Kubernetes (https://kubernetes.io/), RedHat OpenShift (https://www.redhat.com/en/technologies/cloud-computing/openshift), a cloud-managed solution, such as AWS Fargate (https://aws.amazon.com/fargate/), and others. Your organization will often have a preferred, existing system for you to use.
Pay attention to the agent configuration section of this document, because different orchestration systems come with different constraints. Your system, or specific setup, may not permit you to mount writable volumes (as is required with the agent’s primary configuration option).
Later examples will focus on Kubernetes as the most popular orchestration system. The approach will often be similar in other systems, and you will need to adjust the examples for your setup.
Confirm required system resources¶
The agent is a memory-intensive application, and requires a minimum 6GB of RAM to operate correctly.
The optimal number of CPUs is 4. Fewer CPUs can decrease performance. More CPUs will not improve performance.
Set up connectivity¶
The agent needs to connect to every source database where data will be read. Configure your network and firewalls, so that direct connections are possible, and PostgreSQL’s client port is reachable. Typically port 5432
. For more information see PostgreSQL’s Connection Settings documentation (https://www.postgresql.org/docs/current/runtime-config-connection.html#GUC-PORT).
If your source databases reside in isolated networks, and connecting from a single agent isn’t possible, you will need to install additional instances of the connector’s native application, each one with its own agent. This feature is currently in private preview. Please contact Snowflake Support to request access.
The agent also connects directly to your Snowflake deployment. For information on which hostnames need to be available see Allowing Hostnames.
If any of the agent’s connections pass through a proxy, you will need to pass additional configuration to the agent. See Review optional configuration environment variables.
Configure and run the agent¶
Configuring and running the agent is composed of the following steps:
[Optional] Obtain and prepare SSL certificates for source databases
Prepare agent configuration files or environment variables for the agent and start the agent
Where required Set up PrivateLink connectivity
Optionally Configure orchestration using Kubernetes.
[Optional] Obtain and prepare SSL certificates for source databases¶
If you intend to use SSL connections between the agent and the source databases,
you need to acquire the root certificate for your PostgreSQL instances,
and mount it into the agent’s container under /home/agent/.postgresql/root.crt
.
Prepare agent configuration¶
The agent can be configured via container-mounted JSON files, or environment variables, or a mix of both. The access keys required to connect to Snowflake can be mounted from the host’s file system, supplied as container secrets, or as environment variables.
The following sections describe different configuration options, from the most straightforward, to the most comprehensive. Choose an approach based on the specifics of your infrastructure.
The simplest way to configure the agent is to mount two JSON files into the container at runtime:
snowflake.json
contains configuration for the agent to connect to your Snowflake account.Download this file at the end of the connector’s setup process via the wizard available in Snowsight.
datasources.json
contains the list of source databases for the agent to connect to.You will need to prepare this file yourself.
Right after downloading, snowflake.json
includes a temporary private key for the Snowflake service account that represents the agent. When starting the agent for the first time, the agent will automatically replace that temporary key with a new, permanent set of keys, and output them to the path /home/agent/.ssh/
inside the container. Both snowflake.json
and the path under /home/agent/.ssh/
must be mounted as writable for the agent to start.
Alternatively, you can provide your own private key for the agent’s service account. See Review optional configuration environment variables for the required environment variables to pass.
Caution
If the agent finds an existing private key, either as mounted file or as
an environment variable, it will ignore any temporary key that might still be
present in snowflake.json
.
Prepare the datasources.json
file by copying and filling in the following template:
{
"<data_source_name_1>": {
"url": "jdbc:postgresql://<host>:<port>/<databaseName>[?<key1>=<value1>[&<key2>=<value2>]]",
"username": "<postgresql_db_username>",
"password": "<postgresql_db_password>",
"publication": "<postgresql_db_publication>",
"ssl": false
},
"<data_source_name_2>": {
"url": "jdbc:postgresql://<host>:<port>/<databaseName>[?<key1>=<value1>[&<key2>=<value2>]]",
"username": "<postgresql_db_username>",
"password": "<postgresql_db_password>",
"publication": "<postgresql_db_publication>",
"ssl": false
}
}
When creating the file:
You have to add at least one data source, with a URL, otherwise the agent will not start.
You can add as many data sources, as you need, as long as the agent can connect directly to all of them.
The names you enter become the identifiers you will need later to call the connector’s native app and enable replication. They must be unique per data source.
The names of data sources can contain only letters and numbers. Any lowercase letters will be automatically uppercased by the agent.
If you enable SSL connections by setting the
ssl
parameter totrue
, you will also need to mount the root certificate of the source database into the container. See [Optional] Obtain and prepare SSL certificates for source databases.
Once you have both JSON files in place, a directory to output the new set of keys, and optionally the root SSL certificate, start the container.
docker run -d \
--restart unless-stopped \
--name database-connector-agent \
--volume </path/to/ssh/keys/directory>:/home/agent/.ssh \
--volume </path/to/snowflake.json>:/home/agent/snowflake.json \
--volume </path/to/datasources.json>:/home/agent/datasources.json \
--volume </path/to/root.crt>:/home/agent/.postgresql/root.crt \
-m 6g \
snowflakedb/database-connector-agent:latest
Configuration options passed via snowflake.json
and datasources.json
can be supplied via environment variables.
Important
Environment variables take precedence over settings supplied via either of the JSON files.
The environment variable names follow the same structure as the paths in both JSON files.
Nested keys must be separated with underscores _
, every variable must be prefixed with SNOWFLAKE_
, and array entries prefixed with integer indexes.
For example the following script:
docker run \
-e SNOWFLAKE_USERNAME="POSTGRESQL_AGENT_USER" \
-e SNOWFLAKE_APPLICATION_NAME="SNOWFLAKE_CONNECTOR_FOR_POSTGRESQL" \
-e SNOWFLAKE_ALLOWLIST_0_HOST="example_account.us-west-2.aws.snowflakecomputing.cn" \
-e SNOWFLAKE_ALLOWLIST_0_PORT=443 \
-e SNOWFLAKE_ALLOWLIST_0_TYPE="SNOWFLAKE_DEPLOYMENT" \
...
Is equivalent to:
{
"userName": "POSTGRESQL_AGENT_USER",
"applicationName": "SNOWFLAKE_CONNECTOR_FOR_POSTGRESQL",
"allowlist": [
{
"host": "example_account.us-west-2.aws.snowflakecomputing.cn",
"port": 443,
"type": "SNOWFLAKE_DEPLOYMENT"
}
]
}
You don’t need to copy all the entries of the allowList
or allowlistPrivatelink
arrays.
Instead, find the allowList
entry with the type
of SNOWFLAKE_DEPLOYMENT
and use this URL to set the variable SNOWFLAKE_ENFORCEDURL
, as in:
docker run \
-e SNOWFLAKE_USERNAME="POSTGRESQL_AGENT_USER" \
-e SNOWFLAKE_APPLICATION_NAME="SNOWFLAKE_CONNECTOR_FOR_POSTGRESQL" \
-e SNOWFLAKE_ENFORCEDURL="example_account.us-west-2.aws.snowflakecomputing.cn:443" \
...
Data sources follow a similar structure and are prefixed with SNOWFLAKE_DATASOURCES_
.
For example:
docker run \
-e SNOWFLAKE_DATASOURCES_POSTGRESQLDS1_URL="jdbc:postgresql://example.internal:5432/", \
-e SNOWFLAKE_DATASOURCES_POSTGRESQLDS1_USERNAME="example_user" \
-e SNOWFLAKE_DATASOURCES_POSTGRESQLDS1_PASSWORD="example_password" \
-e SNOWFLAKE_DATASOURCES_POSTGRESQLDS1_PUBLICATION="example_publication" \
-e SNOWFLAKE_DATASOURCES_POSTGRESQLDS1_SSL="false" \
...
Is equivalent to:
{
"POSTGRESQLDS1": {
"url": "jdbc:postgresql://example.internal:5432/",
"username": "example_user",
"password": "example_password",
"publication": "example_publication",
"ssl": false
}
}
Review optional configuration environment variables¶
The agent supports the following, optional settings, available by setting additional environment variables on the container:
SNOWFLAKE_PRIVATEKEYPATH
Specifies the absolute path to the file with the agent user’s private key. This is used when mounting your own private key to the container, usually via an orchestration system’s secret.
SNOWFLAKE_PRIVATEKEYPASSWORD
Specifies the password for agent user’s the private key. If you let the agent generate the keys, this password will be set on the private key. If you reuse existing keys, this password will be used to access the existing private key.
SNOWFLAKE_PRIVATEKEY
Specifies the content of the agent user’s private key. This can be set, when mounting the private key as a file in the container is not an option.
SNOWFLAKE_ENFORCEDURL
Specifies the URL to connect to Snowflake, overriding the agent’s own discovery mechanism. This is primarily used to connect to PrivateLink deployments.
JAVA_OPTS
Specifies additional Java settings or properties that will be passed to the agent’s process.
The most commonly used are:
The
-Xmx
option to set the maximum Java heap size. Snowflake recommends setting this value to the amount of memory available to the container, minus 1GB.For example, if the container has 6GB of RAM available, set the following:
JAVA_OPTS=-Xmx5g
When the connection from agent to Snowflake requires a proxy, set the following:
JAVA_OPTS=-Dhttp.useProxy=true -Dhttp.proxyHost=<proxy-host> -Dhttp.proxyPort=<proxy-port>
To bypass the proxy for some hosts or IP addresses, for instance, source databases, set the additonal
http.nonProxyHosts
property. Use a pipe symbol (|
) to separate multiple host names. Use an asterisk (*
) as a wildcard character.JAVA_OPTS=-Dhttp.useProxy=true -Dhttp.proxyHost=<proxy-host> -Dhttp.proxyPort=<proxy-port> -Dhttp.nonProxyHosts='*.my_company.com|localhost|myorganization-myaccount.snowflakecomputing.cn|192.168.91.*'
To pass credentials for the proxy, set the
http.proxyUser
andhttp.proxyPassword
system properties.JAVA_OPTS=-Dhttp.useProxy=true -Dhttp.proxyHost=<proxy-host> -Dhttp.proxyPort=<proxy-port> -Dhttp.proxyUser=<proxy-user> -Dhttp.proxyPassword=<proxy-pass>
Set up PrivateLink connectivity¶
If you’re connecting to a PrivateLink deployment, you must provide the URL for the agent to
connect to explicitly by setting the SNOWFLAKE_ENFORCEDURL
environment variable.
To determine the PrivateLink URL of your account, you can either:
Open the
snowflake.json
file that you obtained during the configuration process. Find the array namedallowlistPrivatelink
, and then the entry with thetype
ofSNOWFLAKE_DEPLOYMENT
.Use the SYSTEM$GET_PRIVATELINK_CONFIG function.
Understanding Snowflake access keys¶
The agent authenticates with Snowflake as a service account,
created by the connector’s setup wizard in Snowsight, using a set of access keys.
The setup wizard creates temporary access keys, and adds the private key
to the snowflake.json
file in a field named temporaryPrivateKey
.
During its initial startup, the agent replaces these temporary keys by:
Generating a new set of access keys, and storing them under
/home/agent/.ssh
asdatabase-connector-agent-app-private-key.p8
anddatabase-connector-agent-app-public-key.pub
inside the container. This directory should be mounted as an external, writable volume to the container, so that the keys persist when the container shuts down.Altering its service account to use the new keys.
Removing the
temporaryPrivateKey
field from thesnowflake.json
file.
After the initial key replacement, the agent never rotates access keys.
You can use the keys generated by the agent. Or you can create your own set, alter the service account, and provide the private key to the agent.
The agent’s private key discovery order is:
Any key passed using the
SNOWFLAKE_PRIVATEKEY
environment variable. If this value is found, the connector will ignore the temporary key fromsnowflake.json
.Keys found on mounted volumes in
/home/agent/.ssh/database-connector-agent-app-private-key.p8
. If this file is found, the connector will ignore the temporary key fromsnowflake.json
.The value of the
temporaryPrivateKey
field from thesnowflake.json
file.
Configure orchestration using Kubernetes¶
Note
While this section concentrates on Kubernetes, the connector can be launched in any container orchestration system. The configuration syntaxes are often similar. For details, refer to your system’s documentation.
When using Kubernetes, mounting writable volumes is typically not an option. As a result, the agent will not be able to automatically replace the keys for its Snowflake user account. You will have to create a set of keys manually, alter the user, and then provide the private key to the container running the agent, typically as a mounted secret. For details on setting key-pairs for Snowflake users see Configuring Key Pair Authentication.
We recommend that you store the secrets in a secure store, such as HashiCorp Vault. These stores usually have existing integrations with Kubernetes, for instance, Vault offers a specialized operator (https://developer.hashicorp.com/vault/tutorials/kubernetes/vault-secrets-operator). The integration details will be specific to your container orchestration system and secure store. Refer to their respective documentation for details.
Kubernetes normally runs in multi-node clusters, with no way to mount files from the host machines. To supply the agent’s container with the configuration JSON files, you can create a Kubernetes ConfigMap (https://kubernetes.io/docs/concepts/configuration/configmap/) storing all three of the files.
The following shows a basic example for configuring the agent in Kubernetes.
Create a ConfigMap that will store
snowflake.json
and optionally the SSL root certificate:kubectl create configmap database-connector-config \ --from-file=snowflake.json=</path/to/snowflake.json> \ --from-file=root.crt=</path/to/root.crt>
Create a secret that will store the content of the agent user’s private key and
datasources.json
:kubectl create secret generic database-connector-secrets \ --from-file=private-key=</path/to/private/key/file> \ --from-file=datasources.json=</path/to/datasources.json>
Configure the agent’s Pod, mounting the configuration files and private key as volumes:
apiVersion: v1 kind: Pod metadata: name: database-connector-agent spec: restartPolicy: Always containers: - name: database-connector-agent image: snowflakedb/database-connector-agent:latest resources: requests: memory: "6Gi" limits: memory: "8Gi" volumeMounts: - name: config mountPath: /home/agent/snowflake.json subPath: snowflake.json - name: config mountPath: /home/agent/.postgresql/root.crt subPath: root.crt - name: secrets mountPath: /home/agent/datasources.json subPath: datasources.json - name: secrets mountPath: /etc/private-key/private-key subPath: private-key env: - name: SNOWFLAKE_PRIVATEKEYPATH value: /etc/private-key/private-key volumes: - name: config configMap: name: database-connector-config - name: secrets secret: secretName: database-connector-secrets
Save the Pod’s configuration as a YAML file, for instance,
database-connector.yaml
and start:kubectl apply -f database-connector.yaml
Monitor the agent¶
The agent’s container outputs logs to stdout
which can be accessed using Docker.
For example, if your container’s name is database-connector-agent
, then the command to view logs would be:
docker container logs database-connector-agent
These logs are also streamed into Snowflake. See Monitoring the Snowflake Connector for PostgreSQL for information about how to access these.
Accessing the health check endpoint¶
The agent exposes a HTTP endpoint with health information. You can use this endpoint when running the agent in an
orchestration system to determine when the agent has fully launched and whether it is healthy.
The endpoint is available under port 8080
and path /actuator/health
.
To use the endpoint as a liveness probe in Kubernetes, add the following to your Pod configuration:
apiVersion: v1
kind: Pod
spec:
containers:
- ...
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Next steps¶
After completing these procedures, follow the steps in Configuring replication for the Snowflake Connector for PostgreSQL.