Tworzenie usługi Cloud Run przy użyciu pliku pomocniczego

1. Przegląd

Wprowadzenie

Z tego samouczka dowiesz się, jak wdrożyć usługę Cloud Run, która korzysta z wielu kontenerów. Utworzysz aplikację Node.js, która będzie używana jako kontener wejściowy Cloud Run, oraz dodatkową aplikację Node.js, która będzie używana jako kontener pomocniczy.

Omówienie techniczne

Jeśli w instancji Cloud Run używasz wielu kontenerów, jeden z nich jest używany jako główny kontener na potrzeby ruchu przychodzącego z internetu. Co najmniej 1 dodatkowy kontener jest nazywany kontenerem pomocniczym.

Istnieją 2 sposoby komunikacji między wieloma kontenerami:

  1. Kontenery współdzielą interfejs sieciowy localhost, więc wszystkie mogą nasłuchiwać na porcie, np. localhost:port.
  2. Możesz też używać woluminów w pamięci i montować je w kontenerach, aby udostępniać pliki.

Przypadki użycia

Ponieważ wszystkie kontenery w instancji Cloud Run współdzielą interfejs sieciowy localhost, możesz użyć kontenera pomocniczego przed głównym kontenerem, aby przekazywać żądania. Takie serwery proxy mogą zapewniać dodatkową warstwę abstrakcji, która usprawnia przepływ ruchu do aplikacji między klientem a serwerami, przechwytując żądania i przekazując je do odpowiedniego punktu końcowego. Możesz na przykład użyć oficjalnego obrazu Nginx z DockerHub (jak pokazano tutaj).

Ponieważ wiele kontenerów może się komunikować, udostępniając pliki za pomocą woluminów współdzielonych, możesz dodać do usługi różne aplikacje pomocnicze. Możesz na przykład instrumentować usługę Cloud Run tak, aby korzystała z agentów niestandardowych, takich jak OpenTelemetry, do eksportowania logów, wskaźników i śladów (przykład OpenTelemetry). Innym przykładem jest użycie kontenera dodatkowego do połączenia z bazą danych Cloud Spanner PostgreSQL (przykład Cloud Spanner PostgreSQL).

Przykłady w tych ćwiczeniach z programowania

W tym module dowiesz się, jak najpierw wdrożyć usługę Cloud Run, w której kontener ruchu przychodzącego komunikuje się z kontenerem pomocniczym za pomocą portu localhost. Następnie zaktualizujesz kontener ruchu przychodzącego i kontener pomocniczy, aby udostępniać plik za pomocą podłączenia woluminu.

Czego się nauczysz

  • Jak utworzyć kontener, który korzysta z kontenera pomocniczego
  • Jak kontener wejściowy może komunikować się z kontenerem pomocniczym za pomocą hosta lokalnego
  • Jak kontener wejściowy i kontener pomocniczy mogą udostępniać plik za pomocą zamontowanego woluminu

2. Konfiguracja i wymagania

Wymagania wstępne

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell d1264ca30785e435.png.

cb81e7c8e34bc8d.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tego środowiska. Jeśli pojawił się ekran pośredni, kliknij Dalej.

d95252b003979716.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

7833d5e1c5d18f54.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Tworzenie aplikacji wejściowej

Ustawianie zmiennych środowiskowych

W tym module utworzysz kilka zmiennych środowiskowych, aby zwiększyć czytelność poleceń gcloud używanych w tym module.

REGION=<YOUR-REGION>
PROJECT_ID=<YOUR-PROJECT-ID>

SERVICE_NAME=sidecar-codelab
REPO_NAME=sidecar-codelab

Tworzenie repozytorium Artifact Registry do przechowywania obrazów kontenerów

W tym samouczku możesz utworzyć repozytorium w Artifact Registry, w którym będziesz przechowywać obrazy kontenerów.

gcloud artifacts repositories create $REPO_NAME --repository-format=docker \
--location=$REGION --description="sidecar codelab"

Następnie utwórz plik package.json o tej treści:

{
  "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"
  }
}

Teraz utwórz plik o nazwie ingress.js z tą treścią:

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}`);
});

Tworzenie pliku Dockerfile dla kontenera wejściowego

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" ]

Utwórz plik „.dockerignore” dla kontenera wejściowego.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

Teraz możesz utworzyć obraz kontenera Ingress, uruchamiając to polecenie:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

4. Tworzenie aplikacji pomocniczej

W tej sekcji utworzysz drugą aplikację Node.js, która będzie używana jako kontener dodatkowy w usłudze Cloud Run.

Przejdź do katalogu sidecar.

cd ../sidecar

Utwórz plik package.json z tą zawartością:

{
  "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"
  }
}

Teraz utwórz plik o nazwie sidecar.js z tą treścią:

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}`);
});

Tworzenie pliku Dockerfile dla kontenera pomocniczego

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" ]

Utwórz plik „.dockerignore” dla kontenera pomocniczego.

# Exclude locally installed dependencies
node_modules/

# Exclude "build-time" ignore files.
.dockerignore
.gcloudignore

# Exclude git history and configuration.
.gitignore

Teraz możesz utworzyć obraz kontenera Ingress, uruchamiając to polecenie:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

Wdrażanie usługi Cloud Run

Usługę Cloud Run wdrożysz za pomocą pliku YAML.

Przejdź do katalogu nadrzędnego.

cd ..

Utwórz plik o nazwie sidecar-codelab.yaml z tą zawartością:

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"

Następnie wdróż usługę za pomocą tego polecenia. Musisz użyć gcloud beta, ponieważ montowanie woluminów jest dostępne w publicznej wersji przedpremierowej.

gcloud beta run services replace sidecar-codelab.yaml

Po wdrożeniu zapisz adres URL usługi w zmiennej środowiskowej.

SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)') 

5. Wywoływanie usługi Cloud Run

Teraz możesz wywołać usługę, podając token tożsamości.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

Wyniki powinny wyglądać podobnie do tych poniżej:

The sidecar says: Hello ingress container! I'm the sidecar.

6. Udostępnianie pliku za pomocą punktu montowania woluminu

W tej sekcji zaktualizujesz kontenery, aby udostępniać plik za pomocą podłączenia woluminu. W tym przykładzie kontener wejściowy będzie zapisywać dane w pliku na woluminie współdzielonym. Kontener pomocniczy odczyta plik i zwróci jego zawartość do kontenera wejściowego.

Najpierw zaktualizuj kod kontenera wejściowego. Przejdź do katalogu ingress.

cd ../ingress

Następnie zamień zawartość pliku ingress.js na taką:

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}`);
});

Aby utworzyć nowy obraz kontenera ruchu przychodzącego, uruchom to polecenie:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest

Teraz przejdź do katalogu sidecar:

cd ../sidecar

Zaktualizuj plik sidecar.js o tę zawartość:

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}`);
});

Aby utworzyć nowy obraz kontenera pomocniczego, uruchom to polecenie:

gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/sidecar:latest

Aby udostępnić wolumin, zaktualizuj sidecar-codelab.yaml w ten sposób:

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

Wdróż zaktualizowany plik sidecar-codelab.yaml.

gcloud beta run services replace sidecar-codelab.yaml

Teraz możesz wywołać usługę, podając token tożsamości.

curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}

Wyniki powinny wyglądać podobnie do tych poniżej:

The sidecar says: the ingress container created this file.

7. Gratulacje!

Gratulujemy ukończenia ćwiczenia!

Zalecamy zapoznanie się z dokumentacją Cloud Run, a w szczególności z informacjami o wdrażaniu wielu kontenerów i korzystaniu z montowania woluminów w pamięci.

Omówione zagadnienia

  • Jak utworzyć kontener, który korzysta z kontenera pomocniczego
  • Jak kontener wejściowy może komunikować się z kontenerem pomocniczym za pomocą hosta lokalnego
  • Jak kontener wejściowy i kontener pomocniczy mogą współdzielić zamontowany wolumin

8. Czyszczenie danych

Aby uniknąć przypadkowych opłat (np. jeśli ta funkcja Cloud Functions zostanie przypadkowo wywołana więcej razy niż miesięczny limit wywołań Cloud Run w ramach bezpłatnej wersji), możesz usunąć usługę Cloud Run lub projekt utworzony w kroku 2.

Aby usunąć funkcję Cloud, otwórz konsolę Cloud Function pod adresem https://console.cloud.google.com/run/ i usuń usługę sidecar-codelab (lub $SERVICE_NAME, jeśli używasz innej nazwy).

Jeśli zdecydujesz się usunąć cały projekt, otwórz stronę https://console.cloud.google.com/cloud-resource-manager, wybierz projekt utworzony w kroku 2 i kliknij Usuń. Jeśli usuniesz projekt, musisz zmienić projekty w Cloud SDK. Listę wszystkich dostępnych projektów możesz wyświetlić, uruchamiając polecenie gcloud projects list.