Deploying Python 3.12 on Cloud Run with Cloud SQL Private Service Connect Using Terraform

Deploying Python 3.12 on Cloud Run with Cloud SQL Private Service Connect Using Terraform

Introduction:

In this post, we will walk through the steps required to provision Cloud SQL Private Service Connect (PSC) using Terraform, build a Python 3.12 Flask application, and deploy it on Google Cloud Run. The application will securely connect to a Cloud SQL PostgreSQL instance using the Cloud SQL Python Connector.

For more detailed instructions on provisioning Cloud SQL with Private Service Connect using Terraform, refer to this post on LinkedIn.

Prerequisites:

  • A Google Cloud project
  • Cloud SQL PostgreSQL instance with Private Service Connect enabled
  • Terraform for infrastructure provisioning
  • Docker for containerizing the Python application

Step 1: Set Up the Flask Application

We'll be creating a simple Flask app that connects to a Cloud SQL PostgreSQL instance. Below is the main.py file that contains our application logic.

main py

import os
from flask import Flask
from google.cloud.sql.connector import Connector
import logging

app = Flask(__name__)

# Setup logger
logger = logging.getLogger("test_cloudsql")
logger.setLevel(logging.DEBUG)
handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)

# Initialize the connector
logger.debug("Initializing Cloud SQL connector.")
connector = Connector()

def get_connection():
    try:
        logger.debug("Attempting to connect to Cloud SQL PostgreSQL instance.")
        # Create a connection to the Cloud SQL PostgreSQL instance using PSC
        conn = connector.connect(
            "<PROJECT-ID>:<REGION>:psc-instance",  # Cloud SQL instance name
            "pg8000",
            user="<user>",
            password="<password>",
            db="<my-database>",
            ip_type="psc"
        )
        logger.info("Successfully connected to the Cloud SQL instance.")
        return conn
    except Exception as e:
        logger.error(f"Failed to connect to the Cloud SQL instance: {str(e)}")
        raise

# Example: Query the database
def query_db():
    try:
        conn = get_connection()
        cursor = conn.cursor()
        try:
            logger.debug("Executing SQL query to fetch PostgreSQL version.")
            cursor.execute("SELECT version();")
            result = cursor.fetchone()
            logger.info(f"Query successful, result: {result}")
        except Exception as e:
            logger.error(f"Error executing SQL query: {str(e)}")
            raise
        finally:
            cursor.close()
            logger.debug("Closed the database cursor.")
        
        conn.close()
        logger.debug("Closed the database connection.")
        return result
    except Exception as e:
        logger.error(f"Error during database query: {str(e)}")
        raise

@app.route("/")
def hello_world():
    """Example Hello World route."""
    name = os.environ.get("NAME", "World")
    logger.debug(f"Handling request for '/' route, NAME={name}")
    return f"Hello {name}!"

@app.route("/db-version")
def db_version():
    """Route to query and return database version."""
    try:
        logger.debug("Handling request for '/db-version' route.")
        version = query_db()
        return f"Database version: {version[0]}"
    except Exception as e:
        logger.error(f"Error while handling '/db-version' request: {str(e)}")
        return f"Error querying database: {str(e)}", 500

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 8080))
    logger.debug(f"Starting Flask application on port {port}.")
    app.run(debug=True, host="0.0.0.0", port=port)
        

This app connects to a Cloud SQL PostgreSQL instance using the Cloud SQL Python Connector via Private Service Connect.

Step 2: Write the Dockerfile

Now, create a Dockerfile to containerize the application.

Dockerfile:

# Use an official Python runtime as the base image
FROM python:3.12-slim

# Set the working directory in the container
WORKDIR /app

# Copy the requirements file into the container
COPY requirements.txt .

# Install the required packages
RUN pip install --no-cache-dir -r requirements.txt

# Copy the rest of the application code
COPY main.py .

# Optionally, copy service account credentials if not using Workload Identity
# COPY your-service-account-key.json /app/service-account-key.json
# ENV GOOGLE_APPLICATION_CREDENTIALS=/app/service-account-key.json

# Set the environment variable for the Cloud SQL instance connection name
# ENV INSTANCE_CONNECTION_NAME="<PROJECT-ID>:<REGION>:psc-instance"

# Run the application
CMD ["python", "main.py"]
        

Step 3: Define the Required Python Packages

Create a requirements.txt file with the necessary dependencies:

requirements.txt:

Flask
gunicorn
Werkzeug
pg8000 
cloud-sql-python-connector
        

Step 4: Build and Push the Docker Image

To build and push the Docker image to Google Artifact Registry, follow these commands:

docker build -t quickstart-python:1.0.1 .
docker tag quickstart-python:1.0.1 us-central1-docker.pkg.dev/MY_PROJECT_ID/my-repo/quickstart-python:1.0.1
docker push us-central1-docker.pkg.dev/MY_PROJECT_ID/my-repo/quickstart-python:1.0.1
        

Make sure to replace MY_PROJECT_ID with your project ID.

Step 5: Deploy to Cloud Run

Once the Docker image is pushed, deploy the containerized application to Google Cloud Run using the following command. Ensure that the Cloud SQL instance has a VPC connector for private communication.

gcloud run deploy python-cloudsql-run \
  --image us-central1-docker.pkg.dev/<PROJECT-ID>/my-repo/quickstart-python:1.0.1 \
  --region=us-central1 \
  --allow-unauthenticated \
  --service-account=cloudsql-service-account-id@<PROJECT-ID>.iam.gserviceaccount.com \
  --vpc-connector private-cloud-sql
        

This command will:

  • Deploy the quickstart-python image on Cloud Run.
  • Use a service account for authentication with Cloud SQL.
  • Ensure the Cloud SQL instance is accessed via the VPC connector.

Conclusion

In this post, we successfully set up a Python 3.12 application on Cloud Run, connecting securely to Cloud SQL PostgreSQL instances using Private Service Connect. We also covered the essential Terraform steps for provisioning the Cloud SQL instances, and demonstrated how to containerize and deploy the application to Cloud Run.

By utilizing tools like Terraform, Docker, and Cloud SQL Python Connector, you can easily build scalable and secure applications on Google Cloud.

TEST



Source Code

Here on?GitHub.


References

https://cloud.google.com/blog/topics/developers-practitioners/how-connect-cloud-sql-using-python-easy-way

https://github.com/GoogleCloudPlatform/cloud-sql-python-connector?tab=readme-ov-file

https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main/cloud-sql/postgres/sqlalchemy

https://github.com/MagicStack/asyncpg?tab=readme-ov-file

https://magicstack.github.io/asyncpg/current/installation.html

https://www.python.org/doc/versions/

https://github.com/GoogleCloudPlatform/cloud-sql-python-connector

https://github.com/GoogleCloudPlatform/python-docs-samples/tree/main

https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/cloud-sql/postgres/sqlalchemy/connect_tcp.py

https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/cloud-sql/postgres/sqlalchemy/connect_connector.py


要查看或添加评论,请登录

Henry Xiloj Herrera的更多文章

社区洞察

其他会员也浏览了