云原生应用监控与故障排除指南
1. 云托管 Kubernetes 服务的选择
在云环境中运行容器化应用时,有几个流行的托管 Kubernetes 服务可供选择,如 Amazon EKS、Microsoft 的 AKS 和 Google 的 GKE。选择这些托管服务的原因如下:
- 无需自行安装和管理 Kubernetes 集群,节省资源和精力。
- 可以专注于业务应用本身,而非 Kubernetes 的管理。
- 采用按需付费的成本模式,降低成本。
- 集群节点会自动进行补丁和更新,保障安全性。
- 轻松实现零停机升级 Kubernetes 版本。
此外,使用云提供商的容器注册表(如 Microsoft Azure 的 ACR)来托管容器镜像的原因有:
- 镜像与 Kubernetes 集群地理位置接近,减少延迟和网络传输成本。
- 生产环境的集群通常与互联网隔离,无法直接访问 Docker Hub。
2. 监控与故障排除概述
在 Kubernetes 集群上运行的应用需要有效的监控和故障排除手段。本章将介绍以下内容:
- 监控单个服务
- 使用 OpenTracing 进行分布式跟踪
- 利用 Prometheus 和 Grafana 监控分布式应用
- 基于关键指标定义警报
- 对生产环境中的服务进行故障排除
3. 技术要求
- 安装并正确配置 Docker Desktop 及其单节点 Kubernetes 集群。
-
使用 GitHub 上实验室仓库中
~/The-Ultimate-Docker-Container-Book/sample-solutions/ch19文件夹下的文件,链接为:https://github.com/PacktPublishing/The-Ultimate-Docker-Container-Book/tree/main/sample-solutions/ch19。
4. 监控单个服务
对于分布式、关键任务的应用,有效的监控至关重要。应用服务和基础设施需要“传感器”来收集重要数据,这些数据以指标的形式呈现,分为功能性指标和非功能性指标:
- 功能性指标:提供与业务相关的数据,如电商平台的每分钟结账率、音乐流媒体服务的 24 小时内最热门的五首歌曲。
- 非功能性指标:反映系统性能,如 Web 请求的平均延迟、4xx 状态码的数量、RAM 或 CPU 周期的资源使用情况。
在分布式系统中,需要一个集中式服务来聚合这些指标,就像飞机驾驶舱整合所有必要的读数一样。
5. 使用 OpenTracing 进行分布式跟踪
OpenTracing 是分布式跟踪的开放标准,提供了与供应商无关的 API 和分布式系统的工具。通过跟踪一个请求在分布式系统中的传播,可以了解每个服务处理请求的时间,识别系统中的瓶颈和问题服务。
5.1 Java 示例
以下是使用 Spring Boot 和 OpenTracing 的简单 Java 示例:
1. 导航到源代码文件夹:
$ cd ~/The-Ultimate-Docker-Container-Book
-
创建子文件夹
ch19并进入:
$ mkdir ch19 && cd ch19
- 访问 https://start.spring.io/ 创建 Spring Boot 应用。
- 选择 Gradle - Groovy 作为项目,Java 作为语言,保留其他默认设置。
-
创建应用并下载 ZIP 文件,解压到
ch19/java子文件夹。 -
修改
build.gradle文件。 -
修改
DemoApplication.java文件。 -
运行应用,点击
DemoApplication类的main方法的运行(或调试)链接。 -
在终端中使用
curl访问http://localhost:8080端点,响应应为Hello, World!。 - 观察 VS Code 终端窗口的输出,会看到一个 span 已创建并报告。
5.2 Node.js 服务的仪器化
以下是对 Node.js 微服务进行仪器化的步骤:
1. 导航到源代码文件夹:
$ cd ~/The-Ultimate-Docker-Container-Book/ch19
-
创建新文件夹
node并进入:
$ mkdir node && cd node
-
运行
npm init,除入口点从index.js改为server.js外,接受所有默认设置。 -
添加
express到项目:
$ npm install --save express
- 安装 Prometheus 适配器:
$ npm install --save prom-client
-
在文件夹中添加
server.js文件,内容如下:
const app = require("express")();
app.get('/hello', (req, res) => {
const { name = 'World' } = req.query;
res.json({ message: `Hello, ${name}!` });
});
app.listen(port=3000, () => {
console.log('Example api is listening on http://localhost:3000');
});
- 在上述代码的第 1 行后添加以下代码初始化 Prometheus 客户端:
const client = require("prom-client");
const register = client.register;
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({ register });
-
在
/hello端点定义后添加一个端点来暴露指标:
app.get('/metrics', (req, res) => {
res.set('Content-Type', register.contentType);
res.end(register.metrics());
});
- 运行示例微服务:
$ npm start
-
访问
/metrics端点:
$ curl localhost:3000/metrics
5.3 自定义指标
可以定义自定义计数器来统计
/hello
请求的数量:
1. 在
server.js
中添加以下代码定义自定义计数器:
const helloCounter = new client.Counter({
name: 'my_hello_counter',
help: 'Counts the number of hello requests',
});
-
修改
/hello端点的代码:
app.get('/hello', (req, res) => {
helloCounter.inc();
const name = req.query.name || 'World';
res.json({ message: `Hello, ${name}!` });
});
- 重新运行应用:
$ npm start
-
访问
/hello端点两次:
$ curl localhost:3000/hello?name=Sue
$ curl localhost:3000/hello?name=Marc
-
访问
/metrics端点,会看到自定义计数器的输出:
# HELP my_hello_counter Counts the number of hello requests
# TYPE my_hello_counter counter
my_hello_counter 2
6. .NET 服务的仪器化
以下是创建基于 Web API 模板的简单 .NET 微服务并进行仪器化的步骤:
1. 导航到源代码文件夹:
$ cd ~/The-Ultimate-Docker-Container-Book/ch19
-
创建新文件夹
dotnet并进入:
$ mkdir dotnet && cd dotnet
-
使用
dotnet工具创建新的微服务sample-api:
$ dotnet new webapi --output sample-api
-
添加
prometheus-net.AspNetCoreNuGet 包:
$ dotnet add sample-api package prometheus-net.AspNetCore
- 在喜欢的代码编辑器中打开项目,如使用 VS Code:
$ code .
-
打开
Program.cs文件,在文件开头添加using Prometheus;。 -
在
app.MapControllers()命令后添加app.MapMetrics()命令:
app.UseAuthorization();
app.MapControllers();
app.MapMetrics();
app.Run();
- 启动应用:
$ dotnet run --project sample-api
-
使用
curl访问服务的/metrics端点:
$ curl http://localhost:5204/metrics
6.1 自定义功能性指标
假设要测量对
/weatherforecast
端点的并发访问数量,可以定义一个 gauge 指标:
1. 定位到
Controllers
文件夹中的
WeatherForecastController.cs
类。
2. 在文件顶部添加
using Prometheus;
。
3. 在
WeatherForecastController
类中定义一个
Gauge
类型的私有实例变量:
private static readonly Gauge callsInProgress = Metrics
.CreateGauge("myapp_calls_in_progress",
"Number of weather forecast operations ongoing.");
-
使用
using语句包装Get方法的逻辑:
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
using(callsInProgress.TrackInProgress())
{
// code of the Get method
}
}
- 重启微服务。
-
使用
curl多次调用/weatherforecast端点:
$ curl http://localhost:5204/weatherforecast
-
使用
curl获取指标:
$ curl http://localhost:5204/metrics
会看到新的指标
myapp_weather_forecasts_in_progress
,当前值为 0,因为没有正在进行的请求。
7. Prometheus 支持的指标类型
Prometheus 支持四种类型的指标:
| 指标类型 | 描述 |
| ---- | ---- |
| Counter | 累积指标,值只能增加或在重启时重置为零。 |
| Gauge | 表示单个数值,可以任意上下波动,常用于测量温度、内存使用等。 |
| Histogram | 对观察值进行采样,统计到可配置的桶中,并提供所有观察值的总和。 |
| Summary | 与 Histogram 类似,但会在滑动时间窗口内计算可配置的分位数。 |
通过以上步骤,我们可以对不同语言编写的应用服务进行仪器化,使其暴露重要指标。接下来,将介绍如何使用 Prometheus 收集和聚合这些指标,以及如何使用 Grafana 监控分布式应用。
graph LR
A[应用服务] --> B[Prometheus]
B --> C[Grafana]
B --> D[指标存储]
C --> E[仪表盘展示]
这个流程图展示了应用服务的指标如何被 Prometheus 收集和存储,然后通过 Grafana 在仪表盘上展示。
云原生应用监控与故障排除指南
8. 利用 Prometheus 和 Grafana 监控分布式应用
在学会如何对应用服务进行仪器化以暴露 Prometheus 指标后,接下来要展示如何收集这些指标并将其转发到 Prometheus 服务器进行聚合和存储。之后,可以使用 Prometheus 的简单 Web UI 或更强大的 Grafana 来在仪表盘上展示重要指标。
与大多数用于从应用服务和基础设施组件收集指标的工具不同,Prometheus 服务器会主动定期抓取所有定义的目标,这种方式被称为拉取指标,而非推送指标,这使得 Prometheus 非常适合我们的场景。
以下将讨论如何将 Prometheus 部署到 Kubernetes,同时部署两个示例应用服务,最后将 Grafana 部署到集群并使用它在仪表盘上展示自定义指标。
8.1 部署 Prometheus 到 Kubernetes
部署 Prometheus 到 Kubernetes 可以按照以下步骤进行:
1.
创建配置文件
:首先需要创建一个 Prometheus 的配置文件
prometheus.yml
,用于定义要抓取的目标等信息。示例配置如下:
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'my_app'
static_configs:
- targets: ['my-app-service:8080']
- 创建 Kubernetes 资源 :使用 Kubernetes 的 YAML 文件创建 Prometheus 的 Deployment、Service 等资源。示例如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus
spec:
replicas: 1
selector:
matchLabels:
app: prometheus
template:
metadata:
labels:
app: prometheus
spec:
containers:
- name: prometheus
image: prom/prometheus
args:
- "--config.file=/etc/prometheus/prometheus.yml"
ports:
- containerPort: 9090
volumeMounts:
- name: config-volume
mountPath: /etc/prometheus
volumes:
- name: config-volume
configMap:
name: prometheus-config
---
apiVersion: v1
kind: Service
metadata:
name: prometheus-service
spec:
selector:
app: prometheus
ports:
- protocol: TCP
port: 9090
targetPort: 9090
-
应用配置
:使用
kubectl命令将配置应用到 Kubernetes 集群:
kubectl apply -f prometheus-config.yaml
kubectl apply -f prometheus-deployment.yaml
8.2 部署示例应用服务
假设我们有两个示例应用服务
my-app-1
和
my-app-2
,它们已经进行了仪器化并暴露了
/metrics
端点。可以使用以下步骤部署它们:
1.
创建 Deployment 和 Service
:为每个应用服务创建 Deployment 和 Service 的 YAML 文件。以
my-app-1
为例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-1
spec:
replicas: 1
selector:
matchLabels:
app: my-app-1
template:
metadata:
labels:
app: my-app-1
spec:
containers:
- name: my-app-1
image: my-app-1-image
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: my-app-1-service
spec:
selector:
app: my-app-1
ports:
- protocol: TCP
port: 8080
targetPort: 8080
-
应用配置
:使用
kubectl命令将配置应用到 Kubernetes 集群:
kubectl apply -f my-app-1-deployment.yaml
kubectl apply -f my-app-2-deployment.yaml
8.3 部署 Grafana 到集群
部署 Grafana 到 Kubernetes 可以按照以下步骤进行:
1.
创建配置文件
:创建 Grafana 的配置文件
grafana.ini
等,用于配置 Grafana 的基本设置。
2.
创建 Kubernetes 资源
:使用 Kubernetes 的 YAML 文件创建 Grafana 的 Deployment、Service 等资源。示例如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: grafana
spec:
replicas: 1
selector:
matchLabels:
app: grafana
template:
metadata:
labels:
app: grafana
spec:
containers:
- name: grafana
image: grafana/grafana
ports:
- containerPort: 3000
volumeMounts:
- name: config-volume
mountPath: /etc/grafana
volumes:
- name: config-volume
configMap:
name: grafana-config
---
apiVersion: v1
kind: Service
metadata:
name: grafana-service
spec:
selector:
app: grafana
ports:
- protocol: TCP
port: 3000
targetPort: 3000
-
应用配置
:使用
kubectl命令将配置应用到 Kubernetes 集群:
kubectl apply -f grafana-config.yaml
kubectl apply -f grafana-deployment.yaml
8.4 配置 Grafana 展示指标
在 Grafana 部署完成后,可以按照以下步骤配置它以展示 Prometheus 的指标:
1.
访问 Grafana
:通过浏览器访问 Grafana 的服务地址(例如
http://grafana-service:3000
),使用默认用户名和密码(通常为
admin/admin
)登录。
2.
添加数据源
:在 Grafana 中添加 Prometheus 作为数据源,配置 Prometheus 的服务地址(例如
http://prometheus-service:9090
)。
3.
创建仪表盘
:在 Grafana 中创建仪表盘,添加面板并选择要展示的指标,通过编写 PromQL 查询语句来获取所需的指标数据。例如,要展示
my_hello_counter
指标,可以编写如下查询语句:
my_hello_counter
9. 基于关键指标定义警报
在监控应用时,基于关键指标定义警报是非常重要的。可以使用 Prometheus 的 Alertmanager 来实现警报功能。以下是定义警报的步骤:
9.1 配置 Alertmanager
-
创建配置文件
:创建 Alertmanager 的配置文件
alertmanager.yml,用于定义警报的接收者、路由规则等。示例配置如下:
global:
resolve_timeout: 5m
route:
group_by: ['alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 12h
receiver: 'email'
receivers:
- name: 'email'
email_configs:
- to: 'your-email@example.com'
- 创建 Kubernetes 资源 :使用 Kubernetes 的 YAML 文件创建 Alertmanager 的 Deployment、Service 等资源。
-
应用配置
:使用
kubectl命令将配置应用到 Kubernetes 集群。
9.2 定义警报规则
在 Prometheus 的配置文件中定义警报规则。例如,当
my_hello_counter
指标在 5 分钟内的增长超过 100 时触发警报:
groups:
- name: my-alerts
rules:
- alert: HighHelloRequests
expr: increase(my_hello_counter[5m]) > 100
for: 1m
labels:
severity: critical
annotations:
summary: "High number of hello requests"
description: "The number of hello requests has increased by more than 100 in the last 5 minutes."
10. 生产环境中服务的故障排除
当生产环境中的服务出现问题时,需要进行故障排除。可以使用一个特殊的工具容器来进行故障排除,以下是具体步骤:
1.
创建工具容器
:创建一个包含常用故障排除工具(如
curl
、
ping
、
telnet
等)的容器镜像。
2.
部署工具容器到集群
:使用 Kubernetes 的 YAML 文件将工具容器部署到集群中。
3.
进入工具容器
:使用
kubectl exec
命令进入工具容器:
kubectl exec -it tool-container -n my-namespace -- /bin/bash
- 进行故障排除 :在工具容器中使用各种工具对服务进行故障排除,例如检查服务的网络连接、访问服务的端点等。
graph LR
A[应用服务] --> B[Prometheus]
B --> C[Alertmanager]
C --> D[通知接收者]
B --> E[Grafana]
E --> F[仪表盘展示]
这个流程图展示了应用服务的指标被 Prometheus 收集后,通过 Alertmanager 触发警报通知接收者,同时通过 Grafana 在仪表盘上展示指标的过程。
通过以上步骤,我们可以实现对分布式应用的有效监控和故障排除,确保应用在生产环境中的稳定运行。
超级会员免费看
862

被折叠的 条评论
为什么被折叠?



