后面我给大家分享了对于分布式链路追踪的基本原理和SkyWalking的k8s部署玩法,如果还没来得及看的敌人能够看我上篇文章。

明天要给大家分享是咱们日常工作中最常见的一种场景,那就是部署在k8s环境下的Java微服务,要接入SkyWalking的具体玩法,通过这个过程咱们能够更深刻的了解SkyWalking进行数据采集的逻辑,也能更粗浅地从运维角度了解日常工作中所写的Java微服务被无侵入的形式接入分布式链路追踪零碎的过程!

废话不多说,接下来就让咱们开启干货模式吧!

Java微服务接入SkyWalking的形式

在上篇文章对于SkyWalking基本原理的内容中有讲过,SkyWalking的数据采集次要是通过业务探针(Agent)来实现的,针对不同的编程语言SkyWalking提供了对应的Agent实现。Java微服务接入SkyWalking能够应用“SkyWalking Java Agent”来上报监控数据。

这就须要Java微服务在部署启动的过程中须要获取"SkyWalking Java Agent"探针包,并在启动参数中通过“--javaagent:xxx”进行参数指定。而具体的集成形式大抵有以下三种:

  • 应用官网提供的根底镜像;
  • 将agent包构建到已存在的根底镜像中;
  • 通过sidecar 模式挂载agent;

其中前两种形式次要是通过在构建Docker镜像的过程中将Agent依赖打包集成到Java服务的Docker镜像中,而sidecar模式则是利用k8s的相干个性来实现在容器启动时挂载Agent相干依赖。

如果微服务是间接部署在Kubernetes集群,那么采纳sidecar模式来应用SkyWalking Agent会更加不便,因为这种形式不须要批改原来的根底镜像,也不须要从新构建新的服务镜像,而是会以sidecar模式,通过共享的volume将agent所需的相干文件间接挂载到曾经存在的服务镜像中。

构建SkyWalking Agent镜像

在开始以sidecar形式,将一个用Spring Cloud框架编写的Java微服务接入SkyWalking之前,咱们须要构建SkyWalking Java Agent的公共镜像,具体步骤如下:

1)、下载SkyWalking官网发行包,并解压到指定目录

#下载skywalking-8.3.0 for es7版本的公布包,与部署的skywalking后端版本统一$ wget https://mirror.bit.edu.cn/apache/skywalking/8.3.0/apache-skywalking-apm-es7-8.3.0.tar.gz#将下载的公布包解压到当前目录$ tar -zxvf apache-skywalking-apm-es7-8.3.0.tar.gz

2)、构建skywalking-agentsidecar镜像并push至hub公有镜像仓库

在后面步骤中解压的skywalking发行包的同级目录编写Dockerfile文件,具体内容如下:

FROM busybox:latestENV LANG=C.UTF-8RUN set -eux && mkdir -p /usr/skywalking/agentadd apache-skywalking-apm-bin-es7/agent /usr/skywalking/agentWORKDIR

在上述Dockefile文件中应用是的bosybox镜像,而不是SkyWalking的发行镜像,这样能够确保构建进去的sidecar镜像放弃最小。

实现Docker文件编写后,执行镜像构建命令:

#执行镜像构建命令$ docker build .  -t springcloud-action/skywalking-agent-sidecar:8.3.0Sending build context to Docker daemon  556.5MBStep 1/5 : FROM busybox:latestlatest: Pulling from library/busyboxd60bca25ef07: Pull complete Digest: sha256:49dae530fd5fee674a6b0d3da89a380fc93746095e7eca0f1b70188a95fd5d71Status: Downloaded newer image for busybox:latest ---> a77dce18d0ecStep 2/5 : ENV LANG=C.UTF-8 ---> Running in e95b4c25ebf3Removing intermediate container e95b4c25ebf3 ---> 83f22bccb6f3Step 3/5 : RUN set -eux && mkdir -p /usr/skywalking/agent ---> Running in 49c2eac2b6ab+ mkdir -p /usr/skywalking/agentRemoving intermediate container 49c2eac2b6ab ---> 89cf3ce8238eStep 4/5 : add apache-skywalking-apm-bin/agent /usr/skywalking/agent ---> 91fe5f06948fStep 5/5 : WORKDIR / ---> Running in 6a64553f1870Removing intermediate container 6a64553f1870 ---> 7e73ddba48bbSuccessfully built 7e73ddba48bbSuccessfully tagged springcloud-action/skywalking-agent-sidecar:8.3.0

为了验证构建的镜像是否胜利,能够通过命令查看本地构建的镜像,命令如下:

#查看本地镜像信息$ docker imagesREPOSITORY                                                   TAG                   IMAGE ID            CREATED             SIZEspringcloud-action/skywalking-agent-sidecar                           8.3.0                 7e73ddba48bb        2 minutes ago       32.2MB...

3)、将打包的镜像推送到harbor镜像仓库

为了便于后续微服务间接应用曾经构建好的SkyWalking Agent SideCar镜像,咱们能够将其push至公有Harbor镜像仓库中。具体命令如下:

#登录镜像仓库,输出用户名明码(admin/Harbor12345)$ docker login http://10.211.55.2:8080Username: adminPassword: Login Succeeded

这里的Harbor公有镜像仓库个别公司都会本人搭建,接下来咱们对构建的镜像打tag并上传,具体如下:

#这里将原先构建的镜像装置{镜像仓库地址}/项目名称/镜像名称的形式打tag$ docker tag springcloud-action/skywalking-agent-sidecar:8.3.0 10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar

之后能够具体查看曾经打过tag镜像信息,命令如下:

$ docker imagesREPOSITORY                                                       TAG                   IMAGE ID            CREATED             SIZEspringcloud-action/skywalking-agent-sidecar                      8.3.0                 e21040c57e42        2 weeks ago         32.2MB10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar     latest                e21040c57e42        2 weeks ago         32.2MB...

接下来咱们将打过tag的镜像推送至公有Harbor仓库,具体操作如下:

#将镜像推送到Harbor公有镜像仓库$ docker push 10.211.55.2:8080/springcloud-action/skywalking-agent-sidecarThe push refers to repository [10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar]e80d641c3ed9: Layer already exists 11fe582bd430: Layer already exists 1dad141bdb55: Layer already exists latest: digest: sha256:b495c18c3ae35f563ad4db91c3db66f245e6038be0ced635d16d0e3d3f3bcb80 size: 946

实现后能够进入harbor仓库进行查看,如下图所示:

SideCar模式接入SkyWalking服务

下面咱们通过手工构建的形式构建了SkyWalking Java Agent的公共Docker镜像,并将其Push到了咱们的公有Harbor镜像仓库,接下来咱们将演示如何通过编写Kubernetes服务公布文件,来将Java服务公布到K8s集群的过程中主动以SideCar的模式集成Agent、并接入SkyWalking服务。

这个过程才是作为一个Java程序员最关怀的步骤。在开始上面步骤前,你应该通过IDEA构建一个Spring Boot微服务工程,具体构建的过程就不拆穿了,但重点是你这个Spring Boot工程应该反对构建Docker镜像,以Maven为例,须要在pom.xml文件中增加打包插件,具体如下:

<!--增加将Java利用打包为Docker Image的Maven插件--><plugin>    <groupId>com.spotify</groupId>    <artifactId>dockerfile-maven-plugin</artifactId>    <version>1.4.13</version>    <executions>        <execution>            <id>build-image</id>            <phase>package</phase>            <goals>                <goal>build</goal>            </goals>        </execution>    </executions>    <configuration>        <!--指定Dockerfile文件地位-->        <dockerfile>docker/Dockerfile</dockerfile>        <repository>${docker.repository}/springcloud-action/${app.name}</repository>        <!--<tag>${project.version}</tag>-->        <buildArgs>            <!--提供参数向Dockerfile传递-->            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>        </buildArgs>    </configuration></plugin>

其中<configuration>标签中指定的Dockerfile文件内容如下:

FROM openjdk:8u191-jre-alpine3.9ENTRYPOINT ["/usr/bin/java", "-jar", "/app.jar"]ARG JAR_FILEADD ${JAR_FILE} /app.jarEXPOSE 8080

这就是一个简略的镜像构建文件,如果不采纳sidecar形式,那么就须要在服务镜像构建文件中增加SkyWalking Agent的相干集成,但这里咱们是sidecar形式,所以服务镜像构建文件就不必那么简单了!

此外<configuration>标签中对于镜像仓库地址、利用名称的动静参数在pom.xml文件中的定义如下(把玩时以本人理论环境为准):

<properties>    <!--定义Docker镜像仓库地址-->    <docker.repository>10.211.55.2:8080</docker.repository>    <!--定义项目名称作为镜像名称生成的组成部分-->    <app.name>chapter10-monitor-demo</app.name></properties>

接下来具体讲述接入步骤:

1)、将Java微服务工程打包成Docker镜像并Push到Harbor镜像仓库

# Maven我的项目构建,会主动依据pom.xml中的相干插件配置进行docker镜像构建$ mvn clean install -X

查看本地新构建的镜像信息,具体如下:

$ docker imagesREPOSITORY                                                       TAG                   IMAGE ID            CREATED             SIZE10.211.55.2:8080/springcloud-action/chapter10-monitor-demo       latest                3ae132cdfeb7        12 seconds ago      121MB10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar     latest                e21040c57e42        2 weeks ago         32.2MBspringcloud-action/skywalking-agent-sidecar                      8.3.0                 e21040c57e42        2 weeks ago         32.2MB...

将微服务镜像push到Harbor镜像仓库:

$ docker push 10.211.55.2:8080/springcloud-action/chapter10-monitor-demo The push refers to repository [10.211.55.2:8080/springcloud-action/chapter10-monitor-demo]5f3427edfc10: Pushed 925523484e00: Layer already exists 344fb4b275b7: Layer already exists bcf2f368fe23: Layer already exists latest: digest: sha256:b424180c56b28a9a7704a1f6476f4247fad12cc27721c21fce32149a8f344dee size: 1159

3)、微服务Kubernetes公布文件集成SkyWalking Agent实现埋点

到这里你并没有发现为了将Java服务接入SkyWalking,你须要在Java微服务自身做任何动作,而接下来在k8s部署文件中的将演示,为什么要将这种形式称之为SideCar。

其次要原理是通过Kubernetes的初始化容器initContainers来实现的,initContainers是一种专用容器,能够在利用容器启动之前运行,能够用于实现利用启动前的必要初始化工作。具体的Kubernetes部署文件(deploy-skywalking.yml)内容如下:

apiVersion: apps/v1kind: Deploymentmetadata:  name: chapter10-monitor-demospec:  selector:    matchLabels:      app: chapter10-monitor-demo  replicas: 1  #设置滚动降级策略  #Kubernetes在期待设置的工夫后才开始进行降级,例如5秒  minReadySeconds: 5  strategy:    type: RollingUpdate    rollingUpdate:      #降级过程中最多能够比原先设置多出的Pod数量      maxSurge: 1      #降级过程中Deployment控制器最多能够删除多少个旧Pod,次要用于提供缓冲工夫      maxUnavailable: 1  template:    metadata:      labels:        app: chapter10-monitor-demo    spec:      #构建初始化镜像(通过初始化镜像的形式集成SkyWalking Agent)      initContainers:        - image: 10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar:latest          name: sw-agent-sidecar          imagePullPolicy: IfNotPresent          command: ["sh"]          args:            [              "-c",              "mkdir -p /skywalking/agent && cp -r /usr/skywalking/agent/* /skywalking/agent",            ]          volumeMounts:            - mountPath: /skywalking/agent              name: sw-agent      containers:        - name: chapter10-devops-demo          image: 10.211.55.2:8080/springcloud-action/chapter10-monitor-demo:latest          env:            #这里通过JAVA_TOOL_OPTIONS,而不是JAVA_OPTS能够实现不通过将agent命令退出到java利用jvm参数而实现agent的集成            - name: JAVA_TOOL_OPTIONS              value: -javaagent:/usr/skywalking/agent/skywalking-agent.jar            - name: SW_AGENT_NAME              value: chapter10-devops-demo            - name: SW_AGENT_COLLECTOR_BACKEND_SERVICES              # FQDN: servicename.namespacename.svc.cluster.local              value: oap.skywalking:11800            - name: SERVER_PORT              value: "8080"            - name: SPRING_PROFILES_ACTIVE              value: test          volumeMounts:            - mountPath: /usr/skywalking/agent              name: sw-agent      volumes:        - name: sw-agent          emptyDir: {}---apiVersion: v1kind: Servicemetadata:  name: chapter10-monitor-demo  labels:    svc: chapter10-monitor-demospec:  selector:    app: chapter10-monitor-demo  ports:    - name: http      port: 8080      nodePort: 30001  type: NodePort

以上是挂载sidecar的k8s公布文件,以微服务“chapter10-devops-demo”为例,次要是通过共享volume的形式挂载agent。其中initContainers通过skywalking-agent卷挂载了skywalking-agent-sidecar镜像中的/skywalking/agent,并将下面构建好的镜像中的agent目录cp到了/skywalking/agent目录,实现之后微服务容器启动时也挂载了skywalking-agent卷,并将其挂载到容器的/usr/skywalking/agent目录,这样就实现了共享过程。

这里有一个有意思的点,Java服务通过Agent接入SkyWalking个别状况下还须要在启动命令中退出JVM参数,例如:“-javaagent:/usr/skywalking/agent/skywalking-agent.jar”。这就须要咱们在定义Java程序镜像打包的Dockerfile文件中通过“ENTRYPOINT”退出相干参数,例如:

ENTRYPOINT [ "sh", "-c", "java ${JAVA_OPTS} -javaagent:/app/agent/skywalking-agent.jar -Dskywalking.collector.backend_service=${SW_AGENT_COLLECTOR_BACKEND_SERVICES} -Dskywalking.agent.service_name=${SW_AGENT_NAME} -Dskywalking.agent.instance_name=${HOSTNAME} -Djava.security.egd=file:/dev/./urandom -jar /app/app.jar $PROFILE"

但这种形式须要在Dockerfile文件中额定设置SkyWalking Agent相干的JVM参数,所以你可能没留神到,在上述k8s部署文件中我所应用的是“JAVA_TOOL_OPTIONS”这个参数,而不是最常见的“JAVA_OPTS”。这个点很多人都不晓得,如果你急躁看到这里,祝贺你Get了一个新技能!至于二者的区别,感兴趣的敌人能够搜寻下!

4)、部署启动微服务,并验证其是否曾经失常接入SkyWalking监控

接下来咱们进入部署文件所在目录,执行发布命令如下:

$ kubectl apply -f deploy-skywalking.ymldeployment.apps/chapter10-monitor-demo createdservice/chapter10-monitor-demo created

之后查看相干Pod是否运行胜利:

$ kubectl get podsNAME                                     READY   STATUS    RESTARTS   AGEchapter10-monitor-demo-5767d54f5-vfqqf   1/1     Running   0          96m

运行胜利了!此时能够拜访下服务的测试接口,多刷几次,之后通过SkyWalking UI查看是否有监控数据,如下图所示:

如上图所示,在拜访微服务测试接口后能够看到SpringCloud微服务曾经通过Agent像SkyWalking上报了APM监控数据!

后记

本文试验步骤比拟多,兴许你很难一次性看完,然而真正的技术都是要练的,所以有空的时候搭建环境后玩一玩是了解文章内容的要害!

写在最初

欢送大家关注我的公众号【惊涛骇浪如码】,海量Java相干文章,学习材料都会在外面更新,整顿的材料也会放在外面。

感觉写的还不错的就点个赞,加个关注呗!点关注,不迷路,继续更新!!!