43、云原生应用监控与故障排除指南

云原生应用监控与故障排除指南

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
  1. 创建子文件夹 ch19 并进入:
$ mkdir ch19 && cd ch19
  1. 访问 https://start.spring.io/ 创建 Spring Boot 应用。
  2. 选择 Gradle - Groovy 作为项目,Java 作为语言,保留其他默认设置。
  3. 创建应用并下载 ZIP 文件,解压到 ch19/java 子文件夹。
  4. 修改 build.gradle 文件。
  5. 修改 DemoApplication.java 文件。
  6. 运行应用,点击 DemoApplication 类的 main 方法的运行(或调试)链接。
  7. 在终端中使用 curl 访问 http://localhost:8080 端点,响应应为 Hello, World!
  8. 观察 VS Code 终端窗口的输出,会看到一个 span 已创建并报告。
5.2 Node.js 服务的仪器化

以下是对 Node.js 微服务进行仪器化的步骤:
1. 导航到源代码文件夹:

$ cd ~/The-Ultimate-Docker-Container-Book/ch19
  1. 创建新文件夹 node 并进入:
$ mkdir node && cd node
  1. 运行 npm init ,除入口点从 index.js 改为 server.js 外,接受所有默认设置。
  2. 添加 express 到项目:
$ npm install --save express
  1. 安装 Prometheus 适配器:
$ npm install --save prom-client
  1. 在文件夹中添加 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. 在上述代码的第 1 行后添加以下代码初始化 Prometheus 客户端:
const client = require("prom-client");
const register = client.register;
const collectDefaultMetrics = client.collectDefaultMetrics;
collectDefaultMetrics({ register });
  1. /hello 端点定义后添加一个端点来暴露指标:
app.get('/metrics', (req, res) => {
    res.set('Content-Type', register.contentType);
    res.end(register.metrics());
});
  1. 运行示例微服务:
$ npm start
  1. 访问 /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',
});
  1. 修改 /hello 端点的代码:
app.get('/hello', (req, res) => {
    helloCounter.inc();
    const name = req.query.name || 'World';
    res.json({ message: `Hello, ${name}!` });
});
  1. 重新运行应用:
$ npm start
  1. 访问 /hello 端点两次:
$ curl localhost:3000/hello?name=Sue
$ curl localhost:3000/hello?name=Marc
  1. 访问 /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
  1. 创建新文件夹 dotnet 并进入:
$ mkdir dotnet && cd dotnet
  1. 使用 dotnet 工具创建新的微服务 sample-api
$ dotnet new webapi --output sample-api
  1. 添加 prometheus-net.AspNetCore NuGet 包:
$ dotnet add sample-api package prometheus-net.AspNetCore
  1. 在喜欢的代码编辑器中打开项目,如使用 VS Code:
$ code .
  1. 打开 Program.cs 文件,在文件开头添加 using Prometheus;
  2. app.MapControllers() 命令后添加 app.MapMetrics() 命令:
app.UseAuthorization();
app.MapControllers();
app.MapMetrics();
app.Run();
  1. 启动应用:
$ dotnet run --project sample-api
  1. 使用 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.");
  1. 使用 using 语句包装 Get 方法的逻辑:
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
    using(callsInProgress.TrackInProgress())
    {
        // code of the Get method
    }
}
  1. 重启微服务。
  2. 使用 curl 多次调用 /weatherforecast 端点:
$ curl http://localhost:5204/weatherforecast
  1. 使用 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']
  1. 创建 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
  1. 应用配置 :使用 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
  1. 应用配置 :使用 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
  1. 应用配置 :使用 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
  1. 创建配置文件 :创建 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'
  1. 创建 Kubernetes 资源 :使用 Kubernetes 的 YAML 文件创建 Alertmanager 的 Deployment、Service 等资源。
  2. 应用配置 :使用 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
  1. 进行故障排除 :在工具容器中使用各种工具对服务进行故障排除,例如检查服务的网络连接、访问服务的端点等。
graph LR
    A[应用服务] --> B[Prometheus]
    B --> C[Alertmanager]
    C --> D[通知接收者]
    B --> E[Grafana]
    E --> F[仪表盘展示]

这个流程图展示了应用服务的指标被 Prometheus 收集后,通过 Alertmanager 触发警报通知接收者,同时通过 Grafana 在仪表盘上展示指标的过程。

通过以上步骤,我们可以实现对分布式应用的有效监控和故障排除,确保应用在生产环境中的稳定运行。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值