在 Google Kubernetes Engine 上运行 Django

GKE 上运行的 Django 应用会根据流量动态扩缩。

本教程假定您熟悉 Django 网络开发。如果您刚开始接触 Django 开发,最好先查看编写您的第一个 Django 应用,然后再继续操作。

本教程专门演示 Django,但您可以将此部署过程与其他基于 Django 的框架(例如 WagtailDjango CMS)搭配使用。

您还需要安装 Docker

目标

在此教程中,您将学习以下操作:

  • 创建并连接 Cloud SQL 数据库。
  • 创建并使用 Kubernetes Secret 值。
  • 将 Django 应用部署到 Google Kubernetes Engine。

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Cloud SQL, GKE 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. Make sure that billing is enabled for your Google Cloud project.

  9. Enable the Cloud SQL, GKE 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

准备环境

克隆示例应用

Django 示例应用的代码位于 GitHub 上的 GoogleCloudPlatform/python-docs-samples 代码库中。

  1. 您可以下载该示例的 ZIP 文件并将其解压缩,或将代码库克隆到本地机器:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
    
  2. 转到包含示例代码的目录:

    Linux/macOS

    cd python-docs-samples/kubernetes_engine/django_tutorial
    

    Windows

    cd python-docs-samples\kubernetes_engine\django_tutorial
    

确认 Python 设置

本教程依赖 Python 在您的机器上运行示例应用。示例代码还需要安装依赖项。

如需了解详情,请参阅 Python 开发环境指南

  1. 确认您的 Python 版本至少为 3.7。

     python -V
    

    您应该会看到 Python 3.7.3 或更高版本。

  2. 创建 Python 虚拟环境并安装依赖项:

    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
    

下载 Cloud SQL Auth 代理以从本地机器连接到 Cloud SQL

部署后,您的应用会使用 Google Kubernetes Engine 环境中内置的 Cloud SQL Auth 代理来与您的 Cloud SQL 实例进行通信。但要在本地测试应用,您必须在开发环境中安装和使用该代理的本地副本。 如需了解详情,请参阅 Cloud SQL Auth 代理指南

Cloud SQL Auth 代理使用 Cloud SQL API 与 SQL 实例进行交互。为此,它需要通过 gcloud 进行应用身份验证。

  1. 对 API 进行身份验证并获取凭据:

    gcloud auth application-default login
    
  2. 将 Cloud SQL Auth 代理下载并安装到本地机器上。

    Linux 64 位

    1. 下载 Cloud SQL Auth 代理:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy

    Linux 32 位

    1. 下载 Cloud SQL Auth 代理:
      wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.386 -O cloud_sql_proxy
    2. 如果找不到 wget 命令,请运行 sudo apt-get install wget 并重复执行下载命令。
    3. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy

    macOS 64 位

    1. 下载 Cloud SQL Auth 代理:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.amd64
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy

    macOS 32 位

    1. 下载 Cloud SQL Auth 代理:
      curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.386
    2. 使 Cloud SQL Auth 代理可执行:
      chmod +x cloud_sql_proxy

    Mac M1

    1. 下载 Cloud SQL Auth 代理:
        curl -o cloud_sql_proxy https://dl.google.com/cloudsql/cloud_sql_proxy.darwin.arm64
        
    2. 使 Cloud SQL Auth 代理可执行:
        chmod +x cloud_sql_proxy
        

    Windows 64 位

    右键点击 https://dl.google.com/cloudsql/cloud_sql_proxy_x64.exe,然后选择链接另存为以下载 Cloud SQL Auth 代理。将文件重命名为 cloud_sql_proxy.exe

    Windows 32 位

    右键点击 https://dl.google.com/cloudsql/cloud_sql_proxy_x86.exe,然后选择链接另存为以下载 Cloud SQL Auth 代理。将文件重命名为 cloud_sql_proxy.exe

    Cloud SQL Auth 代理 Docker 映像

    为方便起见,GitHub 上的 Cloud SQL Auth 代理代码库中提供了多个包含 Cloud SQL Auth 代理的容器映像。您可以通过 Docker 使用以下命令将最新映像拉取到本地机器:
    docker pull gcr.io/cloudsql-docker/gce-proxy:1.30.1
    

    其他操作系统

    对于此处未列出的其他操作系统,您可以通过源代码编译 Cloud SQL Auth 代理

    您可以选择将下载的文件移到其他位置,例如 PATH 上的某个位置或主目录。如果您选择这样做,则在本教程的后面部分启动 Cloud SQL Auth 代理时,请务必在使用 cloud_sql_proxy 命令时引用您选择的位置。

创建支持性服务

本教程使用多种 Google Cloud 服务来提供支持已部署 Django 项目的数据库、媒体存储和 Secret 存储。这些服务部署在特定区域。为了提高服务之间的效率,所有服务都应部署在同一区域中。如需详细了解离您最近的区域,请参阅各区域可使用的产品

设置 Cloud SQL for PostgreSQL 实例

Django 官方支持多个关系型数据库,但为 PostgreSQL 提供了最全面的支持。Cloud SQL 支持 PostgreSQL,因此本教程选择使用此类型的数据库。

以下部分介绍了如何为应用创建 PostgreSQL 实例、数据库和数据库用户。

  1. 创建 PostgreSQL 实例:

    控制台

    1. 在 Cloud Console 中,转到 Cloud SQL 实例页面。

      转到“Cloud SQL 实例”页面

    2. 点击创建实例

    3. 点击 PostgreSQL

    4. 实例 ID 字段中,输入 INSTANCE_NAME

    5. 为 postgres 用户输入密码。

    6. 对于其他字段,请保留默认值。

    7. 点击创建

    创建实例并准备好使用需要几分钟时间。

    gcloud

    • 创建 PostgreSQL 实例:

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

    替换以下内容:

    • INSTANCE_NAME:Cloud SQL 实例名称
    • PROJECT_ID:Google Cloud 项目 ID
    • REGIONGoogle Cloud 区域

    创建实例并准备好使用需要几分钟时间。

  2. 在所创建的实例中,创建一个数据库:

    控制台

    1. 在实例页面中,转到数据库标签页。
    2. 点击创建数据库
    3. 数据库名称对话框中,输入 DATABASE_NAME
    4. 点击创建

    gcloud

    • 在最近创建的实例中创建数据库:

      gcloud sql databases create DATABASE_NAME \
          --instance INSTANCE_NAME
      

      DATABASE_NAME 替换为实例中数据库的名称。

  3. 创建数据库用户:

    控制台

    1. 在实例页面中,转到用户标签页。
    2. 点击添加用户帐号
    3. 将用户帐号添加到实例对话框中的“内置身份验证”下:
    4. 输入用户名 DATABASE_USERNAME
    5. 输入密码 DATABASE_PASSWORD
    6. 点击添加

    gcloud

    • 在最近创建的实例中创建用户:

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

      PASSWORD 替换为安全密码。

创建服务帐号

代理需要一个拥有 Cloud SQL 实例编辑者权限的服务帐号。如需详细了解服务帐号,请参阅 Google Cloud 身份验证概览

  1. 在 Cloud Console 中,转到服务帐号页面。

    转到“服务帐号”

  2. 选择包含您的 Cloud SQL 实例的项目。
  3. 点击创建服务帐号
  4. 服务帐号名称字段中输入服务帐号的描述性名称。
  5. 服务帐号 ID 更改为一个不重复且易于识别的值,然后点击创建并继续
  6. 点击选择角色字段,然后选择以下角色之一:
    • Cloud SQL > Cloud SQL Client
    • Cloud SQL > Cloud SQL Editor
    • Cloud SQL > Cloud SQL Admin
  7. 点击完成以完成服务帐号的创建过程。
  8. 点击新服务帐号的操作菜单,然后选择管理密钥
  9. 点击添加键下拉菜单,然后点击创建新密钥
  10. 确认密钥类型是 JSON,然后点击创建

    私钥文件将下载到您的机器上。您可以将此文件移至其他位置,但要确保密钥文件的安全。

配置数据库设置

使用以下命令为数据库访问设置环境变量。这些环境变量用于本地测试。

Linux/MacOS

export DATABASE_NAME=DATABASE_NAME
export DATABASE_USER=DATABASE_USERNAME
export DATABASE_PASSWORD=DATABASE_PASSWORD

Windows

set DATABASE_USER=DATABASE_USERNAME
set DATABASE_PASSWORD=DATABASE_PASSWORD

设置 GKE 配置

  1. 此应用以单个 Kubernetes 配置表示,称为 polls。在 polls.yaml 中,将 <your-project-id> 替换为您的 Google Cloud 项目 ID (PROJECT_ID)。

  2. 运行以下命令并记下 connectionName 的值:

    gcloud sql instances describe INSTANCE_NAME --format "value(connectionName)"
    
  3. polls.yaml 文件中,将 <your-cloudsql-connection-string> 替换为 connectionName 值。

在本地计算机上运行应用

配置支持性服务后,您现在可以在计算机上运行应用。此设置允许本地开发、创建超级用户以及应用数据库迁移。

  1. 在单独的终端中启动 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
    

    此步骤会建立从本地计算机到您的 Cloud SQL 实例的连接,以进行本地测试。在您对应用进行本地测试的整个过程中,请确保 Cloud SQL Auth 代理一直运行。通过在单独的终端中运行此进程,您可以在此进程运行时继续工作。

  2. 通过新终端,在本地设置项目 ID:

    Linux/macOS

      export GOOGLE_CLOUD_PROJECT=PROJECT_ID
    

    Windows

      set GOOGLE_CLOUD_PROJECT=PROJECT_ID
    
  3. 运行 Django 迁移以设置模型和资源:

    python manage.py makemigrations
    python manage.py makemigrations polls
    python manage.py migrate
    python manage.py collectstatic
    
  4. 启动 Django 网络服务器:

    python manage.py runserver
    
  5. 在浏览器中,转到 http://localhost:8000

    该页面将显示以下文本:“Hello, world. You're at the polls index."。您的计算机上运行的 Django 网络服务器会提供示例应用页面。

  6. Ctrl/Cmd+C 停止本地网络服务器。

使用 Django 管理控制台

若要登录 Django 的管理控制台,您需要创建超级用户。由于您具有可在本地访问的数据库连接,因此可以运行管理命令:

  1. 创建超级用户。系统将提示您输入用户名、电子邮件和密码。

    python manage.py createsuperuser
    
  2. 启动本地网络服务器:

    python manage.py runserver
    
  3. 在浏览器中,转到 http://localhost:8000/admin

  4. 使用您在运行 createsuperuser 时使用的用户名和密码登录管理站点。

将应用部署到 GKE

将应用部署到 Google Cloud 后,应用会使用 Gunicorn 服务器。Gunicorn 服务器不提供静态内容,因此应用将使用 Cloud Storage 来提供静态内容。

收集并上传静态资源

  1. 创建 Cloud Storage 存储分区并将其配置为可公开读取。

    gsutil mb gs://PROJECT_ID_MEDIA_BUCKET
    gsutil defacl set public-read gs://PROJECT_ID_MEDIA_BUCKET
    
  2. 将所有静态内容收集到一个本地文件夹中:

    python manage.py collectstatic
    
  3. 将静态内容上传到 Cloud Storage:

    gsutil -m rsync -r ./static gs://PROJECT_ID_MEDIA_BUCKET/static
    
  4. mysite/settings.py 中,将 STATIC_URL 的值设置为以下网址,将 [YOUR_GCS_BUCKET] 替换为您的存储分区名称:

    http://storage.googleapis.com/PROJECT_ID_MEDIA_BUCKET/static/
    

设置 GKE

  1. 要初始化 GKE,请转到集群页面。

    转到“集群”页面

    首次在项目中使用 GKE 时,您需要等待“Kubernetes Engine 正在做准备,这可能需要一分钟或更长时间”消息消失。

  2. 创建 GKE 集群:

    gcloud container clusters create polls \
      --scopes "https://www.googleapis.com/auth/userinfo.email","cloud-platform" \
      --num-nodes 4 --zone "us-central1-a"
    

    您是否收到错误消息:"Project [PROJECT_ID] is not fully initialized with the default service accounts."

    初始化 GKE

    如果您收到错误,请转到 Google Cloud Console 以初始化项目中的 GKE。

    转到“集群”页面

    等待“Kubernetes Engine 正在做准备,这可能需要一分钟或更长时间”消息消失。

  3. 创建集群后,请使用与 gcloud 工具集成的 kubectl 命令行工具与 GKE 集群进行交互。由于 gcloudkubectl 是独立的工具,因此请确保将 kubectl 配置为与正确的集群进行交互。

    gcloud container clusters get-credentials polls --zone "us-central1-a"
    

设置 Cloud SQL

  1. 您需要多个密钥才能使您的 GKE 应用与 Cloud SQL 实例连接。一个密钥用于实例级访问(连接),而另外两个密钥用于数据库访问。如需了解两级访问控制的详情,请参阅实例访问控制

    1. 要为实例级访问创建密钥,请提供您在创建服务帐号时下载的 JSON 服务帐号密钥的位置 ([PATH_TO_CREDENTIAL_FILE])(请参阅创建服务帐号):

      kubectl create secret generic cloudsql-oauth-credentials \
        --from-file=credentials.json=[PATH_TO_CREDENTIAL_FILE]
      
    2. 如需创建用于数据库访问的 Secret,请使用初始化您的 Cloud SQL 实例第 2 步中定义的 SQL 数据库、用户名和密码:

      kubectl create secret generic cloudsql \
        --from-literal=database=DATABASE_NAME \
        --from-literal=username=DATABASE_USERNAME \
        --from-literal=password=DATABASE_PASSWORD
      
  2. 检索 Cloud SQL 代理的公共 Docker 映像。

    docker pull b.gcr.io/cloudsql-docker/gce-proxy
    
  3. 构建 Docker 映像,将 <your-project-id> 替换为您的项目 ID。

    docker build -t gcr.io/PROJECT_ID/polls .
    
  4. 配置 Docker 以将 gcloud 用作凭据帮助程序,以便您可以将映像推送到 Container Registry

    gcloud auth configure-docker
    
  5. 推送 Docker 映像。将 <your-project-id> 替换为您的项目 ID。

    docker push gcr.io/PROJECT_ID/polls
    
  6. 创建 GKE 资源:

    kubectl create -f polls.yaml
    

将应用部署到 GKE

创建资源后,集群上有三个 polls pod。检查您的 pod 的状态:

kubectl get pods

等待几分钟,让 pod 状态显示为 Running。如果 pod 未准备就绪或者您看到重启,则可以获取特定 pod 的日志以解决问题。[YOUR-POD-ID] 是上一个 kubectl get pods 命令返回的输出的一部分。

kubectl logs [YOUR_POD_ID]

查看在 Google Cloud 中运行的应用

在 pod 准备就绪后,您可以获取负载均衡器的公共 IP 地址:

kubectl get services polls

记下 EXTERNAL-IP 地址,然后在浏览器中转到 http://[EXTERNAL-IP],以查看 Django 轮询着陆页并访问管理控制台。

了解代码

示例应用

Django 示例应用使用标准 Django 工具创建。以下命令将创建项目及意见调查应用:

django-admin startproject mysite
python manage.py startapp polls

基础视图、模型和路由配置是从编写您的第一个 Django 应用第 1 部分第 2 部分)复制的。

数据库配置

settings.py 包含 SQL 数据库的配置:

DATABASES = {
    'default': {
        # If you are using Cloud SQL for MySQL rather than PostgreSQL, set
        # 'ENGINE': 'django.db.backends.mysql' instead of the following.
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.getenv('DATABASE_NAME'),
        'USER': os.getenv('DATABASE_USER'),
        'PASSWORD': os.getenv('DATABASE_PASSWORD'),
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Kubernetes pod 配置

polls.yaml 文件指定了两个 Kubernetes 资源。第一个是服务,它为 Django Web 应用定义了一致的名称和专用 IP 地址。第二个是具有公共外部 IP 地址的 HTTP 负载平衡器

# The polls service provides a load-balancing proxy over the polls app
# pods. By specifying the type as a 'LoadBalancer', Kubernetes Engine will
# create an external HTTP load balancer.
# For more information about Services see:
#   https://kubernetes.io/docs/concepts/services-networking/service/
# For more information about external HTTP load balancing see:
#   https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/
apiVersion: v1
kind: Service
metadata:
  name: polls
  labels:
    app: polls
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: polls

该服务会提供网络名称和 IP 地址,GKE pod 会在该服务后台运行应用的代码。polls.yaml 文件指定了为 GKE pod 提供声明式更新的部署。该服务将服务的选择器与部署的标签相匹配,以将流量定向到部署。在此示例中,选择器 polls 与标签 polls 匹配。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: polls
  labels:
    app: polls
spec:
  replicas: 3
  selector:
    matchLabels:
      app: polls
  template:
    metadata:
      labels:
        app: polls
    spec:
      containers:
      - name: polls-app
        # Replace  with your project ID or use `make template`
        image: gcr.io/<your-project-id>/polls
        # This setting makes nodes pull the docker image every time before
        # starting the pod. This is useful when debugging, but should be turned
        # off in production.
        imagePullPolicy: Always
        env:
            - name: DATABASE_NAME
              valueFrom:
                secretKeyRef:
                  name: cloudsql
                  key: database
            - name: DATABASE_USER
              valueFrom:
                secretKeyRef:
                  name: cloudsql
                  key: username
            - name: DATABASE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: cloudsql
                  key: password
        ports:
        - containerPort: 8080

      - image: gcr.io/cloudsql-docker/gce-proxy:1.16
        name: cloudsql-proxy
        command: ["/cloud_sql_proxy", "--dir=/cloudsql",
                  "-instances=<your-cloudsql-connection-string>=tcp:5432",
                  "-credential_file=/secrets/cloudsql/credentials.json"]
        volumeMounts:
          - name: cloudsql-oauth-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: ssl-certs
            mountPath: /etc/ssl/certs
          - name: cloudsql
            mountPath: /cloudsql
      volumes:
        - name: cloudsql-oauth-credentials
          secret:
            secretName: cloudsql-oauth-credentials
        - name: ssl-certs
          hostPath:
            path: /etc/ssl/certs
        - name: cloudsql
          emptyDir: {}

清理

为避免因本教程中使用的资源导致您的 Google Cloud 帐号产生费用,请删除包含这些资源的项目,或者保留项目但删除各个资源。

删除项目

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

逐个删除资源

如果您不想删除项目,请删除个别资源。

  1. 删除 Google Kubernetes Engine 集群:

    gcloud container clusters delete polls
    
  2. 删除您推送到 Container Registry 的 Docker 映像:

    gcloud container images delete gcr.io/PROJECT_ID/polls
    
  3. 删除 Cloud SQL 实例:

    gcloud sql instances delete INSTANCE_NAME
    

后续步骤