前面我給你們分享了關於分佈式鏈路追蹤的基本原理和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相關文章,學習資料都會在裏面更新,整理的資料也會放在裏面。
以爲寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!