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:

  1. Review prerequisites and choose an orchestration system

  2. Configure and run the agent

  3. [Optionally] Configure orchestration using Kubernetes

  4. Monitor the agent

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:

  1. [Optional] Obtain and prepare SSL certificates for source databases

  2. Prepare agent configuration files or environment variables for the agent and start the agent

  3. Review optional configuration environment variables

  4. 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
   }
}
Copy

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 to true, 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
Copy

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
    
    Copy
  • 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>
    
    Copy
  • 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.*'
    
    Copy
  • To pass credentials for the proxy, set the http.proxyUser and http.proxyPassword system properties.

    JAVA_OPTS=-Dhttp.useProxy=true -Dhttp.proxyHost=<proxy-host> -Dhttp.proxyPort=<proxy-port>
      -Dhttp.proxyUser=<proxy-user> -Dhttp.proxyPassword=<proxy-pass>
    
    Copy

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:

  1. Generating a new set of access keys, and storing them under /home/agent/.ssh as database-connector-agent-app-private-key.p8 and database-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.

  2. Altering its service account to use the new keys.

  3. Removing the temporaryPrivateKey field from the snowflake.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:

  1. Any key passed using the SNOWFLAKE_PRIVATEKEY environment variable. If this value is found, the connector will ignore the temporary key from snowflake.json.

  2. 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 from snowflake.json.

  3. The value of the temporaryPrivateKey field from the snowflake.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.

  1. 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>
    
    Copy
  2. 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>
    
    Copy
  3. 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
    
    Copy
  4. Save the Pod’s configuration as a YAML file, for instance, database-connector.yaml and start:

    kubectl apply -f database-connector.yaml
    
    Copy

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
Copy

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
Copy

Next steps

After completing these procedures, follow the steps in Configuring replication for the Snowflake Connector for PostgreSQL.

Language: English