Chuyển tới nội dung chính

🏪 Mở Chi Nhánh - Deployment

Khi nhà hàng đã hoạt động tốt, đã đến lúc mở chi nhánh để phục vụ nhiều khách hàng hơn! Deployment trong Go giống như việc mở các chi nhánh mới - bạn cần đóng gói món ăn (build), chuẩn bị hệ thống giao hàng (cloud), và tự động hóa quy trình sản xuất (CI/CD).

1. Chuẩn Bị Món Ăn - Building Go Binary

Trước khi mở chi nhánh, bạn cần đóng gói món ăn của mình thành sản phẩm hoàn chỉnh.

Build cho hệ điều hành hiện tại

// main.go - Món ăn chính của nhà hàng
package main

import (
"fmt"
"log"
"net/http"
)

func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "🍜 Chào mừng đến nhà hàng Code!")
})

log.Println("🏪 Chi nhánh đang mở cửa tại :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
# Đóng gói món ăn (build binary)
go build -o restaurant-app main.go

# Chạy ứng dụng
./restaurant-app

Build cho nhiều nền tảng khác nhau

# Build cho Linux (chi nhánh Linux)
GOOS=linux GOARCH=amd64 go build -o restaurant-linux main.go

# Build cho Windows (chi nhánh Windows)
GOOS=windows GOARCH=amd64 go build -o restaurant-windows.exe main.go

# Build cho macOS (chi nhánh macOS)
GOOS=darwin GOARCH=amd64 go build -o restaurant-macos main.go

# Build nhỏ gọn hơn (giảm kích thước hộp đóng gói)
go build -ldflags="-s -w" -o restaurant-app main.go

2. Hộp Đóng Gói Món Ăn - Docker

Docker giống như hộp đóng gói món ăn chuyên nghiệp - giữ cho món ăn luôn tươi ngon và đồng nhất ở mọi chi nhánh.

Dockerfile cơ bản

# Dockerfile - Công thức đóng gói món ăn

# Giai đoạn 1: Bếp chuẩn bị (Build stage)
FROM golang:1.21-alpine AS builder

# Thiết lập bếp
WORKDIR /kitchen

# Sao chép danh sách nguyên liệu
COPY go.mod go.sum ./
RUN go mod download

# Sao chép nguyên liệu và nấu món
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o restaurant-app .

# Giai đoạn 2: Hộp giao hàng (Runtime stage)
FROM alpine:latest

# Cài đặt công cụ cần thiết
RUN apk --no-cache add ca-certificates

WORKDIR /root/

# Lấy món ăn đã nấu từ bếp
COPY --from=builder /kitchen/restaurant-app .

# Mở cửa cho khách hàng
EXPOSE 8080

# Khởi động nhà hàng
CMD ["./restaurant-app"]

Docker Compose - Quản lý nhiều dịch vụ

# docker-compose.yml - Thiết kế cả hệ thống nhà hàng

version: '3.8'

services:
# Nhà hàng chính
restaurant:
build: .
ports:
- "8080:8080"
environment:
- DB_HOST=database
- REDIS_HOST=cache
depends_on:
- database
- cache
networks:
- restaurant-network

# Kho lưu trữ (Database)
database:
image: postgres:15-alpine
environment:
- POSTGRES_DB=restaurant_db
- POSTGRES_USER=chef
- POSTGRES_PASSWORD=secret123
volumes:
- db-data:/var/lib/postgresql/data
networks:
- restaurant-network

# Tủ lạnh (Cache)
cache:
image: redis:7-alpine
networks:
- restaurant-network

volumes:
db-data:

networks:
restaurant-network:
driver: bridge

Lệnh Docker thường dùng

# Đóng gói món ăn vào hộp
docker build -t restaurant-app:v1.0 .

# Chạy thử hộp đóng gói
docker run -p 8080:8080 restaurant-app:v1.0

# Chạy cả hệ thống
docker-compose up -d

# Kiểm tra tình trạng các dịch vụ
docker-compose ps

# Xem log của nhà hàng
docker-compose logs -f restaurant

# Dừng hệ thống
docker-compose down

3. Hệ Thống Giao Hàng - Cloud Deployment

Sau khi đóng gói, bạn cần chọn hệ thống giao hàng (cloud platform) phù hợp.

Heroku - Giao hàng đơn giản

# Cài đặt Heroku CLI
# Tạo file Procfile
echo "web: ./restaurant-app" > Procfile

# Đăng nhập và tạo ứng dụng
heroku login
heroku create my-restaurant-app

# Triển khai
git push heroku main

# Xem log
heroku logs --tail

# Mở ứng dụng
heroku open

AWS Elastic Beanstalk

# Cài đặt EB CLI
pip install awsebcli

# Khởi tạo môi trường
eb init -p go restaurant-app

# Tạo môi trường
eb create restaurant-prod

# Triển khai
eb deploy

# Mở ứng dụng
eb open

# Xem trạng thái
eb status

Google Cloud Platform (GCP)

# Tạo file app.yaml
cat > app.yaml << EOF
runtime: go121
main: .

env_variables:
PORT: "8080"
EOF

# Triển khai lên App Engine
gcloud app deploy

# Xem ứng dụng
gcloud app browse

# Xem log
gcloud app logs tail -s default

4. Kubernetes - Hệ Thống Chi Nhánh Lớn

Kubernetes giống như quản lý chuỗi nhà hàng lớn với nhiều chi nhánh.

Deployment YAML

# deployment.yaml - Kế hoạch mở chi nhánh

apiVersion: apps/v1
kind: Deployment
metadata:
name: restaurant-deployment
spec:
replicas: 3 # Mở 3 chi nhánh
selector:
matchLabels:
app: restaurant
template:
metadata:
labels:
app: restaurant
spec:
containers:
- name: restaurant-app
image: restaurant-app:v1.0
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: "postgres-service"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: restaurant-service
spec:
selector:
app: restaurant
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: LoadBalancer
# Triển khai lên Kubernetes
kubectl apply -f deployment.yaml

# Kiểm tra pods (các chi nhánh)
kubectl get pods

# Kiểm tra service
kubectl get services

# Xem log của một chi nhánh
kubectl logs <pod-name>

# Scale lên 5 chi nhánh
kubectl scale deployment restaurant-deployment --replicas=5

5. Dây Chuyền Tự Động - CI/CD

CI/CD giống như dây chuyền sản xuất tự động - tự động kiểm tra, đóng gói và giao hàng.

GitHub Actions

# .github/workflows/deploy.yml - Quy trình tự động hóa

name: 🏪 Mở Chi Nhánh Tự Động

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
# Kiểm tra chất lượng món ăn
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: '1.21'

- name: Chạy tests
run: |
go test -v ./...
go test -race -coverprofile=coverage.txt -covermode=atomic ./...

- name: Kiểm tra chất lượng code
run: |
go vet ./...
go fmt ./...

# Đóng gói và triển khai
deploy:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'

steps:
- uses: actions/checkout@v3

- name: Đăng nhập Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build và push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
myusername/restaurant-app:latest
myusername/restaurant-app:${{ github.sha }}

- name: Triển khai lên production
run: |
# Triển khai lên cloud platform của bạn
echo "🚀 Đang mở chi nhánh mới..."

GitLab CI/CD

# .gitlab-ci.yml

stages:
- test
- build
- deploy

variables:
DOCKER_IMAGE: registry.gitlab.com/mygroup/restaurant-app

# Kiểm tra món ăn
test:
stage: test
image: golang:1.21
script:
- go test -v ./...
- go vet ./...

# Đóng gói món ăn
build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t $DOCKER_IMAGE:$CI_COMMIT_SHA .
- docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
only:
- main

# Mở chi nhánh
deploy:
stage: deploy
script:
- kubectl set image deployment/restaurant-deployment restaurant-app=$DOCKER_IMAGE:$CI_COMMIT_SHA
only:
- main
environment:
name: production

6. Cấu Hình Môi Trường - Environment Variables

Mỗi chi nhánh có thể cần cấu hình khác nhau.

// config/config.go - Cấu hình cho từng chi nhánh

package config

import (
"os"
"strconv"
)

type Config struct {
ServerPort string
DatabaseURL string
RedisURL string
Environment string
LogLevel string
}

func Load() *Config {
return &Config{
ServerPort: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", "postgres://localhost/restaurant"),
RedisURL: getEnv("REDIS_URL", "localhost:6379"),
Environment: getEnv("ENV", "development"),
LogLevel: getEnv("LOG_LEVEL", "info"),
}
}

func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}

func getEnvAsInt(key string, defaultValue int) int {
if value := os.Getenv(key); value != "" {
if intValue, err := strconv.Atoi(value); err == nil {
return intValue
}
}
return defaultValue
}

File .env cho các môi trường

# .env.development - Chi nhánh thử nghiệm
ENV=development
PORT=8080
DATABASE_URL=postgres://localhost:5432/restaurant_dev
REDIS_URL=localhost:6379
LOG_LEVEL=debug

# .env.production - Chi nhánh chính thức
ENV=production
PORT=8080
DATABASE_URL=postgres://prod-db:5432/restaurant_prod
REDIS_URL=prod-redis:6379
LOG_LEVEL=info

7. Health Checks - Kiểm Tra Sức Khỏe

Đảm bảo chi nhánh luôn hoạt động tốt.

// health/health.go - Kiểm tra sức khỏe nhà hàng

package health

import (
"encoding/json"
"net/http"
"time"
)

type HealthStatus struct {
Status string `json:"status"`
Timestamp time.Time `json:"timestamp"`
Services map[string]string `json:"services"`
}

func HealthCheckHandler(w http.ResponseWriter, r *http.Request) {
status := HealthStatus{
Status: "healthy",
Timestamp: time.Now(),
Services: make(map[string]string),
}

// Kiểm tra database
if checkDatabase() {
status.Services["database"] = "ok"
} else {
status.Services["database"] = "error"
status.Status = "unhealthy"
}

// Kiểm tra cache
if checkRedis() {
status.Services["redis"] = "ok"
} else {
status.Services["redis"] = "error"
status.Status = "degraded"
}

w.Header().Set("Content-Type", "application/json")
if status.Status != "healthy" {
w.WriteHeader(http.StatusServiceUnavailable)
}
json.NewEncoder(w).Encode(status)
}

func ReadinessHandler(w http.ResponseWriter, r *http.Request) {
// Kiểm tra xem service đã sẵn sàng phục vụ chưa
w.WriteHeader(http.StatusOK)
w.Write([]byte("ready"))
}

func checkDatabase() bool {
// Implement database check
return true
}

func checkRedis() bool {
// Implement redis check
return true
}

8. Monitoring và Logging - Giám Sát Chi Nhánh

Theo dõi hoạt động của các chi nhánh.

// logging/logger.go - Hệ thống ghi chép

package logging

import (
"log"
"os"
"time"
"net/http"
)

type Logger struct {
infoLog *log.Logger
errorLog *log.Logger
}

func NewLogger() *Logger {
return &Logger{
infoLog: log.New(os.Stdout, "INFO\t", log.Ldate|log.Ltime),
errorLog: log.New(os.Stderr, "ERROR\t", log.Ldate|log.Ltime|log.Lshortfile),
}
}

func (l *Logger) Info(format string, v ...interface{}) {
l.infoLog.Printf(format, v...)
}

func (l *Logger) Error(format string, v ...interface{}) {
l.errorLog.Printf(format, v...)
}

// Middleware để log requests
func RequestLogger(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()

next.ServeHTTP(w, r)

log.Printf(
"🍽️ %s %s %s - Thời gian xử lý: %v",
r.Method,
r.RequestURI,
r.RemoteAddr,
time.Since(start),
)
})
}

Tích hợp với monitoring services

// monitoring/metrics.go

package monitoring

import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"net/http"
)

var (
// Đếm số khách hàng
requestsTotal = prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "restaurant_requests_total",
Help: "Tổng số yêu cầu",
},
[]string{"method", "endpoint"},
)

// Thời gian phục vụ
requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "restaurant_request_duration_seconds",
Help: "Thời gian xử lý yêu cầu",
},
[]string{"method", "endpoint"},
)
)

func init() {
prometheus.MustRegister(requestsTotal)
prometheus.MustRegister(requestDuration)
}

func MetricsHandler() http.Handler {
return promhttp.Handler()
}

9. Bài Tập Thực Hành

Bài 1: Đóng gói cơ bản

Tạo một Go web server đơn giản và viết Dockerfile để đóng gói nó.

Bài 2: Multi-stage build

Tối ưu hóa Dockerfile để giảm kích thước image xuống dưới 20MB.

Bài 3: Docker Compose

Tạo docker-compose.yml cho ứng dụng có web server, PostgreSQL và Redis.

Bài 4: Health checks

Implement các endpoint /health và /ready cho ứng dụng của bạn.

Bài 5: CI/CD pipeline

Thiết lập GitHub Actions để tự động test và build Docker image.

Bài 6: Kubernetes deployment

Viết deployment.yaml để deploy ứng dụng lên Kubernetes với 3 replicas.

Bài 7: Environment configuration

Tạo hệ thống config hỗ trợ nhiều môi trường (dev, staging, production).

Bài 8: Monitoring

Tích hợp Prometheus metrics vào ứng dụng của bạn.

Tổng Kết

Deployment giống như mở chi nhánh nhà hàng:

  • 📦 Build: Đóng gói món ăn
  • 🐳 Docker: Hộp đóng gói chuyên nghiệp
  • ☁️ Cloud: Hệ thống giao hàng
  • 🔄 CI/CD: Dây chuyền tự động
  • 📊 Monitoring: Giám sát chi nhánh
  • 🏥 Health checks: Kiểm tra sức khỏe
  • ⚙️ Config: Tùy chỉnh từng chi nhánh
  • 🚀 K8s: Quản lý chuỗi lớn

Việc deployment đúng cách giúp ứng dụng của bạn chạy ổn định và dễ dàng mở rộng!


Tiếp theo: 🛠️ Công Cụ & Best Practices - Tools