在微服务架构日益普及的今天,全链路监控已成为保障系统稳定性的关键组件。Apache SkyWalking 作为一款优秀的应用性能监控(APM)工具,提供了灵活的 Agent 接入方式。本文将详细阐述如何在 Kubernetes 环境下,通过 Sidecar 模式部署 SkyWalking Agent,并针对 Spring Boot 微服务进行实战配置。
一、SkyWalking Agent在K8s中的部署模式分析与选型
在 Java 应用中接入 SkyWalking Agent,主要有以下三种方式:
- 使用官方基础镜像:直接基于
skywalking-base镜像构建应用。 - 构建集成镜像:将 Agent 包直接构建到业务镜像中。
- Sidecar 模式挂载:推荐模式。
为何推荐 Sidecar 模式?
官方镜像属于精简版 OpenJDK,可能缺少部分常用命令,且修改基础镜像会增加维护成本。而 Sidecar 模式具有显著优势:
- 零侵入:无需修改原有的业务基础镜像,也无需重新构建服务镜像。
- 解耦:Agent 与应用容器分离,通过共享 Volume 的方式挂载文件,互不干扰。
- 灵活性:便于统一管理和升级 Agent 版本。
二、构建独立的SkyWalking Agent Docker镜像
首先,我们需要构建一个包含 SkyWalking Agent 的独立镜像,以便在 K8s 中作为 Sidecar 使用。
1. 编写 Dockerfile
基于 Alpine Linux 构建轻量级镜像,并开启必要的插件(如 trace-ignore-plugin 用于忽略特定路径)以及日志配置。
FROM alpine:3.8
LABEL maintainer="DevOps Team"
ENV SKYWALKING_VERSION=8.5.0
# 下载并解压 SkyWalking
ADD https://archive.apache.org/dist/skywalking/${SKYWALKING_VERSION}/apache-skywalking-apm-${SKYWALKING_VERSION}.tar.gz /
RUN tar -zxvf /apache-skywalking-apm-${SKYWALKING_VERSION}.tar.gz && \
mv apache-skywalking-apm-bin skywalking && \
# 启用 trace-ignore-plugin 插件
mv /skywalking/agent/optional-plugins/apm-trace-ignore-plugin* /skywalking/agent/plugins/ && \
# 优化日志配置,防止日志文件过多
sed -i 's@# logging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:-1}@logging.max_history_files=${SW_LOGGING_MAX_HISTORY_FILES:2}@' /skywalking/agent/config/agent.config && \
# 配置忽略路径(例如健康检查)
echo -e "\n# Ignore Path" >> /skywalking/agent/config/agent.config && \
echo "trace.ignore_path=${SW_IGNORE_PATH:/health}" >> /skywalking/agent/config/agent.config
2. 构建与推送
构建完成后,将其推送到私有镜像仓库。
$ docker build -t harbor.nebulait.cn/library/skywalking-agent:8.5.0 .
$ docker push harbor.nebulait.cn/library/skywalking-agent:8.5.0
三、Sidecar模式挂载机制与基础实现
Sidecar 模式的核心在于 Kubernetes 的 Init Containers 和 emptyDir 卷。
实现原理:
- Init Container:启动时先将 Agent 文件从 Sidecar 镜像复制到共享的
emptyDir卷中。 - Application Container:业务容器启动时,将共享卷挂载到指定目录,并通过 JVM 参数加载 Agent。
示例:以 Nginx 为例的挂载配置
虽然 Nginx 不需要 Java Agent,但以下 YAML 清晰地展示了 Sidecar 挂载的标准结构:
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-skywalking
spec:
replicas: 1
selector:
matchLabels:
app: demo-skywalking
template:
metadata:
labels:
app: demo-skywalking
spec:
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command: ['sh', '-c', 'set -ex; mkdir -p /vmskywalking/agent; cp -r /skywalking/agent/* /vmskywalking/agent;']
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- image: nginx:1.7.9
name: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath: /opt/skywalking/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
四、Spring Cloud应用的集成与K8s部署
对于 Java/Spring Boot 应用,我们需要在 Dockerfile 中预设 Agent 的挂载点,并在 K8s 启动参数中指明 OAP 服务地址。
1. 改造 Spring Boot Dockerfile
注意 ENTRYPOINT 中的 -javaagent 参数配置,这是 Java Agent 生效的关键。
FROM harbor.nebulait.cn/library/openjdk:8-jdk
COPY ./springdemo2023.jar /opt/
# 创建必要目录
RUN mkdir -p data/logs/ && mkdir -p data/skywalking/agent
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo 'Asia/Shanghai' > /etc/timezone
# 配置启动参数:包含 Agent 路径、服务名及后端 OAP 地址
ENTRYPOINT [ "java", \
"-Dapp.id=springdemo2023", \
"-javaagent:/data/skywalking/agent/skywalking-agent.jar", \
"-Dskywalking.agent.service_name=springdemo2023", \
"-Dskywalking.collector.backend_service=skywalking-oap.devops.svc.cluster.local:11800", \
"-jar", "/opt/springdemo2023.jar" , \
"-Dfile.encoding=UTF-8" ]
注意:Kubernetes 内部服务调用需使用完全限定域名(FQDN),格式为
<service-name>.<namespace>.svc.cluster.local。跨命名空间访问时必须使用完整域名。
$ docker build -t harbor.nebulait.cn/library/springdemo-skywalking:v1 .$ docker push harbor.nebulait.cn/library/springdemo-skywalking:v1
2. 编写 Kubernetes 部署文件 (YAML)
完整的 Deployment 配置包含 InitContainer、业务容器探针以及 Service 暴露。
apiVersion: v1
kind: Service
metadata:
name: springdemo2023
namespace: default
spec:
ports:
- port: 8080
targetPort: 8080
selector:
app: springdemo2023
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: springdemo2023
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: springdemo2023
template:
metadata:
labels:
app: springdemo2023
spec:
imagePullSecrets:
- name: harborsecret
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command: ['sh', '-c', 'set -ex; mkdir -p /vmskywalking/agent; cp -r /skywalking/agent/* /vmskywalking/agent;']
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- image: harbor.nebulait.cn/demo/springdemo-skywalking:v1
name: springdemo2023
ports:
- containerPort: 8080
# 健康检查配置
livenessProbe:
httpGet:
path: /apptwo
port: 8080
initialDelaySeconds: 30
readinessProbe:
httpGet:
path: /apptwo
port: 8080
initialDelaySeconds: 20
volumeMounts:
- mountPath: /data/skywalking/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
五、生产环境微服务全链路监控实战
在实际的微服务场景中,通常包含 UI、业务中台(Office、Account)等模块。以下展示了典型的多服务部署配置。
1. UI 服务 (acme-financial-ui)
UI 服务通常作为流量入口,通过 Ingress 暴露。
apiVersion: apps/v1
kind: Deployment
metadata:
name: acme-financial-ui
spec:
replicas: 1
selector:
matchLabels:
app: acme-financial-ui
template:
metadata:
labels:
app: acme-financial-ui
spec:
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command: ['sh', '-c', 'set -ex; mkdir -p /vmskywalking/agent; cp -r /skywalking/agent/* /vmskywalking/agent;']
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- name: ui
image: harbor.nebulait.cn/library/acme-financial-ui:v0.1
env:
# 通过环境变量传递 JVM 参数,灵活注入 Agent
- name: JAVA_OPTS
value: "-javaagent:/opt/sw/agent/skywalking-agent.jar"
- name: SW_AGENT_NAME
value: "acme-financial-ui"
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: "skywalking-oap.devops.svc.cluster.local:11800"
ports:
- containerPort: 8081
volumeMounts:
- mountPath: /opt/sw/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: acme-financial-ui
spec:
ports:
- port: 8081
selector:
app: acme-financial-ui
2. 其他微服务 (Office/Account/Customer)
其他后端服务(如 acme-financial-office, acme-financial-account)的配置结构完全一致,仅需修改 SW_AGENT_NAME、镜像名称及端口号即可。
配置要点:
- SW_AGENT_NAME:在 SkyWalking UI 中显示的服务名称,需保证唯一性。
- InitContainer:所有微服务 Pod 均需包含此步骤以拷贝 Agent。
- Volume 挂载:确保 Agent 目录挂载路径与
JAVA_OPTS中的路径一致。
Springboot微服务 – office服务:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: acme-financial-office
name: acme-financial-office
spec:
replicas: 1
selector:
matchLabels:
app: acme-financial-office
template:
metadata:
labels:
app: acme-financial-office
spec:
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command:
- 'sh'
- '-c'
- 'set -ex;mkdir -p /vmskywalking/agent;cp -r /skywalking/agent/* /vmskywalking/agent;'
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- env:
- name: JAVA_OPTS
value: "-javaagent:/opt/sw/agent/skywalking-agent.jar"
- name: SW_AGENT_NAME
value: "acme-financial-office"
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: "skywalking-oap.devops.svc.cluster.local:11800"
image: harbor.nebulait.cn/library/acme-financial-office:v0.1
imagePullPolicy: Always
name: office
ports:
- containerPort: 8082
protocol: TCP
volumeMounts:
- mountPath: /opt/sw/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: acme-financial-office
name: acme-financial-back-office
spec:
ports:
- name: http
port: 8082
protocol: TCP
targetPort: 8082
selector:
app: acme-financial-office
sessionAffinity: None
type: ClusterIP
Springboot微服务 – account服务:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: acme-financial-account
name: acme-financial-account
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: acme-financial-account
template:
metadata:
labels:
app: acme-financial-account
spec:
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command:
- 'sh'
- '-c'
- 'set -ex;mkdir -p /vmskywalking/agent;cp -r /skywalking/agent/* /vmskywalking/agent;'
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- env:
- name: JAVA_OPTS
value: "-javaagent:/opt/sw/agent/skywalking-agent.jar"
- name: SW_AGENT_NAME
value: "acme-financial-account"
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: "skywalking-oap.devops.svc.cluster.local:11800"
image: harbor.nebulait.cn/library/acme-financial-account:v0.1
imagePullPolicy: Always
name: account
ports:
- containerPort: 8083
protocol: TCP
volumeMounts:
- mountPath: /opt/sw/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: acme-financial-account
name: acme-financial-account
spec:
ports:
- name: http
port: 8083
protocol: TCP
targetPort: 8083
selector:
app: acme-financial-account
sessionAffinity: None
type: ClusterIP
Springboot微服务 – customer服务:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: acme-financial-customer
name: acme-financial-customer
spec:
replicas: 1
selector:
matchLabels:
app: acme-financial-customer
template:
metadata:
labels:
app: acme-financial-customer
spec:
initContainers:
- name: init-skywalking-agent
image: harbor.nebulait.cn/library/skywalking-agent:8.5.0
command:
- 'sh'
- '-c'
- 'set -ex;mkdir -p /vmskywalking/agent;cp -r /skywalking/agent/* /vmskywalking/agent;'
volumeMounts:
- mountPath: /vmskywalking/agent
name: skywalking-agent
containers:
- env:
- name: JAVA_OPTS
value: "-javaagent:/opt/sw/agent/skywalking-agent.jar"
- name: SW_AGENT_NAME
value: "acme-financial-customer"
- name: SW_AGENT_COLLECTOR_BACKEND_SERVICES
value: "skywalking-oap.devops.svc.cluster.local:11800"
image: harbor.nebulait.cn/library/acme-financial-customer:v0.1
imagePullPolicy: Always
name: customer
ports:
- containerPort: 8084
protocol: TCP
volumeMounts:
- mountPath: /opt/sw/agent
name: skywalking-agent
volumes:
- name: skywalking-agent
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app: acme-financial-customer
name: acme-financial-customer
namespace: default
spec:
ports:
- name: http
port: 8084
protocol: TCP
targetPort: 8084
selector:
app: acme-financial-customer
sessionAffinity: None
type: ClusterIP
3. 配置 Ingress
最后,配置 Ingress 将外部流量路由至 UI 服务。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: acme-financial-ing
spec:
ingressClassName: nginx
rules:
- host: acme.zhoumx.cc
http:
paths:
- pathType: Prefix
backend:
service:
name: acme-financial-ui
port:
number: 8081
path: /
六、流量模拟与SkyWalking数据大盘验证
部署完成后,我们需要通过模拟流量来验证监控数据的准确性。
1. 模拟 API 访问压力
使用 curl 循环调用 UI 服务的不同接口,生成追踪数据。
## 模拟正常接口调用
$ for i in {1..5000}; do curl http://acme.zhoumx.cc/hello && sleep 1; done
## 模拟业务启动流程
$ for i in {1..5000}; do curl http://acme.zhoumx.cc/start && sleep 1; done
## 模拟超时/慢调用场景
$ for i in {1..5000}; do curl http://acme.zhoumx.cc/readtimeout && sleep 1; done
2. SkyWalking UI 指标解读
登录 SkyWalking Web 控制台,观察以下核心指标:
- 吞吐量 (CPM):每分钟调用次数,反映系统负载。
- Apdex (应用性能指数):衡量用户对应用性能满意度的标准分数。
- 响应时间百分位:重点关注 P99、P95、P90,识别长尾请求。
- SLA (服务等级协议):通常指 HTTP 状态码为 200 的请求成功率。
- 拓扑图:可视化的服务调用链路图,点击节点可查看具体实例的监控详情。
- 追踪查询:定位具体的慢请求或报错接口,分析调用栈耗时。



通过以上步骤,我们已在 Kubernetes 环境下成功实现了基于 Sidecar 模式的 SkyWalking 全链路监控部署。这种模式既保证了业务镜像的纯净性,又实现了监控能力的灵活注入,非常适合生产环境的微服务治理。
