使用 Nginx 实现前端代理

本页面介绍了如何将 NGINX 用作应用容器的前端代理。如果您需要处理请求或响应,这会非常有用。如果您的应用容器仅支持 HTTP/1,并且您出于性能原因需要使用 HTTP/2 端到端,则可以添加 gzip 压缩,或将 HTTP/2 转换为 HTTP/1。

在本页面提供的示例中,Nginx 容器作为主服务容器在每个 Cloud Run 实例上运行,并且配置为将请求转发到作为边车容器运行的应用容器,如下图所示:

Cloud Run mc hello nginx 1

在 Cloud Run 中进行前端代理的最有效方法是将 Nginx 服务器代理服务器容器和 Web 应用容器部署为单个 Cloud Run 服务:

Cloud Run mc hello nginx 2

此单个 Cloud Run 服务接受请求并将其传送到入站流量(服务)容器,在本例中为代理服务器。然后,代理服务器通过 localhost 网络接口向 Web 应用发送请求,以避免经过任何外部网络。

部署为单个 Cloud Run 服务可以缩短延迟时间,减少服务管理开销,并且可消除外部网络暴露。Cloud Run 不会直接与 Sidecar 容器交互,除了在服务启动或停止时启动或停止 Sidecar 容器。

Web 应用容器和任何 Sidecar 容器可以使用不同的编程语言编写。如需查看以 PHP 编写的示例,请参阅 GitHub 中的 PHP nginx 示例

须知事项

  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. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

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

  6. Enable the Cloud Run and Secret Manager APIs.

    Enable the APIs

  7. 安装并初始化 gcloud CLI
  8. 更新 Google Cloud CLI:gcloud components update
  9. 配置 Google Cloud CLI:gcloud init
  10. 使用 Google Cloud CLI 进行身份验证:gcloud auth login

部署所需的权限

您必须拥有下列角色之一:

  • Cloud Run Admin 和 Service Account User 角色
  • 包含此特定权限列表的任何自定义角色。

配置概览

以下说明使用预构建的容器映像,因此实现前端代理只需配置容器和服务本身。

配置 Nginx 入站流量容器

容器映像是 Docker Hub 中提供nginx。它基本可以按原样使用,但需要配置为作为代理服务运行,并将代理的请求传送到边车容器监听 localhost 所通过的端口。本页面上的示例还为请求和响应启用了 gzip 压缩。

配置使用装载在 /etc/nginx/conf.d/nginx.conf 中的文本文件提供。由于您无法直接修改容器中的文件,因此必须在 /etc/nginx/conf.d/ 中装载一个包含配置文件的卷。在 Cloud Run 上运行的容器中的特定位置装载文件的一种方法是将文件内容存储在 Secret Manager Secret 中,然后将该 Secret 装载到所选位置。

将以下内容复制到本地机器的当前目录下名为 nginx.conf 的文件中。


server {
    # Listen at port 8080
    listen 8080; 
    # Server at localhost
    server_name _;
    # Enables gzip compression to make our app faster
    gzip on;

    location / {
        # Passes initial requests to port 8080 to `hello` container at port 8888
        proxy_pass   http://127.0.0.1:8888;
    }
}

在配置中,执行以下操作:

  • 分配 nginx 以监听位于 localhost 的同一 Cloud Run 默认端口 8080
  • 应用 gzip 压缩以提升性能。
  • 指示 proxy_pass 将对此入站流量容器的任何请求传送到 localhost 端口 8888 处的 Web 应用边车容器。

创建包含 nginx.conf 文件的内容的 Secret。

控制台

  1. 进入 Google Cloud 控制台中的 Secret Manager 页面:

    前往 Secret Manager

  2. 点击创建密钥

  3. name 字段中,输入 nginx_config

  4. 上传位于 multi-container/hello-nginx-sample/nginx.confnginx.conf 文件作为 Secret 值。

  5. 保留默认值 (Google-managed encryption key, etc)。

  6. 点击创建密钥

  7. 为项目计算服务账号授予对此新 Secret 的访问权限。为此,请进入 Google Cloud 控制台中的 IAM 页面:

    进入 IAM

  8. 找到名为 Compute Engine default service account 的主服务账号,然后点击修改主账号

  9. 点击添加其他角色,然后选择 Secret Manager Secret Accessor

  10. 点击保存

gcloud

  1. 在终端中,使用以下命令在 Secret Manager 中创建新的 nginx_config Secret:

    gcloud secrets create nginx_config --replication-policy='automatic' --data-file='./nginx.conf'

  2. 使用以下命令为项目计算服务账号授予对此新 Secret 的访问权限

    export PROJECT_NUMBER=$(gcloud projects describe $(gcloud config get-value project) --format='value(projectNumber)')
    gcloud secrets add-iam-policy-binding nginx_config --member=serviceAccount:$PROJECT_NUMBER-compute@developer.gserviceaccount.com --role='roles/secretmanager.secretAccessor'

  3. 通过运行 gcloud secrets list 验证 Secret 是否已创建。

Web 应用 Sidecar 示例映像简介

以下说明使用 us-docker.pkg.dev/cloudrun/container/hello 中的示例容器映像。您需要指定容器监听的端口号,并将 localhost 指定为主机,如以下部分中的指定边车容器配置下所述。

配置多容器服务

您可以使用 Google Cloud 控制台或 Cloud Run YAML 文件配置具有多个容器的 Cloud Run 服务。

在服务配置中,将 Nginx 代理服务器指定为入站流量(服务)容器、容器监听的端口、容器是接受 HTTP 1 请求还是 HTTP 2 请求,以及容器启动顺序。入站流量容器(代理服务器)依赖于 Web 应用 Sidecar,因此必须先启动 Web 应用 Sidecar。

接下来的几个部分中介绍了这些配置。

添加 YAML 元数据

控制台

前往部署服务以查看完整的控制台说明。

YAML

  1. 如果您要创建新的服务,请跳过此步骤。如果您要更新现有服务,请下载其 YAML 配置

    gcloud run services describe SERVICE --format export > service.yaml
  2. service.yaml 中,添加以下内容:

    metadata:
      name: "MC_SERVICE_NAME"
      labels:
        cloud.googleapis.com/location: "REGION"
      annotations:
        # Required to use Cloud Run multi-containers (preview feature)
        run.googleapis.com/launch-stage: BETA
        run.googleapis.com/description: sample tutorial service
        # Externally available
        run.googleapis.com/ingress: all

本部分介绍了服务的修订版本,其中包括可能因修订版本而异的属性。

指定容器启动顺序

控制台

前往部署服务以查看完整的控制台说明。

YAML

service.yaml 中,附加以下内容:

spec:
  template:
    metadata:
      annotations:
        # Defines container startup order within multi-container service.
        # Below requires hello container to spin up before nginx container,
        # which depends on the hello container.
        # https://cloud.google.com/run/docs/configuring/containers#container-ordering
        run.googleapis.com/container-dependencies: "{nginx: [hello]}"

请注意 container-dependencies 注解,用于指示 Cloud Run 在启动 nginx 容器之前先等待 hello 容器启动。否则,如果 nginx 容器先启动,它可能会尝试将 Web 请求代理到尚未准备就绪的 Web 应用容器,这将生成 Web 错误响应。

每个容器都可以视需要定义一个名称属性,该属性可用于在其他指令中引用它。服务容器运行名为 nginx 的代理服务器。这是 Cloud Run 将传入请求发送到的容器,因此您必须指定 HTTP 的版本以及要将传入请求发送到的容器端口。

指定服务容器配置

控制台

前往部署服务以查看完整的控制台说明。

YAML

service.yaml 文件中,附加以下内容:

spec:
  containers:
    # A) Serving ingress container "nginx" listening at PORT 8080
    # Main entrypoint of multi-container service.
    # Source is stored in nginx_config secret in Secret Manager.
    # Any pings to this container will proxy over to hello container at PORT 8888.
    # https://cloud.google.com/run/docs/container-contract#port
    - image: nginx
      name: nginx
      ports:
        - name: http1
          containerPort: 8080
      resources:
        limits:
          cpu: 500m
          memory: 256Mi
      # Referencing declared volume below,
      # Declaring volume to mount in current ingress container's filesystem
      # https://cloud.google.com/run/docs/reference/rest/v2/Container#volumemount
      volumeMounts:
        - name: nginx-conf-secret
          readOnly: true
          mountPath: /etc/nginx/conf.d/
      startupProbe:
        timeoutSeconds: 240
        periodSeconds: 240
        failureThreshold: 1
        tcpSocket:
          port: 8080

nginx 服务器需要 /etc/nginx/conf.d/ 目录中的配置文件。为此,请在该位置装载一个包含此文件的卷。volumeMount 部分指定要放置在其中的名为 configuration 的卷。卷本身是在文件后面自己的部分中定义的。

指定边车容器配置

控制台

前往部署服务以查看完整的控制台说明。

YAML

service.yaml 中,附加以下内容:

- image: us-docker.pkg.dev/cloudrun/container/hello
  name: hello
  env:
    - name: PORT
      value: "8888"
  resources:
    limits:
      cpu: 1000m
      memory: 512Mi
  startupProbe:
    timeoutSeconds: 240
    periodSeconds: 240
    failureThreshold: 1
    tcpSocket:
      port: 8888

hello 应用还需要配置信息。它会在 PORT 环境变量中指定的端口上监听传入请求。该名称和值在 env 部分指定。

指定 Secret 卷

控制台

前往部署服务以查看完整的控制台说明。

YAML

service.yaml 文件中,附加以下内容:

volumes:
  - name: nginx-conf-secret
    secret:
      secretName: nginx_config
      items:
        - key: latest
          path: default.conf

指定在 volumeMount 部分中装载的配置 volume。它包含一个名为 nginx.conf 的文件,其内容定义成名为 nginx-conf-secret 的 Secret 的值。

部署该服务

控制台

  1. 进入 Google Cloud 控制台中的 Cloud Run 页面:

    转到 Cloud Run

  2. 点击部署容器,然后选择服务,以显示创建服务表单。

    1. 选择从现有容器映像部署一个修订版本,然后输入 nginx 作为容器映像网址
    2. 服务名称字段中,提供服务的名称,例如 hello-mc
    3. 区域列表中,选择要部署到的位置,例如 us-west1
    4. 身份验证下,选择 Allow unauthenticated invocations。如果您没有选择此选项的权限(Cloud Run Admin 角色),系统会部署服务并要求进行身份验证。
  3. 点击容器、卷、网络、安全性以展开配置表单。

    1. 点击标签页。
    2. 点击添加卷
    3. 卷类型列表中,选择 Secret
    4. 卷名称字段中,输入 nginx-conf-secret
    5. Secret 字段中,输入 nginx_config
    6. 指定 Secret 版本的路径下,将 default.conf 指定为路径,并将 latest 指定为版本。
    7. 点击创建以创建 Secret 卷。
  4. 点击容器标签页以显示修改容器表单。

    1. 点击设置,然后在资源下,将内存更改为 256MiB,并将 CPU 更改为 1 个 CPU
    2. 点击卷装载
    3. 点击装载卷
    4. 从名称列表中选择 nginx-conf-secret
    5. 装载路径字段中,输入 etc/nginx/conf.d
    6. 点击完成,即可完成第一个容器的配置。
  5. 点击添加容器以添加边车容器并显示新建容器表单。

    1. 选择默认容器映像网址 us-docker.pkg.dev/cloudrun/container/hello
    2. 点击设置标签页,然后在资源下,将内存更改为 256MiB,并将 CPU 更改为 1 个 CPU
    3. 点击变量和 Secret
    4. 点击添加变量
    5. 输入 PORT 作为新环境变量的名称,输入 8888 作为值。
    6. 点击完成
  6. 前往第一个容器 (nginx) 的修改容器表单。

    1. 点击设置标签。
    2. 容器启动顺序下,从根据列表中选择 nginx。这意味着,nginx 容器仅会在 hello 容器成功启动后启动。
    3. 点击创建,等待服务部署完成。

gcloud

如需将代理服务器容器和 Web 应用容器部署为单个服务,请运行以下命令:

gcloud run services replace service.yaml

验证已部署的服务

gcloud

如需验证部署是否成功,请复制生成的 Cloud Run 网址并在浏览器中打开该网址,或者使用以下命令发送经过身份验证的请求:

curl --header "Authorization: Bearer $(gcloud auth print-identity-token)" 

您应该会看到 nginx 代理已成功移植到 hello 边车容器且响应状态为 200

亲自试用

如需学习本教程,请执行以下操作:

gcloud

  1. 在终端中,将示例应用代码库克隆到本地机器:

    git clone https://github.com/GoogleCloudPlatform/cloud-run-samples

  2. 切换到包含 Cloud Run 示例代码的目录:

    cd cloud-run-samples/multi-container/hello-nginx-sample/

后续步骤

如需详细了解如何在 Cloud Run 服务中使用 Sidecar,请参阅: