K8S中微服务链路监控系统

一、全链路监控

1.1、全链路监控是什么

随着微服务架构的流行,服务按照不同的维度进行拆分,一次请求往往需要涉及到多个服务。这些服务可能不同编程语言开发,不同团队开发,可能部署很多副本。因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,以便发生故障的时候,能够快速定位和解决问题。全链路监控组件就在这样的问题背景下产生了。

全链路性能监控从整体维度到局部维度展示各项指标,将跨应用的所有调用链性能信息集中展现,可方便度量整体和局部性能,并且方便找到故障产生的源头,生产上可极大缩短故障排除时间。

mark

1.2、全链路监控解决什么问题

  • 请求链路追踪,故障快速定位:可以通过调用链结合业务日志快速定位错误信息。
  • 可视化: 各个阶段耗时,进行性能分析。
  • 依赖优化:各个调用环节的可用性、梳理服务依赖关系以及优化。
  • 数据分析,优化链路:可以得到用户的行为路径,汇总分析应用在很多业务场景。

1.3、全链路监控选择依据

全链路监控系统有很多,应从这几方面选择:

  • 探针的性能消耗

APM组件服务的影响应该做到足够小,数据分析要快,性能占用小。 - 代码的侵入性

即也作为业务组件,应当尽可能少入侵或者无入侵其他业务系统, 对于使用方透明,减少开发人员的负担。

  • 监控维度

分析的维度尽可能多。

  • 可扩展性

一个优秀的调用跟踪系统必须支持分布式部署,具备良好的可扩展 性。能够支持的组件越多当然越好。

主流系统: zipkin、 skywalking、 pinpoint

二、Pinpoint

Pinpoint是一个APM(应用程序性能管理)工具,适用于用Java/PHP编写的大型分布式系统。

2.1、特性:

  • 服务器地图(ServerMap)通过可视化分布式系统的模块和他们之间的相互联系来理解系统拓扑。点击某个节点会展示这个模块的详情,比如它当前的状态和请求数量。

  • 实时活动线程图 (Realtime Active Thread Chart) :实时监控应用内部的活动线程。

  • 请求/响应分布图(Request/Response Scatter Chart ) :长期可视化请求数量和应答模式来定位潜在问题。通过在图表上拉拽可以选择请求查看 更多的详细信息。

  • 调用栈(CallStack ):在分布式环境中为每个调用生成代码级别的可视图,在单个视图中定位瓶颈和失败点。

  • 检查器(Inspector ) :查看应用上的其他详细信息,比如CPU使用率,内存/垃圾回收,TPS,和JVM参数。

2.2、Pinpoint 部署

mark

如上就是pinpoint一个整体架构,也是基于c/s。所有的应用在启动的时候通过JVM参数或者jar的方式启动,服务端的collector采集器通过agent采集各个指标并写入到HBase中,然后进行数据分析和展示。

Docker部署:

git clone https://github.com/naver/pinpoint-docker.git
cd pinpoint-docker
docker-compose pull && docker-compose up -d

docker-compose ps #查看启动的服务
通过安装服务端的IP:8079 访问:

mark

当然启动后官方会给我们启动一个简单的quickapp的一个demon示例;

如果需要将现有的业务接入咱们的pinpoint就需要按照如下方式:

2.3、Pinpoint Agent部署

Tomcat:
# catalina.sh
CATALINA_OPTS="$CATALINA_OPTS -javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar"
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.agentId=$AGENT_ID"
CATALINA_OPTS="$CATALINA_OPTS -Dpinpoint.applicationName=$APPLICATION_NAME"

Jar:
java -jar -javaagent:$AGENT_PATH/pinpoint-bootstrap-$VERSION.jar -Dpinpoint.agentId=$AGENT_ID -Dpinpoint.applicationName=$APPLICATION_NAME xxx.jar

如上agent 在我们安装好pinpoint后会提供一个下载连接:

mark

下载完成后,2种目前我们在用的方式接入: - ①将下载好的jar文件打入应用的基础镜像; - ②将下载好的jar包推到仓库,配置下载链接并解压缩,然后开发配置启动即可;

第二种方式:
ARG envType
ADD http://XXX.XXXX.com/download/apmagent/apm.agent_${envType}.tar.gz /usr/local/apm_agent/apm.agent.tar.gz
RUN tar -xzf /usr/local/apm_agent/apm.agent.tar.gz -C /usr/local/apm_agent/

2.3、Pinpoint 组件加载

回到微服务,我在dev4环境中自动引入了pinpoint组件:

先看一个典型的前端portal示例:

# pwd
/root/microservic-code/simple-microservice-dev4/portal-service

# cat Dockerfile
FROM java:8-jdk-alpine
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
COPY ./target/portal-service.jar ./
COPY pinpoint /pinpoint
EXPOSE 8080
CMD java -jar -javaagent:/pinpoint/pinpoint-bootstrap-1.8.3.jar -Dpinpoint.agentId=${HOSTNAME} -Dpinpoint.applicationName=ms-protal /portal-service.jar

# ll
总用量 8
-rw-r--r-- 1 root root  379 83 23:03 Dockerfile
drwxr-xr-x 7 root root  129 83 23:03 pinpoint  ##组件所在的位置
-rw-r--r-- 1 root root 1154 83 23:03 pom.xml
drwxr-xr-x 3 root root   18 83 23:03 src

### 进入pinpoint目录配置pinpoint.config(**每个微服都需要修改下**)

# vim pinpoint.config

profiler.collector.ip=192.168.171.10    ##指定采集端的server_IP

然后只需要按照我之前修改的docker_build.sh 重新部署 即可:

[root@k8s-master1 k8s]# cat docker_build.sh
#!/bin/bash

docker_registry=192.168.171.10
kubectl create secret docker-registry registry-pull-secret --docker-server=$docker_registry --docker-username=admin --docker-password=XXXX --docker-email=zhdya@zhdya.cn -n ms

service_list="gateway-service order-service product-service stock-service portal-service"
service_list=${1:-${service_list}}
work_dir=$(dirname $PWD)
current_dir=$PWD

cd $work_dir
mvn clean package -Dmaven.test.skip=true

for service in $service_list; do
   cd $work_dir/$service
   if ls |grep biz &>/dev/null; then
      cd ${service}-biz
   fi
   service=${service%-*}
   image_name=$docker_registry/microservice/${service}:$(date +%F-%H-%M-%S)
   docker build -t ${image_name} .
   docker push ${image_name}
  sed -i -r "s#(image: )(.*)#\1$image_name#" ${current_dir}/${service}.yaml
  kubectl apply -f ${current_dir}/${service}.yaml
done

最后在dashboard中查看各个应用的调用关系(其中ms-portal):

mark

写在最后:

  • 线上应用主要监控哪些指标?
    • 堆内存:年轻代、老年代、非堆内存(PermSize,默认是物理内存的1/4);
    • 线程数量;
    • GCC(垃圾回收);
    • CPU,内存,利用率;
    • 堆栈跟踪;
    • web请求,上级调用,外部调用;

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!