吴波bruce_wu
2019-08-26
5004浏览量
随着小步快跑、快速迭代的开发模式被越来越多的企业认同和采用,应用的发布、升级频率变得越来越频繁。进入云原生时代后,越来越多的应用被容器化,如何方便地对容器类应用进行平稳的发布和升级受到了广泛关注。
使用 Kubernetes 的 RollingUpdate 可以方便地实现滚动发布,但这种方式只会检查 pod 本身的状态,缺乏对服务整体 SLA 的感知。一种更科学的方式是将发布与监控指标联动起来。当指标出现异常时,能及时地停止发布或进行回滚。本文将以运行在 kubernetes 中的微服务应用 podinfo 为例介绍如何实现发布与监控的联动。
现代系统中,我们面对的监控数据呈现出了爆炸性的增长趋势。从监控维度上看,包括宿主机、编排工具、容器、应用等。同时,每个维度又包含成百上千个可监控的指标。面对如此丰富的数据,如何及时地发现问题,如何快速地定位系统的性能瓶颈,变得越来越困难。本章介绍的 USE 方法和 RED 方法将为系统的可观测性提供良好的指导。
USE 方法以系统使用的资源作为观测对象,提出了一套快速定位系统性能瓶颈的方法论。对于每一类资源,它建议关注如下指标:
基于上述指标并结合 USE 提供的策略,我们能快速定位常见的性能问题。
RED 方法是 Weaveworks 的工程师基于 Google 的“四个黄金指标”并结合自己的实践经验,提出了一套适合于微服务场景的应用监控方法论。它从更上层、以更贴近终端用户的视角对系统进行观测。它为每个微服务定义了如下三个关键的度量指标:
上述指标能让我们清楚地感知微服务应用的运行状况,并能帮助衡量终端用户的体验问题。
RED 方法和 USE 方法包含了最基本、最有用的监控指标,帮助我们从两方面理解一个系统 - 工作负载的外部视图,以及系统资源对工作负载的反应。这些指标共同构成了系统可观测性的基础。
根据上一章的理论,这里将监控对象按逻辑划分成资源和应用两大类,下面分别介绍如何采集和计算它们的关键监控指标。
由于应用运行在容器中,这里重点关注容器级别的资源状况,包括 CPU、内存等。Kubelet 内置的 cAdvisor 采集了当前主机上容器级别的监控指标,结合 Prometheus 的服务发现功能可以轻松获取集群中所有容器的监控信息。下面以 CPU 和内存为例,介绍如何计算 USE 方法中提到的某些指标。
sum(
rate(
container_cpu_usage_seconds_total{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}[1m]
)
) /
sum(
container_spec_cpu_quota{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}/100000
)
sum(
container_cpu_load_average_10s{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}
) /
sum(
container_spec_cpu_quota{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}
)
sum(
rate(
container_memory_rss{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}[1m]
)
) /
sum(
container_spec_memory_limit_bytes{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}
)
rate(
container_memory_failures_total{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}[1m]
)
将 NGINX Ingress Controller 的开关controller.metrics.enabled
打开,便可以通过 Promtheus 轻松地获取服务请求相关的各类指标。
helm upgrade -i nginx-ingress stable/nginx-ingress \
--namespace ingress-nginx \
--set controller.stats.enabled=true \
--set controller.metrics.enabled=true
下面介绍如何计算 RED 方法中提到的三个关键指标。
sum(
rate(
nginx_ingress_controller_requests{
namespace="...",
ingress="podinfo"
}[1m]
)
)
sum(
rate(
nginx_ingress_controller_requests{
namespace="...",
ingress="podinfo",
status=~"5.*"
}[1m]
)
)
histogram_quantile(0.99,
sum(
rate(
nginx_ingress_controller_request_duration_seconds_bucket{
namespace="...",
ingress="podinfo"
}[1m]
)
) by (le)
)
监控指标准备好后,下一步就是如何利用这些指标来影响发布过程,实现更科学和安全的发布。
Flagger 是一款开源的,用于自动执行金丝雀发布、蓝绿发布、A/B 测试的工具。它实现了一个控制循环,利用 Istio、Linkerd、App Mesh、NGINX、Gloo 等产品的路由功能,调整发往不同版本间的流量。更重要的是,它能基于 Prometheus 中的监控指标进行金丝雀分析,并根据结果终止或继续金丝雀发布,实现了发布与监控指标的联动。
本文开头提到的微服务应用 podinfo 使用 NGINX Ingress Controller 作为流量入口,这里将介绍如何通过 Flagger 实现自动金丝雀发布。
Flagger 的安装非常简单,具体步骤可参考文档 Flagger Install on Kubernetes。Flagger 安装好后,需要为 podinfo 的金丝雀发布创建一个自定义资源对象 Canary,如下:
...
kind: Canary
spec:
provider: nginx
# deployment reference
targetRef:
apiVersion: apps/v1
kind: Deployment
name: podinfo
# ingress reference
ingressRef:
apiVersion: extensions/v1beta1
kind: Ingress
name: podinfo
# the maximum time in seconds for the canary deployment
# to make progress before it is rollback (default 600s)
progressDeadlineSeconds: 60
service:
# container port
port: 9898
canaryAnalysis:
# schedule interval (default 60s)
interval: 10s
# max number of failed metric checks before rollback
threshold: 10
# max traffic percentage routed to canary
# percentage (0-100)
maxWeight: 50
# canary increment step
# percentage (0-100)
stepWeight: 5
# NGINX Prometheus checks
metrics:
# Error
- name: request-success-rate
# minimum req success rate (non 5xx responses)
# percentage (0-100)
threshold: 99
interval: 1m
# Duration
- name: "latency"
threshold: 0.5
query: |
histogram_quantile(0.99,
sum(
rate(
http_request_duration_seconds_bucket{
kubernetes_namespace="test",
kubernetes_pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}[1m]
)
) by (le)
)
# CPU Utilization
- name: "cpu-utilization"
threshold: 0.8
query: |
sum(
rate(
container_cpu_usage_seconds_total{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}[1m]
)
) /
sum(
container_spec_cpu_quota{
container_name="podinfo",
pod_name=~"podinfo-[0-9a-zA-Z]+(-[0-9a-zA-Z]+)"
}/100000
)
...
其中,spec.canaryAnalysis
配置了金丝雀发布的具体策略,包括检查频率、失败阈值、增量步长等。这里需要重点关注spec.canaryAnalysis.metrics
部分,它指定了金丝雀分析引用的监控数据,这里包含了 RED 方法中的 Error、Duration,以及 USE 方法中的 CPU Utilization。
完成上述配置后,当我们更改下列对象便会触发金丝雀发布。
主要流程如下:
Ingress/podinfo-canary
、Service/podinfo-canary
、Deployment/podinfo
。Ingress/podinfo-canary
的metadata.annotations.nginx.ingress.kubernetes.io/canary
设置为 true,将metadata.annotations.nginx.ingress.kubernetes.io/canary-weight
的初始值设置为spec.canaryAnalysis.stepWeight
,让 NGINX Ingress Controller 将一部分流量转发至金丝雀版本。分析spec.canaryAnalysis.metrics
中指定的监控指标。
metadata.annotations.nginx.ingress.kubernetes.io/canary-weight
,让 NGINX Ingress Controller 将更多的流量发往金丝雀版本。spec.canaryAnalysis.threshold
,或者金丝雀发布时间超过了约定的时间spec.progressDeadlineSeconds
,则进行回滚。spec.canaryAnalysis.maxWeight
,同时各项指标均未达失败阈值,则对原版本进行升级。Ingress/podinfo-canary
的metadata.annotations.nginx.ingress.kubernetes.io/canary
设置为 false,同时将metadata.annotations.nginx.ingress.kubernetes.io/canary-weight
设置为 0,让 NGINX Ingress Controller 不再将流量发往金丝雀版本 。本文完整地介绍了 Kubernetes 应用发布与监控指标联动的实现方案。除了监控指标,日志也是反映系统运行状况的重要依据。后面我们将持续关注如何基于日志分析的结果来控制和影响发布过程。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
阿里云存储基于飞天盘古2.0分布式存储系统,产品多种多样,充分满足用户数据存储和迁移上云需求。