【2020.07.03】asp.net core程序在k8s中基于rabbitmq队列消息数的HPA实践!

背景

最近一段时间,陆陆续续的把手里头项目都迁移到了k8s中,期间遇到很多的坑,并且也学到了许多k8s的知识(从0-1),大家都知道k8s中的一大特性是自动扩容,对此结合自己的业务发现很是有“用武之地”,我有个业务,是向消息队列中插入消息,然后.net core console app进行消费,但是我这个业务有个特点,要么没有消息生产,要么就是有一大批消息产生。在引用HPA之前,我不得不提前启动“合适数量”的pod(1个pod多个消费者容器)来消费消息,要不然业务方要叫了Don't tell anyone smile。但是作为有“洁癖”的开发者,我不想相同的容器有太多的闲置,无所事事,又占用资源。所以我们需要借助HPA来实现自动伸缩扩容,消息多的时候,自动扩容;消息少的时候,自动缩容。

前期准备:

  1. 要有一个k8s集群(我是通过kubeadm搭建的3master+N node的集群 1.18.2)
  2. 有一个rabbitmq实例3.8.x
  3. rabbitmq_exporter:一个通过转化mq:15672接口数据,以metrics接口暴露出来的exporter
  4. kube-prometheus:一个将prometheus全家桶集合安装的开源项目

大体实现方向:

将rabbitmq的数据指标,以metrics接口的形式,暴露给prometheus server;然后再promethus中通过添加record rule规则来自定义你的队列指标;然后再promethus adapter中添加一条rule来将之前的指标转化成k8s api所能识别的接口;最后在k8s中定义HPA去监测prometheus adapter service暴露的转化好的接口来动态伸缩。

第一步:暴露rabbitmq数据指标

  • rabbitmq官网中monitor一节中有提到它有一个插件是给pormetheus用的,但是我看了下用起来不方便,达不到效果,遂用下面的这个开源项目。
  • rabbitmq_exporter这个项目它sample中使用的是直接docker run去启动容器,来进行mq数据指标的暴露,但是你最好把他运行在k8s中,方便管理。
  • 准备一个yaml文件,将rabbitmq exporter运行在k8s集群中,并以service的形式,暴露给k8s中安装的prometheus server去抓取
  •   1 apiVersion: apps/v1
      2 kind: Deployment
      3 metadata:
      4   name: rabbitmq-exporter
      5   namespace: monitoring #暂且放在这个命名空间下,因为后面prometheus也在这个命名空间,如果没有的话你可以先创建一个kubectl create ns monitoring
      6   labels:
      7     app: rabbitmq-exporter
      8     author: jamestao
      9 spec:
     10   replicas: 1
     11   selector:
     12     matchLabels:
     13       app: rabbitmqpod
     14   template:
     15     metadata:
     16       name: rabbitmq-exporter-pod
     17       labels:
     18         app: rabbitmqpod
     19     spec:
     20       restartPolicy: Always
     21       containers:
     22         - name: rabbitmq-exporter-container
     23           image: kbudde/rabbitmq-exporter:latest
     24           resources:
     25             requests:
     26               memory: 10Mi
     27           ports:
     28             - containerPort: 9419
     29           env:
     30             - name: RABBIT_URL
     31               value: http://你的ip:15672  #这里需修改
     32             - name: RABBIT_USER
     33               value: "你的用户名" #这里需修改
     34             - name: RABBIT_PASSWORD
     35               value: "你的密码" #这里需修改
     36             - name: INCLUDE_VHOST
     37               value: ".*"
     38             - name: INCLUDE_QUEUES
     39               value: ".*"
     40 ---
     41 apiVersion: v1
     42 kind: Service
     43 metadata:
     44   name: svc-rabbitmq-management
     45   namespace: monitoring
     46 spec:
     47   selector:
     48     app: rabbitmqpod
     49   ports:
     50     - protocol: TCP
     51       port: 39419 #定义了svc的端口号,可以修改为你自己的,就是通过这个端口暴露metrics给prometheus server抓取
     52       targetPort: 9419
     53       name: metrics
    rabbitmq_exporter.yaml
  • 然后在k8s master中创建这个yaml: kubectl apply –f rabbitmq_exporter.yaml
  • 看到如下内容代表部署成功了:image
  • 我们看看39419端口暴露的metrics暴露的接口数据长什么样:
    • 我们先用kubectl exec命令随便进入一个容器,在容器内部访问上面的svc ip + port
    • 然后访问我们上面的svc: curl 10.110.14.151:39419/metrics | grep rabbitmq_queue_messages{image
    • 看到有图片中的数据,就代表你rabbitmq exporter搭建成功了,否则的话查看下日志解决下。
  • 至此,k8s集群中已经存在一个这样的svc接口(10.110.14.151:39419/metrics)他只能在k8s集群内部访问,他暴露的metrics数据中,就包含了队列中消息的数量。

第二步:使rabbitmq metrics指标能够被prometheus server所定时抓取

  • 安装prometheus监控全家桶

    • 先把原项目clone下来: git conle https://github.com/coreos/kube-prometheus.git
    • image
    • manifests:这个文件夹里放的全都是prometheus所需资源清单文件
    • example.jsonnet:这个文件是生成manifests文件夹的引导文件
    • 理论上,你git clone下来的mainfests文件夹,可以直接用的,但是需要做下调整,接下来我通过example.jsonnet来重新编译生成manifests资源清单
      • 参考于:https://github.com/coreos/kube-prometheus#compiling
      • 为了避免干扰,先将mainfests文件夹删除。
      • 我们先修改example.jsonnet文件,让其按照我的要求生成mainfests资源清单:
        • image
      • 在项目目录下,先执行(第一次会比较慢,大概10来分钟吧,或者失败,请重试!):
      • docker run --rm -v $(pwd):$(pwd) --workdir $(pwd) quay.io/coreos/jsonnet-ci jb update
      • 然后再执行:
      • docker run --rm -v $(pwd):$(pwd) --workdir $(pwd) quay.io/coreos/jsonnet-ci ./build.sh example.jsonnet
      • 等执行好了,我们能看到新的mainfests文件夹已经生成好了。
      • 安装:kubectl apply –f mainfests/setup/.
      • 安装:kubectl apply –f mainfests/.
    • 看下安装好了之后,所启动的svc有哪些
      • image
      • 3个UI的组件,之所以是nodeport(可以直接外网通过 主机ip+端口进行访问),是因为上面的jsonnet文件。请详细看下上面图片中的备注
    • image
    • image
    • 至此,全家桶不出意外的话,应该都安装完成了。
  • 让prometheus server可以抓取的到rabbitmq metrics指标

    • 参考资料:https://github.com/coreos/prometheus-operator/blob/master/Documentation/additional-scrape-config.md
    • 创建prometheus-additional.yaml文件用于配置rabbitmq metrics job
        1 - job_name: "bookstoremqjob"
        2   static_configs:
        3   - targets: ["svc-rabbitmq-management.monitoring.svc.cluster.local:39419"]
      prometheus-additional.yaml
    • 执行:kubectl create secret generic additional-scrape-configs --from-file=prometheus-additional.yaml -n monitoring
    • 验证:image
    • 然后修改:manifests/prometheus-prometheus.yamlimage
    • 执行:kubectl apply -f manifests/prometheus-prometheus.yaml
    • 此时prometheus server并没有抓取rabbitmq metrics,需要重新启动下,以加载到我们上述的新targetimage
    • 最后我们看下UI,是否成功添加targetimage
    • graph中,也能看到rabbitmq_queue_messages指标了image

第三步:使用prometheus-adapter来让k8s能够访问的到自定义的资源指标

  • 上面全家桶中已经包含了adapter,所以不需要再安装了,推荐实战的小伙伴,仔细看下这个全家桶项目doc。
  • 首先,先确保k8s中custom.metrics.k8s.io自定义指标接口可用
    • image
    • image
  • 虽然你能在graph中看到rabbitmq_queue_messages指标,但是这个指标也只有prometheus自己认得,k8s api server并不认得。
    • 我们得添加一条prometheus rule,参考资料:点我
    • 其实我们在上面已经添加了一条,并且已经运行起来了,监测vhost为xxxx,queue为xxxx的队列。image
    • image
    • labels必选要打上:image
  • 然后我们给prometheus-adapter添加一条rule用于映射到上面prometheus中的record rule:enriched_rabbitmq_queue_messages
    • 参考资料:请戳我,看最后那个人的留言,最佳解释
    • 那我们怎么添加呢,我们先看看prometheus-adapter容器的配置文件(rule默认都有一个配置文件维护的)
    • 先看下adapter的描述:kubectl describe pod prometheus-adapter-5cdcdf9c8d-5bq5p
    • image
    • 发现他把配置信息都放到configmap里,那换个角度,只要我们能将给prometheus-adapter添加的rule,追加到这个configmap里面,理论上就可以实现动态增加了。
    • 其实adapter所有的配置都在manifests/prometheus-adapter-configMap.yamlimage
    • 记得执行让它生效:kubectl apply -f manifests/prometheus-adapter-configMap.yaml
    • 等待几十秒后,验证下:image
    • 至此自定义metrics指标已经成功,实现了prometheus server不停的监测某个队列的消息数,然后k8s api通过prometheus adapter能够访问到这个指标,这样后面的HPA就简单的多了。

第四步:定义HPA

  • image

补充(上面有些步骤的优化):

【2020.07.06】kube-prometheus中如何添加新scrape api?

【2020.07.07】如何自动探测到自定义的record rule

posted @ 2020-07-03 17:50  James陶  阅读(584)  评论(0编辑  收藏  举报