本文发表于一年多前。旧文章可能包含过时内容。请检查页面中的信息自发布以来是否已变得不正确。

为人类注解 Kubernetes 服务

您是否曾被要求排查出现故障的 Kubernetes 服务,却难以找到有关该服务的基本信息,例如源仓库和所有者?

随着 Kubernetes 应用程序的增长,其中一个问题是服务的泛滥。随着服务数量的增加,开发人员开始专注于处理特定服务。然而,在故障排除时,开发人员需要能够找到任何服务的来源、理解服务及其依赖项,并与拥有团队进行沟通。

人工服务发现

故障排除总是从信息收集开始。虽然人们对集中机器数据(例如日志、指标)给予了大量关注,但对服务发现的人工方面却关注甚少。谁拥有特定的服务?团队在哪个 Slack 频道上工作?服务的来源在哪里?目前已知并正在跟踪哪些问题?

Kubernetes 注解

Kubernetes 注解正是为解决这个问题而设计的。Kubernetes 注解经常被忽视,但它旨在为 Kubernetes 对象添加元数据。Kubernetes 文档指出,注解可以“将任意非标识性元数据附加到对象”。这意味着注解应该用于附加 Kubernetes 外部的元数据(即 Kubernetes 不会用于识别对象的元数据)。因此,注解可以包含任何类型的数据。这与标签形成对比,标签是为 Kubernetes 内部使用而设计的。因此,标签的结构和值受到约束,以便 Kubernetes 可以高效地使用它们。

Kubernetes 注解的实际应用

这里有一个例子。假设您有一个用于报价的 Kubernetes 服务,称为报价服务。您可以执行以下操作:

kubectl annotate service quote a8r.io/owner=”@sally”

在这个例子中,我们添加了一个名为 `a8r.io/owner` 的注解,其值为 `@sally`。现在,我们可以使用 `kubectl describe` 来获取信息。

Name:              quote
Namespace:         default
Labels:            <none>
Annotations:       a8r.io/owner: @sally
Selector:          app=quote
Type:              ClusterIP
IP:                10.109.142.131
Port:              http  80/TCP
TargetPort:        8080/TCP
Endpoints:         <none>
Session Affinity:  None
Events:            <none>

如果您正在实践 GitOps(您应该这样做!),您会希望将这些值直接编码到您的 Kubernetes 清单中,例如:

apiVersion: v1
kind: Service
metadata:
  name: quote
  annotations:
    a8r.io/owner: “@sally”
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: quote

注解的约定

采用通用的注解约定可确保一致性和可理解性。通常,您会将注解附加到服务对象,因为服务是与团队职责最清晰对应的高级资源。对注解进行命名空间划分也非常重要。以下是一组约定,记录在a8r.io,并转载如下

人类可读服务的注解约定
注解描述
a8r.io/description服务的非结构化文本描述,供人类阅读。
a8r.io/ownerSSO 用户名(GitHub)、电子邮件地址(链接到 GitHub 帐户)或非结构化所有者描述。
a8r.io/chatSlack 频道或外部聊天系统链接。
a8r.io/bugs外部错误跟踪器链接。
a8r.io/logs外部日志查看器链接。
a8r.io/documentation外部项目文档链接。
a8r.io/repository外部 VCS 仓库链接。
a8r.io/support外部支持中心链接。
a8r.io/runbook外部项目运行手册链接。
a8r.io/incidents外部事件仪表板链接。
a8r.io/uptime外部运行时间仪表板链接。
a8r.io/performance外部性能仪表板链接。
a8r.io/dependencies服务的非结构化文本描述,供人类阅读。

注解可视化:服务目录

随着微服务和注解数量的激增,运行 `kubectl describe` 可能会变得繁琐。此外,使用 `kubectl describe` 要求每个开发人员都能够直接访问 Kubernetes 集群。在过去几年中,服务目录在 Kubernetes 生态系统中获得了更高的可见性。通过 Shopify 的 ServicesDBSpotify 的 System Z 等工具的推广,服务目录成为了面向内部的开发者门户,提供了有关微服务的关键信息。

请注意,这些服务目录不应与Kubernetes 服务目录项目混淆。Kubernetes 服务目录基于开放服务代理 API 构建,使 Kubernetes 运营商能够将不同的服务(例如数据库)连接到其集群。

现在就为你的服务添加注解,以后你会感谢自己的

就像在微服务系统中实现可观测性一样,你常常直到为时已晚才意识到自己需要人工服务发现。不要等到生产环境中出现问题才开始希望自己能够实现更好的度量,并记录下如何联系负责该部分的组织。

构建一个有效的“版本 0”服务具有巨大的优势:一个跳舞的骨架应用程序,具有一小部分完整的功能,可以通过最小但有效的持续交付管道部署到生产环境。

添加服务注解应该成为所有服务的“版本 0”的重要组成部分。现在就添加它们,以后你会感谢自己的。