作者:David LoriteSolanas
译者:littlefish
原文链接:https://sysdig.com/blog/monitor-etcd/?utm_sq=ghrnv67yh1
产品中使用了Kubernetes,了解如何监控etcd就变得很重要了。监控etcd会帮助你判断服务运行是否符合预期,探测并解决有可能导致整个架构宕掉的故障。接下来,你将读到如何从etcd中收集重要数据指标并通过这些指标监控服务。
Etcd是Kubernetes控制平面的一个基础组件,它存储了集群需要的状态(包括pods,secrets,deployment等)以及其他信息。如果这个服务不在运行状态,你将不能继续部署任何应用,集群也不可自愈。
了解什么是etcd,在检查和解决可能会让整个应用宕掉的故障,它竟如此重要!
1
Etcd是什么?
Etcd是一个分布式的、键值、动态数据库,这个数据库维护了配置注册表,而注册表是Kubernetesjiqun 服务目录、对等发现、集中配置管理的基础之一。它类似于一个到Redis 数据库,传统LDAP配置后端,甚至windows注册表。
开发者创造etcd的目的是:
- 简单:已定义的,面向用户的API(JSON 和qRPC)
- 安全:支持可选择的客户端证书身份认证的自动协商TLS协议
- 效率:每秒支持10000写入为基准
- 可靠:合理分布使用Raft
Kubernetes 使用etcd 分部署数据库来存储Rest API对象(在/registry路径下的键值):pods,secrets,daemonsets,deployments,namespaces,events等。
Raft是一种“一致”算法,一种在分布式和容错机制的集群节点上获取收敛值的方法。
无需深究细节(这些细节你将在参考文章中读到),这里列出一些你需要知道的基础情况:
- 节点可能有三种身份:跟随节点(follower),候选节点(candidate),领导节点(leader)
- 如果跟随节点不能联系到当前的领导节点,他会成为候选节点
- 选举系统会在多个选举节点中选举出新的领导节点
- 注册表值总是通过领导节点更新(提交)
- 一旦领导节点收到大多数跟随节点的确认消息,这个值则被认为是“提交”
- 集群将伴随大多数节点的活动而存在
- etcd最显著的特征,也许是使用像HTTP请求的REST接入到服务这种最直接的方式。它采用尽可能简单的方式集成第三方应用,利用主-主协议自动选举集群领导节点,并为这种角色切换工作提供一个反馈机制。
2
Etcd集群常见的故障点
大多情况下,etcd集群平稳运行,以至于你很容易忘记这些节点还在跑着。然而,记住Kubernetes一定需要注册表才可以工作,etcd的一个关键故障,将会严重影响使用甚至导致你的容器结构损毁宕机。当下正在运行的Pods将持续运行,但是你不能进行其他更多的操作。当只有再次连接etcd和Kubernetes,状态不一致将会导致额外故障。
3
如何监控etcd?
你可以在kubernetes上,在Docker 容器上,或者作为独立集群(部署在VM或裸金属之上)运行etcd。通常情况下,对于简单的场景,etcd被部署在docker 容器中,像其他kubernetes服务一样,如API服务器、控制管理、调度或Kubelet。在更高级场景中,etcd常是一个外部服务;在这些案例中,通常会使用三个或三个以上的节点做冗余。
在etcd上获取监控指标
默认情况下,Etcd 是被监控的,通过master节点的4001端口对外暴露Prometheus指标,以提供存储信息。对端将容易获取到有用的信息,而无需额外的脚本或导出步骤。
直接通过节点上的端口获取etcd指标,需要身份认证。Etcd是所有kubernetes集群的核心,所以它的指标也很保护的。你需要接入到4001端口或者登录在master节点上,且提供客户端证书,才可以获取这些指标。如果已经登录到master节点,则执行一个带有客户端证书路径的curl命令;证书和秘钥位置分别为:/etc/kubrnetes/pki/etcd-manager-main/etcd-clients-ca.crt和/etc/kubrnetes/pki/etcd-manager-main/etcd-clients-ca.key。
代码语言:javascript复制curl https://localhost:4001/metrics -k --cert/etc/kubernetes/pki/etcd-manager-main/etcd-clients-ca.crt --key/etc/kubernetes/pki/etcd-manager-main/etcd-clients-ca.key
如果你想从外部连接到master节点,请确保已从master节点获取了证书,并且保证4001是打开状态,那么可以通过IP访问。
代码语言:javascript复制curl https://[master_ip]:4001/metrics -k --cert/etc/kubernetes/pki/etcd-manager-main/etcd-clients-ca.crt --key/etc/kubernetes/pki/etcd-manager-main/etcd-clients-ca.key
命令返回结果是包含了如下结构的长列表指标(截取部分):
代码语言:javascript复制# HELP etcd_disk_backend_snapshot_duration_seconds The latencydistribution of backend snapshots.
# TYPE etcd_disk_backend_snapshot_duration_seconds histogram
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.01"} 0
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.02"} 0
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.04"} 0
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.08"} 0
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.16"} 0
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.32"}3286
etcd_disk_backend_snapshot_duration_seconds_bucket{le="0.64"}4617
etcd_disk_backend_snapshot_duration_seconds_bucket{le="1.28"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="2.56"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="5.12"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="10.24"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="20.48"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="40.96"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="81.92"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="163.84"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="327.68"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le="655.36"}4620
etcd_disk_backend_snapshot_duration_seconds_bucket{le=" Inf"}4620
etcd_disk_backend_snapshot_duration_seconds_sum 1397.2374600930025
etcd_disk_backend_snapshot_duration_seconds_count 4620
# HELP etcd_disk_wal_fsync_duration_seconds The latency distributions offsync called by wal.
# TYPE etcd_disk_wal_fsync_duration_seconds histogram
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.001"}4.659349e 06
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.002"}7.276276e 06
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.004"}8.589085e 06
如果你想配置prometheus来获取etcd,你必须挂载证书并创建一个工作项。
证书位于master节点的以下路径:/etc/kubrnetes/pki/etcd-manager-main/etcd-clients-ca.key和/etc/kubrnetes/pki/etcd-manager-main/etcd-clients-ca.crt。只需要下载这些证书,使用以下命令创建秘钥文件。
免责声明:etcd是任何kubeternetes集群的核心,如果不注意证书,你可能暴露整个集群成为别人的攻击目标。
代码语言:javascript复制kubectl -n monitoring create secret generic etcd-ca--from-file=etcd-clients-ca.key --from-file etcd-clients-ca.crt
代码语言:javascript复制kubectl -n monitoring patch deployment prometheus-server -p'{"spec":{"template":{"spec":{"volumes":[{"name":"etcd-ca","secret":{"defaultMode":420,"secretName":"etcd-ca"}}]}}}}'
kubectl -n monitoring patch deployment prometheus-server -p'{"spec":{"template":{"spec":{"containers":[{"name":"prometheus-server","volumeMounts":[{"mountPath": "/opt/prometheus/secrets","name":"etcd-ca"}]}]}}}}'
代码语言:javascript复制scrape_configs:
...
- job_name: etcd
scheme: https
kubernetes_sd_configs:
- role: pod
relabel_configs:
- action: keep
source_labels:
-__meta_kubernetes_namespace
- __meta_kubernetes_pod_name
separator: '/'
regex:'kube-system/etcd-manager-main. '
- source_labels:
- __address__
action: replace
target_label: __address__
regex: (. ?)(\:\d)?
replacement: $1:4001
tls_config:
insecure_skip_verify: true
cert_file:/opt/prometheus/secrets/etcd-clients-ca.crt
key_file:/opt/prometheus/secrets/etcd-clients-ca.key
你需要进行labels客户化,或重新配置标签。
监控etcd:应该关注什么?
免责声明:etcd指标可能会因为kubernetes的版本不同而有所区别。在这里,我们使用kubernetes的版本是1.15。你可以点击 Kubernetes repo(该链接指向v1.15.3),检查一下指标在您的版本上是否可用。
etcd 节点可用性:对于一个集群,一类明显的错误情况是:你丢掉了其中一个节点。集群可以继续操作,可以收到告警,通过诊断在其他节点继续失陷甚至面临全部服务故障的风险前恢复,但它可能是一个比较好的建议了。最简单的方式是通过PromSQL检查:
代码语言:javascript复制sum(up{job="etcd"}
它会给出运行节点的数量,如一些节点已down掉,你可以发现它;最糟糕的情况可能是运行节点数量为0,你将会知道这有问题。
Etcd集群有一个领导节点。所有节点是否有同一个leader,这是一个重要指标。如果一个节点没有leader,这个节点将是不可用的。如果所有节点都没有leader,那么集群将变得完全不可用。通过下面的检查,可以检查出节点是否有leader。
代码语言:javascript复制# HELP etcd_server_has_leader Whether or not a leader exists. 1 isexistence, 0 is not.
# TYPE etcd_server_has_leader gauge
etcd_server_has_leader 1
Etcd 的leader角色变化。随时间向前,Leader也会变化,但是过于频繁的变化可能影响etcd本身的性能。这可能是一个信号:由于连接问题leader变得不稳定,或者etcd 负载过重。
代码语言:javascript复制# HELP etcd_server_leader_changes_seen_total The number of leader changesseen.
# TYPE etcd_server_leader_changes_seen_total counter
etcd_server_leader_changes_seen_total 1
Consensusproposal一致建议:一个方案是一个通过raft协议的请求(比如:一个写请求,一个配置变更请求)。这个方案的指标有四个不同类型:committed、applied、pending和failed。以上四种可以提供etcd可能面临的问题的信息,其中最重要的是failed这个状态,如果是failed,则可能有两个原因:或是leader选举失败,或者失去法定节点数。
例如,我们想要设置一个告警去展示:在一个15min周期之内多于5次一直方案失败,则可使用以下描述:
代码语言:javascript复制rate(etcd_server_proposals_failed_total{job=~"etcd"}[15m]) >5
代码语言:javascript复制# HELP etcd_server_proposals_applied_total The total number of consensusproposals applied.
# TYPE etcd_server_proposals_applied_total gauge
etcd_server_proposals_applied_total 1.3605153e 07
# HELP etcd_server_proposals_committed_total The total number of consensusproposals committed.
# TYPE etcd_server_proposals_committed_total gauge
etcd_server_proposals_committed_total 1.3605153e 07
# HELP etcd_server_proposals_failed_total The total number of failedproposals seen.
# TYPE etcd_server_proposals_failed_total counter
etcd_server_proposals_failed_total 0
# HELP etcd_server_proposals_pending The current number of pendingproposals to commit.
# TYPE etcd_server_proposals_pending gauge
etcd_server_proposals_pending 0
磁盘同步周期:随着etcd存储kubernetes所有重要的信息,如果etcd正在运行妥当,向磁盘提交数据的速度和存储的健康度是重要指标。如果磁盘同步有比较高的延迟,那么磁盘可能有问题或者集群变得不可用。可以显示这些指标的是:wal_fsync_duration_seconds和backend_commit_duration_seconds.
代码语言:javascript复制# HELP etcd_disk_backend_commit_duration_seconds The latency distributionsof commit called by backend.
# TYPE etcd_disk_backend_commit_duration_seconds histogram
etcd_disk_backend_commit_duration_seconds_bucket{le="0.001"} 0
etcd_disk_backend_commit_duration_seconds_bucket{le="0.002"}5.402102e 06
etcd_disk_backend_commit_duration_seconds_bucket{le="0.004"}6.0471e 06
...
etcd_disk_backend_commit_duration_seconds_sum 11017.523900176226
etcd_disk_backend_commit_duration_seconds_count 6.157407e 06
# HELP etcd_disk_wal_fsync_duration_seconds The latency distributions offsync called by wal.
# TYPE etcd_disk_wal_fsync_duration_seconds histogram
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.001"}4.659349e 06
etcd_disk_wal_fsync_duration_seconds_bucket{le="0.002"}7.276276e 06
...
etcd_disk_wal_fsync_duration_seconds_sum 11580.35429902582
etcd_disk_wal_fsync_duration_seconds_count 8.786736e 06
后端提交数据期间性能是否足够可以通过观察一个历史周期是否足够来判断。通过下面的命令,你可以观察到99%请求的时延情况。
代码语言:javascript复制histogram_quantile(0.99,rate(etcd_disk_backend_commit_duration_seconds_bucket{job=~"etcd"}[5m]))
在sysdig下监控etcd指标
为了在SysdigMonitor中跟踪etcd,你必须在agent的YAML配置文件中添加一些内容,使用Prometheus收集指标数据并做一些过滤。你也可以不做这些,但是你将保存一系列debug指标。所以首先你应运行一个Prometheus,但是如果不这样做也无需担心。部署一个Prometheus像执行两条命令一样简单,首先为promethus创建一个namespace,第二步是使用helm3做部署。
代码语言:javascript复制kubectl create ns monitoring
helm install -f values.yaml prometheus -n monitoring stable/prometheus
以下是value.yaml文件:
代码语言:javascript复制server:
strategy:
type: Recreate
podAnnotations:
prometheus.io/scrape:"true"
prometheus.io/port:"9090"
一旦prometheus启动运行,你必须创建规则。这些规则创建新的指标,这些指标带有客户化的标记,它可以通过sysfdig agent过滤掉指标。你可以在PromCat.io上查找规则和在Sysdig上操作需要遵循的所有步骤。下面是一个配置示例。
代码语言:javascript复制apiVersion: v1
kind: ConfigMap
metadata:
name: sysdig-agent
namespace: sysdig-agent
data:
prometheus.yaml: |-
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus' #config for federation
honor_labels: true
metrics_path: '/federate'
metric_relabel_configs:
- regex: 'kubernetes_pod_name'
action: labeldrop
params:
'match[]':
-'{sysdig="true"}'
sysdig_sd_configs:
- tags:
namespace: monitoring
deployment:prometheus-server
4
结论
Etcd是一个简单而强大,且在部署kubernetes 集群时必需的服务。即使Raft分布式收敛算法能够避免大多临时网络故障,节点丢失,集群分裂等故障,如果产品正运行kubernetes,仍然需要在以上集群事件发生前监控etcd并设置告警。
当然,如果你深挖etcd的错误码,有更多高级的案例是本篇短文无法覆盖到的:集群对等方的最大数量,kubernetes和etcd节点间的异常检测,raft内部错误,注册表大小等。我们将其单独分开,安排在后面第二部分中。
利用sysdig montitor监控etcd相对容易,一个工具既监控了etcd又监控了kubernetes。Sysdig monitor agent 收集所有etcd指标,从而快速设置最重要的etcd告警。