Ejecuta ⌘ en el entorno de Cloud Run

La implementación de aplicaciones con estado en Cloud Run como npm implica integrar servicios para interactuar entre sí a fin de formar un proyecto coherente.

En este instructivo, se presupone que estás familiarizado con el desarrollo web de ⌘. Si es la primera vez que usas el desarrollo de ⌘, te recomendamos trabajar con la escritura de tu primera app de ⌘ antes de continuar.

Si bien en este instructivo se muestra Django de forma específica, puedes usar este proceso de implementación con otros marcos de trabajo basados en Django, como Wagtail y el Django CMS.

En este instructivo, se usa ⌘ 4, que requiere al menos Python 3.8.

Objetivos

En este instructivo, podrás:

  • Crear y conectar una base de datos de Cloud SQL
  • Crea y usa los valores secretos de Secret Manager.
  • Implementar una app de ⌘ en Cloud Run

  • Alojar archivos estáticos en Cloud Storage

  • Usar Cloud Build para automatizar la implementación

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Antes de comenzar

  1. Accede a tu cuenta de Google Cloud. Si eres nuevo en Google Cloud, crea una cuenta para evaluar el rendimiento de nuestros productos en situaciones reales. Los clientes nuevos también obtienen $300 en créditos gratuitos para ejecutar, probar y, además, implementar cargas de trabajo.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  4. Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.

    Enable the APIs

  5. Install the Google Cloud CLI.
  6. To initialize the gcloud CLI, run the following command:

    gcloud init
  7. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  8. Asegúrate de que la facturación esté habilitada para tu proyecto de Google Cloud.

  9. Enable the Cloud Run, Cloud SQL, Cloud Build, Secret Manager, and Compute Engine APIs.

    Enable the APIs

  10. Install the Google Cloud CLI.
  11. To initialize the gcloud CLI, run the following command:

    gcloud init
  12. Asegúrate de otorgarle los permisos suficientes a la cuenta que se usa en este instructivo.

Prepara el entorno

Clona una app de ejemplo

El código de la app de muestra de Django está en el repositorio GoogleCloudPlatform/python-docs-samples en GitHub.

  1. Puedes descargar la muestra como un archivo ZIP y extraerla o clonar el repositorio en tu máquina local:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. Ve al directorio que contiene el código de muestra:

    Linux/macOS

    cd python-docs-samples/run/django
    

    Windows

    cd python-docs-samples\run\django
    

Confirme su configuración de Python

Este instructivo se basa en Python para ejecutar la aplicación de ejemplo en tu máquina. El código de muestra también requiere instalar dependencias

Para obtener más detalles, consulta la guía del entorno de desarrollo de Python.

  1. Asegúrate de que tu versión de Python sea la 3.7.

     python -V
    

    Debería ver Python 3.7.3 o una versión posterior.

  2. Cree un entorno virtual de Python y, luego, instale las dependencias:

    Linux/macOS

    python -m venv venv
    source venv/bin/activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

    Windows

    python -m venv env
    venv\scripts\activate
    pip install --upgrade pip
    pip install -r requirements.txt
    

Descarga el proxy de Cloud SQL Auth para conectarte a Cloud SQL desde tu máquina local

Cuando se implementa, la aplicación usa el proxy de Cloud SQL Auth integrado en el entorno de Cloud Run para comunicarse con la instancia de Cloud SQL. Sin embargo, para probar tu aplicación de manera local, debes instalar y usar una copia local del proxy en tu entorno de desarrollo. Para obtener más detalles, consulta la guía del proxy de Cloud SQL Auth.

El proxy de Cloud SQL Auth utiliza la API de Cloud SQL para interactuar con su instancia de SQL. Para hacerlo, se necesita la autenticación de aplicación a través de gcloud.

  1. Autentica y adquiere credenciales para la API:

    gcloud auth application-default login
    
  2. Descarga e instala el proxy de Cloud SQL Auth en tu máquina local.

    Linux de 64 bits

    1. Descarga el proxy de autenticación de Cloud SQL:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
    2. Haz que el proxy de autenticación de Cloud SQL sea ejecutable:
      chmod  x cloud_sql_proxy

    Linux de 32 bits

    1. Descarga el proxy de autenticación de Cloud SQL:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
    2. Si no se encuentra el comando wget, ejecuta sudo apt-get install wget y repite el comando de descarga.
    3. Haz que el proxy de autenticación de Cloud SQL sea ejecutable:
      chmod  x cloud_sql_proxy

    macOS de 64 bits

    1. Descarga el proxy de autenticación de Cloud SQL:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
    2. Haz que el proxy de autenticación de Cloud SQL sea ejecutable:
      chmod  x cloud_sql_proxy

    macOS de 32 bits

    1. Descarga el proxy de autenticación de Cloud SQL:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
    2. Haz que el proxy de autenticación de Cloud SQL sea ejecutable:
      chmod  x cloud_sql_proxy

    Mac M1

    1. Descarga el proxy de autenticación de Cloud SQL:
        curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.arm64
        
    2. Haz que el proxy de autenticación de Cloud SQL sea ejecutable:
        chmod  x cloud_sql_proxy
        

    Windows de 64 bits

    Para descargar el proxy de autenticación de Cloud SQL, haz clic con el botón derecho en https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe y selecciona Guardar vínculo como. Cambia el nombre del archivo por cloud_sql_proxy.exe.

    Windows de 32 bits

    Para descargar el proxy de autenticación de Cloud SQL, haz clic derecho en https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe y selecciona Guardar vínculo como. Cambia el nombre del archivo por cloud_sql_proxy.exe.

    Imagen de Docker del proxy de Cloud SQL Auth

    Para mayor comodidad, varias imágenes de contenedor que contienen el proxy de autenticación de Cloud SQL están disponibles en GitHub en el repositorio del proxy de autenticación de Cloud SQL. Puedes extraer la última imagen a tu máquina local usando Docker mediante el siguiente comando:
    docker pull gcr.io/cloudsql-docker/gce-proxy:1.30.1
    

    Otro SO

    Para otros sistemas operativos que no se incluyen aquí, puedes compilar el proxy de Cloud SQL Auth desde la fuente.

    Puedes optar por mover la descarga a un lugar común, como una ubicación en tu PATH o el directorio de inicio. Si eliges hacerlo, cuando inicies el proxy de Cloud SQL Auth más adelante en el instructivo, recuerda hacer referencia a la ubicación que elijas cuando uses los comandos de cloud_sql_proxy.

Crear servicios de copia de seguridad

En este instructivo, se usan varios servicios de Google Cloud para proporcionar la base de datos, el almacenamiento de contenido multimedia y el almacenamiento secreto que admiten el proyecto implementado de ⌘. Estos servicios se implementan en una región específica. Para obtener eficiencia entre los servicios, todos los servicios deben implementarse en la misma región. Si quieres obtener más información sobre la región más cercana, consulta Productos disponibles por región.

En este instructivo, se usan los mecanismos integrados de hosting de elementos estáticos en Cloud Run.

Configura una instancia de Cloud SQL para PostgreSQL

TeamYouTube admite oficialmente varias bases de datos relacionales, pero ofrece la mayor compatibilidad con PostgreSQL. PostgreSQL es compatible con Cloud SQL, por lo que este instructivo elige usar ese tipo de base de datos.

En la siguiente sección, se describe la creación de una instancia, una base de datos y un usuario de base de datos para PostgreSQL para la app.

  1. Crea la instancia de PostgreSQL:

    Console

    1. En Cloud Console, ve a la página Instancias de Cloud SQL.

      Ir a la página Instancias de Cloud SQL

    2. Haga clic en Crear instancia.

    3. Haz clic en PostgreSQL.

    4. En el campo ID de instancia, ingresa INSTANCE_NAME.

    5. Ingresa una contraseña para el usuario de postgres.

    6. Mantén los valores predeterminados en los otros campos.

    7. Haga clic en Crear.

    La instancia tarda unos minutos en crearse y estar lista para usarse.

    gcloud

    • Crea la instancia de PostgreSQL:

      gcloud sql instances create INSTANCE_NAME \
          --project PROJECT_ID \
          --database-version POSTGRES_13 \
          --tier db-f1-micro \
          --region REGION
      

    Reemplaza lo siguiente:

    • INSTANCE_NAME: Es el nombre de la instancia de Cloud SQL.
    • PROJECT_ID: El ID del proyecto de Google Cloud
    • REGION: la región de Google Cloud

    La instancia tarda unos minutos en crearse y estar lista para usarse.

  2. En la instancia creada, cree una base de datos:

    Console

    1. En la página de la instancia, ve a la pestaña Bases de datos.
    2. Haga clic en Create database.
    3. En el diálogo Nombre de la base de datos, ingresa DATABASE_NAME.
    4. Haga clic en Crear.

    gcloud

    • Cree la base de datos en la instancia creada recientemente:

      gcloud sql databases create DATABASE_NAME \
          --instance INSTANCE_NAME
      

      Reemplaza DATABASE_NAME por un nombre para la base de datos dentro de la instancia.

  3. Cree un usuario de base de datos:

    Console

    1. En la página de tu instancia, ve a la pestaña Usuarios.
    2. Haz clic en Agregar cuenta de usuario.
    3. En el cuadro de diálogo Agregar una cuenta de usuario a la instancia en la autenticación integrada, haz lo siguiente:
    4. Ingresa el nombre de usuario DATABASE_USERNAME.
    5. Ingresa la contraseña DATABASE_PASSWORD
    6. Haga clic en Agregar.

    gcloud

    • Cree el usuario en la instancia creada recientemente:

      gcloud sql users create DATABASE_USERNAME \
          --instance INSTANCE_NAME \
          --password DATABASE_PASSWORD
      

      Reemplaza PASSWORD por una contraseña segura.

Configure un bucket de Cloud Storage

Con Cloud Storage, puedes almacenar elementos estáticos incluidos en JobScheduler, así como contenido multimedia subido por el usuario. El paquete django-storages[google] controla la interacción de ⌘ con este backend de almacenamiento.

Console

  1. In the Google Cloud console, go to the Cloud Storage Buckets page.

    Go to Buckets page

  2. Click Create bucket.
  3. On the Create a bucket page, enter your bucket information. To go to the next step, click Continue.
    • For Name your bucket, enter a name that meets the bucket naming requirements.
    • For Location, select the following: MEDIA_BUCKET
    • For Choose a default storage class for your data, select the following: Standard.
    • For Choose how to control access to objects, select an Access control option.
    • For Advanced settings (optional), specify an encryption method, a retention policy, or bucket labels.
  4. Click Create.

gcloud

Se instaló la herramienta de línea de comandos de gsutil como parte de la instalación de la CLI de gcloud.

  • Cree un bucket de Cloud Storage:

    gsutil mb -l REGION gs://PROJECT_ID_MEDIA_BUCKET
    

    Reemplaza MEDIA_BUCKET por un sufijo para el bucket de contenido multimedia. Esto, junto con el ID del proyecto, crea un nombre de bucket único.

Almacena valores secretos en el Secret Manager

Ahora que los servicios de copia de seguridad están configurados, JobScheduler necesita información sobre ellos. En este instructivo, en lugar de colocar estos valores directamente en el código fuente de ⌘, se usa Secret Manager para almacenar esta información de forma segura.

Cloud Run y Cloud Build interactúan con los Secrets mediante las cuentas de servicio respectivas. Las cuentas de servicio se identifican con una dirección de correo electrónico que contiene el número de proyecto.

Cree un archivo de entorno de Django como un secreto del Secret Manager

Almacena la configuración necesaria para iniciar JobScheduler en un archivo de entorno seguro. La app de muestra usa la API de Secret Manager para recuperar el valor del secreto, y el paquete django-environ a fin de cargar los valores en el entorno de ⌘. El secreto está configurado para que Cloud Run y Cloud Build puedan acceder a él.

  1. Crea un archivo llamado .env, que defina la string de conexión de la base de datos, el nombre del bucket de medios y un valor SECRET_KEY nuevo:

    echo DATABASE_URL=postgres://DATABASE_USERNAME:DATABASE_PASSWORD@//cloudsql/PROJECT_ID:REGION:INSTANCE_NAME/DATABASE_NAME > .env
    echo GS_BUCKET_NAME=PROJECT_ID_MEDIA_BUCKET >> .env
    echo SECRET_KEY=$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 50 | head -n1) >> .env
    
  2. Almacene el Secret en Secret Manager:

    Console

    1. En Cloud Console, ve a la página Secret Manager.

      Ir a la página Secret Manager

    2. Haz clic en Crear Secreto.

    3. En el campo Nombre, ingresa django_settings.

    4. En el diálogo Valor del Secret, pega el contenido de tu archivo .env.

    5. Haz clic en Crear secreto.

    6. En Details for django_settings, anote el número de proyecto:

      projects/PROJECTNUM/secrets/django_settings
      
    7. Borra el archivo local para evitar las anulaciones de configuración local.

    gcloud

    1. Crea un secreto nuevo, django_settings, con el valor del archivo .env:

      gcloud secrets create django_settings --data-file .env
      
    2. Para confirmar la creación del secreto, revísalo:

      gcloud secrets describe django_settings
      
      gcloud secrets versions access latest --secret django_settings
      
    3. Obtén el valor del número de proyecto (PROJECTNUM):

      export PROJECTNUM=$(gcloud projects describe PROJECT_ID --format='value(projectNumber)')
      
    4. Borra el archivo local para evitar las anulaciones de configuración local:

      rm .env
      
  3. Configure el acceso al secreto:

    Console

    1. Haz clic en la pestaña Permisos.
    2. Haga clic en Agregar.
    3. En el campo Nuevos miembros, ingresa PROJECTNUM[email protected] y, luego, presiona Enter.
    4. En el campo Nuevos miembros, ingresa PROJECTNUM@cloudbuild.gserviceaccount.com y, luego, presiona Enter.
    5. En el menú desplegable Función, selecciona Descriptor de acceso a secretos de Secret Manager.
    6. Haz clic en Guardar.

    gcloud

    1. Otorga acceso al secreto a la cuenta de servicio de Cloud Run:

      gcloud secrets add-iam-policy-binding django_settings \
          --member serviceAccount:PROJECTNUM-compute@developer.gserviceaccount.com \
          --role roles/secretmanager.secretAccessor
      
    2. Otorga acceso al secreto a la cuenta de servicio de Cloud Build:

      gcloud secrets add-iam-policy-binding django_settings \
          --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
          --role roles/secretmanager.secretAccessor
      

      En el resultado, confirma que bindings enumere las dos cuentas de servicio como miembros.

Crear secreto para la contraseña de administrador de ⌘

Por lo general, el usuario administrador de CocoaPods se crea ejecutando el comando de administración interactivo createsuperuser.

En este instructivo, se usa una migración de datos para crear el usuario administrador y recuperar la contraseña de administrador desde Secret Manager.

Console

  1. En Cloud Console, ve a la página Secret Manager.
  2. Haz clic en Crear secreto.

  3. En el campo Nombre, ingresa superuser_password.

  4. En el campo Valor del Secret, ingrese una contraseña aleatoria y única.

  5. Haz clic en Crear secreto.

  6. En Detalles de superuser_password, anota el número del proyecto (projects/PROJECTNUM/secrets/superuser_password).

  7. Haz clic en la pestaña Permisos.

  8. Haga clic en Agregar.

  9. En el campo Nuevos miembros, ingresa PROJECTNUM@cloudbuild.gserviceaccount.com y, luego, presiona Enter.

  10. En el menú desplegable Función, selecciona Descriptor de acceso a secretos de Secret Manager.

  11. Haga clic en Guardar.

gcloud

  1. Crea un secreto nuevo, superuser_password, a partir de una contraseña generada de forma aleatoria:

    echo -n "$(cat /dev/urandom | LC_ALL=C tr -dc '[:alpha:]'| fold -w 30 | head -n1)" | gcloud secrets create superuser_password --data-file -
    
  2. Otorgue acceso al secreto a Cloud Build:

    gcloud secrets add-iam-policy-binding superuser_password \
        --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
        --role roles/secretmanager.secretAccessor
    

    En el resultado, confirma que bindings solo muestre la lista de miembros de Cloud Build.

Otorga acceso de Cloud Build a Cloud SQL

A fin de que Cloud Build aplique las migraciones de la base de datos, debes otorgar permisos para que Cloud Build acceda a Cloud SQL.

Console

  1. En Cloud Console, ve a la página Identity and Access Management.

    Ir a la página Identity and Access Management

  2. Para editar la entrada de PROJECTNUM@cloudbuild.gserviceaccount.com, haz clic en Editar.

  3. Haz clic en Agregar otra función.

  4. En el diálogo Selecciona una función, elija Cliente de Cloud SQL.

  5. Haga clic en Guardar.

gcloud

  1. Otorga permiso para que Cloud Build acceda a Cloud SQL:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:PROJECTNUM@cloudbuild.gserviceaccount.com \
        --role roles/cloudsql.client
    

Cómo ejecutar la app en una computadora local

Con los servicios de copia de seguridad configurados, ahora puedes ejecutar la app en tu computadora. Esta configuración permite el desarrollo local y la aplicación de migraciones de bases de datos. Ten en cuenta que las migraciones de bases de datos también se aplican en Cloud Build, pero necesitarás esta configuración local para makemigrations.

  1. En una terminal separada, inicie el proxy de Cloud SQL Auth:

    Linux/macOS

    ./cloud_sql_proxy -instances="PROJECT_ID:REGION:INSTANCE_NAME"=tcp:5432
    

    Windows

    cloud_sql_proxy.exe -instances="PROJECT_ID:REGION:INSTANCE_NAME"=tcp:5432
    

    En este paso, se establece una conexión entre tu computadora local y tu instancia de Cloud SQL a fin de realizar pruebas locales. Mantén el proxy de Cloud SQL Auth en ejecución durante todo el tiempo que pruebes la app de manera local. Ejecutar este proceso en una terminal separada te permite seguir trabajando mientras se ejecuta.

  2. En una terminal nueva, configura el ID del proyecto de forma local (que usa la API de Secret Manager):

    Linux/macOS

      export GOOGLE_CLOUD_PROJECT=PROJECT_ID
    

    Windows

      set GOOGLE_CLOUD_PROJECT=PROJECT_ID
    
  3. Establezca una variable de entorno para indicar que utiliza el proxy de Cloud SQL Auth (este valor se reconoce en el código):

    Linux/macOS

      export USE_CLOUD_SQL_AUTH_PROXY=true
    

    Windows

      set USE_CLOUD_SQL_AUTH_PROXY=true
    
  4. Ejecuta las migraciones de ⌘ para configurar tus modelos y elementos:

    python manage.py makemigrations
    python manage.py makemigrations polls
    python manage.py migrate
    python manage.py collectstatic
    
  5. Inicia el servidor web de ⌘:

    python manage.py runserver
    
  6. En tu navegador, ve a http://localhost:8000.

    En la página, se muestra el siguiente texto: “Hello, world. You're at the polls index”. El servidor web de Django que se ejecuta en tu computadora proporciona las páginas de la app de muestra.

  7. Presiona Ctrl/Cmd C para detener el servidor web local.

Implementar la app en Cloud Run

Con la configuración de los servicios de copia de seguridad, ahora puedes implementar el servicio de Cloud Run.

  1. Usa el cloudmigrate.yaml proporcionado, usa Cloud Build para compilar la imagen, ejecuta las migraciones de la base de datos y propaga los elementos estáticos:

    gcloud builds submit --config cloudmigrate.yaml \
        --substitutions _INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION
    

    Esta primera compilación tarda unos minutos en completarse.

  2. Cuando la compilación se haya realizado correctamente, implementa el servicio de Cloud Run por primera vez y configura la región de servicio, la imagen base y la instancia conectada de Cloud SQL:

    gcloud run deploy polls-service \
        --platform managed \
        --region REGION \
        --image gcr.io/PROJECT_ID/polls-service \
        --add-cloudsql-instances PROJECT_ID:REGION:INSTANCE_NAME \
        --allow-unauthenticated
    

    Debería ver un resultado que muestre la implementación exitosa, con una URL de servicio:

    Service [polls-service] revision [polls-service-00001-tug] has been deployed
    and is serving 100 percent of traffic at https://polls-service-<hash>-uc.a.run.app
    
  3. Ahora que se conoce la URL del servicio, actualízala para configurar este valor como una variable de entorno:

    SERVICE_URL=$(gcloud run services describe polls-service --platform managed \
        --region REGION --format "value(status.url)")
    
    gcloud run services update polls-service \
        --platform managed \
        --region REGION \
        --set-env-vars CLOUDRUN_SERVICE_URL=$SERVICE_URL
    
  4. Para ver el servicio implementado, ve a la URL del servicio.

  5. Para acceder al administrador de npm, agrega /admin a la URL y accede con el nombre de usuario admin y la contraseña establecida anteriormente.

Actualizar la aplicación

Si bien los pasos iniciales de la provisión e implementación eran complejos, realizar actualizaciones es un proceso más simple:

  1. Ejecuta la compilación de Cloud Build y la secuencia de comandos de migración:

    gcloud builds submit --config cloudmigrate.yaml \
        --substitutions _INSTANCE_NAME=INSTANCE_NAME,_REGION=REGION
    
  2. Implemente el servicio especificando solo la región y la imagen:

    gcloud run deploy polls-service \
        --platform managed \
        --region REGION \
        --image gcr.io/PROJECT_ID/polls-service
    

Configuración para producción

Ahora tienes una implementación de ⌘ en funcionamiento, pero hay más pasos que puedes seguir para asegurarte de que tu aplicación esté lista para producción.

Inhabilitar depuración

Confirma que la variable DEBUG de mysite/settings.py esté configurada en False. Esto evitará que el usuario vea páginas de error detalladas, lo que puede filtrar información sobre las configuraciones.

Limita los privilegios de usuario de la base de datos.

Todos los usuarios que se crean mediante Cloud SQL tienen los privilegios asociados a la función de cloudsqlsuperuser: CREATEROLE, CREATEDB y LOGIN.

Crea el usuario de PostgreSQL de forma manual para evitar que tenga permisos. Deberás tener instalada la terminal interactiva psql o usar Cloud Shell, que tenga esta herramienta preinstalada.

Console

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  2. En Cloud Shell, usa la terminal integrada para conectarte a tu instancia de INSTANCE_NAME:

    gcloud sql connect INSTANCE_NAME --user postgres
    
  3. Ingresa la contraseña de usuario de postgres.

    Ahora estás usando psql. Deberías ver el mensaje de postgres=>.

  4. Crear un usuario

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    

    Reemplaza PASSWORD por una contraseña aleatoria.

  5. Otorga todos los derechos sobre la base de datos nueva al usuario nuevo:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  6. Salga de psql:

    \q
    

gcloud

  1. Inicia una conexión a la instancia de SQL:

    gcloud sql connect INSTANCE_NAME --user postgres
    

    Reemplaza INSTANCE_NAME por la instancia de Cloud SQL creada.

  2. Ingresa la contraseña de usuario de postgres.

    Ahora estás usando psql. Deberías ver el mensaje de postgres=>.

  3. Crear un usuario

    CREATE USER DATABASE_USERNAME WITH PASSWORD 'DATABASE_PASSWORD';
    
  4. Otorga todos los derechos sobre la base de datos nueva al usuario nuevo:

    GRANT ALL PRIVILEGES ON DATABASE DATABASE_NAME TO DATABASE_USERNAME;
    
  5. Salga de psql:

    \q
    

Configura permisos mínimos

De forma predeterminada, este servicio se implementa con la cuenta de servicio de procesamiento predeterminada. Sin embargo, en algunos casos, usar la cuenta de servicio predeterminada puede proporcionar demasiados permisos. Si deseas ser más restrictivo, debes crear tu propia cuenta de servicio y asignar solo los permisos que requiere tu servicio. Los permisos necesarios pueden variar de un servicio a otro, según los recursos que use un servicio en particular.

Las funciones mínimas que requiere este servicio son las siguientes:

  • Invocador de Cloud Run
  • Cliente de Cloud SQL
  • Administrador de almacenamiento, en el bucket de medios
  • Usuario con acceso a Secret Manager, en el secreto de configuración de ⌘. (El servicio no necesita acceder al secreto de administrador de ⌘).

Para crear una cuenta de servicio con los permisos necesarios y asignarla al servicio, ejecute el siguiente comando:

  1. En la CLI de gcloud, crea una cuenta de servicio con las funciones necesarias:

    gcloud iam service-accounts create polls-service-account
    SERVICE_ACCOUNT=polls-service-account@PROJECT_ID.iam.gserviceaccount.com
    
    # Cloud Run Invoker
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/run.invoker
    
    # Cloud SQL Client
    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/cloudsql.client
    
    # Storage Admin, on the media bucket
    gsutil iam ch \
        serviceAccount:${SERVICE_ACCOUNT}:roles/storage.objectAdmin \
        gs://MEDIA_BUCKET
    
    # Secret Accessor, on the Django settings secret.
    gcloud secrets add-iam-policy-binding django_settings \
        --member serviceAccount:${SERVICE_ACCOUNT} \
        --role roles/secretmanager.secretAccessor
    
  2. Asocia el servicio con la cuenta de servicio nueva para implementarla:

    gcloud run services update polls-service \
        --platform managed \
        --region REGION \
        --service-account ${SERVICE_ACCOUNT}
    

Examine el código

Aplicación de muestra

La app de muestra de Django se creó con las herramientas estándar de Django. Con los siguientes comandos, se crea el proyecto y la app de encuestas:

django-admin startproject mysite
python manage.py startapp polls

Las vistas base, los modelos y las configuraciones de ruta se copiaron de Cómo escribir tu primera app de npm (Parte 1 y Parte 2).

Secretos del Secret Manager

El archivo settings.py contiene código que usa la API de Python de Secret Manager para recuperar la versión más reciente del secreto con nombre y extraerlo en el entorno (con django-environ):

# SECURITY WARNING: don't run with debug turned on in production!
# Change this to "False" when you are ready for production
env = environ.Env(DEBUG=(bool, True))
env_file = os.path.join(BASE_DIR, ".env")

# Attempt to load the Project ID into the environment, safely failing on error.
try:
    _, os.environ["GOOGLE_CLOUD_PROJECT"] = google.auth.default()
except google.auth.exceptions.DefaultCredentialsError:
    pass

if os.path.isfile(env_file):
    # Use a local secret file, if provided

    env.read_env(env_file)
# ...
elif os.environ.get("GOOGLE_CLOUD_PROJECT", None):
    # Pull secrets from Secret Manager
    project_id = os.environ.get("GOOGLE_CLOUD_PROJECT")

    client = secretmanager.SecretManagerServiceClient()
    settings_name = os.environ.get("SETTINGS_NAME", "django_settings")
    name = f"projects/{project_id}/secrets/{settings_name}/versions/latest"
    payload = client.access_secret_version(name=name).payload.data.decode("UTF-8")

    env.read_env(io.StringIO(payload))
else:
    raise Exception("No local .env or GOOGLE_CLOUD_PROJECT detected. No secrets found.")

El secreto se usa para almacenar varios valores de Secrets a fin de reducir la cantidad de Secrets diferentes que se deben configurar. Si bien superuser_password podría haberse creado directamente desde la línea de comandos, en su lugar se usó el método basado en archivos. Si se generaba desde la línea de comandos, se tuvo cuidado de usar head -c para determinar la longitud de la string generada de manera aleatoria, a la vez que se garantizaba que no hubiera un carácter de línea nueva al final del archivo, lo que habría causado problemas cuando se ingresó la contraseña al administrador de ⌘.

Configuraciones de CSRF

Python tiene protección integrada contra la falsificación de solicitudes entre sitios (CSRF). A partir de npm 4.0, los cambios en el funcionamiento de esto implican que es importante indicarle a ⌘ qué es la URL alojada, de modo que pueda ofrecer las mejores protecciones para los usuarios que envían datos.

Proporciona la URL de la app como una variable de entorno en el archivo settings.py. Este es el valor que npm usa para la configuración relevante.

# SECURITY WARNING: It's recommended that you use this when
# running in production. The URL will be known once you first deploy
# to Cloud Run. This code takes the URL and converts it to both these settings formats.
CLOUDRUN_SERVICE_URL = env("CLOUDRUN_SERVICE_URL", default=None)
if CLOUDRUN_SERVICE_URL:
    ALLOWED_HOSTS = [urlparse(CLOUDRUN_SERVICE_URL).netloc]
    CSRF_TRUSTED_ORIGINS = [CLOUDRUN_SERVICE_URL]
    SECURE_SSL_REDIRECT = True
    SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
else:
    ALLOWED_HOSTS = ["*"]

Anulaciones de Secrets locales

Si se encuentra un archivo .env en el sistema de archivos local, se usa en lugar del valor de Secret Manager. Crear un archivo .env de forma local puede ayudarte con las pruebas locales (p.ej., el desarrollo local en función de una base de datos SQLite o cualquier otra configuración local).

Conexión a base de datos

El archivo settings.py contiene la configuración de tu base de datos de SQL: Si configuras USE_CLOUD_SQL_AUTH_PROXY, la configuración DATABASES cambia para inferir el uso del proxy de Cloud SQL Auth.

# Use django-environ to parse the connection string
DATABASES = {"default": env.db()}

# If the flag as been set, configure to use proxy
if os.getenv("USE_CLOUD_SQL_AUTH_PROXY", None):
    DATABASES["default"]["HOST"] = "127.0.0.1"
    DATABASES["default"]["PORT"] = 5432

Estática almacenada en la nube

El archivo settings.py también usa django-storages para integrar el bucket de medios de Cloud Storage directamente en el proyecto:

# Define static storage via django-storages[google]
GS_BUCKET_NAME = env("GS_BUCKET_NAME")
STATIC_URL = "/static/"
DEFAULT_FILE_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
STATICFILES_STORAGE = "storages.backends.gcloud.GoogleCloudStorage"
GS_DEFAULT_ACL = "publicRead"

Automatización con Cloud Build

El archivo cloudmigrate.yaml realiza no solo los pasos típicos de compilación de la imagen (crear la imagen de contenedor y enviarla a Container Registry), sino también los comandos migrate y collectstatic de ⌘. Estas requieren acceso a la base de datos, que se realiza mediante el app-engine-exec-wrapper, un asistente para el proxy de autenticación de Cloud SQL:

steps:
  - id: "build image"
    name: "gcr.io/cloud-builders/docker"
    args: ["build", "-t", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}", "."]

  - id: "push image"
    name: "gcr.io/cloud-builders/docker"
    args: ["push", "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"]

  - id: "apply migrations"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "--",
        "python",
        "manage.py",
        "migrate",
      ]

  - id: "collect static"
    name: "gcr.io/google-appengine/exec-wrapper"
    args:
      [
        "-i",
        "gcr.io/$PROJECT_ID/${_SERVICE_NAME}",
        "-s",
        "${PROJECT_ID}:${_REGION}:${_INSTANCE_NAME}",
        "-e",
        "SETTINGS_NAME=${_SECRET_SETTINGS_NAME}",
        "--",
        "python",
        "manage.py",
        "collectstatic",
        "--verbosity",
        "2",
        "--no-input",
      ]

substitutions:
  _INSTANCE_NAME: django-instance
  _REGION: us-central1
  _SERVICE_NAME: polls-service
  _SECRET_SETTINGS_NAME: django_settings

images:
  - "gcr.io/${PROJECT_ID}/${_SERVICE_NAME}"

En esta configuración, se usan variables de sustitución. Si cambias los valores del archivo directamente, la marca --substitutions se puede descartar en el momento de la migración.

En esta configuración, solo se aplican las migraciones existentes. Las migraciones deben crearse de forma local con el método del proxy de Cloud SQL Auth definido en Cómo ejecutar la app de forma local. Esta plantilla se puede extender para que ejecute otros comandos manage.py, según sea necesario.

A fin de extender la configuración de Cloud Build para incluir la implementación en una sola configuración sin tener que ejecutar dos comandos, consulta Implementación continua desde Git con Cloud Build. Esto requiere cambios de IAM, como se describe.

Creación de superusuarios con migraciones de datos

El comando de administración de ⌘ createsuperuser solo se puede ejecutar de manera interactiva, es decir, cuando el usuario puede ingresar información en respuesta a mensajes. Si bien puedes usar este comando con el proxy de Cloud SQL y ejecutar comandos dentro de una configuración local de Docker, otra forma es crear el superusuario como una migración de datos:

import os

from django.contrib.auth.models import User
from django.db import migrations
from django.db.backends.postgresql.schema import DatabaseSchemaEditor
from django.db.migrations.state import StateApps

import google.auth
from google.cloud import secretmanager

def createsuperuser(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None:
    """
    Dynamically create an admin user as part of a migration
    Password is pulled from Secret Manger (previously created as part of tutorial)
    """
    if os.getenv("TRAMPOLINE_CI", None):
        # We are in CI, so just create a placeholder user for unit testing.
        admin_password = "test"
    else:
        client = secretmanager.SecretManagerServiceClient()

        # Get project value for identifying current context
        _, project = google.auth.default()

        # Retrieve the previously stored admin password
        PASSWORD_NAME = os.environ.get("PASSWORD_NAME", "superuser_password")
        name = f"projects/{project}/secrets/{PASSWORD_NAME}/versions/latest"
        admin_password = client.access_secret_version(name=name).payload.data.decode(
            "UTF-8"
        )

    # Create a new user using acquired password, stripping any accidentally stored newline characters
    User.objects.create_superuser("admin", password=admin_password.strip())

class Migration(migrations.Migration):

    initial = True
    dependencies = []
    operations = [migrations.RunPython(createsuperuser)]

Limpia

Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.

Borra el proyecto

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

¿Qué sigue?