Mở rộng Container không còn “đau đầu” vì Kubernetes: Hướng dẫn về Google Cloud Run

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Tìm điểm cân bằng giữa VM và Kubernetes

Quản lý hạ tầng thường là cuộc giằng co giữa khả năng kiểm soát và sự tiện lợi. Các máy ảo (Virtual machines) mang lại quyền hạn tuyệt đối nhưng đòi hỏi phải vá lỗi và bảo trì hệ điều hành liên tục. Ngược lại, Kubernetes cung cấp khả năng mở rộng cực lớn nhưng lại đi kèm với lộ trình học tập gian nan, có thể khiến một đội ngũ nhỏ mất hàng tháng trời để làm quen. Tôi đã làm việc với hàng chục đội ngũ kỹ thuật chỉ muốn chạy một microservice đơn giản mà không muốn phải thuê một nhân sự DevOps toàn thời gian để quản lý cụm máy chủ.

Google Cloud Run giải quyết vấn đề này bằng cách cung cấp một môi trường được quản lý hoàn toàn (fully managed) cho các stateless container. Bạn chỉ cần bàn giao container image, và Google sẽ lo liệu việc cung cấp tài nguyên, thiết lập mạng và mở rộng quy mô. Đây là một lựa chọn thực tế cho các nhà phát triển hiện đại. Bạn có được sự linh hoạt của Docker cùng với sự đơn giản của một nền tảng dạng dịch vụ (PaaS), cho phép bạn tập trung vào việc ra mắt tính năng thay vì phải gỡ lỗi các tệp YAML.

Bắt đầu nhanh: Từ code đến production trong 5 phút

Để đưa một dịch vụ lên môi trường thực tế, bạn chỉ cần một ứng dụng và một Dockerfile. Mặc dù ví dụ này sử dụng ứng dụng Python Flask, nhưng Cloud Run không phụ thuộc vào ngôn ngữ lập trình. Miễn là ứng dụng của bạn lắng nghe các yêu cầu HTTP trên một cổng (port) đã xác định, nó sẽ hoạt động.

1. Mã nguồn ứng dụng (app.py)

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
def hello_world():
    return "Cloud Run đang hoạt động và đang mở rộng!"

if __name__ == "__main__":
    # Cloud Run truyền vào biến môi trường PORT
    port = int(os.environ.get('PORT', 8080))
    app.run(debug=False, host='0.0.0.0', port=port)

2. Dockerfile

FROM python:3.9-slim
ENV PYTHONUNBUFFERED True
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

3. Triển khai chỉ với một câu lệnh

Hãy quên việc build image thủ công hay đẩy lên registry. Google Cloud SDK có thể xử lý toàn bộ quy trình chỉ trong một lần thực hiện. Chạy lệnh này trong terminal của bạn:

gcloud run deploy my-service \
  --source . \
  --region us-central1 \
  --allow-unauthenticated

Lệnh này sẽ kích hoạt Google Cloud Build để đóng gói container của bạn, lưu trữ nó trong Artifact Registry và triển khai lên một URL production. Trong khoảng 60 đến 90 giây, bạn sẽ nhận được một liên kết HTTPS trực tiếp.

Cách Cloud Run xử lý lưu lượng và mở rộng

Cloud Run được xây dựng trên Knative, một framework mã nguồn mở mang các mô hình serverless lên Kubernetes. Tuy nhiên, Google đã ẩn đi tất cả sự phức tạp đó. Khi một yêu cầu gửi đến endpoint của bạn, nền tảng sẽ kiểm tra xem có instance nào đang hoạt động không. Nếu không có, nó sẽ kích hoạt một quy trình “cold start” và khởi tạo một instance trong khoảng hai giây đối với các ứng dụng nhẹ.

Concurrency: Sử dụng tài nguyên hiệu quả

Các hàm serverless truyền thống như AWS Lambda thường xử lý một yêu cầu trên mỗi instance. Cloud Run thì khác. Một container đơn lẻ có thể xử lý tới 1.000 yêu cầu đồng thời (concurrent requests). Đây là một lợi thế lớn cho các ứng dụng bị giới hạn bởi I/O (I/O-bound). Bằng cách xử lý nhiều yêu cầu trong một container, bạn giảm được tổng số instance cần thiết, điều này có thể cắt giảm hóa đơn hàng tháng của bạn từ 30% trở lên so với mô hình mỗi-instance-một-yêu cầu.

Chia lưu lượng để phát hành không gây gián đoạn (Zero-Downtime)

Việc triển khai an toàn đã được tích hợp sẵn vào nền tảng. Bạn có thể triển khai một phiên bản mới của ứng dụng mà không cần gửi bất kỳ lưu lượng truy cập nào cho nó ban đầu. Tôi khuyên bạn nên sử dụng phương pháp ‘canary’: gửi 5% người dùng sang phiên bản mới, theo dõi log lỗi trong Cloud Logging, sau đó mới chuyển sang 100%.

gcloud run services update-traffic my-service --to-revisions=NEW_REVISION=5,OLD_REVISION=95

Bảo mật và Dữ liệu: Secret và Cơ sở dữ liệu

Các ứng dụng production cần nhiều hơn là chỉ mã nguồn; chúng cần API key và thông tin đăng nhập cơ sở dữ liệu. Việc ghi cứng (hardcoding) những thông tin này vào Docker image là một thảm họa bảo mật. Thay vào đó, hãy sử dụng Google Secret Manager để truyền các dữ liệu nhạy cảm trực tiếp vào biến môi trường khi chạy (runtime).

Kết nối với Cơ sở dữ liệu nội bộ

Nếu ứng dụng của bạn cần kết nối với một Cloud SQL instance, đừng mở cơ sở dữ liệu của bạn ra internet công cộng. Hãy sử dụng VPC Connector. Nó đóng vai trò như một cầu nối riêng tư, cho phép container serverless của bạn truy cập vào các địa chỉ IP nội bộ trong Virtual Private Cloud (VPC) như thể nó đang nằm trong cùng một mạng cục bộ.

Những bài học kinh nghiệm cho môi trường Production

Sau khi quản lý các dịch vụ có lưu lượng truy cập cao trên Cloud Run, tôi đã đúc kết được một số cách để tối ưu hóa hiệu suất và chi phí.

  • Giữ image gọn nhẹ: Sử dụng các base image như Alpine hoặc Slim. Một image 100MB khởi động nhanh hơn đáng kể so với image 1GB, giúp giảm thiểu tác động của cold start đối với người dùng.
  • Thiết lập số lượng instance tối thiểu: Đối với các ứng dụng nhạy cảm về độ trễ, hãy đặt --min-instances là 1. Điều này giúp luôn giữ một container ở trạng thái “warm” (đang chạy), đảm bảo người dùng đầu tiên trong ngày không gặp phải tình trạng trễ.
  • Điều chỉnh Memory và CPU: Cloud Run mặc định cấp 512MiB RAM. Nếu bạn đang chạy các tác vụ xử lý dữ liệu nặng, bạn có thể nâng cấp lên tới 32GB và 8 vCPUs. Tuy nhiên, đừng cấp dư thừa; bạn phải trả tiền cho những gì bạn phân bổ.
  • Tận dụng Scale-to-Zero: Cloud Run hoàn toàn miễn phí khi không có lưu lượng truy cập. Điều này khiến nó trở nên hoàn hảo cho các môi trường phát triển. Bạn có thể host một trang staging đầy đủ với chi phí 0 đồng vào cuối tuần khi đội ngũ không làm việc.

Việc chuyển đổi từ phát triển bằng Docker tại máy cục bộ sang môi trường production trên Cloud Run diễn ra cực kỳ mượt mà. Nó mang lại tính di động của container cùng với sự nhàn nhã trong vận hành của serverless, khiến đây trở thành một trong những cách hiệu quả nhất để triển khai các ứng dụng web hiện đại.

Share: