首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >云原生不是"上K8s":声明式交付、弹性、可观测与GitOps的工程底线,附可运行代码

云原生不是"上K8s":声明式交付、弹性、可观测与GitOps的工程底线,附可运行代码

原创
作者头像
IT大佬 jzit-top
发布于 2026-10-17 16:36:22
发布于 2026-10-17 16:36:22
430
举报

云原生的专业内核不是"把应用塞进容器",而是声明式交付、资源契约、弹性伸缩、故障自愈、全链路可观测、GitOps闭环。下面按生产级落地拆解,每环给可运行代码。

一、容器化:多阶段构建 + 非root + 健康探针

镜像不是能跑就行。多阶段构建压体积,非root降攻击面,探针让K8s知道何时接流量、何时重启。

代码语言:javascript
复制
# Dockerfile
FROM golang:1.22 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app ./cmd/server

FROM gcr.io/distroless/static:nonroot
COPY --from=build /app /app
USER nonroot:nonroot
EXPOSE 8080
ENTRYPOINT ["/app"]
代码语言:javascript
复制
# deployment.yaml 关键片段
containers:
- name: api
  image: registry.example.com/api:v1.2.0   # 禁止 latest
  resources:
    requests: {cpu: "100m", memory: "128Mi"}
    limits:   {cpu: "500m", memory: "256Mi"}
  readinessProbe:
    httpGet: {path: /readyz, port: 8080}
    periodSeconds: 5
  livenessProbe:
    httpGet: {path: /healthz, port: 8080}
    periodSeconds: 10
    failureThreshold: 3
  securityContext:
    runAsNonRoot: true
    readOnlyRootFilesystem: true
    allowPrivilegeEscalation: false

工程约束:requests必须设,否则调度器瞎排、HPA算不准;limits必须设,否则一个Pod OOM拖垮节点;readinessProbe失败摘流量,livenessProbe失败重启,两者路径不能混用。

二、弹性:HPA看对指标,别只看CPU

CPU弹性对IO密集型服务无效。用Prometheus Adapter暴露QPS/队列深度等业务指标,HPA按业务指标扩缩。

代码语言:javascript
复制
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata: {name: api-hpa}
spec:
  scaleTargetRef: {apiVersion: apps/v1, kind: Deployment, name: api}
  minReplicas: 2
  maxReplicas: 20
  metrics:
  - type: Pods
    pods:
      metric: {name: http_requests_per_second}
      target: {type: AverageValue, averageValue: "100"}
  behavior:
    scaleDown:
      stabilizationWindowSeconds: 300   # 防抖动

工程约束:minReplicas≥2保证高可用;stabilizationWindowSeconds防指标毛刺导致反复扩缩;HPA依赖requests,requests虚低会导致扩容后仍过载。

三、自愈与可用性:PDB + 拓扑分布 + 优雅停机

滚动更新和节点驱逐时,必须保证可用副本数,且副本跨可用区。

代码语言:javascript
复制
spec:
  replicas: 4
  template:
    spec:
      terminationGracePeriodSeconds: 30
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector: {matchLabels: {app: api}}
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: {name: api-pdb}
spec:
  minAvailable: 3
  selector: {matchLabels: {app: api}}
代码语言:javascript
复制
// 优雅停机:先摘流量,再停服务
srv := &http.Server{Addr: ":8080", Handler: mux}
go srv.ListenAndServe()
sig := make(chan os.Signal, 1); signal.Notify(sig, syscall.SIGTERM)
<-sig
ctx, cancel := context.WithTimeout(context.Background(), 25*time.Second)
defer cancel()
srv.Shutdown(ctx)   // 处理完存量请求再退出

工程约束:terminationGracePeriodSeconds必须大于应用最大请求耗时;preStop里可加sleep 5等endpoint同步;PDB防运维误操作把副本驱逐光。

四、声明式与GitOps:集群状态只认Git

不要kubectl apply手工改集群。所有 manifests 进Git,ArgoCD持续比对、自动同步,漂移可回滚。

代码语言:javascript
复制
# argocd-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata: {name: api-prod, namespace: argocd}
spec:
  project: default
  source:
    repoURL: https://git.example.com/platform.git
    targetRevision: main
    path: apps/api/overlays/prod   # Kustomize overlay
  destination:
    server: https://kubernetes.default.svc
    namespace: prod
  syncPolicy:
    automated: {prune: true, selfHeal: true}   # 自动纠偏
    syncOptions: [CreateNamespace=true]

工程约束:selfHeal: true让手工改动被自动还原;prune: true清理Git中已删资源;生产环境用SyncWindow限制发布时段。

五、可观测:指标、日志、追踪三件套一次接入

代码语言:javascript
复制
// OpenTelemetry 接入,trace + metrics 一次埋点
import (
  "go.opentelemetry.io/otel"
  "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
  sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
func initTracer() {
  exp, _ := otlptracegrpc.New(context.Background())
  tp := sdktrace.NewTracerProvider(sdktrace.WithBatcher(exp))
  otel.SetTracerProvider(tp)
}
// 业务代码
ctx, span := otel.Tracer("api").Start(ctx, "handleOrder")
defer span.End()

工程约束:traceID要透传到日志和下游调用;指标带service、version、pod标签;日志统一JSON结构化,禁止打印敏感字段。

六、安全与成本:网络策略 + 资源配额 + 镜像扫描

代码语言:javascript
复制
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata: {name: api-allow-ingress}
spec:
  podSelector: {matchLabels: {app: api}}
  ingress:
  - from: [{podSelector: {matchLabels: {app: gateway}}}]
    ports: [{protocol: TCP, port: 8080}]
---
apiVersion: v1
kind: ResourceQuota
metadata: {name: prod-quota, namespace: prod}
spec:
  hard: {requests.cpu: "20", requests.memory: 40Gi, pods: "50"}

工程约束:默认拒绝入站,按需放行;ResourceQuota防单命名空间吃光集群;CI里加Trivy镜像扫描,高危漏洞阻断发布。

总结:云原生的专业度不在"会kubectl",而在多阶段非root镜像、requests/limits与双探针、业务指标HPA、PDB与拓扑分布、优雅停机、GitOps自动纠偏、OTel三件套、网络策略与配额这八件事。能给别人讲清楚"为什么HPA只看CPU会翻车""为什么手工改集群是事故源头",你就站稳了云原生工程。觉得有用点赞收藏,需要完整工程目录留言。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、容器化:多阶段构建 + 非root + 健康探针
  • 二、弹性:HPA看对指标,别只看CPU
  • 三、自愈与可用性:PDB + 拓扑分布 + 优雅停机
  • 四、声明式与GitOps:集群状态只认Git
  • 五、可观测:指标、日志、追踪三件套一次接入
  • 六、安全与成本:网络策略 + 资源配额 + 镜像扫描
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档