1. 개요
소개
이 Codelab에서는 여러 컨테이너를 사용하는 Cloud Run 서비스를 배포하는 방법을 알아봅니다. Cloud Run 인그레스 컨테이너로 사용될 Node.js 앱과 사이드카로 사용될 추가 Node.js 앱을 만듭니다.
기술 개요
Cloud Run 인스턴스 내에서 여러 컨테이너를 사용하는 경우 하나의 컨테이너가 웹 인그레스의 기본 컨테이너로 사용됩니다. 하나 이상의 추가 컨테이너를 사이드카라고 합니다.
여러 컨테이너가 서로 통신하는 방법은 두 가지가 있습니다.
- 컨테이너는 localhost 네트워크 인터페이스를 공유하므로 모든 컨테이너가 localhost:port와 같은 포트를 수신할 수 있습니다.
- 인메모리 볼륨을 사용하여 컨테이너에 마운트하여 파일을 공유할 수도 있습니다.
사용 사례
Cloud Run 인스턴스 내의 모든 컨테이너는 localhost 네트워크 인터페이스를 공유하므로 기본 컨테이너 앞에 사이드카를 사용하여 요청을 프록시할 수 있습니다. 이러한 프록시는 요청을 가로채 적절한 엔드포인트로 전달하여 클라이언트와 서버 간 애플리케이션으로의 트래픽 흐름을 더 효율적으로 추상화하는 추가 레이어를 제공할 수 있습니다. 예를 들어 여기에 표시된 대로 DockerHub의 공식 Nginx 이미지를 사용할 수 있습니다.
여러 컨테이너가 공유 볼륨을 통해 파일을 공유하여 통신할 수 있으므로 서비스에 다양한 사이드카 애플리케이션을 추가합니다. 예를 들어 OpenTelemetry와 같은 커스텀 에이전트를 사용하여 로그, 측정항목, 트레이스를 내보내도록 Cloud Run 서비스를 계측할 수 있습니다 (OpenTelemetry 예시). 또 다른 예는 사이드카를 사용하여 Cloud Spanner PostgreSQL 데이터베이스에 연결하는 것입니다 (Cloud Spanner Postgress 예).
이 Codelab의 예
이 Codelab에서는 먼저 인그레스 컨테이너가 localhost 포트를 통해 사이드카와 통신하는 Cloud Run 서비스를 배포합니다. 그런 다음 볼륨 마운트를 통해 파일을 공유하도록 인그레스 컨테이너와 사이드카를 업데이트합니다.
학습할 내용
- 사이드카를 사용하는 컨테이너를 만드는 방법
- 인그레스 컨테이너가 localhost를 사용하여 사이드카와 통신하는 방법
- 인그레스 컨테이너와 사이드카가 마운트된 볼륨을 통해 파일을 공유하는 방법
2. 설정 및 요구사항
기본 요건
- Cloud 콘솔에 로그인되어 있습니다.
- 이전에 Cloud Run 서비스를 배포한 적이 있습니다. 예를 들어 소스 코드에서 웹 서비스 배포 빠른 시작을 따라 시작할 수 있습니다.
Cloud Shell 활성화
- Cloud Console에서 Cloud Shell 활성화
를 클릭합니다.

Cloud Shell을 처음 시작하는 경우 설명이 포함된 중간 화면이 제공됩니다. 중간 화면이 표시되면 계속을 클릭합니다.

Cloud Shell을 프로비저닝하고 연결하는 작업은 몇 분이면 끝납니다.

이 가상 머신에는 필요한 개발 도구가 모두 로드되어 있습니다. 영구적인 5GB 홈 디렉터리를 제공하고 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. 인그레스 앱 만들기
환경 변수 설정
이 Codelab에서는 이 Codelab에서 사용되는 gcloud 명령어의 가독성을 높이기 위해 몇 가지 환경 변수를 만듭니다.
REGION=<YOUR-REGION> PROJECT_ID=<YOUR-PROJECT-ID> SERVICE_NAME=sidecar-codelab REPO_NAME=sidecar-codelab
컨테이너 이미지를 저장할 ArtifactRegistry 저장소 만들기
이 Codelab의 컨테이너 이미지를 저장할 Artifact Registry 저장소를 만들 수 있습니다.
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}`);
});
인그레스 컨테이너의 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" ]
그리고 인그레스 컨테이너를 위한 `.dockerignore` 파일을 만듭니다.
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
이제 다음 명령어를 실행하여 인그레스 컨테이너의 이미지를 빌드할 수 있습니다.
gcloud builds submit --tag $REGION-docker.pkg.dev/$PROJECT_ID/$REPO_NAME/ingress:latest
4. 사이드카 앱 만들기
이 섹션에서는 Cloud Run 서비스에서 사이드카로 사용할 두 번째 node.js 앱을 만듭니다.
사이드카 디렉터리로 이동합니다.
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}`);
});
사이드카 컨테이너의 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" ]
그리고 사이드카 컨테이너용 `.dockerignore` 파일을 만듭니다.
# Exclude locally installed dependencies node_modules/ # Exclude "build-time" ignore files. .dockerignore .gcloudignore # Exclude git history and configuration. .gitignore
이제 다음 명령어를 실행하여 인그레스 컨테이너의 이미지를 빌드할 수 있습니다.
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 베타를 사용해야 합니다.
gcloud beta run services replace sidecar-codelab.yaml
배포가 완료되면 서비스 URL을 환경 변수에 저장합니다.
SERVICE_URL=$(gcloud run services describe $SERVICE_NAME --platform managed --region $REGION --format 'value(status.url)')
5. Cloud Run 서비스 호출
이제 ID 토큰을 제공하여 서비스를 호출할 수 있습니다.
curl -X GET -H "Authorization: Bearer $(gcloud auth print-identity-token)" ${SERVICE_URL}
결과는 아래 출력 예와 유사합니다.
The sidecar says: Hello ingress container! I'm the sidecar.
6. 볼륨 마운트를 통해 파일 공유
이 섹션에서는 볼륨 마운트를 통해 파일을 공유하도록 컨테이너를 업데이트합니다. 이 예시에서 인그레스 컨테이너는 공유 볼륨의 파일에 씁니다. 사이드카가 파일을 읽고 콘텐츠를 인그레스 컨테이너에 다시 반환합니다.
먼저 인그레스 컨테이너 코드를 업데이트합니다. 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
이제 사이드카 디렉터리로 이동합니다.
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}`);
});
다음 명령어를 실행하여 사이드카 컨테이너의 새 이미지를 빌드합니다.
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
이제 ID 토큰을 제공하여 서비스를 호출할 수 있습니다.
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 문서, 특히 멀티 컨테이너 배포 및 인메모리 볼륨 마운트 사용에 관한 문서를 검토하는 것이 좋습니다.
학습한 내용
- 사이드카를 사용하는 컨테이너를 만드는 방법
- 인그레스 컨테이너가 localhost를 사용하여 사이드카와 통신하는 방법
- 인그레스 컨테이너와 사이드카가 모두 마운트된 볼륨을 공유하는 방법
8. 삭제
의도치 않은 요금이 청구되지 않도록 하려면(예: 이 Cloud 함수가 무료 등급의 월별 Cloud Run 호출 할당량보다 더 많이 호출되는 경우) Cloud Run 서비스를 삭제하거나 2단계에서 만든 프로젝트를 삭제하면 됩니다.
Cloud 함수를 삭제하려면 https://console.cloud.google.com/run/의 Cloud 함수 Cloud Console로 이동하여 sidecar-codelab 서비스 (다른 이름을 사용한 경우 $SERVICE_NAME)를 삭제합니다.
전체 프로젝트를 삭제하려면 https://console.cloud.google.com/cloud-resource-manager로 이동하여 2단계에서 만든 프로젝트를 선택하고 삭제를 선택합니다. 프로젝트를 삭제하면 Cloud SDK에서 프로젝트를 변경해야 합니다. gcloud projects list를 실행하여 사용 가능한 모든 프로젝트의 목록을 볼 수 있습니다.