本文档通过一步一步展示如何通过nginx输出指标,并通过exporter转化为Prometheus指标,最后通过Grafana的面板进行展示的全过程。最后部分会演示如何通过docker-compose进行快捷部署。
本文选自于本人gitbook,地址:https://maxidea.gitbook.io/k8s-testing/
转载请标注出处。
NGINX 通过 stub_status page 页面公开了一些有用的指标,NGINX Prometheus exporter 则通过获取这些指标,转换成适合Prometheus处理的指标格式,并通过HTTP服务输出,方便我们使用 Prometheus 进行收集和处理。
对于nginx-prometheus-exporter说明,请见这里:https://github.com/nginxinc/nginx-prometheus-exporter
对应的镜像文件地址:
https://hub.docker.com/r/nginx/nginx-prometheus-exporter
利用多阶段部署方式,把nginx:alpine镜像合入nginx/nginx-prometheus-exporter中的程序,并使用脚本同时启动二者,注意让nginx运行于前台,且nginx-prometheus-exporter程序能正常输出nginx的指标。
下载测试到用到镜像:
docker pull nginx:alpine
docker pull nginx/nginx-prometheus-exporter:latest
然后运行一下nginx:alpine
容器,看看里面是否包含 stub_status 模块
docker run --name nginx1 -d nginx:alpine
docker exec -it nginx1 /bin/sh
/ # /usr/sbin/nginx -V
nginx version: nginx/1.17.10 built by gcc 9.2.0 (Alpine 9.2.0) built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1g 21 Apr 2020) TLS SNI support enabled configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --with-perl_modules_path=/usr/lib/perl5/vendor_perl --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-Os -fomit-frame-pointer' --with-ld-opt=-Wl,--as-needed
看到--with-http_stub_status_module
,证明这个镜像已经编译好了stub_status 模块
创建/etc/nginx/conf.d/status.conf
,加入:
server {
listen 8080;
server_name localhost;
location /stub_status {
stub_status on;
access_log off;
}
}
/usr/sbin/nginx -s reload
重启,然后在新terminal访问容器ip:8080/stub_status
页面:
root@31:/home/ubuntu# curl 172.17.0.5:8080/stub_status
Active connections: 1
server accepts handled requests
3 3 3
Reading: 0 Writing: 1 Waiting: 0
利用while语句做一个循环输出就可以实现简单的访问量监控:
while true ; do curl 172.17.0.5:8080/stub_status; sleep 2; done
然后把/etc/nginx/conf.d/status.conf复制到宿主机备用:
docker cp nginx1:/etc/nginx/conf.d/status.conf ./
通过nginx-prometheus-exporter容器来监控nginx1的指标,命令如下:
root@31:/home/ubuntu# docker run -p 9113:9113 nginx/nginx-prometheus-exporter:latest -nginx.scrape-uri http://172.17.0.5:8080/stub_status
2020/05/01 11:31:38 Starting NGINX Prometheus Exporter Version=0.7.0 GitCommit=a2910f1
2020/05/01 11:31:38 Listening on :9113
2020/05/01 11:31:38 NGINX Prometheus Exporter has successfully started
然后在另一个terminal下每秒访问一次nginx1容器的80服务:
while true ; do curl -s -o /dev/null http://172.17.0.2/; sleep 1; done
最后访问宿主机IP:9113/metrics
页面,就能看到读取出来的nginx指标数据了。
创建一个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"]
编写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永不运行完成,容器不退出。
把dockerfile生成镜像文件:
docker build . -t nginx-exporter:v0.2
运行容器:
docker run --name exporter2 -d -p 9113:9113 nginx-exporter:v0.2
访问宿主机:9113/metrics检查exporter运作情况:
本测试由三部分组成:
1)Nginx指标收集,由nginx-prometheus-exporter转化为prometheus可以处理的指标格式,这部分我们上一节已经完成,本节将复用我们做好的nginx-exporter:v0.2镜像
。
2)配置Prometheus对指标进行收集(镜像https://hub.docker.com/r/prom/prometheus
)
3)配置Grafana对指标进行展示(镜像https://hub.docker.com/r/grafana/grafana
)
首先,在宿主机上创建prometheus.yml文件,内容如下:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'nginx_exporter'
static_configs:
- targets: ['192.168.2.31:9113']
labels:
group: 'services'
启动Prometheus容器:
docker run --name prometheus1 -d -p 9090:9090 -v /simon-testing/docker/compose/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
然后访问宿主机 http://宿主机IP:9090/targets
,获得如下界面即代表Prometheus和Nginx指标均可获取:
使用Nginx指标名称能在Prometheus绘制出简单图表:
首先我们需要定制一个适合展示prometheus收集回来的nginx的指标参数的dashboards仪表板模板,最快的方式是上官网的选择现成的,参考https://grafana.com/grafana/dashboards/
实际工作中,我们通常使用的nginx-vts-exporter能获得更多的指标。
这里我们自己定义一个适合nginx-prometheus-exporter指标的json文件,并命名为dashboard.json:(为了节约文章篇幅,文件请从我的仓库下载(RAW地址):https://gitee.com/maxidea/k8s-testing-files/raw/master/docker/compose/grafana/dashboards/dashboard.json
参考:https://grafana.com/docs/grafana/latest/administration/provisioning/
创建一个dashboard.yaml文件:
apiVersion: 1
providers:
- name: 'nginx'
orgId: 1
folder: 'dashboard1'
folderUid: ''
type: file
disableDeletion: false
editable: true
updateIntervalSeconds: 10
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
创建一个datasouce.yaml文件:
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: http://192.168.2.31:9090
basicAuth: false
isDefault: true
version: 1
editable: true
docker run -d --name=grafana1 \
-v $(pwd)/grafana/dashboards/dashboard.json:/var/lib/grafana/dashboards/dashboard.json \
-v $(pwd)/grafana/provisioning/dashboard.yaml:/etc/grafana/provisioning/dashboards/dashboard.yaml \
-v $(pwd)/grafana/provisioning/datasource.yaml:/etc/grafana/provisioning/datasources/datasource.yaml \
-p 3000:3000 grafana/grafana
现在宿主机上三个容器是:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
04b5ee1a4128 grafana/grafana "/run.sh" 3 seconds ago Up 2 seconds 0.0.0.0:3000->3000/tcp grafana1
556ca4ec29f8 prom/prometheus "/bin/prometheus --c…" 12 hours ago Up 12 hours 0.0.0.0:9090->9090/tcp prometheus1
71dda6ff4612 nginx-exporter:v0.2 "/bin/sh /run.sh" 12 hours ago Up 12 hours 80/tcp, 0.0.0.0:9113->9113/tcp exporter2
访问http://宿主机ip:3000
端口,打开Grafana,正常可以看到如下仪表板,即代表测试成功:
基于我们之前制作的nginx-exporter:v0.2
镜像,我们使用docker compose编排文件实现一次性部署Prometheus和Grafana
与前面手工部署三个容器不一样的地方是,我们这里需要修改一下Prometheus和Grafana配置里的数据源地址。
清除之前测试的容器:
docker stop $(docker ps -q)
docker rm $(docker ps -aq)
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'nginx_exporter'
static_configs:
- targets: ['nginx_exporter:9113']
labels:
group: 'services'
apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
basicAuth: false
isDefault: true
version: 1
editable: true
version: '3'
services:
nginx:
image: nginx-exporter:v0.2
networks:
webnet:
aliases:
- "nginx_exporter"
expose:
- "9113"
ports:
- "9113:9113"
prometheus:
image: prom/prometheus
volumes:
- ./prometheus/prometheus-compose.yml:/etc/prometheus/prometheus.yml
networks:
webnet:
aliases:
- "prometheus"
expose:
- "9090"
ports:
- "9090:9090"
depends_on:
- nginx
grafana:
image: grafana/grafana
volumes:
- ./grafana/dashboards/dashboard.json:/var/lib/grafana/dashboards/dashboard.json
- ./grafana/provisioning/dashboard.yaml:/etc/grafana/provisioning/dashboards/dashboard.yaml
- ./grafana/provisioning/datasource-compose.yaml:/etc/grafana/provisioning/datasources/datasource.yaml
networks:
webnet:
aliases:
- "grafana"
expose:
- "3000"
ports:
- "3000:3000"
depends_on:
- prometheus
networks:
webnet: {}
然后使用docker-compose up -d
命令运行起来,之后访问宿主机3000端口即可获取grafana界面。