SkyWalking 部署与应用服务接入全流程指南

📋 主要步骤概览

  1. 创建 SkyWalking 目录
  2. 创建 docker-compose.yml 配置文件
  3. 启动 SkyWalking 容器
  4. 访问 SkyWalking-UI 确认服务部署成功
  5. 项目代码依赖配置
  6. 构建应用服务镜像
  7. 启动应用服务容器
  8. 常见问题排查与解决

一、创建 SkyWalking 目录

1.1 批量创建目录

为了方便后续部署,我们首先创建 SkyWalking 相关的目录结构。使用以下命令一次性创建所有需要的目录:

mkdir -p /data/deploy/skywalking/{elasticsearch/{data,logs},{oap/logs,ui/logs}}

命令说明:

  • mkdir -p:递归创建目录,如果父目录不存在也会一并创建
  • /data/deploy/skywalking/:SkyWalking 部署根目录
  • elasticsearch/{data,logs}:Elasticsearch 的数据和日志目录
  • oap/logs:SkyWalking OAP 服务器日志目录
  • ui/logs:SkyWalking UI 日志目录

目录结构创建完成后,可以使用以下命令验证:

tree /data/deploy/skywalking/

预期输出结构:

/data/deploy/skywalking/
├── elasticsearch
│   ├── data
│   └── logs
├── oap
│   └── logs
└── ui
    └── logs

二、环境配置与容器启动

2.1 elasticsearch 文件夹授权

在启动容器前,需要为 elasticsearch 数据目录设置正确的权限:

chmod 777 /data/deploy/skywalking/elasticsearch/*

2.2 创建环境变量文件

/data/deploy/skywalking 目录下创建 .env 环境变量文件:

# SkyWalking 组件镜像版本配置
ES_VERSION=registry.cn-hangzhou.aliyuncs.com/docker_image-ljx/elasticsearch:8.14.3
OAP_IMAGE=registry.cn-hangzhou.aliyuncs.com/docker_image-ljx/skywalking-oap-server:10.2.0
UI_IMAGE=registry.cn-hangzhou.aliyuncs.com/docker_image-ljx/skywalking-ui:10.2.0

提示:如果不使用外部配置文件,可以直接在 docker-compose.yml 中替换对应的参数值。

2.3 配置 docker-compose.yml

在相同目录下创建 docker-compose.yml 文件:

version: '3.8'

services:
  elasticsearch:
    image: ${ES_VERSION}
    container_name: skywalking-elasticsearch
    restart: always
    environment:
      discovery.type: "single-node"
      cluster.name: "docker-cluster"
      network.host: 0.0.0.0
      ELASTIC_PASSWORD: "elastic"
      xpack.security.enabled: "true"
      xpack.security.http.ssl.enabled: "false"
      xpack.security.transport.ssl.enabled: "false"
      xpack.security.enrollment.enabled: "true"
      ES_JAVA_OPTS: "-Xms1g -Xmx1g"
      TZ: "Asia/Shanghai"
    ulimits:
      memlock: { soft: -1, hard: -1 }
      nofile:  { soft: 65536, hard: 65536 }
    volumes:
      - /data/deploy/skywalking/elasticsearch/data:/usr/share/elasticsearch/data
      - /data/deploy/skywalking/elasticsearch/logs:/usr/share/elasticsearch/logs
    ports:
      - "9200:9200"
    healthcheck:
      test: ["CMD-SHELL", "curl -s -k -u elastic:elastic http://127.0.0.1:9200 >/dev/null || exit 1"]
      start_period: 30s
      interval: 10s
      timeout: 10s
      retries: 50

  skywalking-oap:
    image: ${OAP_IMAGE}
    container_name: skywalking-oap
    restart: unless-stopped
    depends_on:
      elasticsearch:
        condition: service_healthy
    environment:
      SW_STORAGE: elasticsearch
      SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
      SW_STORAGE_ES_HTTP_PROTOCOL: http
      SW_ES_USER: elastic
      SW_ES_PASSWORD: "elastic"
      JAVA_OPTS: "-Xms2g -Xmx2g"
      TZ: "Asia/Shanghai"
      SW_STORAGE_ES_INDEX_SHARDS_NUMBER: "1"
      SW_STORAGE_ES_INDEX_REPLICAS_NUMBER: "0"
      SW_STORAGE_ES_SUPER_DATASET_INDEX_SHARDS_FACTOR: "3"
      SW_STORAGE_ES_SUPER_DATASET_INDEX_REPLICAS_NUMBER: "0"
      SW_TRACEQL: default
      SW_TRACEQL_ENABLE_DATASOURCE_SKYWALKING: "true"
      SW_ENABLE_UPDATE_UI_TEMPLATE: "true"
      SW_RECEIVER_LOG_ENABLED: "true"
      SW_RECEIVER_LOG_HOST: 0.0.0.0
      SW_RECEIVER_LOG_PORT: 11800
    volumes:
      - /data/deploy/skywalking/oap-logs:/skywalking/logs
    ports:
      - "11800:11800"
      - "12800:12800"
      - "3200:3200"
    healthcheck:
      test: ["CMD-SHELL", "curl -s http://127.0.0.1:12800/graphql -X POST -H 'Content-Type: application/json' -d '{\"query\":\"{ version }\"}' | grep -q data || exit 1"]
      interval: 15s
      timeout: 5s
      retries: 20

  skywalking-ui:
    image: ${UI_IMAGE}
    container_name: skywalking-ui
    restart: unless-stopped
    depends_on:
      - skywalking-oap
    environment:
      SW_OAP_ADDRESS: "http://skywalking-oap:12800"
      TZ: "Asia/Shanghai"
    volumes:
      - /data/deploy/skywalking/ui-logs:/skywalking/logs
    ports:
      - "12138:8080"

2.4 启动 SkyWalking 容器

完成上述配置后,执行以下命令启动所有容器:

# 进入部署目录
cd /data/deploy/skywalking

# 启动容器(后台运行)
docker-compose up -d

# 查看容器启动状态
docker-compose ps

启动过程可能需要一些时间,请等待镜像拉取和容器初始化完成。

三、查看容器启动状态

执行以下命令检查 SkyWalking 相关容器是否正常启动:

docker ps | grep sky

重要提示:

  • skywalking-oap 启动依赖 elasticsearch,请务必等待 ES 初始化完成后再检查容器状态
  • 当 elasticsearch 和 oap 容器状态均为 healthy 时,说明启动成功

四、访问 SkyWalking Web UI

SkyWalking 启动成功后,可以通过浏览器访问 Web UI:

  • 访问地址:http://服务器IP:12138
  • 默认端口:12138(可在 docker-compose.yml 中修改)

五、Java 应用接入配置

5.1 添加 Maven 依赖

在项目的 pom.xml 中添加 SkyWalking 日志工具包依赖:

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <!-- 版本需与 agent 版本保持一致 -->
    <version>9.6.0</version>
</dependency>

5.2 配置 Logback

修改 logback-spring.xml 配置文件:

关键修改点:

  1. 在日志格式中添加 %X{tid}(SkyWalking 链路追踪编号)
  2. 配置 GRPC_LOG appender
  3. <root level="INFO"> 中添加 <appender-ref ref="GRPC_LOG"/>

完整配置示例:

<configuration>
    <!-- 引用 Spring Boot 的 logback 基础配置 -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    
    <!-- 应用名称变量 -->
    <springProperty scope="context" name="APP_NAME" source="spring.application.name"/>
    
    <!-- 日志文件路径变量 -->
    <springProperty scope="context" name="LOG_FILE_PATH" source="logging.file.path" defaultValue="/logs/${APP_NAME}"/>
    
    <!-- 日志格式定义 -->
    <property name="PATTERN_CONSOLE" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr([%thread]){faint} %clr(%-40.40logger{39}){cyan} [%X{tid}] : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
    <property name="PATTERN_FILE" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%thread] [%X{tid}] %logger{50} : %m%n%wEx"/>

    <!-- SkyWalking GRPC 日志 Appender -->
    <appender name="GRPC_LOG" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender" charset="UTF-8">
        <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
            <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.mdc.TraceIdMDCPatternLogbackLayout">
                <Pattern>${PATTERN_FILE}</Pattern>
            </layout>
        </encoder>
    </appender>

    <!-- 本地环境配置 -->
    <springProfile name="local">
        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ASYNC_FILE_INFO"/>
            <appender-ref ref="ASYNC_FILE_ERROR"/>
        </root>
    </springProfile>

    <!-- 其他环境配置(dev/test/sit/uat/prod) -->
    <springProfile name="dev,test,sit,uat,prod,default">
        <root level="INFO">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="ASYNC_FILE_INFO"/>
            <appender-ref ref="ASYNC_FILE_ERROR"/>
            <appender-ref ref="GRPC_LOG"/>
        </root>
    </springProfile>
</configuration>

六、构建应用服务 Docker 镜像

6.1 Dockerfile 示例

# 使用官方 SkyWalking Java Agent 镜像作为基础
FROM apache/skywalking-java-agent:9.6.0-java21
MAINTAINER god_cv

# 设置时区
ENV TZ="Asia/Shanghai"

# SkyWalking 配置环境变量
ENV SKYWALKING_OAP_HOST='oap服务地址'
ENV SKYWALKING_OAP_PORT='11800'
ENV SKYWALKING_COLLECTOR="${SKYWALKING_OAP_HOST}:${SKYWALKING_OAP_PORT}"
ENV SKYWALKING_AGENT_SERVICE_NAME="应用服务名称"

# Java 启动参数(包含 SkyWalking Agent)
ENV SKYWALKING_OPTS="-javaagent:/skywalking/agent/skywalking-agent.jar \
    -Dskywalking.agent.service_name=${SKYWALKING_AGENT_SERVICE_NAME} \
    -Dskywalking.collector.backend_service=${env.SKYWALKING_COLLECTOR} \
    -DSW_GRPC_LOG_SERVER_HOST=${SKYWALKING_OAP_HOST} \
    -DSW_GRPC_LOG_SERVER_PORT=${SKYWALKING_OAP_PORT} \
    -DSW_GRPC_LOG_MAX_MESSAGE_SIZE=10485760 \
    -DSW_GRPC_LOG_GRPC_UPSTREAM_TIMEOUT=30"

# 添加应用 JAR 包
ADD 应用服务.jar /app.jar

# 暴露端口
EXPOSE 8080
EXPOSE 8088

# 启动命令
ENTRYPOINT ["java", "${SKYWALKING_OPTS}", "-jar", "/app.jar"]

6.2 关键参数说明

# skywalking-agent.jar 在容器内的路径
# 注意:不同版本的镜像路径可能不同,需自行确认
-javaagent:/skywalking-agent/skywalking-agent.jar

# 应用服务在 SkyWalking 中的显示名称
-Dskywalking.agent.service_name=应用服务名

# SkyWalking OAP 服务地址
-Dskywalking.collector.backend_service=skywalking-oap:11800

七、启动应用容器

# 如果应用容器与 OAP 在同一服务器,使用同一网络
docker run --privileged -d -p 9000:8080 --name 容器名 --network skywalking_default 镜像名

# 如果应用容器与 OAP 不在同一服务器,不需要指定网络
# docker run --privileged -d -p 9000:8080 --name 容器名 镜像名

八、常见问题及解决方法

以下问题多出现在手动下载 jar 包部署时,通过官方 agent 镜像部署流程已尽量避免或处理。

8.1 skywalking-agent.jar 不存在

问题:Docker 构建时找不到 skywalking-agent.jar

解决方案

# 方法1:复制整个 agent 目录到容器
COPY skywalking-agent /skywalking-agent

# 方法2:解压压缩包
COPY apache-skywalking-java-agent-9.6.0.tgz /apache-skywalking-java-agent-9.6.0.tgz
RUN tar -zxvf /apache-skywalking-java-agent-9.6.0.tgz \
    && rm -rf /skywalking-agent/plugins/spring-webflux-6.x-webclient-plugin-9.6.0.jar

8.2 skywalking-oap 启动异常

问题:docker ps 显示状态为 start healthy

排查步骤

# 查看 OAP 容器日志
docker logs -f skywalking-oap

# 如果为 ES 鉴权失败,检查 docker-compose.yml 中 ES 密码配置

# 重启 OAP 容器
docker-compose up -d skywalking-oap

8.3 应用容器启动失败

排查步骤

# 查看容器日志
docker logs -f 容器名

# 容器停止时,启动临时容器排查
docker run -it --entrypoint /bin/bash 容器名

8.3.1 skywalking-oap 域名解析错误

问题:应用容器无法解析 skywalking-oap 主机名

解决方案

# 检查容器网络
docker inspect 容器名 --format '{{json .NetworkSettings.Networks}}'

# 添加网络连接
docker network connect skywalking_default 容器名

# 如果仍不行,修改 Dockerfile 使用 IP 地址
-Dskywalking.collector.backend_service=skywalking-oap的服务IP:11800

8.3.2 webclient 请求被阻断

问题:多个 webflux 插件冲突

解决方案

# 删除冲突的插件
RUN rm -rf /skywalking-agent/plugins/spring-webflux-6.x-webclient-plugin-9.6.0.jar

8.4 java.lang.IllegalStateException: environment is not locked

原因:Elasticsearch 容器以 1000 用户运行,宿主机挂载目录归属 root 导致无权限创建 node.lock

解决

sudo chown -R 1000:1000 /data/deploy/skywalking/elasticsearch

8.5 [0.000s][error][logging] Error opening log file ‘logs/gc.log’: Permission denied

解决

chmod 777 /data/deploy/skywalking/elasticsearch/data/ /data/deploy/skywalking/elasticsearch/logs/

8.6 elasticsearch 修改配置后不生效

解决

# 停止相关容器
docker-compose down

# 删除旧数据
rm -rf /data/deploy/skywalking/elasticsearch/data/*
rm -rf /data/deploy/skywalking/elasticsearch/logs/*

# 重新启动
docker-compose up -d

8.7 ./elasticsearch-create-enrollment-token -s kibana 报错

报错:Failed to determine the health of the cluster. Cluster health is currently RED.

解决

./elasticsearch-create-enrollment-token -s kibana -f

更多推荐