前面我给你们分享了关于分布式链路追踪的基本原理和SkyWalking的k8s部署玩法,若是还没来得及看的朋友能够看我上篇文章。java
今天要给你们分享是咱们平常工做中最多见的一种场景,那就是部署在k8s环境下的Java微服务,要接入SkyWalking的具体玩法,经过这个过程我们能够更深刻的理解SkyWalking进行数据采集的逻辑,也能更深入地从运维角度理解平常工做中所写的Java微服务被无侵入的方式接入分布式链路追踪系统的过程!node
废话很少说,接下来就让咱们开启干货模式吧!程序员
在上篇文章关于SkyWalking基本原理的内容中有讲过,SkyWalking的数据采集主要是经过业务探针(Agent)来实现的,针对不一样的编程语言SkyWalking提供了对应的Agent实现。Java微服务接入SkyWalking可使用“SkyWalking Java Agent”来上报监控数据。 spring
这就须要Java微服务在部署启动的过程当中须要获取"SkyWalking Java Agent"探针包,并在启动参数中经过“--javaagent:xxx”进行参数指定。而具体的集成方式大体有如下三种:docker
其中前两种方式主要是经过在构建Docker镜像的过程当中将Agent依赖打包集成到Java服务的Docker镜像中,而sidecar模式则是利用k8s的相关特性来实如今容器启动时挂载Agent相关依赖。 apache
若是微服务是直接部署在Kubernetes集群,那么采用sidecar模式来使用SkyWalking Agent会更加方便,由于这种方式不须要修改原来的基础镜像,也不须要从新构建新的服务镜像,而是会以sidecar模式,经过共享的volume将agent所需的相关文件直接挂载到已经存在的服务镜像中。编程
在开始以sidecar方式,将一个用Spring Cloud框架编写的Java微服务接入SkyWalking以前,咱们须要构建SkyWalking Java Agent的公共镜像,具体步骤以下: 后端
1)、下载SkyWalking官方发行包,并解压到指定目录api
#下载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私有镜像仓库 app
在前面步骤中解压的skywalking发行包的同级目录编写Dockerfile文件,具体内容以下:
FROM busybox:latest ENV LANG=C.UTF-8 RUN set -eux && mkdir -p /usr/skywalking/agent add apache-skywalking-apm-bin-es7/agent /usr/skywalking/agent WORKDIR
在上述Dockefile文件中使用是的bosybox镜像,而不是SkyWalking的发行镜像,这样能够确保构建出来的sidecar镜像保持最小。
完成Docker文件编写后,执行镜像构建命令:
#执行镜像构建命令 $ docker build . -t springcloud-action/skywalking-agent-sidecar:8.3.0 Sending build context to Docker daemon 556.5MB Step 1/5 : FROM busybox:latest latest: Pulling from library/busybox d60bca25ef07: Pull complete Digest: sha256:49dae530fd5fee674a6b0d3da89a380fc93746095e7eca0f1b70188a95fd5d71 Status: Downloaded newer image for busybox:latest ---> a77dce18d0ec Step 2/5 : ENV LANG=C.UTF-8 ---> Running in e95b4c25ebf3 Removing intermediate container e95b4c25ebf3 ---> 83f22bccb6f3 Step 3/5 : RUN set -eux && mkdir -p /usr/skywalking/agent ---> Running in 49c2eac2b6ab + mkdir -p /usr/skywalking/agent Removing intermediate container 49c2eac2b6ab ---> 89cf3ce8238e Step 4/5 : add apache-skywalking-apm-bin/agent /usr/skywalking/agent ---> 91fe5f06948f Step 5/5 : WORKDIR / ---> Running in 6a64553f1870 Removing intermediate container 6a64553f1870 ---> 7e73ddba48bb Successfully built 7e73ddba48bb Successfully tagged springcloud-action/skywalking-agent-sidecar:8.3.0
为了验证构建的镜像是否成功,能够经过命令查看本地构建的镜像,命令以下:
#查看本地镜像信息 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE springcloud-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:8080 Username: admin Password: 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 images REPOSITORY TAG IMAGE ID CREATED SIZE springcloud-action/skywalking-agent-sidecar 8.3.0 e21040c57e42 2 weeks ago 32.2MB 10.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-sidecar The 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仓库进行查看,以下图所示:
上面咱们经过手工构建的方式构建了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.9 ENTRYPOINT ["/usr/bin/java", "-jar", "/app.jar"] ARG JAR_FILE ADD ${JAR_FILE} /app.jar EXPOSE 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 images REPOSITORY TAG IMAGE ID CREATED SIZE 10.211.55.2:8080/springcloud-action/chapter10-monitor-demo latest 3ae132cdfeb7 12 seconds ago 121MB 10.211.55.2:8080/springcloud-action/skywalking-agent-sidecar latest e21040c57e42 2 weeks ago 32.2MB springcloud-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/v1 kind: Deployment metadata: name: chapter10-monitor-demo spec: 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: v1 kind: Service metadata: name: chapter10-monitor-demo labels: svc: chapter10-monitor-demo spec: 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.yml deployment.apps/chapter10-monitor-demo created service/chapter10-monitor-demo created
以后查看相关Pod是否运行成功:
$ kubectl get pods NAME READY STATUS RESTARTS AGE chapter10-monitor-demo-5767d54f5-vfqqf 1/1 Running 0 96m
运行成功了!此时能够访问下服务的测试接口,多刷几回,以后经过SkyWalking UI查看是否有监控数据,以下图所示:
如上图所示,在访问微服务测试接口后能够看到SpringCloud微服务已经经过Agent像SkyWalking上报了APM监控数据!
本文实验步骤比较多,也许你很难一次性看完,可是真正的技术都是要练的,因此有空的时候搭建环境后玩一玩是理解文章内容的关键!
欢迎你们关注个人公众号【风平浪静如码】,海量Java相关文章,学习资料都会在里面更新,整理的资料也会放在里面。
以为写的还不错的就点个赞,加个关注呗!点关注,不迷路,持续更新!!!