目录
一、前言
在现代云原生架构中,监控和可观察性已成为确保系统稳定性和性能的关键。Kubernetes,作为容器编排的领军者,不断演进以满足日益增长的需求。随着 Kubernetes 1.27 的发布,我们迎来了更多创新和优化。在这个版本中,如何高效地部署和配置监控系统变得尤为重要。
Prometheus,作为一款开源的系统监控和告警工具包,以其强大的数据采集、存储和查询能力,成为了许多开发者和运维人员的首选。而 Grafana,则以其直观的数据可视化和丰富的插件生态系统,为 Prometheus 提供了完美的可视化界面。
Prometheus和Grafana是两个在监控和数据分析领域广泛使用的开源工具,它们各自有着独特的功能和角色,但也可以协同工作以提供更全面的解决方案。
Prometheus的基本概念:
Prometheus是一个开源的系统监控和报警系统,用于收集、存储和查询时间序列数据。它由SoundCloud公司开发,后来成为了一个独立的开源项目,并得到了Google和许多其他公司的支持。Prometheus的主要特点包括:
- 数据模型:Prometheus使用强大的多维度数据模型,通过metric(度量指标名称)和标签(labels)键值对来区分时间序列数据。
- Exporter:Exporter是一个组件,负责采集监控数据并通过Prometheus监控规范对外提供数据。Prometheus通过轮询的方式定期从Exporter(称为target)中获取样本数据。
- 数据存储:Prometheus将这些数据存储在时间序列数据库中,Prometheus server本身就是一个时序数据库以便后续查询和分析。
- 查询和聚合:Prometheus提供了一个表达式语言(PromQL),用于查询和聚合数据。这使得用户可以灵活地获取和处理监控数据。
- 告警和通知:Prometheus还具备内置的告警规则和通知机制,可以在数据达到特定阈值时触发告警,并通过多种通知方式(如电子邮件、Slack等)将告警信息发送给相关人员。
Grafana的基本概念:
Grafana是一个开源的度量分析和可视化套件,常用于对大量数据进行实时分析和可视化。Grafana的主要特点包括:
- 数据源:Grafana支持多种不同的时序数据库数据源,对每种数据源提供不同的查询方法,并能够很好地支持每种数据源的特性。
- 组织:Grafana支持多组织架构,可以为一个单一的Grafana实例提供多个潜在的不受信任的组织的服务。每个组织可以有一个或多个数据源,所有的仪表板是由一个特定的组织拥有的。
- 数据可视化:Grafana提供了丰富的可视化选项,包括图表、表格、地图等,使用户能够直观地展示和分析数据。
- 警报规则:Grafana也支持创建警报规则,当监控数据达到特定阈值时,可以触发警报。
Prometheus和Grafana的协同工作:
Prometheus和Grafana通常一起使用,以提供全面的监控和可视化解决方案。Prometheus负责收集、存储和查询时间序列数据,而Grafana则提供强大的数据可视化功能。通过将Prometheus作为Grafana的数据源,用户可以在Grafana中创建仪表板来展示Prometheus收集的数据,并进行深入的分析和告警设置。这种组合使得用户能够更好地理解系统的运行状态,及时发现并解决问题。
二、k8sv1.27部署Prometheus
2.1 项目地址
[root@master ~]# git clone https://github.com/bibinwilson/kubernetes-prometheus
2.2 创建命名空间和集群角色
创建命名空间
[root@master ~]# kubectl create namespace monitoring
定义命名空间(namespace)的原因主要涉及到资源的组织和隔离。以下是几个关键原因:
- 组织资源:Kubernetes支持多个虚拟集群,这些虚拟集群被称为命名空间。这些命名空间允许您根据项目的性质、环境(如开发、测试、生产)或用户/租户将资源(如Pods、Services、Deployments等)组合在一起。通过为每个环境或项目创建单独的命名空间,您可以更好地组织和管理这些资源。
- 隔离资源:命名空间提供了资源之间的隔离。在Kubernetes中,资源的名称在命名空间内必须是唯一的,但跨命名空间则不必。这意味着您可以在不同的命名空间中拥有相同名称的资源,而不会发生冲突。这为跨多个项目或环境部署和管理资源提供了灵活性。
- 权限控制:命名空间还可以与Kubernetes的RBAC(基于角色的访问控制)一起使用,以限制用户对资源的访问。通过为每个命名空间定义不同的角色和角色绑定,您可以控制哪些用户可以访问哪些资源,从而增强系统的安全性。
- 清晰的管理边界:定义命名空间可以为Prometheus和相关资源(如Alertmanager、Grafana等)提供清晰的管理边界。您可以在特定的命名空间中部署和管理这些资源,而不会影响其他命名空间中的资源。
创建集群角色
[root@master kubernetes-prometheus]# cat clusterRole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: default
namespace: monitoring
kubectl create -f clusterRole.yaml
定义了两个K8s资源:一个ClusterRole和一个ClusterRoleBinding,确保特定的服务账户(或用户)具有执行某些操作的权限。
1、ClusterRole(prometheus):
- 这是一个集群级别的角色,它定义了一组权限规则,这些规则允许对Kubernetes集群中的资源执行特定的操作。
- prometheus ClusterRole允许对节点(nodes)、服务(services)、端点(endpoints)、Pod(pods)以及Ingress资源执行“get”、“list”和“watch”操作。此外,它还允许对“/metrics”这个非资源URL执行“get”操作,这通常用于从Kubernetes组件中获取度量数据。
2、ClusterRoleBinding(prometheus)
- 这是一个集群级别的角色绑定,它将前面定义的prometheus ClusterRole绑定到一个或多个服务账户(或用户)上。
- prometheus ClusterRoleBinding将prometheus ClusterRole绑定到名为default的服务账户上,并且这个服务账户位于monitoring命名空间中。这意味着在monitoring命名空间中的default服务账户现在具有prometheus ClusterRole所定义的权限。
2.3 使用Config Map外部化Prometheus配置
Prometheus 的所有配置都是
prometheus.yaml
文件的一部分,而 Alertmanager 的所有警报规则都配置在prometheus.rules
.
prometheus.yaml
:这是主要的 Prometheus 配置,包含所有抓取配置、服务发现详细信息、存储位置、数据保留配置等prometheus.rules
:此文件包含所有 Prometheus 警报规则通过将 Prometheus 配置外部化到 Kubernetes 的 config map,那么就无需当需要添加或删除配置时,再来构建 Prometheus 镜像。这里需要更新配置映射并重新启动 Prometheus pod 以应用新配置。
带有所有Prometheus 抓取配置和警报规则的 config map 被挂载到 Prometheus 容器的
prometheus.yaml
和prometheus.rules
文件中,这些文件位于/etc/prometheus
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: prometheus
rules:
- apiGroups: [""]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
- ingresses
verbs: ["get", "list", "watch"]
- nonResourceURLs: ["/metrics"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: prometheus
subjects:
- kind: ServiceAccount
name: default
namespace: monitoring
[root@master kubernetes-prometheus]# cat config-map.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-server-conf
labels:
name: prometheus-server-conf
namespace: monitoring
data:
prometheus.rules: |-
groups:
- name: devopscube demo alert
rules:
- alert: High Pod Memory
expr: sum(container_memory_usage_bytes) > 1
for: 1m
labels:
severity: slack
annotations:
summary: High Memory Usage
prometheus.yml: |-
global:
scrape_interval: 5s
evaluation_interval: 5s
rule_files:
- /etc/prometheus/prometheus.rules
alerting:
alertmanagers:
- scheme: http
static_configs:
- targets:
- "alertmanager.monitoring.svc:9093"
scrape_configs:
- job_name: 'node-exporter'
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_endpoints_name]
regex: 'node-exporter'
action: keep
- job_name: 'kubernetes-apiservers' #它从 API 服务器获取所有指标
kubernetes_sd_configs:
- role: endpoints
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
relabel_configs:
- source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
action: keep
regex: default;kubernetes;https
- job_name: 'kubernetes-nodes' #收集所有 Kubernetes 节点指标
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics
- job_name: 'kubernetes-pods' #如果 pod 元数据用prometheus.io/scrape和 prometheus.io/port来注释,那么所有的 pod 都得以发现
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
target_label: __address__
- action: labelmap
regex: __meta_kubernetes_pod_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: kubernetes_pod_name
- job_name: 'kube-state-metrics' #收集所有 cAdvisor 指标
static_configs:
- targets: ['kube-state-metrics.kube-system.svc.cluster.local:8080']
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex: __meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement: kubernetes.default.svc:443
- source_labels: [__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor
- job_name: 'kubernetes-service-endpoints' #如果服务元数据使用 prometheus.io/scrape 和 prometheus.io/port 注释来进行注释,那么所有服务端点都将被报废。它可以用于黑盒监控。
kubernetes_sd_configs:
- role: endpoints
relabel_configs:
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- action: labelmap
regex: __meta_kubernetes_service_label_(.+)
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: kubernetes_namespace
- source_labels: [__meta_kubernetes_service_name]
action: replace
target_label: kubernetes_name
kubectl create -f config-map.yaml
2.3 部署Prometheus
[root@master kubernetes-prometheus]# cat prometheus-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-deployment
namespace: monitoring
labels:
app: prometheus-server
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-server
template:
metadata:
labels:
app: prometheus-server
spec:
containers:
- name: prometheus
image: prom/prometheus
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus/"
ports:
- containerPort: 9090
volumeMounts:
- name: prometheus-config-volume
mountPath: /etc/prometheus/
- name: prometheus-storage-volume
mountPath: /prometheus/
volumes:
- name: prometheus-config-volume
configMap:
defaultMode: 420
name: prometheus-server-conf
- name: prometheus-storage-volume
emptyDir: {}
kubectl create -f prometheus-deployment.yaml
kubectl get deployments --namespace=monitoring
2.4 创建service暴露访问端口
[root@master kubernetes-prometheus]# cat prometheus-service.yaml
apiVersion: v1
kind: Service
metadata:
name: prometheus-service
namespace: monitoring
annotations:
prometheus.io/scrape: 'true'
prometheus.io/port: '9090'
spec:
selector:
app: prometheus-server
type: NodePort
ports:
- port: 8080
targetPort: 9090
nodePort: 30000
kubectl apply -f prometheus-service.yaml
查看状态
使用任意一个NodeIP加端口进行访问,访问地址:http://NodeIP:Port
三、k8sv1.27部署Grafana
[root@master kubernetes-prometheus]# cat grafana.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: grafana
namespace: kube-system
spec:
serviceName: "grafana"
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana
ports:
- containerPort: 3000
protocol: TCP
resources:
limits:
cpu: 100m
memory: 256Mi
requests:
cpu: 100m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: kube-system
spec:
type: NodePort
ports:
- port : 80
targetPort: 3000
nodePort: 30091
selector:
app: grafana
使用任意一个NodeIP加端口进行访问,访问地址:http://NodeIP:Port
默认账号密码都为admin
第一步需要进行数据源添加
第二步,添加完了之后点击底部的绿色的Save&Test
3.1 导入监控模板
13105模板