一,部署Prometheus Operator
废话不多说了,如何用operator方式在集群中部署Prometheus已经有很多教程,但是如何给operator部署的Prometheus添加访问时的basic auth认证却几乎没有人写,所以本篇在借鉴他人经验结合自己摸索之后写个操作文档。首先在kube-Prometheus的github主页下方可以找到快速部署的流程,需要注意的是在下载Prometheus前需要部署好集群(至少1master1node),再根据自己集群的版本来选择release版本:
1, 选择release版本:
在branch处选择合适的release跳转之后下载代码
2, 在本地下载代码
$ git clone https://github.com/prometheus-operator/kube-prometheus.git
$ cd kube-prometheus
3, 创建Operator资源并启动Prometheus
先手动修改Prometheus,grafana和alertmanager-main的service.yaml,在spec下添加type字段,将service类型修改为nodeport类型设置为静态端口公开服务。注意不要有格式错误(比如我就错了两次)
$ vim manifests/prometheus-service.yaml
...
spec:
type: NodePort #这里添加NodePort
ports:
- name: web
port: 9090
targetPort: web
- name: reloader-web
port: 8080
targetPort: reloader-web
$ vim manifests/alertmanager-service.yaml
...
spec:
type: NodePort #添加
ports:
- name: web
port: 9093
$ vim manifests/grafana-service.yaml
...
spec:
type: NodePort #添加
ports:
- name: http
port: 3000
targetPort: http
kubectl create -f manifests/setup
kubectl create -f manifests/
注意: 如果用kubectl apply去生成CRD资源可能会报如下错,用create就没有问题
Error from server (Invalid): error when creating "manifests/setup/0alertmanagerCustomResourceDefinition.yaml": CustomResourceDefinition.apiextensions.k8s.io "alertmanagers.monitoring.coreos.com" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
受限于国内网络原因,Prometheus组件启动时有两个镜像需要手动拉取,不然会报Imagepullbackoff错误.下面两个镜像亲测可以在修改dokcer镜像源之后直接下载
修改镜像源:
cat <<EOF > /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.nju.edu.cn",
"https://dockerproxy.com"
]
}
EOF
拉取其他仓库镜像:
docker pull bitnami/kube-state-metrics:2.12.0
docker pull thinkingdata/prometheus-adapter:v0.11.2
接下来在manifests/目录下,vim编辑kubeStateMetrics-deployment.yaml和prometheusAdapter-deployment.yaml这两个配置文件,输入/image定位到镜像配置并改成刚刚下的这两个镜像,然后再重新create就可以.
4, 卸载Prometheus组件和CRD资源(按需)
需要卸载所有Prometheus组件,在manifests/目录下执行:
kubectl delete -f manifests/ -f manifests/setup
5,访问Prometheus和grafana
[root@node-151 kube-prometheus-release-0.12]# kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager-main NodePort 10.233.62.173 <none> 9093:31512/TCP,8080:32125/TCP 35m
alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 36m
blackbox-exporter ClusterIP 10.233.15.237 <none> 9115/TCP,19115/TCP 36m
grafana NodePort 10.233.22.150 <none> 3000:32325/TCP 36m
kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 36m
node-exporter ClusterIP None <none> 9100/TCP 36m
prometheus-adapter ClusterIP 10.233.51.154 <none> 443/TCP 36m
prometheus-k8s NodePort 10.233.14.215 <none> 9090:30460/TCP,8080:30458/TCP 36m
prometheus-operated ClusterIP None <none> 9090/TCP 36m
prometheus-operator ClusterIP None <none> 8443/TCP 36m
注意有坑:因为 Prometheus Operator 默认设置了 NetworkPolicy,需要手动删除后才能访问。参考文献:https://zhuanlan.zhihu.com/p/624478715
kubectl delete -f manifests/prometheus-networkPolicy.yaml
kubectl delete -f manifests/grafana-networkPolicy.yaml
kubectl delete -f manifests/alertmanager-networkPolicy.yaml
先kubectl get svc查看服务的端口,Prometheus-k8s的9090端口对应可从外部访问端口为30460,那么访问http://节点ip:30460 即可访问Prometheus服务。
例如在浏览器地址框输入:192.168.107.151:30460
访问grafana服务则输入:192.168.107.151:32325
注意,grafana需要登录,初始账号和密码均为admin。
6,在grafana中显示Prometheus数据
在Prometheus中检查数据源状态:Status > Target
检查确定是否都是up状态。检查完毕后打开grafana,新建数据源:Configuration>Data source>add data source>Prometheus
填写url即可,注意需要填写主机ip+设置好node port端口,比如我的是http://192.168.107.151:30460,然后save&test
Dashboard>import:
确认好数据源之后就要选择展示模板,先登录grafana的 官网 找自己喜欢的模板,比如我要监控集群状态,选择的是Node Exporter Dashboard EN ,ID: 11074,可以直接在上面页面输入id,也可以下载json文件后上传。导入之后大概是这样:
二,添加Basic Auth认证
由于找遍了Prometheus operator官方的GitHub主页都没能找到能够直接配置basic auth的web config file的地方,有找到servicemonitor添加auth认证的办法,如果有大佬知道如何给Prometheus k8s和grafana添加请告诉我。现阶段还可以用ingress-nginx来控制流量入口的方式给Prometheus添加auth认证,参考文档:Prometheus配置Basic Auth进行安全防护,实现登录控制;
该文中提到实现ingress添加认证的流程为:htpasswd创建密码 - 创建secret - 创建ingress - 配置成功,但是笔者在测试的时候了解到在k8s中ingress需要配合ingress-controller方可使用,因为ingress它本身不会直接处理或转发流量,而是需要配合一个 Ingress 控制器来实现,参考文档:做一个不背锅运维:一篇搞定K8s Ingress。因此实际流程如下:
1,下载工具httpd:yum -y install httpd,这会在本地生成一个auth文件
2,利用auth文件创建secret
kubectl create secret generic basic-auth --from-file=auth -n monitoring
3,从官方主页下载deploy.yaml,部署ingress-nginx-controller
注意:先找到对应k8s版本的version,再下载deploy.yaml
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.9.5/deploy/static/provider/cloud/deploy.yaml
同时由于ingress-controller中用的镜像来自registry.k8s.io/仓库,国内下载不到需要替换镜像,我找到一个仓库可以较快下载这两个镜像,之后在deploy.yaml里替换镜像即可:
docker pull dyrnq/ingress-nginx-controller:v1.9.5
docker pull dyrnq/kube-webhook-certgen:v20231011-8b53cabe0
替换完之后kubectl apply -f deploy.yaml创建ingress-nginx-controller服务
4,创建ingress实例
$ vim ingress-prom.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-realm: Authentication Required
nginx.ingress.kubernetes.io/auth-secret: basic-auth #认证密码
nginx.ingress.kubernetes.io/auth-type: basic #认证类型
kubernetes.io/ingress.class: nginx
name: prometheus-k8s
namespace: monitoring
spec:
rules:
- host: prometheus.example.com
http:
paths:
- backend:
service:
name: prometheus-k8s #ingress绑定的服务
port:
number: 9090 #容器监听端口
path: / #指定url匹配方式,这里全部匹配
pathType: Prefix
这里由于我用的k8s版本是1.25,所以采用这种写法,1.22以前的写法稍有区别不过主要就是apiversion不同和service的写法不同。注意几个事项:1,修改使用的auth-secret,与自己创建的secret相同;2,ingress class类别,选择nginx;3,host使用自己要用的域名,在下面绑定要关联的service入口,名称与端口。
配置好之后kubectl apply即可:
[root@master-151 ~]# kubectl get ingress -n monitoring
NAME CLASS HOSTS ADDRESS PORTS AGE
prometheus-k8s <none> prometheus.example.com 10.233.18.41 80 3h49m
ingress资源建立后,它的路由规则是将所有的访问都路由到hosts地址,监听80端口,同时我们还可以进入ingress-nginx-controller内部检索nginx.conf,查看ingress是否已经注入规则:
[root@node-151 ~]# kubectl exec -it -n ingress-nginx ingress-nginx-controller-584974fddd-s2mhs -- /bin/bash
ingress-nginx-controller-584974fddd-s2mhs:/etc/nginx$ grep prometheus-k8s nginx.conf -n
可以看到controller中已经注入了该ingress路由规则,但是此时并不能直接访问controller来访问Prometheus数据,还需要对外暴露ingress-nginx-controller的NodePort端口。
5,暴露ingress-nginx-controller对外服务端口
修改deploy.yaml,找到controller的service部分:
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
app.kubernetes.io/version: 1.9.5
name: ingress-nginx-controller
namespace: ingress-nginx
spec:
externalTrafficPolicy: Local
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- appProtocol: http
name: http
port: 80
protocol: TCP
targetPort: http
nodePort: 30080 # 添加
- appProtocol: https
name: https
port: 443
protocol: TCP
targetPort: https
nodePort: 30443 # 添加
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
type: NodePort # 修改
修改完delete + apply重新部署controller,紧接着在/etc/hosts中添加域名和ip,例如:
192.168.107.151 prometheus.example.com
6,测试
不加用户密码,提示401需要鉴权:
添加账户密码(admin:test123)后,能成功获取到Prometheus监控数据:
curl -u "admin:test123" http://prometheus.example.com:30080/api/v1/query?query=up ; echo " "
注意:
1,要从外部浏览器访问测试,需要在外部修改hosts文件,确保能进行ip和域名转换;
2,之前用grafana抓取Prometheus的监控数据,在prom添加鉴权后,也需要去grafana的data source栏添加basic auth认证后方可继续抓取数据。