在云原生体系里,Kubernetes 已经成为容器编排的事实标准。对于 Go 应用而言,Kubernetes 不只是一个“把容器跑起来”的平台,更是一套完整的部署、扩缩容、故障恢复和多环境治理方案。
本文会以一个可运行的 Go HTTP 服务为例,系统讲清楚 Kubernetes 部署模型的关键概念,并给出一套相对完整的实战 YAML 配置,覆盖以下内容:
- K8s 核心资源:Pod、Deployment、Service、ConfigMap、Secret
- Go 应用完整 K8s 部署 YAML 编写
- 资源限制(requests/limits)与 HPA 自动扩缩容
- Readiness/Liveness/Startup Probe 配置
- 滚动更新与回滚策略
- 多环境配置管理(dev/staging/prod)
如果你已经会写 Dockerfile,但还不太清楚如何让服务在 Kubernetes 中稳定、可控、可扩展地运行,这篇文章可以作为一份从概念到落地的实战模板。
一、先理解 Kubernetes 的部署模型
在 Kubernetes 中,应用部署通常不是“启动一个容器”这么简单,而是由一组资源对象共同协作完成。
我们可以先从一个典型链路来理解:
- 开发者将 Go 服务打包成镜像。
- Kubernetes 使用 Deployment 管理 Pod 的副本数和发布策略。
- Pod 中运行真正的容器实例。
- Service 为 Pod 提供稳定访问入口。
- ConfigMap 和 Secret 为应用注入配置与敏感信息。
- HPA 根据 CPU 或内存等指标进行自动扩缩容。
- Probe 探针负责健康检查,保证流量只进入可用实例。
也就是说,Kubernetes 的部署模型本质上是:用声明式资源描述“应用应该如何运行”,再由控制器持续把集群状态收敛到目标状态。
二、K8s 核心资源详解
先把本文涉及到的几个核心资源捋清楚。
| 资源 | 作用 | 典型职责 |
|---|---|---|
| Pod | Kubernetes 中最小调度单元 | 承载一个或多个紧密协作的容器 |
| Deployment | 无状态应用的部署控制器 | 管理副本、滚动更新、回滚 |
| Service | 服务访问抽象 | 为一组 Pod 提供稳定地址和负载均衡 |
| ConfigMap | 非敏感配置管理 | 注入环境变量、配置文件、启动参数 |
| Secret | 敏感配置管理 | 存储密码、Token、密钥等 |
1. Pod
Pod 是 Kubernetes 的最小调度单位。一个 Pod 中可以包含一个主容器,也可以有多个协同容器,但最常见的场景仍然是“一个 Pod 跑一个应用容器”。
对 Go Web 服务来说,一个 Pod 往往就代表一个服务实例。
Pod 有几个很重要的特点:
- Pod 内多个容器共享网络命名空间
- Pod 有独立 IP,但这个 IP 不是稳定不变的
- Pod 可能因为重建、漂移、故障恢复而被替换
因此,不要直接依赖 Pod IP 访问服务,而应通过 Service 暴露稳定入口。
2. Deployment
Deployment 是日常部署 Go 无状态服务最常用的资源。它并不直接管理容器,而是通过 ReplicaSet 间接管理 Pod。
Deployment 主要解决这些问题:
- 维持指定副本数
- 支持滚动更新
- 支持历史版本回滚
- 支持声明式变更
例如,你希望服务始终有 3 个副本在线,那么即使其中某个 Pod 异常退出,Deployment 也会自动补齐。
3. Service
Pod 会变化,但业务访问入口不能变化。所以 Kubernetes 引入了 Service。
Service 会把一组带有相同 label 的 Pod 聚合起来,对外暴露一个稳定的访问地址,并在内部进行负载均衡。
常见的 Service 类型包括:
- ClusterIP:集群内部访问,默认类型
- NodePort:通过节点端口暴露服务
- LoadBalancer:通过云厂商负载均衡对外暴露
在微服务内部调用场景中,ClusterIP 是最常用的。
4. ConfigMap
ConfigMap 用于存储非敏感配置,例如:
- 服务监听端口
- 日志级别
- 运行环境标识
- 下游服务地址
这样做的好处是:镜像与配置解耦。同一个镜像,可以在不同环境通过不同 ConfigMap 注入不同配置,而不需要重新构建镜像。
5. Secret
Secret 用于存储敏感信息,例如:
- 数据库用户名和密码
- JWT 签名密钥
- 第三方 API Token
虽然 Secret 默认只是 Base64 编码,不等于绝对安全,但它仍然是 Kubernetes 中管理敏感配置的标准做法。生产环境一般还会配合 KMS、外部密钥管理系统或密文方案使用。
三、实战示例:一个可运行的 Go HTTP 服务
下面我们先准备一个简单的 Go 服务,用于后续完整部署演示。
1. 目录结构
.
├── Dockerfile
├── go.mod
├── main.go
└── k8s
├── base
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── secret.yaml
│ └── service.yaml
└── overlays
├── dev
│ └── kustomization.yaml
├── staging
│ └── kustomization.yaml
└── prod
└── kustomization.yaml
2. Go 应用代码
这个服务提供几个接口:
/healthz:用于 liveness 检查/readyz:用于 readiness 检查/startupz:用于 startup 检查/config:查看当前环境配置
package main
import (
"encoding/json"
"log"
"net/http"
"os"
"sync/atomic"
"time"
)
type App struct {
started atomic.Bool
}
type Config struct {
AppName string `json:"appName"`
AppEnv string `json:"appEnv"`
Port string `json:"port"`
LogLevel string `json:"logLevel"`
FeatureFlag string `json:"featureFlag"`
DBHost string `json:"dbHost"`
DBUser string `json:"dbUser"`
}
func getEnv(key, fallback string) string {
if value := os.Getenv(key); value != "" {
return value
}
return fallback
}
func loadConfig() Config {
return Config{
AppName: getEnv("APP_NAME", "go-k8s-demo"),
AppEnv: getEnv("APP_ENV", "dev"),
Port: getEnv("PORT", "8080"),
LogLevel: getEnv("LOG_LEVEL", "info"),
FeatureFlag: getEnv("FEATURE_FLAG", "false"),
DBHost: getEnv("DB_HOST", "mysql.default.svc.cluster.local"),
DBUser: getEnv("DB_USER", "demo_user"),
}
}
func main() {
cfg := loadConfig()
app := &App{}
go func() {
time.Sleep(12 * time.Second)
app.started.Store(true)
log.Println("application startup completed")
}()
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("hello from go app on kubernetes\n"))
})
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ok\n"))
})
mux.HandleFunc("/startupz", func(w http.ResponseWriter, r *http.Request) {
if !app.started.Load() {
http.Error(w, "starting", http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("started\n"))
})
mux.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
if !app.started.Load() {
http.Error(w, "not ready", http.StatusServiceUnavailable)
return
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte("ready\n"))
})
mux.HandleFunc("/config", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(cfg)
})
addr := ":" + cfg.Port
log.Printf("app=%s env=%s listening on %s", cfg.AppName, cfg.AppEnv, addr)
if err := http.ListenAndServe(addr, mux); err != nil {
log.Fatalf("server exited: %v", err)
}
}
3. go.mod
module github.com/example/go-k8s-demo
go 1.22
4. Dockerfile
下面是一个适合 Go 服务的多阶段构建镜像示例。
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod .
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o server main.go
FROM alpine:3.20
WORKDIR /app
RUN addgroup -S app && adduser -S app -G app
COPY --from=builder /app/server /app/server
USER app
EXPOSE 8080
ENTRYPOINT ["/app/server"]
构建并推送镜像示例:
docker build -t registry.example.com/demo/go-k8s-demo:v1.0.0 .
docker push registry.example.com/demo/go-k8s-demo:v1.0.0
四、Go 应用完整 K8s 部署 YAML 编写
下面给出一套较完整的 Kubernetes 部署清单。
1. ConfigMap
用于保存非敏感配置。
apiVersion: v1
kind: ConfigMap
metadata:
name: go-k8s-demo-config
labels:
app: go-k8s-demo
data:
APP_NAME: go-k8s-demo
PORT: "8080"
LOG_LEVEL: info
FEATURE_FLAG: "false"
DB_HOST: mysql.default.svc.cluster.local
2. Secret
用于保存敏感配置。这里使用 stringData 便于编写明文,Kubernetes 会自动转换。
apiVersion: v1
kind: Secret
metadata:
name: go-k8s-demo-secret
labels:
app: go-k8s-demo
type: Opaque
stringData:
DB_USER: demo_user
DB_PASSWORD: demo_password
JWT_SECRET: demo-jwt-secret
3. Service
为 Deployment 管理的 Pod 提供稳定访问入口。
apiVersion: v1
kind: Service
metadata:
name: go-k8s-demo
labels:
app: go-k8s-demo
spec:
type: ClusterIP
selector:
app: go-k8s-demo
ports:
- name: http
port: 80
targetPort: 8080
protocol: TCP
4. Deployment
这是本文的核心配置,包含:
- 副本数
- 资源限制
- 探针
- 滚动更新策略
- ConfigMap / Secret 注入
- 安全上下文
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-k8s-demo
labels:
app: go-k8s-demo
spec:
replicas: 2
revisionHistoryLimit: 10
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
selector:
matchLabels:
app: go-k8s-demo
template:
metadata:
labels:
app: go-k8s-demo
spec:
terminationGracePeriodSeconds: 30
containers:
- name: app
image: registry.example.com/demo/go-k8s-demo:v1.0.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
- name: APP_ENV
value: "dev"
envFrom:
- configMapRef:
name: go-k8s-demo-config
- secretRef:
name: go-k8s-demo-secret
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
startupProbe:
httpGet:
path: /startupz
port: http
periodSeconds: 3
timeoutSeconds: 1
failureThreshold: 10
readinessProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
runAsUser: 10001
capabilities:
drop:
- ALL
5. HPA
HPA 会根据资源使用情况自动调整副本数。
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: go-k8s-demo
labels:
app: go-k8s-demo
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: go-k8s-demo
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
behavior:
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
6. 一次性应用全部资源
如果你不做环境区分,可以直接按顺序应用:
kubectl apply -f k8s/base/configmap.yaml
kubectl apply -f k8s/base/secret.yaml
kubectl apply -f k8s/base/service.yaml
kubectl apply -f k8s/base/deployment.yaml
kubectl apply -f k8s/base/hpa.yaml
检查部署结果:
kubectl get deploy,po,svc,hpa
kubectl describe deployment go-k8s-demo
kubectl get events --sort-by=.metadata.creationTimestamp
五、为什么资源限制和 HPA 必须一起设计
很多团队刚接触 Kubernetes 时,会把 requests/limits 和 HPA 分开理解,但在真实生产环境里,它们应该一起设计。
1. requests 与 limits 的区别
requests:调度时的保底资源需求limits:容器运行时允许使用的资源上限
如果不给 requests,调度器就难以合理安置 Pod;如果不给 limits,某个实例可能会在异常情况下吃掉过多资源,影响节点稳定性。
一个典型配置如下:
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "512Mi"
这里的含义是:
- 应用至少需要 0.1 核 CPU、128Mi 内存才能稳定运行
- 允许峰值最多使用 0.5 核 CPU、512Mi 内存
2. HPA 为什么依赖 requests
很多人会忽略一点:基于 CPU 使用率的 HPA,本质上是相对于 requests 来计算目标利用率的。
例如:
- Pod
requests.cpu = 100m - 当前实际使用为
80m - 那么 CPU 利用率约为
80%
如果 HPA 目标是 70%,那么就可能触发扩容。
这意味着:
- requests 配太小,HPA 容易频繁扩容
- requests 配太大,HPA 又可能不敏感
所以 requests 不能凭感觉拍脑袋设置,而应基于压测数据、历史监控和业务峰谷规律来确定。
3. 一个更稳妥的资源规划思路
可以按下面的思路进行:
- 先压测单 Pod 的吞吐和平均资源占用。
- 根据常态流量设置 requests。
- 根据峰值流量和节点容量设置 limits。
- 再根据业务目标设置 HPA 的目标利用率和副本区间。
例如:
- 常态 CPU 使用 80m,峰值 250m
- requests 可设为 100m
- limits 可设为 500m
- HPA CPU target 可先设为 70%
这样系统会更稳定,也更容易预测扩容行为。
六、Readiness、Liveness、Startup Probe 如何正确配置
探针配置是 Kubernetes 稳定部署的关键。很多线上故障并不是程序本身崩了,而是探针配置不合理导致实例反复被重启或流量误切。
1. 三种探针的职责分工
| 探针 | 作用 | 常见问题场景 |
|---|---|---|
| Startup Probe | 判断应用是否完成启动 | 启动慢、预热时间长 |
| Readiness Probe | 判断是否可以接收流量 | 依赖未就绪、缓存未加载完成 |
| Liveness Probe | 判断是否还活着 | 死锁、卡死、主循环异常 |
2. 为什么 Go 应用也需要 Startup Probe
很多人觉得 Go 程序启动很快,不需要 Startup Probe。实际上,服务本身启动快,不代表“业务已可用”。
例如下面这些场景:
- 需要预热本地缓存
- 需要加载大字典或规则文件
- 需要等待下游连接准备完毕
- 需要初始化连接池
如果没有 Startup Probe,Liveness 可能过早介入,导致服务还没启动完就被重启。
3. 本文示例中的探针逻辑
示例程序中,应用会在 12 秒后把内部状态标记为启动完成。
因此:
/startupz在启动完成前返回 503/readyz在启动完成前返回 503/healthz始终返回 200,表示进程还活着
这对应的探针配置如下:
startupProbe:
httpGet:
path: /startupz
port: http
periodSeconds: 3
timeoutSeconds: 1
failureThreshold: 10
readinessProbe:
httpGet:
path: /readyz
port: http
initialDelaySeconds: 3
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 1
failureThreshold: 3
4. 实战中的配置建议
healthz尽量只表示“进程是否存活”,不要把太多外部依赖判断塞进去readyz应体现“当前实例是否适合接流量”- 启动耗时超过数秒的应用,优先补上
startupProbe - 探针阈值不要过于激进,否则容易误杀正常实例
七、滚动更新与回滚策略
Kubernetes 中最常用的发布方式就是滚动更新。它能在不中断服务的前提下,逐步替换旧版本 Pod。
1. RollingUpdate 配置含义
Deployment 中常见配置如下:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 0
maxSurge: 1
含义如下:
maxUnavailable: 0:更新过程中,至少保证当前期望副本数全部可用maxSurge: 1:更新时允许额外多启动 1 个新 Pod
如果 Deployment 期望副本数为 2,那么更新过程可能会这样进行:
- 先额外拉起 1 个新版本 Pod,总数变成 3
- 新 Pod readiness 成功后,下掉 1 个旧 Pod
- 再拉起下一个新 Pod
- 最终完成全部替换
这种方式对线上服务更平滑。
2. 触发滚动更新
修改镜像版本后重新 apply 即可。
kubectl set image deployment/go-k8s-demo app=registry.example.com/demo/go-k8s-demo:v1.0.1
kubectl rollout status deployment/go-k8s-demo
查看发布历史:
kubectl rollout history deployment/go-k8s-demo
3. 回滚策略
如果新版本异常,可以直接回滚。
kubectl rollout undo deployment/go-k8s-demo
如果你想回滚到指定 revision:
kubectl rollout history deployment/go-k8s-demo
kubectl rollout undo deployment/go-k8s-demo --to-revision=3
4. 生产实践建议
- 保留足够的
revisionHistoryLimit - 配合 readiness probe,确保新实例就绪后才接流量
- 不要把大版本配置改动、镜像升级、资源参数改动一次性全部混在一起发布
- 发布前后观察
rollout status、Pod 日志和关键指标
八、多环境配置管理:dev / staging / prod
多环境管理是 Kubernetes 落地中的核心问题之一。同一个 Go 服务,通常会在开发、预发、生产等环境使用不同配置,例如:
- 镜像标签不同
- 副本数不同
- 资源配额不同
- 日志级别不同
- 功能开关不同
- 下游依赖地址不同
如果把这些差异都硬编码到一份 YAML 中,后期会非常难维护。因此建议采用 base + overlay 的方式管理。
本文使用 Kustomize 来演示多环境配置。
1. base 层:放公共配置
先准备 k8s/base/kustomization.yaml。
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- configmap.yaml
- secret.yaml
- service.yaml
- deployment.yaml
- hpa.yaml
2. dev 环境
开发环境通常副本更少、日志更详细、功能开关更灵活。
k8s/overlays/dev/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
namePrefix: dev-
resources:
- ../../base
labels:
- pairs:
env: dev
replicas:
- name: go-k8s-demo
count: 1
images:
- name: registry.example.com/demo/go-k8s-demo
newTag: v1.0.0-dev
configMapGenerator:
- name: go-k8s-demo-config
behavior: merge
literals:
- APP_NAME=go-k8s-demo
- APP_ENV=dev
- PORT=8080
- LOG_LEVEL=debug
- FEATURE_FLAG=true
- DB_HOST=mysql.dev.svc.cluster.local
patches:
- target:
kind: Deployment
name: go-k8s-demo
patch: |
- op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "50m"
- op: replace
path: /spec/template/spec/containers/0/resources/requests/memory
value: "64Mi"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/cpu
value: "200m"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/memory
value: "256Mi"
- op: replace
path: /spec/template/spec/containers/0/env/0/value
value: dev
3. staging 环境
预发环境更接近生产环境,用于联调、灰度和验收。
k8s/overlays/staging/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: staging
namePrefix: staging-
resources:
- ../../base
labels:
- pairs:
env: staging
replicas:
- name: go-k8s-demo
count: 2
images:
- name: registry.example.com/demo/go-k8s-demo
newTag: v1.0.0-rc1
configMapGenerator:
- name: go-k8s-demo-config
behavior: merge
literals:
- APP_NAME=go-k8s-demo
- APP_ENV=staging
- PORT=8080
- LOG_LEVEL=info
- FEATURE_FLAG=false
- DB_HOST=mysql.staging.svc.cluster.local
patches:
- target:
kind: Deployment
name: go-k8s-demo
patch: |
- op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "100m"
- op: replace
path: /spec/template/spec/containers/0/resources/requests/memory
value: "128Mi"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/cpu
value: "500m"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/memory
value: "512Mi"
- op: replace
path: /spec/template/spec/containers/0/env/0/value
value: staging
4. prod 环境
生产环境通常副本更多,资源更稳健,日志级别更保守。
k8s/overlays/prod/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: prod
namePrefix: prod-
resources:
- ../../base
labels:
- pairs:
env: prod
replicas:
- name: go-k8s-demo
count: 3
images:
- name: registry.example.com/demo/go-k8s-demo
newTag: v1.0.0
configMapGenerator:
- name: go-k8s-demo-config
behavior: merge
literals:
- APP_NAME=go-k8s-demo
- APP_ENV=prod
- PORT=8080
- LOG_LEVEL=warn
- FEATURE_FLAG=false
- DB_HOST=mysql.prod.svc.cluster.local
patches:
- target:
kind: Deployment
name: go-k8s-demo
patch: |
- op: replace
path: /spec/template/spec/containers/0/resources/requests/cpu
value: "200m"
- op: replace
path: /spec/template/spec/containers/0/resources/requests/memory
value: "256Mi"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/cpu
value: "1000m"
- op: replace
path: /spec/template/spec/containers/0/resources/limits/memory
value: "1024Mi"
- op: replace
path: /spec/template/spec/containers/0/env/0/value
value: prod
- target:
kind: HorizontalPodAutoscaler
name: go-k8s-demo
patch: |
- op: replace
path: /spec/minReplicas
value: 3
- op: replace
path: /spec/maxReplicas
value: 20
5. 按环境部署
部署开发环境:
kubectl apply -k k8s/overlays/dev
部署预发环境:
kubectl apply -k k8s/overlays/staging
部署生产环境:
kubectl apply -k k8s/overlays/prod
查看渲染后的 YAML:
kubectl kustomize k8s/overlays/prod
6. 多环境管理的实践建议
- 公共逻辑放
base - 环境差异放
overlay - 镜像版本、资源规格、环境变量按环境拆分
- Secret 尽量通过外部密钥系统管理,不要长期明文提交到仓库
- 生产环境变更应可审计、可回滚、可追踪
九、一套完整的部署流程示例
把前面的内容串起来,一个典型的 Go 服务 Kubernetes 部署流程可以是这样:
1. 本地构建镜像
docker build -t registry.example.com/demo/go-k8s-demo:v1.0.0 .
docker push registry.example.com/demo/go-k8s-demo:v1.0.0
2. 预览生产环境配置
kubectl kustomize k8s/overlays/prod
3. 部署到集群
kubectl apply -k k8s/overlays/prod
4. 观察发布状态
kubectl rollout status deployment/prod-go-k8s-demo -n prod
kubectl get po -n prod -w
5. 检查 Service 与 HPA
kubectl get svc,hpa -n prod
kubectl describe hpa prod-go-k8s-demo -n prod
6. 模拟发布新版本
kubectl set image deployment/prod-go-k8s-demo app=registry.example.com/demo/go-k8s-demo:v1.0.1 -n prod
kubectl rollout status deployment/prod-go-k8s-demo -n prod
7. 异常时快速回滚
kubectl rollout undo deployment/prod-go-k8s-demo -n prod
十、实战中最容易踩的几个坑
最后再总结几个非常常见的问题。
1. 只配 liveness,不配 readiness
结果往往是容器刚启动就被 Service 转发流量,导致请求失败。正确做法是优先保证 readiness 正确。
2. requests 设置不合理
如果 requests 太低,HPA 会频繁触发;如果太高,会降低节点利用率,甚至造成调度失败。
3. 把配置写死在镜像里
这样 dev、staging、prod 三个环境就必须构建三次镜像,成本高且容易出错。更合理的方式是镜像统一、配置外置。
4. 发布策略过于激进
例如 maxUnavailable 设置过大,可能导致更新时可用实例骤降。对线上业务来说,应该优先保证平滑发布。
5. 忽略启动慢场景
即使 Go 服务本身很轻,也可能因为预热、连接建立、依赖检查而延迟可用,因此 Startup Probe 在很多场景下是有必要的。
十一、总结
Kubernetes 部署 Go 应用时,真正需要掌握的并不只是“会写一个 Deployment”,而是整套部署模型的协同关系:
- 用 Pod 承载实例
- 用 Deployment 管理副本和发布
- 用 Service 提供稳定访问入口
- 用 ConfigMap 和 Secret 管理配置
- 用 resources 和 HPA 控制资源与弹性
- 用三类 Probe 保证稳定接流量与故障恢复
- 用 Kustomize 管理多环境差异
当这些要素组合在一起后,你的 Go 服务才真正具备了云原生部署能力:可发布、可扩展、可观测、可回滚、可治理。
如果你正在推进 Go 服务上云或容器化改造,建议直接把本文里的结构作为模板,先搭出一条完整链路,再结合业务特性逐步细化探针、资源和弹性策略。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!