Skip to content

29|后端项目部署

go-gateway 开发完成后,需要部署到服务器或容器平台。Go 程序最终通常以两种形态运行:一个二进制文件,或者一个包含二进制的容器镜像。网关作为常驻服务,适合用 systemd 管理,或用 Docker/Kubernetes 部署。部署要记录清楚四件事:二进制怎么构建,配置从哪里来,进程怎么运行,失败时从哪里看日志。

一、交叉编译

开发机可能是 Windows 或 macOS,服务器通常是 Linux。Go 支持交叉编译,在一台机器上生成另一台机器的可执行文件:

bash
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 \
  go build -trimpath -ldflags="-s -w" \
  -o bin/go-gateway \
  ./cmd/gateway
参数作用
GOOS=linux构建 Linux 可执行文件
GOARCH=amd64x86_64 架构,ARM 机器用 arm64
CGO_ENABLED=0静态链接,不依赖 glibc,容器里更容易运行
-trimpath去掉本机源码路径
-ldflags="-s -w"去掉符号表和调试信息,减小体积

二、版本注入

发布后排查问题,需要知道当前二进制来自哪个版本。在代码里留变量,构建时注入:

go
package version

var (
	Version = "dev"
	Commit  = "unknown"
	Date    = "unknown"
)

构建时注入:

bash
VERSION=v1.0.0
COMMIT=$(git rev-parse --short HEAD)
DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)

go build \
  -ldflags="-X example.com/go-gateway/internal/version.Version=$VERSION \
            -X example.com/go-gateway/internal/version.Commit=$COMMIT \
            -X example.com/go-gateway/internal/version.Date=$DATE" \
  -o bin/go-gateway \
  ./cmd/gateway

三、systemd 服务

ini
[Unit]
Description=Go Gateway
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=gateway
Group=gateway
ExecStart=/usr/local/bin/go-gateway
Restart=on-failure
RestartSec=5s

NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true

[Install]
WantedBy=multi-user.target

启动:

bash
systemctl daemon-reload
systemctl enable --now go-gateway
systemctl status go-gateway
journalctl -u go-gateway -f

四、多阶段 Docker 镜像

dockerfile
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
    go build -trimpath -ldflags="-s -w" \
    -o /out/go-gateway ./cmd/gateway

FROM alpine:3.20
RUN adduser -D -H -u 10001 app
USER app
WORKDIR /app
COPY --from=builder /out/go-gateway /app/go-gateway
COPY configs/ /app/configs/
EXPOSE 8080 8081
ENTRYPOINT ["/app/go-gateway"]

构建和运行:

bash
docker build -t registry.example.com/ops/go-gateway:v1.0.0 .
docker run -p 8080:8080 -p 8081:8081 \
  -e GATEWAY_JWT_SECRET=xxx \
  registry.example.com/ops/go-gateway:v1.0.0

五、Kubernetes 部署

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-gateway
  namespace: gateway
spec:
  replicas: 2
  selector:
    matchLabels:
      app: go-gateway
  template:
    metadata:
      labels:
        app: go-gateway
    spec:
      containers:
        - name: gateway
          image: registry.example.com/ops/go-gateway:v1.0.0
          ports:
            - name: proxy
              containerPort: 8080
            - name: admin
              containerPort: 8081
          readinessProbe:
            httpGet:
              path: /healthz
              port: proxy
            initialDelaySeconds: 3
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /healthz
              port: proxy
            initialDelaySeconds: 10
            periodSeconds: 20
---
apiVersion: v1
kind: Service
metadata:
  name: go-gateway
  namespace: gateway
spec:
  selector:
    app: go-gateway
  ports:
    - name: proxy
      port: 80
      targetPort: proxy
    - name: admin
      port: 8081
      targetPort: admin

六、发布排查

层级现象排查入口
镜像ImagePullBackOff镜像名、tag、仓库凭据
启动参数Pod 反复重启kubectl logs、配置路径
端口冲突bind: address already in use端口占用检查
探针Pod Running 但 NotReadyreadinessProbe 路径、端口
Service访问不通selector、EndpointSlice

kubectl logs deploy/go-gateway -n gateway --previous 看上一轮退出容器的日志,定位启动失败原因。