Tutorial Google Cloud Run untuk ML: Serverless ML Deployment

# Tutorial Lengkap Google Cloud Run untuk ML: Deployment ML Serverless Google Cloud Run menyediakan platform serverless untuk mendeploy model ML yang dikontainerisasi. Menawarkan auto-scaling, harga...

By Ruby Abdullah · · tutorial
GCPCloud RunServerlessML DeploymentDockerProduction

Tutorial Lengkap Google Cloud Run untuk ML: Deployment ML Serverless

Google Cloud Run menyediakan platform serverless untuk mendeploy model ML yang dikontainerisasi. Menawarkan auto-scaling, harga pay-per-use, dan integrasi seamless dengan layanan Google Cloud.

Mengapa Cloud Run untuk ML?

Manfaat Utama:
  • Serverless: Tidak perlu manajemen infrastruktur
  • Auto-scaling: Scale ke nol dan naik otomatis
  • Hemat biaya: Bayar hanya untuk penggunaan aktual
  • Berbasis container: Deploy framework apapun
  • Deployment cepat: Deploy dalam hitungan detik

Prerequisites

pip install google-cloud-run flask gunicorn

gcloud auth login

gcloud config set project your-project-id

Quick Start

1. Buat ML Service

# app.py

from flask import Flask, request, jsonify

import joblib

import numpy as np

app = Flask(name)

Load model saat startup

model = joblib.load("model.joblib")

@app.route("/predict", methods=["POST"])

def predict():

data = request.getjson()

features = np.array(data["features"]).reshape(1, -1)

prediction = model.predict(features)

probability = model.predictproba(features)

return jsonify({

"prediction": int(prediction[0]),

"probability": probability[0].tolist()

})

@app.route("/health", methods=["GET"])

def health():

return jsonify({"status": "healthy"})

if name == "main":

app.run(host="0.0.0.0", port=8080)

2. Buat Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY model.joblib .

COPY app.py .

ENV PORT=8080

EXPOSE 8080

CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 app:app

3. requirements.txt

flask==2.3.0

gunicorn==21.2.0

joblib==1.3.0

scikit-learn==1.3.0

numpy==1.24.0

4. Deploy ke Cloud Run

# Build container

gcloud builds submit --tag gcr.io/your-project/ml-service

Deploy

gcloud run deploy ml-service \

--image gcr.io/your-project/ml-service \

--platform managed \

--region us-central1 \

--memory 2Gi \

--cpu 2 \

--min-instances 0 \

--max-instances 10 \

--allow-unauthenticated

FastAPI Service

1. Aplikasi FastAPI

# main.py

from fastapi import FastAPI, HTTPException

from pydantic import BaseModel

import joblib

import numpy as np

app = FastAPI(title="ML Prediction API")

Load model

model = joblib.load("model.joblib")

class PredictionRequest(BaseModel):

features: list[float]

class PredictionResponse(BaseModel):

prediction: int

probability: list[float]

@app.post("/predict", responsemodel=PredictionResponse)

async def predict(request: PredictionRequest):

try:

features = np.array(request.features).reshape(1, -1)

prediction = model.predict(features)

probability = model.predictproba(features)

return PredictionResponse(

prediction=int(prediction[0]),

probability=probability[0].tolist()

)

except Exception as e:

raise HTTPException(statuscode=400, detail=str(e))

@app.get("/health")

async def health():

return {"status": "healthy"}

2. FastAPI Dockerfile

FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

COPY model.joblib .

COPY main.py .

ENV PORT=8080

EXPOSE 8080

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

PyTorch Service

1. PyTorch Inference

# servepytorch.py

from flask import Flask, request, jsonify

import torch

import torch.nn as nn

import numpy as np

app = Flask(name)

class SimpleNN(nn.Module):

def init(self, inputsize, hiddensize, outputsize):

super().init()

self.fc1 = nn.Linear(inputsize, hiddensize)

self.fc2 = nn.Linear(hiddensize, outputsize)

self.relu = nn.ReLU()

self.softmax = nn.Softmax(dim=1)

def forward(self, x):

x = self.relu(self.fc1(x))

x = self.softmax(self.fc2(x))

return x

Load model

model = SimpleNN(10, 50, 2)

model.loadstatedict(torch.load("model.pt", maplocation="cpu"))

model.eval()

@app.route("/predict", methods=["POST"])

def predict():

data = request.getjson()

features = torch.tensor(data["features"], dtype=torch.float32)

with torch.nograd():

output = model(features)

prediction = torch.argmax(output, dim=1)

return jsonify({

"prediction": prediction.tolist(),

"probabilities": output.tolist()

})

if name == "main":

app.run(host="0.0.0.0", port=8080)

TensorFlow Serving

1. TensorFlow Service

# servetensorflow.py

from flask import Flask, request, jsonify

import tensorflow as tf

import numpy as np

app = Flask(name)

Load SavedModel

model = tf.savedmodel.load("savedmodel")

@app.route("/predict", methods=["POST"])

def predict():

data = request.getjson()

features = np.array(data["features"], dtype=np.float32)

predictions = model(features)

return jsonify({

"predictions": predictions.numpy().tolist()

})

if name == "main":

app.run(host="0.0.0.0", port=8080)

Batch Processing

1. Batch Prediction Endpoint

from flask import Flask, request, jsonify

import joblib

import numpy as np

from concurrent.futures import ThreadPoolExecutor

app = Flask(name)

model = joblib.load("model.joblib")

executor = ThreadPoolExecutor(maxworkers=4)

def predictbatch(batch):

return model.predict(batch)

@app.route("/predict/batch", methods=["POST"])

def batchpredict():

data = request.getjson()

features = np.array(data["features"])

# Proses secara paralel

batchsize = 100

batches = [features[i:i+batchsize] for i in range(0, len(features), batchsize)]

futures = [executor.submit(predictbatch, batch) for batch in batches]

results = [f.result() for f in futures]

predictions = np.concatenate(results)

return jsonify({

"predictions": predictions.tolist()

})

Model Versioning

1. Multiple Model Versions

# multimodelservice.py

from flask import Flask, request, jsonify

import joblib

import os

app = Flask(name)

Load multiple model versions

models = {}

modeldir = "models/"

for version in os.listdir(modeldir):

models[version] = joblib.load(f"{modeldir}/{version}/model.joblib")

@app.route("/predict/", methods=["POST"])

def predict(version):

if version not in models:

return jsonify({"error": "Versi model tidak ditemukan"}), 404

data = request.getjson()

model = models[version]

prediction = model.predict([data["features"]])

return jsonify({

"version": version,

"prediction": int(prediction[0])

})

Authentication

1. IAM Authentication

# Deploy dengan authentication required

gcloud run deploy ml-service \

--image gcr.io/your-project/ml-service \

--no-allow-unauthenticated

Berikan akses

gcloud run services add-iam-policy-binding ml-service \

--member="serviceAccount:caller@project.iam.gserviceaccount.com" \

--role="roles/run.invoker"

2. Panggil Service dengan Authentication

import google.auth.transport.requests

import google.oauth2.idtoken

import requests

def callauthenticatedservice(url, data):

authreq = google.auth.transport.requests.Request()

idtoken = google.oauth2.idtoken.fetchidtoken(authreq, url)

response = requests.post(

f"{url}/predict",

json=data,

headers={"Authorization": f"Bearer {idtoken}"}

)

return response.json()

CI/CD dengan Cloud Build

1. cloudbuild.yaml

steps:

# Build container

  • name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'gcr.io/$PROJECTID/ml-service:$COMMITSHA', '.']

# Push ke registry

  • name: 'gcr.io/cloud-builders/docker'
args: ['push', 'gcr.io/$PROJECTID/ml-service:$COMMITSHA']

# Deploy ke Cloud Run

  • name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
entrypoint: gcloud

args:

  • 'run'
  • 'deploy'
  • 'ml-service'
  • '--image'
  • 'gcr.io/$PROJECTID/ml-service:$COMMITSHA'
  • '--region'
  • 'us-central1'
  • '--platform'
  • 'managed'

images:

  • 'gcr.io/$PROJECTID/ml-service:$COMMITSHA'

Monitoring

1. Custom Metrics

from flask import Flask, request, jsonify

from google.cloud import monitoringv3

import time

app = Flask(name)

client = monitoringv3.MetricServiceClient()

projectname = f"projects/your-project"

def recordlatency(latencyms):

series = monitoringv3.TimeSeries()

series.metric.type = "custom.googleapis.com/ml/predictionlatency"

series.resource.type = "global"

point = monitoringv3.Point()

point.value.doublevalue = latencyms

point.interval.endtime.seconds = int(time.time())

series.points = [point]

client.createtimeseries(name=projectname, timeseries=[series])

@app.route("/predict", methods=["POST"])

def predict():

start = time.time()

# Logika prediksi

result = model.predict(...)

latency = (time.time() - start) * 1000

recordlatency(latency)

return jsonify({"prediction": result})

Best Practices

1. Optimasi Container

# Gunakan multi-stage build

FROM python:3.9-slim as builder

WORKDIR /app

COPY requirements.txt .

RUN pip install --user -r requirements.txt

FROM python:3.9-slim

COPY --from=builder /root/.local /root/.local

COPY . .

ENV PATH=/root/.local/bin:$PATH

CMD ["gunicorn", "--bind", ":8080", "app:app"]

2. Warm-up Requests

@app.beforefirstrequest

def warmup():

# Buat prediksi dummy untuk warm up model

dummyinput = np.zeros((1, 10))

model.predict(dummyinput)

print("Model sudah di-warm up")

Kesimpulan

Cloud Run untuk ML menyediakan:

  • Serverless: Tidak perlu manajemen infrastruktur
  • Auto-scaling: Tangani lonjakan traffic
  • Hemat biaya: Bayar per request
  • Fleksibel: Framework ML apapun
  • Cepat: Deployment cepat
  • Key takeaways:

    • Kontainerisasi model ML Anda
    • Optimasi untuk cold starts
    • Gunakan memory/CPU yang sesuai
    • Implementasikan health checks
    • Monitor metrik performa

    Artikel Terkait

    RAGFlow: Bikin RAG Engine yang Ngerti Dokumen Beneran, Lengkap dengan Sitasi

    RAGFlow: Bikin RAG Engine yang Ngerti Dokumen Beneran, Lengkap dengan Sitasi Halo temen-temen, balik lagi sama aku. Kala...

    Tutorial Text Generation Inference (TGI): Serving LLM untuk Produksi

    Menyajikan LLM di Produksi dengan Text Generation Inference (TGI) Text Generation Inference (TGI) adalah toolkit buatan ...

    Modal: Serverless GPU Cloud untuk Deploy Model ML

    Modal: Serverless GPU Cloud untuk Deploy Model ML Salah satu tantangan terbesar dalam machine learning bukan membuat mod...

    Tutorial MLOps End-to-End Project: Dari Data ke Produksi

    Tutorial 20: Proyek MLOps End-to-End Daftar Isi Pendahuluan Prasyarat Gambaran Proyek Versioning Data dengan DVC