go应用在kubernetes中跑起来需先本地验证服务监听8080端口并响应/healthz,再通过docker多阶段构建镜像;部署时用deployment定义replicas、containerport、readiness/liveness探针(http get /healthz,initialdelayseconds=10s,failurethreshold=5),设置resources限制,镜像必须带明确tag(如v1.2.3),禁用latest。

Go应用在Kubernetes里怎么跑起来
先确保你的Go服务能本地跑通,监听 8080 端口、响应健康检查(比如 /healthz),再打包进Docker镜像。关键点不是“能不能跑”,而是“Kubernetes能不能管住它”。
用最小化 Deployment 就够:指定 replicas、containerPort、加上 readiness/liveness 探针。别漏掉 resources 限制,否则 Pod 可能被 OOMKilled 或调度失败。
-
readinessProbe用 HTTP GET 到/healthz,初始延迟设为10s,避免启动慢导致反复重启 -
livenessProbe同样走 HTTP,但失败阈值建议设高一点(如failureThreshold: 5),防止偶发超时误杀 - 镜像必须带明确 tag(如
v1.2.3),别用latest—— Kubernetes 不会主动拉新镜像
Jaeger Agent 是该用 DaemonSet 还是 Sidecar
两者都能用,但选错会导致 span 上报失败或资源浪费。DaemonSet 更适合集群级统一采集,Sidecar 更适合隔离性强、协议混杂的场景。
如果你的 Go 服务只走 HTTP,且集群里其他服务也用 Jaeger,优先 DaemonSet:每个节点起一个 jaeger-agent,监听 6831/udp,所有 Pod 都往 localhost:6831 发数据。简单、低开销、易维护。
- DaemonSet 的
hostNetwork: true要关掉,改用hostPort或 Service ClusterIP + headless 模式,避免端口冲突 - Sidecar 模式下,Go 应用容器和
jaeger-agent必须在同一个 Pod,且 Agent 的LocalAgentHostPort配成127.0.0.1:6831,不能写localhost(某些 DNS 配置下解析失败) - 如果用了 Istio,别自己部署 Agent —— 它自带 Envoy 的 tracing filter,直接配好
tracing.zipkin.address即可
Go SDK 初始化 Tracer 时最容易错的三件事
初始化本身几行代码,但配错参数,链路就断在第一跳。最常踩的坑不是不会写,而是没验证上报路径是否通。
以 OpenTelemetry Go SDK 为例:jaeger.New() 或 otlptracegrpc.New() 的 endpoint 必须和你实际部署的组件对得上。Agent 默认收 UDP 6831,Collector 默认收 HTTP 14268 或 gRPC 14250 —— 写反了,span 就静默丢弃。
- 用
jaeger.New(jaeger.WithCollectorEndpoint(...))时,endpoint 地址要是http://jaeger-collector:14268/api/traces,不是http://jaeger-agent:6831 - 用
otlptracegrpc.New()时,地址格式是jaeger-collector:14250(无协议头),且要确认 Collector 的 gRPC server 已启用(envJAEGER_COLLECTOR_GRPC_HOST_PORT) - 务必调
tracer.StartSpan(..., opentracing.ChildOf(span.Context()))做上下文透传,光有初始化不够;Gin 中间件里漏掉opentracing.ContextWithSpan(r.Context(), span),后续业务逻辑就拿不到 span
怎么确认链路真的串起来了
别只看 Jaeger UI 有没有数据,要看数据从哪来、经过了哪些跳、有没有丢失上下文。最有效的验证方式是打日志 + 抓包 + 查 traceID。
在 Go 代码里加一行 log.Printf("traceID: %s", span.Context().(opentracing.SpanContext).TraceID().String()),然后 curl 一次接口,拿到 traceID 后去 Jaeger UI 搜。如果搜不到,说明上报失败;如果只有一段(只有入口,没有下游 HTTP/gRPC 调用),说明上下文没透传或下游没集成。
- 用
tcpdump -i any port 6831在 Pod 所在节点抓包,确认 UDP 包是否发出(目标 IP 是 Agent 所在节点) - Agent 日志里搜
span reported,Collector 日志里搜span received,两头都看到才算链路通 - 跨协议调用(比如 Go HTTP → Java gRPC)必须手动 inject/extract
span.Context(),HTTP Header 里的uber-trace-id对 gRPC 无效
复杂点在于上下文透传不是“配一次就完事”,而是每经过一次中间件、每一次远程调用、每一个 goroutine 启动,都要显式传递。漏掉任意一环,链路就断在那。











