K8S中使用Prometheus监控nginx指标

一、环境描述

K8S中一般使用Prometheus进行指标数据的监控,而对于custom metrics自定义指标,需要满足Prometheus可以识别的格式发送。这时候一般需要写exporter来搞定自定义数据,然后上报。本篇结合nginx示例来配置下自定义指标监控。

为了省于前期复制的k8s配置和Prometheus的集成,这里选用了华为的云容器引擎CCE,创建完CCE,把metrics-server和prometheus两个插件勾选上就可以了,会自动安装上grafana和prometheus-adapter(将自定义指标通过API上报Prometheus)。

这里出于测试目的,使用的nginx(stub_status开启内部访问)和nginx_exporter(将stub_status数据转换),如果需要采集更多指标,可以使用nginx_vts替代nginx_exporter。

二、编译nginx镜像

编辑nginx.conf配置文件,开启stub_status功能,配置文件内容如下:

user  nginx;
worker_processes  auto;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    #gzip  on;
    include /etc/nginx/conf.d/*.conf;
    server {
      listen 8080;
      server_name  localhost;
      location /stub_status {
         stub_status on;
         access_log off;
      }
    }
}

编辑Dockerfile文件,将该文件复制到对应的镜像内容(重新生成docker image这部也可以不做,因为大部分的nginx images是支持nginx.conf指定本地目录下的nginx.conf文件进去的):

FROM nginx:1.21.5-alpine
ADD nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

将build新生成的镜像文件上传华为SWR镜像仓库。

三、Deployment发布应用

编辑一个deployment文件,内容如下:

kind: Deployment
apiVersion: apps/v1
metadata:
  name: nginx-exporter
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx-exporter
  template:
    metadata:
      labels:
        app: nginx-exporter
      annotations:
        # metrics.alpha.kubernetes.io/custom-endpoints: '[{"api":"prometheus","path":"/metrics","port":"9113","names":""}]'  //这个是上报华为AOM服务使用的,可以删除该行
        prometheus.io/path: /metrics
        prometheus.io/port: "9113"
        prometheus.io/scrape: "true"
    spec:
      containers:
        - name: container-nginx
          image: 'swr.la-north-2.myhuaweicloud.com/testca/nginx:exporter'
          resources:
            limits:
              cpu: 250m
              memory: 512Mi
            requests:
              cpu: 250m
              memory: 512Mi
        - name: container-exporter
          image: 'nginx/nginx-prometheus-exporter:0.9.0'
          command:
            - nginx-prometheus-exporter
          args:
            - '-nginx.scrape-uri=http://127.0.0.1:8080/stub_status'
      imagePullSecrets:
        - name: default-secret

Prometheus可以动态监测,一般来说给Pod打上Prometheus的annotations,Prometheus会自动采集该Pod的监控信息,这里注意下annotations这里面的几个关键内容,具体的解释如下:

prometheus.io/scrape: true的话该pod会作为监控目标
prometheus.io/path: 采集的url,默认为/metrics
prometheus.io/port: 采集endpoint的端口号
prometheus.io/scheme: 默认http,如果为了安全设置了https,此处需要改为https

通常打上prometheus.io/scrape这个annotations就可以了,这样Prometheus就会从“/metrics”采集Pod的的监控信息。执行kubectl create/apply应用该yaml文件。

四、监控配置

由于CCE上默认prometheus和grafana默认都是ClusterIP内部访问的,这里我新增加了一个nodeport的service服务,对外暴漏prometheus,同样grafan需要暴漏的时候,操作也是一样的。
k8s-cce-prometheus
通过kubectl get pods -o wide获取到Pod的内部IP,通过prometheus的target部分,可以看到kubernetes-pods endpoint里已经有了这部分数据:
nginx-prometheus

[root@testcce-47617-dk54v ~]# kubectl get deployments -n monitoring
NAME                                     READY   UP-TO-DATE   AVAILABLE   AGE
cceaddon-prometheus-kube-state-metrics   1/1     1            1           2d5h
cceaddon-prometheus-operator             1/1     1            1           2d5h
custom-metrics-apiserver                 1/1     1            1           2d5h
grafana                                  1/1     1            1           2d5h
[root@testcce-47617-dk54v ~]# kubectl get svc -n monitoring
NAME                                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cceaddon-prometheus-kube-state-metrics   ClusterIP   None             <none>        80/TCP           2d5h
custom-metrics-apiserver                 ClusterIP   10.247.2.162     <none>        443/TCP          2d5h
grafana                                  ClusterIP   10.247.208.180   <none>        3000/TCP         2d5h
prometheus                               ClusterIP   10.247.177.188   <none>        80/TCP           2d5h
prometheus-nodeport                      NodePort    10.247.255.97    <none>        9090:32384/TCP   44h
[root@testcce-47617-dk54v ~]# kubectl expose deployment grafana --type=NodePort --name=grafana-nodeport -n monitoring
service/grafana-nodeport exposed
[root@testcce-47617-dk54v ~]# kubectl get svc -n monitoring
NAME                                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
cceaddon-prometheus-kube-state-metrics   ClusterIP   None             <none>        80/TCP           2d5h
custom-metrics-apiserver                 ClusterIP   10.247.2.162     <none>        443/TCP          2d5h
grafana                                  ClusterIP   10.247.208.180   <none>        3000/TCP         2d5h
grafana-nodeport                         NodePort    10.247.195.200   <none>        3000:30269/TCP   3s
prometheus                               ClusterIP   10.247.177.188   <none>        80/TCP           2d5h
prometheus-nodeport                      NodePort    10.247.255.97    <none>        9090:32384/TCP   44h

这里在grafana上增加了下每秒请求数量的图,具体代码为sum(rate(nginx_http_requests_total[1m])) by (kubernetes_pod_name),通过循环请求对应的图如下:
nginx-grafana
这里请求是对单pod进行的while true;do curl 172.16.0.12;done,多pod服务的情况下,也可以通过内部域名,在一台测试容器中进行,或者通过NodePort暴漏后,访问对应的地址进行集群测试。

后记

这里nginx和nginx-exporter使用的是sidecar模式,如果要放在一个容器里也可以实现,具体步骤如下:
1. 创建dockerfile,内容如下:

# 编译阶段 命名为 exporter
FROM nginx/nginx-prometheus-exporter:latest as exporter
# 运行阶段
FROM nginx:alpine
COPY ./nginx/status.conf /etc/nginx/conf.d/status.conf
COPY --from=exporter /usr/bin/exporter /usr/bin/exporter
ADD run.sh /run.sh
RUN chmod 777 /run.sh
EXPOSE 80 9113
CMD ["/bin/sh", "/run.sh"]
  1. 编写run.sh:
#!/bin/bash
nginx -c /etc/nginx/nginx.conf
nginx -s reload
/usr/bin/exporter -nginx.scrape-uri http://127.0.0.1/stub_status
tail -f /dev/null #实现本shell永不运行完成,容器不退出。

同样,通过docker命令执行生成image的指令如下:

docker build . -t nginx-exporter:v2

发表回复

您的电子邮箱地址不会被公开。