云原生架构下微服务接入 SkyWalking 最佳实践

    banner.jpg

    背景

    本文介绍在 Kubernetes 集群中,如何通过 Sidecar 模式为 Java 应用无侵入式部署 SkyWalking 探针,并利用 DataKit 内置的 SkyWalking 采集器,一站式收集链路数据(Trace)与应用日志(Log),最终在观测云平台实现强大的链路与日志联动查询,全面提升可观测性能力。

    部署 SkyWalking 探针

    SkyWalking Agent Sidecar 容器

    该容器负责提供 skywalking-agent.jar 及其配置文件。

    • 环境变量: 配置应用名(SW_AGENT_NAME
    • Volume 挂载: 将 Agent 目录挂载到共享 Volume
    • Sidecar 容器镜像 dockerfile:
    FROM alpine:3.14
    
      
    
    # 下载SkyWalking探针
    
    RUN wget -O /tmp/skywalking-agent.tar.gz \
    
        https://archive.apache.org/dist/skywalking/java-agent/8.8.0/apache-skywalking-java-agent-8.8.0.tgz \
    
        && tar -zxvf /tmp/skywalking-agent.tar.gz -C / \
    
        && mv /skywalking-agent /agent \
    
        && rm /tmp/skywalking-agent.tar.gz
    
      
    
    # 复制启动脚本
    
    COPY entrypoint.sh /entrypoint.sh
    
    RUN chmod +x /entrypoint.sh
    
      
    
    ENTRYPOINT ["/entrypoint.sh"]
    

    entrypoint.sh

    #!/bin/sh
    
      
    
    # 创建配置目录
    
    mkdir -p /agent/config
    
      
    
    # 动态生成agent.config
    
    cat <<EOF > /agent/config/agent.config
    
    # 服务名由环境变量传入
    
    agent.service_name=\${SW_AGENT_NAME:demo}
    
    # DataKit地址由环境变量传入
    
    collector.backend_service=\${SW_AGENT_COLLECTOR_BACKEND_SERVICES:datakit-service.datakit.svc.cluster.local:11800}
    
    EOF
    
      
    
    # 将探针复制到共享卷
    
    cp -r /agent/* /sw-agent/
    
      
    
    # 保持容器运行
    
    tail -f /dev/null
    

    业务容器

    • 无需修改镜像: 业务镜像本身无需包含任何 SkyWalking 依赖。
    • JVM 参数注入: 通过 JAVA_TOOL_OPTIONS 环境变量,指向共享 Volume 中的 skywalking-agent.jar。
    • Volume 挂载: 同样挂载共享 Volume,以访问其中的 Agent 文件。

    业务 yaml

    apiVersion: apps/v1
    
    kind: Deployment
    
    metadata:
    
      name: service-b
    
    spec:
    
      replicas: 1
    
      selector:
    
        matchLabels:
    
          app: service-b
    
      template:
    
        metadata:
    
          labels:
    
            app: service-b
    
        spec:
    
          volumes:
    
            - name: sw-agent
    
              emptyDir: {}
    
          containers:
    
            # 主应用容器
    
            - name: service-b-app
    
              image: zhaoje/service-b:sw3.0
    
              ports:
    
                - containerPort: 8081
    
              volumeMounts:
    
                - name: sw-agent
    
                  mountPath: /sw-agent
    
              env:
    
                - name: JAVA_TOOL_OPTIONS
    
                  value: "-javaagent:/sw-agent/skywalking-agent.jar"
    
            # SkyWalking边车容器
    
            - name: sw-agent-sidecar
    
              image: xxx/sw-agent-sidecar:8.8.2
    
              env:
    
                - name: SW_AGENT_NAME
    
                  value: "service-b"
    
              volumeMounts:
    
                - name: sw-agent
    
                  mountPath: /sw-agent
    
    ---
    
    apiVersion: v1
    
    kind: Service
    
    metadata:
    
      name: service-b
    
    spec:
    
      #type: NodePort
    
      selector:
    
        app: service-b
    
      ports:
    
        - protocol: TCP
    
          port: 8081
    
          targetPort: 8080
    

    应用日志关联 Trace

    本最佳实践以 log4j2 示例,将 toolkit 依赖包添加到 maven 或者 gradle 中:

             <dependency>
    
                <groupId>org.apache.skywalking</groupId>
    
                <artifactId>apm-toolkit-log4j-2.x</artifactId>
    
                <version>8.8.0</version> 
    
            </dependency>
    
            <dependency>
    
                <groupId>org.apache.skywalking</groupId>
    
                <artifactId>apm-toolkit-trace</artifactId>
    
                <version>8.8.0</version>
    
            </dependency>
    
    • apm-toolkit-log4j-2.x: 这是最关键的依赖。它为 Log4j2 这个日志框架提供了扩展。具体来说,它提供了一个特殊的 %tid 模式转换器(Pattern Layout Converter)。正是因为有了这个依赖,您才能在后面的 log4j2.xml 配置中使用 [%tid] 来输出 Trace ID。
    • apm-toolkit-trace: 这个依赖提供了一些有用的 API,例如 TraceContext.traceId() 用于在代码中手动获取当前链路的 Trace ID。虽然很多功能由探针自动完成,但如果您想在业务代码中主动操作追踪上下文,就需要它。

    并在服务目录下新增 log4j2.xml 定义输出格式,在示例中的路径是:/root/service-a/src/main/resources

    <?xml version="1.0" encoding="UTF-8"?>
    
    <Configuration status="WARN">
    
        <Appenders>
    
            <!-- 控制台输出 -->
    
            <Console name="Console" target="SYSTEM_OUT">
    
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n"/>
    
            </Console>
    
            <!-- SkyWalking gRPC日志输出 -->
    
            <GRPCLogClientAppender name="GrpcLog">
    
                <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{36} - %msg%n"/>
    
            </GRPCLogClientAppender>
    
        </Appenders>
    
        <Loggers>
    
            <!-- 设置Spring框架日志级别 -->
    
            <Logger name="org.springframework" level="WARN" additivity="false">
    
                <AppenderRef ref="Console"/>
    
                <AppenderRef ref="GrpcLog"/>
    
            </Logger>
    
            <Root level="INFO">
    
                <AppenderRef ref="Console"/>
    
                <AppenderRef ref="GrpcLog"/>
    
            </Root>
    
        </Loggers>
    
    </Configuration>
    

    DataKit 开启 SkyWalking 采集器

    部署配置 DataKit

    在观测云控制台点击「集成」-「DataKit」-「Kubernetes」,运行脚本下载。

    wget https://static.guance.com/datakit/datakit.yaml
    

    开启 SkyWalking 采集器

    在 volumeMounts 中添加

            - mountPath: /usr/local/datakit/conf.d/skywalking/skywalking.conf
    
              name: datakit-conf
    
              subPath: skywalking.conf
    
              readOnly: true
    

    在 configmap 中增加 SkyWalking 配置

    apiVersion: v1
    
    kind: ConfigMap
    
    metadata:
    
      name: datakit-conf
    
      namespace: datakit
    
    data:
    
        skywalking.conf: |-
    
          [inputs.skywalking]
    
           endpoints = ["/v3/trace", "/v3/metric", "/v3/logging", "/v3/profiling"]
    
           address = "0.0.0.0:11800"
    

    观测云

    可以看到链路数据正常上报的观测云空间

    链路和日志也通过 trace_id 串联起来

    在日志页面也可以反向查询链路数据

    总结

    通过本文介绍的 Sidecar 模式与 DataKit 相结合的方案,我们成功实现了:

    • 轻量级集成: 以非侵入方式为集群 Java 应用快速赋予了链路追踪能力。
    • 架构简化: 利用 DataKit 替代了 SkyWalking OAP + Storage 的复杂组件,降低了运维成本。
    • 数据融合: 最终在观测云平台上实现了链路追踪数据与应用日志数据的无缝关联与联动查询,形成了完整的可观测性闭环。

    联系我们

    加入社区

    微信扫码
    加入官方交流群

    立即体验

    在线开通,按量计费,真正的云服务!

    立即开始

    选择观测云版本

    代码托管平台