1. 概览
简介
在此 Codelab 中,您将学习如何部署使用多个容器的 Cloud Run 服务。您将创建一个将用作 Cloud Run Ingress 容器的 node.js 应用,以及一个将用作辅助信息文件的额外 node.js 应用。
技术概览
在一个 Cloud Run 实例中使用多个容器时,一个容器用作 Web 入站流量的主容器。一个或多个其他容器称为 Sidecar。
多个容器相互通信的方式有两种:
- 这些容器共享 localhost 网络接口,因此所有容器都可以监听端口,例如localhost:port.
- 您还可以使用内存中的卷并将其装载到容器上以共享文件。
使用场景
由于 Cloud Run 实例中的所有容器都共用 localhost 网络接口,因此您可以在主容器前面使用辅助信息文件来代理请求。这种代理可以提供一个额外的抽象层,通过拦截请求并将其转发到适当的端点,在客户端和服务器之间更高效地流向应用。例如,您可以使用 DockerHub 中的官方 Nginx 映像(如此处所示)。
由于多个容器可以通过共享卷共享文件来进行通信,因此您可以向服务添加各种 Sidecar 应用。例如,您可以对 Cloud Run 服务进行插桩,以使用 OpenTelemetry 等自定义代理导出日志、指标和跟踪记录(OpenTelemetry 示例)。另一个示例是使用 Sidecar 连接到 Cloud Spanner PostgreSQL 数据库(Cloud Spanner Postgress 示例)。
此 Codelab 中的示例
在此 Codelab 中,您将首先部署一项 Cloud Run 服务,该服务的入站流量容器通过 localhost 端口与 Sidecar 通信。然后,您将更新 Ingress 容器和 Sidecar,以通过卷装载共享文件。
学习内容
- 如何创建使用 Sidecar 的容器
- 入站流量容器如何使用 localhost 与 Sidecar 通信
- 入站流量容器和 Sidecar 如何通过装载的卷共享文件
2. 设置和要求
前提条件
- 您已登录 Cloud 控制台。
- 您之前已部署了 Cloud Run 服务。例如,您可以按照快速入门:部署 Web 服务开始操作。
激活 Cloud Shell
- 在 Cloud Console 中,点击激活 Cloud Shell。
如果这是您第一次启动 Cloud Shell,系统会显示一个中间屏幕,说明它是什么。如果您看到中间屏幕,请点击继续。
预配和连接到 Cloud Shell 只需花几分钟时间。
这个虚拟机装有所需的所有开发工具。它提供了一个持久的 5 GB 主目录,并在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。您在此 Codelab 中的大部分(即使不是全部)工作都可以通过浏览器完成。
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设为您的项目 ID。
- 在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list
命令输出
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- 在 Cloud Shell 中运行以下命令,以确认 gcloud 命令了解您的项目:
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 创建 Ingress 应用
设置环境变量
在此 Codelab 中,您将创建一些环境变量,以提高此 Codelab 中使用的 gcloud
命令的可读性。
REGION=<YOUR-REGION> PROJECT_ID=<YOUR-PROJECT-ID> SERVICE_NAME=sidecar-codelab REPO_NAME=sidecar-codelab
创建 ArtifactRegistry 代码库以保存您的容器映像
您可以在 Artifact Registry 中创建代码库,用于存储此 Codelab 的容器映像。
gcloud artifacts repositories create $REPO_NAME --repository-format=docker \ --location=$REGION --description="sidecar codelab"
然后,创建一个包含以下内容的 package.json
文件:
{ "name": "sidecar-codelab", "version": "1.0.0", "private": true, "description": "demonstrates how to use sidecars in cloud run", "main": "index.js", "author": "Google LLC", "license": "Apache-2.0", "scripts": { "start": "node ingress.js" }, "dependencies": { "axios": "^1.6.2", "express": "^4.18.2" } }
现在,创建一个名为 ingress.js
且包含以下内容的文件:
const express = require('express'); const app = express(); const axios = require("axios"); app.get('/', async (req, res) => { let response = await axios.get("http://localhost:5000"); res.send("The sidecar says: " + response.data); }); const port = parseInt(process.env.PORT) || 8080; app.listen(port, () => { console.log(`Ingress container listening on port ${port}`); });
为 Ingress 容器创建 dockerfile
FROM node:20.10.0-slim WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --production # Copy local code to the container image. COPY . . # Run the web service on container startup. ENV PORT=8080 CMD [ "npm", "start" ]
并为 Ingress 容器创建一个 ``.dockerignore` 文件。
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
现在,您可以通过运行以下命令为 Ingress 容器构建映像:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest
4. 创建 Sidecar 应用
在本部分中,您将创建第二个 node.js 应用,该应用将在 Cloud Run 服务中用作辅助信息文件。
前往 Sidecar 目录。
cd ../sidecar
创建一个包含以下内容的 package.json
文件:
{ "name": "sidecar-codelab", "version": "1.0.0", "private": true, "description": "demonstrates how to use sidecars in cloud run", "main": "index.js", "author": "Google LLC", "license": "Apache-2.0", "scripts": { "start": "node sidecar.js" }, "dependencies": { "axios": "^1.6.2", "express": "^4.18.2" } }
现在,创建一个名为 sidecar.js
且包含以下内容的文件:
const express = require('express'); const app = express(); app.get('/', async (req, res) => { res.send("Hello ingress container! I'm the sidecar."); }); const port = parseInt(process.env.PORT || 5000); app.listen(port, () => { console.log(`Sidecar container listening on port ${port}`); });
为 Sidecar 容器创建 Dockerfile
FROM node:20.10.0-slim WORKDIR /usr/src/app COPY package*.json ./ RUN npm install --production # Copy local code to the container image. COPY . . # Run the web service on container startup. ENV PORT=5000 CMD [ "npm", "start" ]
然后为 Sidecar 容器创建一个 ``.dockerignore` 文件。
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
现在,您可以通过运行以下命令为 Ingress 容器构建映像:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest
部署 Cloud Run 服务
您将使用 yaml 文件部署 Cloud Run 服务。
导航到父级目录。
cd ..
创建一个名为 sidecar-codelab.yaml
且包含以下内容的文件:
apiVersion: serving.knative.dev/v1 kind: Service metadata: annotations: name: sidecar-codelab labels: cloud.googleapis.com/location: "<YOUR_REGION>" spec: template: spec: containers: - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest" ports: - containerPort: 8080 - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest" env: - name: PORT value: "5000"
然后,使用以下命令部署该服务。您需要使用 gcloud beta,因为卷装载处于公开预览版阶段。
gcloud beta run services replace sidecar-codelab.yaml
部署后,将服务网址保存在环境变量中。
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)')
5. 调用 Cloud Run 服务
现在,您可以通过提供身份令牌来调用服务。
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}
结果应类似于以下示例输出:
The sidecar says: Hello ingress container! I'm the sidecar.
6. 通过卷装载共享文件
在本部分中,您将更新容器,以通过卷装载共享文件。在此示例中,入站流量容器将写入共享卷上的文件。Sidecar 将读取文件,并将其内容返回给 Ingress 容器。
首先,您将更新入站流量容器代码。导航到 Ingress 目录。
cd ../ingress
然后将 ingress.js
文件的内容替换为以下代码:
const express = require('express'); const app = express(); const fs = require('fs'); const axios = require("axios"); const filename = "test.txt" let path = "/my-volume-mount"; app.use(path, express.static(path)); try { fs.writeFileSync(`${path}/${filename}`, "The ingress container created this file."); } catch (err) { console.error(err); } app.get('/', async (req, res) => { let response = await axios.get("http://localhost:5000"); res.send("The sidecar says: " + response.data); }); const port = parseInt(process.env.PORT) || 8080; app.listen(port, () => { console.log(`Ingress container listening on port ${port}`); });
运行以下命令,为您的入站流量容器构建新映像:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest
现在,导航到 Sidecar 目录:
cd ../sidecar
并使用以下内容更新 sidecar.js
:
const express = require('express'); const app = express(); const fs = require('fs'); const filename = "test.txt" let path = "/my-volume-mount"; app.use(path, express.static(path)); async function readFile() { try { return await fs.readFileSync(`${path}/${filename}`, { encoding: 'utf8' }); } catch (err) { console.log(err); } } app.get('/', async (req, res) => { let contents = await readFile(); res.send(contents); }); const port = parseInt(process.env.PORT || 5000); app.listen(port, () => { console.log(`Sidecar container listening on port ${port}`); });
运行以下命令,为您的 Sidecar 容器构建新映像:
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest
使用以下代码更新 sidecar-codelab.yaml
以共享卷:
apiVersion: serving.knative.dev/v1 kind: Service metadata: annotations: name: sidecar-codelab labels: cloud.googleapis.com/location: "<YOUR_REGION>" spec: template: spec: containers: - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/ingress:latest" ports: - containerPort: 8080 volumeMounts: - mountPath: /my-volume-mount name: in-memory-1 - image: "<YOUR_REGION>-docker.pkg.dev/<YOUR_PROJECT_ID>/sidecar-codelab/sidecar:latest" env: - name: PORT value: "5000" volumeMounts: - mountPath: /my-volume-mount name: in-memory-1 volumes: - emptyDir: medium: Memory name: in-memory-1
部署更新后的 sidecar-codelab.yaml
文件
gcloud beta run services replace sidecar-codelab.yaml
现在,您可以通过提供身份令牌来调用服务。
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}
结果应类似于以下示例输出:
The sidecar says: the ingress container created this file.
7. 恭喜!
恭喜您完成此 Codelab!
建议您查看有关 Cloud Run 的文档,特别是部署多容器和使用内存中卷装载。
所学内容
- 如何创建使用 Sidecar 的容器
- 入站流量容器如何使用 localhost 与 Sidecar 通信
- 入站流量容器和 Sidecar 如何共享装载的卷
8. 清理
为避免产生意外费用(例如,如果此 Cloud Functions 函数被意外调用的次数超过免费层级中的每月 Cloud Run 调用次数),您可以删除 Cloud Run 服务或删除您在第 2 步中创建的项目。
如需删除此 Cloud Functions 函数,请前往 https://console.cloud.google.com/run/ 前往 Cloud Functions 函数 Cloud 控制台,然后删除 sidecar-codelab
服务(如果您使用其他名称,则删除 $SERVICE_NAME)。
如果您选择删除整个项目,可以前往 https://console.cloud.google.com/cloud-resource-manager,选择您在第 2 步中创建的项目,然后选择“删除”。如果删除项目,则需要在 Cloud SDK 中更改项目。您可以通过运行 gcloud projects list
来查看所有可用项目的列表。