linux 环境 & 应用服务 docker 化 & skywalking Agent 接入 (全网唯一教程)

docker化应用接入skywalking Agent

本文柯苏远写于2024年3月21日15点50分

1. SkyWalking 架构简介

2. 背景

服务容器化的过程中想要引入sw来监控整个系统的信息。

目前运维同学已经在开发环境上搭建好了oap以及存储层和sw-ui层。

我们需要将探针层和应用层接入整个sw架构。

3. 问题 & 解决思路

3.1 问题描述

在我们应用中接入探针层主要是在jar的启动命令上指定agent的jar包以及oap地址,格式如下:

bash 复制代码
# skywalking agent jar包路径
-javaagent:/sw/skywalking-agent/skywalking-agent.jar

# 服务名称
-Dskywalking.agent.service_name=provider

# sw-oap地址
-Dskywalking.collector.backend_service=127.0.0.1:11800

这里涉及两个变动点:

  • -javaagent 指定的agent包路径。
  • -Dskywalking.collector.backend_service 指定sw-oap服务地址。

由于现在服务容器化,这两个点都需要在dockerfile文件中体现,可是dockerfile文件又不支持这两个属性动态变化(我调研的结果是dockerfile里不支持写一些if之类逻辑的)。

由于整个部署是cicd的,所以dev、test、uat以及prod都是用这一个dockerfile,那么如何实现各个环境基于同一个dockerfile来满足上面说的两个变动点呢?

3.2 解决思路

  • 将动的变成不动的。-javaagent
  • 将一定要动的抽取出来。-Dskywalking.collector.backend_service

3.3 具体方案

探针的配置优先级:

  1. 启动命令上的。
  2. config/agent.config 配置文件里的配置

根据这个优先级我们可以将-Dskywalking.collector.backend_service 从dockerfile文件里抽取出来放在 agent.config 里。

下面是对于 -javaagent 动变不动的具体方案:

3.3.1 复制一份agent文件到docker容器内

关键点:直接将探针copy一份到服务对应的容器里,然后在dockerfile里 -javaagent 指向容器里的探针地址。

缺点:

  • 每个服务对应的容器里都有一份探针,冗余了很多份。
  • 从宿主机往容器里拷贝agent的时候有一个docker构建上下文环境,被拷贝的文件只能在dockerfile所处的当前目录以及当前目录的子目录。不在这个范围的会报文件找不到,所以对于复制的路径不够灵活。

3.3.2 将一份agent文件分别挂载到多个docker容器内

关键点:将探针文件挂载在每个docker容器里,同一个服务器上的docker容器用同一份探针文件。

优点:

  • 容器内没有冗余探针文件,共用一份,节省物理资源。
  • 在挂载的时候不需要将探针放在当前dockerfile目录或者是子目录下,可以放置在服务器任意地址进行挂载操作,更加灵活。

4. 可行性实践

有两个服务:consumerprovider,都注册在 nacos 上。 consumer 对外暴露了一个接口:/echo/{str}

整个调用链就是:consumerprovidermysql

4.1 复制到容器里的方式

  • 首先将我们的两个jar包以及本地编写的两个dockerfile文件,以及我们要用到的sw-agent上传的dev服务器上,在服务器上的目录如下所示:
  • 具体的 consumer-dockerfile 文件内容如下所示:

    bash 复制代码
    # 使用官方提供的Spring Boot基础镜像  
    FROM openjdk:8-jdk-alpine
    
    # 设置工作目录为/app  
    WORKDIR /app
    
    # 将当前目录内容复制到容器的/app内  
    COPY consumer.jar /app/consumer.jar
    
    # 拷贝宿主机的skywalking-agent/ 文件夹下的内容到容器的/skywalking-agent目录下  
    COPY skywalking-agent/ /skywalking-agent/
    
    # 使用容器内在上一步复制进来的agent地址
    ENV JAVA_OPTS="-javaagent:/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=consumer"
    
    # 暴露容器的 8082 端口  
    EXPOSE 8082
    
    # 设置容器启动时运行jar包  
    ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app/consumer.jar"]
  • 将consumer-dockerfile文件打包成镜像

    bash 复制代码
    docker build -f Consumer-Dockerfile -t consumer:1.0 .
  • 运行镜像生成对应容器

    bash 复制代码
    docker run -t -d -i -p 8082:8082 --name=consumer consumer:1.0
  • Provider是相同的操作

    • dockerfile

      bash 复制代码
      FROM openjdk:8-jdk-alpine
      
      # 设置工作目录为/app  
      WORKDIR /app
      
      # 将当前目录内容复制到容器的/app内  
      COPY provider.jar /app/provider.jar
      
      # 拷贝宿主机的skywalking-agent/ 文件夹下的内容到容器的/skywalking-agent目录下  
      COPY skywalking-agent/ /skywalking-agent/
      
      # 使用容器内的agent地址
      ENV JAVA_OPTS="-javaagent:/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=provider"
      
      # 暴露容器的 8081 端口  
      EXPOSE 8081
      
      # 设置容器启动时运行jar包  
      ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app/provider.jar"]
    • 构建镜像 & 运行容器

      bash 复制代码
       docker build -f Provider-Dockerfile -t provider:1.0 .
       
       docker build -f Consumer-Dockerfile -t consumer:1.0 .
  • 测试

    • 暴露出来的接口是:http://192.24.100.118:8082/echo/{str} , {str} 是路径参数,循环调用100次,去sw-ui界面看看是否有对应的跟踪链路。

复制方案的测试结论是可行的。

4.2 挂载到容器里的方式

去调研了下dockerfile的语法,发现在dockerfile里是不可以直接进行挂载的,只能指定卷,挂载操作要在镜像起容器的时候才可以。

  • 首先服务还是上面两个jar包,只不过这次不是copy探针了,而是挂载,所以我们要对应修改dockerfile文件,分别注释掉copy指令,更改容器暴露端口,以及启动时候在命令行指定端口。

    复制了一份到另外一个目录,然后进行了修改dockerfile,目录详情。

  • Consumer-dockerfile & Provider-dockerfile

    bash 复制代码
    # 使用官方提供的Spring Boot基础镜像  
    FROM openjdk:8-jdk-alpine
    
    # 设置工作目录为/app  
    WORKDIR /app
    
    # 将当前目录内容复制到容器的/app内  
    COPY consumer.jar /app/consumer.jar
    
    # 拷贝宿主机的skywalking-agent/ 文件夹下的内容到容器的/skywalking-agent目录下  
    # COPY skywalking-agent/ /skywalking-agent/
    
    # 使用容器内挂载agent的地址
    ENV JAVA_OPTS="-javaagent:/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=consumer"
    
    # 暴露容器的 8083 端口  
    EXPOSE 8083
    
    # 设置容器启动时运行jar包  
    ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app/consumer.jar --server.port=8083"]
    bash 复制代码
    FROM openjdk:8-jdk-alpine
    
    # 设置工作目录为/app  
    WORKDIR /app
    
    # 将当前目录内容复制到容器的/app内  
    COPY provider.jar /app/provider.jar
    
    # 拷贝宿主机的skywalking-agent/ 文件夹下的内容到容器的/skywalking-agent目录下  
    # COPY skywalking-agent/ /skywalking-agent/
    
    # 使用容器内的agent地址
    ENV JAVA_OPTS="-javaagent:/skywalking-agent/skywalking-agent.jar -Dskywalking.agent.service_name=provider"
    
    # 暴露容器的 8084 端口  
    EXPOSE 8084
    
    # 设置容器启动时运行jar包  
    ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} -jar /app/provider.jar --server.port=8084"]
  • 构建并运行 consumer & provider

    这里的 -v 是挂载 宿主机目录到容器里的参数

    bash 复制代码
    docker build -f Consumer-Dockerfile -t consumer:2.0 .
    docker run -t -d -i -p 8083:8083 -v /sw/mount/skywalking-agent:/skywalking-agent --name=consumer2 consumer:2.0
     
    docker build -f Provider-Dockerfile -t provider:2.0 .
    docker run -t -d -i -p 8084:8084 -v /sw/mount/skywalking-agent:/skywalking-agent --name=provider2 provider:2.0
  • 测试

    • 暴露出来的接口是:http://192.24.100.118:8083/echo/{str} , {str} 是路径参数,循环调用100次,去sw-ui界面看看是否有对应的跟踪链路。

挂载方案的测试结论是可行的。

5. 总结

关于如何将探针和我们的应用接入sw架构,主要是两种方式:

  1. 将探针复制到应用容器内。
  2. 将探针挂载到应用容器内。

推荐使用第二种

相关推荐
森林猿15 分钟前
docker-compose-kafka 4.1.0
docker·容器·kafka
蓑笠翁00130 分钟前
Django REST Framework 全面指南:从模型到完整API接口开发
后端·python·django
鸽鸽程序猿33 分钟前
【项目】基于Spring全家桶的论坛系统 【下】
后端·spring·restful
IT_陈寒43 分钟前
Redis性能优化:5个被低估的配置项让你的QPS提升50%
前端·人工智能·后端
radient1 小时前
初识Agent、Prompt、Function Coding、MCP
后端·程序员·架构
Lisonseekpan1 小时前
Spring Boot 中使用 Caffeine 缓存详解与案例
java·spring boot·后端·spring·缓存
SimonKing1 小时前
分布式日志排查太头疼?TLog 让你一眼看穿请求链路!
java·后端·程序员
Gss7771 小时前
Docker 容器核心知识总结
docker·容器
罗技1231 小时前
Docker 启动 Easysearch 时自定义初始密码的几种方式
运维·docker·容器
小许学java1 小时前
Spring AI快速入门以及项目的创建
java·开发语言·人工智能·后端·spring·ai编程·spring ai