kubernetes API Server 看这篇试试(2)

简介: kubernetes API Server 看这篇试试(2)

8. 访问 API Server

有多种方式可以访问 Kubernetes 提供的 REST API:

其他 OpenAPI 支持的语言,可以通过 gen 工具生成相应的 client

8.1 kubectl

kubectl get --raw /api/v1/namespaces
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes
kubectl get --raw /apis/metrics.k8s.io/v1beta1/pods

8.2 kubectl proxy

当然,为了能够向 API 发出请求,有必要了解客户端可以使用哪些 API 对象。此过程通过客户端的 API 发现进行。要查看此过程的实际效果并以更实际的方式探索 API Server,我们可以自己执行此 API 发现。

首先,为了简化事情,我们使用kubectl命令行工具的内置proxy来为我们的集群提供身份验证

$ kubectl proxy --port=8080 &
$ curl http://localhost:8080/api/
{
  "versions": [
    "v1"
  ]
}

或者

kubectl proxy

这将创建一个在本地计算机上的端口 8001 上运行的简单服务器。

我们可以使用这个服务器来启动 API 发现的过程。我们首先检查/api前缀:

$ curl localhost:8001/api
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.0.1:6443"
    }
  ]
}

您可以看到服务器返回了一个类型为 的 API 对象APIVersions。这个对象为我们提供了一个versions字段,列出了可用的版本。

在这种情况下,只有一个,但对于/apis前缀,有很多。我们可以使用这个版本继续我们的调查

$ curl localhost:8001/api/v1
{
  "kind": "APIResourceList",
  "groupVersion": "v1",
  "resources": [
    {
….
    {
      "name": "namespaces",
      "singularName": "",
      "namespaced": false,
      "kind": "Namespace",
      "verbs": [
        "create",
        "delete",
        "get",
        "list",
        "patch",
        "update",
        "watch"
      ],
      "shortNames": [
        "ns"
      ]
    },
    {
      "name": "pods",
      "singularName": "",
      "namespaced": true,
      "kind": "Pod",
      "verbs": [
        "create",
        "delete",
        "deletecollection",
        "get",
        "list",
        "patch",
        "proxy",
        "update",
        "watch"
      ],
      "shortNames": [
        "po"
      ],
      "categories": [
        "all"
      ]
    },
    {
      "name": "pods/attach",
      "singularName": "",
      "namespaced": true,
      "kind": "Pod",
      "verbs": []
    },
    {
      "name": "pods/binding",
      "singularName": "",
      "namespaced": true,
      "kind": "Binding",
      "verbs": [
        "create"
      ]
    },
   ….
  ]
}

返回的对象包含/api/v1/路径下暴露的资源列表。

描述 API(元 API 对象)的 OpenAPI/Swagger JSON 规范除了资源类型之外还包含各种有趣的信息。考虑Pod对象的 OpenAPI 规范:

{
      "name": "pods",
      "singularName": "",
      "namespaced": true,
      "kind": "Pod",
      "verbs": [
        "create",
        "delete",
        "deletecollection",
        "get",
        "list",
        "patch",
        "proxy",
        "update",
        "watch"
      ],
      "shortNames": [
        "po"
      ],
      "categories": [
        "all"
      ]
    },
    {
      "name": "pods/attach",
      "singularName": "",
      "namespaced": true,
      "kind": "Pod",
      "verbs": []
    }

查看此对象,该name字段提供此资源的名称。它还指示这些资源的子路径。由于推断英语单词的复数形式具有挑战性,因此 API 资源还包含一个singularName字段,该字段指示应用于该资源的单个实例的名称。我们之前讨论过命名空间。对象描述中的namespaced字段指示对象是否被命名空间。该kind字段提供了存在于 API 对象的 JSON 表示中的字符串,以指示它是什么类型的对象。该verbs字段是 API 对象中最重要的字段之一,因为它指示可以对该对象执行哪些类型的操作。这pods宾语包含所有可能的动词。动词的大部分效果从它们的名字就很明显了。需要更多解释的两个是watch和proxy。watch表示可以为资源建立监视。监视是一个长时间运行的操作,它提供有关对象更改的通知。proxy是一种专门的操作,它通过 API Server与网络端口建立代理网络连接。目前只有两种资源(Pod 和Services)支持proxy.


除了可以对对象执行的操作(描述为动词)之外,还有其他操作被建模为资源类型的子资源。例如,attach命令被建模为子资源:

    {
      "name": "pods/attach",
      "singularName": "",
      "namespaced": true,
      "kind": "Pod",
      "verbs": []
    }

8.3 curl

$ TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
$ CACERT=/run/secrets/kubernetes.io/serviceaccount/ca.crt
$ curl --cacert $CACERT --header "Authorization: Bearer $TOKEN"  https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}
$ APISERVER=$(kubectl config view | grep server | cut -f 2- -d ":" | tr -d " ")
$ TOKEN=$(kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token'| cut -f2 -d':'| tr -d '\t')
$ curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure
{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

9. 调试 API Server

当然,了解 API Server的实现是很好的,但通常情况下,您真正需要的是能够调试 API Server(以及调用 API 的客户端)的实际情况服务器)。实现这一点的主要方式是通过 API Server写入的日志。API Server导出两个日志流——the standard or basic logs,以及更有针对性的审计日志,它们试图捕获发出请求的原因和方式以及更改的 API Server状态。此外,可以打开更详细的日志记录来调试特定问题。

9.1 Basic Logs

默认情况下,API Server记录发送到 API Server的每个请求。此日志包括客户端的 IP 地址、请求的路径以及服务器返回的代码。如果意外错误导致服务器崩溃,服务器也会捕捉到这种恐慌,返回 500,并记录该错误。

I0803 19:59:19.929302       1 trace.go:76] Trace[1449222206]:
 "Create /api/v1/namespaces/default/events" (started: 2018-08-03
 19:59:19.001777279 +0000 UTC m=+25.386403121) (total time: 927.484579ms):
Trace[1449222206]: [927.401927ms] [927.279642ms] Object stored in database
I0803 19:59:20.402215       1 controller.go:537] quota admission added
 evaluator for: { namespaces}

在此日志中,您可以看到它以I0803 19:59:…发出日志行时的时间戳开始,然后是发出它的行号,trace.go:76最后是日志消息本身。

9.2 Audit Logs

审计日志(Audit Logs)旨在使服务器管理员能够取证恢复服务器的状态以及导致 Kubernetes API 中数据当前状态的一系列客户端交互。例如,它使用户能够回答诸如“为什么要ReplicaSet扩大到 100 个?”、“谁删除了那个 Pod?”等问题。


审计日志有一个可插入的后端,用于记录它们的写入位置。通常,审计日志会写入文件,但也可以将它们写入 webhook。在任何一种情况下,记录的数据都是API 组中类型event的结构化 JSON 对象audit.k8s.io。


审计本身可以通过同一 API 组中的策略对象进行配置。此策略允许您指定将审计事件发送到审计日志的规则。

9.3 激活附加日志

Kubernetes 使用 leveled logging github.com/golang/glog 包进行日志记录。使用 API Server上的标志--v,您可以调整日志记录的详细程度。一般来说,Kubernetes 项目已将日志详细级别 2 ( --v=2) 设置为记录相关但不太垃圾邮件的合理默认值。如果您正在调查特定问题,您可以提高日志记录级别以查看更多(可能是垃圾邮件)消息。由于过多的日志记录会影响性能,我们建议不要在生产中使用详细的日志级别运行。如果您正在寻找更有针对性的日志记录,该--vmodule标志可以提高单个源文件的日志级别。这对于仅限于一小部分文件的非常有针对性的详细日志记录非常有用。

9.4 调试 kubectl 请求

除了通过日志调试 API Server外,还可以通过kubectl命令行工具调试与 API Server的交互。与 API Server一样,kubectl命令行工具通过github.com/golang/glog包记录并支持–v详细度标志。将详细程度设置为级别 10 ( --v=10) 会启用最大程度详细记录。在此模式下,kubectl记录它向服务器发出的所有请求,以及尝试打印curl可用于复制这些请求的命令。请注意,这些curl命令有时不完整。


此外,如果您想直接戳 API Server,我们之前用于探索 API 发现的方法效果很好。Running kubectl proxy在 localhost 上创建一个代理服务器,它会根据本地$HOME/.kube/config文件自动提供您的身份验证和授权凭据。运行代理后,使用该curl命令查看各种 API 请求相当简单。

10. API 版本

1035234-20181020215539574-213176954.png

在 Kubernetes 中,API 最初是一个 alpha API(例如,v1alpha1)。alpha 名称表示 API 不稳定且不适合生产用例。采用 alpha API 的用户应该预料到 API 表面区域可能会在 Kubernetes 版本之间发生变化,并且 API 本身的实现可能会不稳定,甚至可能会破坏整个 Kubernetes 集群的稳定性。因此,在生产 Kubernetes 集群中禁用了 Alpha API。


一旦 API 成熟,它就会成为 beta API(例如,v1beta1)。Beta 指定表明 API 通常是稳定的,但可能存在错误或最终的 API 表面改进。通常,假设 Kubernetes 版本之间的 beta API 是稳定的,并且向后兼容是一个目标。但是,在特殊情况下,Beta API 可能仍然在 Kubernetes 版本之间不兼容。同样,beta API 旨在保持稳定,但可能仍然存在错误。Beta API 通常在生产 Kubernetes 集群中启用,但应谨慎使用。


最后,API 变得普遍可用(例如,v1)。通用可用性 (GA) 表明 API 是稳定的。这些 API 带有向后兼容性保证和弃用保证。在 API 被标记为计划删除后,Kubernetes 会将该 API 保留至少三个版本或一年,以先到者为准。弃用也不太可能。只有在开发出更好的替代方案后,API 才会被弃用。同样,GA API 是稳定的,适用于所有生产用途。


Kubernetes 的特定版本可以支持多个版本(alpha、beta 和 GA)。为了实现这一点,API Server始终具有三种不同的 API 表示:外部表示,即通过 API 请求进入的表示;内部表示,它是在 API Server中用于处理的对象的内存表示;和存储表示,它被记录到存储层以持久化 API 对象。API Server中的代码知道如何在所有这些表示之间执行各种转换。API 对象可以作为v1alpha1版本提交,作为v1对象存储,然后作为v1beta1对象或任何其他任意支持的版本检索。

11. 替代编码

除了支持请求对象的 JSON 编码外,API Server还支持另外两种请求格式。请求的编码由请求上的 Content-Type HTTP 标头指示。如果缺少此标头,则假定内容为application/json,表示 JSON 编码。第一个替代编码是 YAML,由application/yamlContent Type 指示。YAML 是一种基于文本的格式,通常被认为比 JSON 更易于阅读。几乎没有理由使用 YAML 进行编码以与服务器通信,但在某些情况下它可能很方便(例如,通过 手动将文件发送到服务器curl)。


请求和响应的另一种替代编码是协议缓冲区编码格式。Protocol Buffers 是一个相当有效的二进制对象协议。使用协议缓冲区可以为 API Server带来更高效和更高吞吐量的请求。事实上,许多 Kubernetes 内部工具都使用协议缓冲区作为它们的传输。Protocol Buffers 的主要问题是,由于它们的二进制性质,它们在有线格式中更难可视化/调试。此外,目前并非所有客户端库都支持 Protocol Buffers 请求或响应。协议缓冲区格式由application/vnd.kubernetes.protobufContent-Type 标头指示。

12. 常见响应代码

因为 API Server是作为 RESTful 服务器实现的,所以来自服务器的所有响应都与 HTTP 响应代码保持一致。除了典型的 200 表示 OK 响应和 500 表示内部服务器错误之外,以下是一些常见的响应代码及其含义:


202

公认。已收到创建或删除对象的异步请求。结果以状态对象响应,直到异步请求完成,此时将返回实际对象。


400

错误的请求。服务器无法解析或理解该请求。


401

未经授权。在没有已知身份验证方案的情况下接收到请求。


403

禁止。已收到并理解请求,但禁止访问。


409

冲突。已收到请求,但它是更新旧版本对象的请求。


422

无法处理的实体。请求已正确解析,但未通过某种验证.

13. API Server Internals

除了操作 HTTP RESTful 服务的基础知识之外,API Server还有一些内部服务来实现部分 Kubernetes API。通常,这些类型的控制循环在称为控制器管理器的单独二进制文件中运行。但是有一些控制循环必须在 API Server内运行。在每种情况下,我们都会描述其功能以及它存在于 API Server中的原因。

14. CRD Control Loop

自定义资源定义 (CRD) 是可以添加到正在运行的 API Server的动态 API 对象。因为创建 CRD 的行为本质上会创建 API Server必须知道如何提供服务的新 HTTP 路径,所以负责添加这些路径的控制器位于 API Server内部。随着委托 API Server的增加(在后面的章节中描述),这个控制器实际上已经大部分从 API Server中抽象出来了。它目前仍默认在进程中运行,但也可以在进程外运行。

CRD 控制回路的操作如下:

for crd in AllCustomResourceDefinitions:
    if !RegisteredPath(crd):
       registerPath
for path in AllRegisteredPaths:
    if !CustomResourceExists(path):
       markPathInvalid(path)
       delete custom resource data
       delete path

自定义资源路径的创建相当简单,但自定义资源的删除稍微复杂一些。这是因为删除自定义资源意味着删除与该类型资源关联的所有数据。这样一来,如果 CRD 被删除,然后在稍后的某个日期被读取,旧数据就不会以某种方式复活。


因此,在可以删除 HTTP 服务路径之前,首先将该路径标记为无效,以便无法创建新资源。然后,与 CRD 关联的所有数据都被删除,最后,路径被删除。

15. OpenAPI 规范服务

当然,了解可用于访问 API Server的资源和路径只是访问 Kubernetes API 所需信息的一部分。除了 HTTP 路径之外,您还需要知道要发送和接收的 JSON 有效负载。API Server还提供路径,为您提供有关 Kubernetes 资源模式的信息。这些模式使用 OpenAPI(以前的 Swagger)语法表示。您可以在以下路径下拉 OpenAPI 规范:


/swaggerapi

在 Kubernetes 1.10 之前,服务于 Swagger 1.2

/openapi/v2

Kubernetes 1.10 及更高版本,服务于 OpenAPI (Swagger 2.0)

OpenAPI 规范本身就是一个完整的主题,超出了本书的范围。无论如何,您不太可能需要在 Kubernetes 的日常操作中访问它。然而,各种客户端编程语言库是使用这些 OpenAPI 规范生成的(值得注意的例外是 Go 客户端库,它目前是手动编码的)。因此,如果您或用户在通过客户端库访问 Kubernetes API 的某些部分时遇到问题,那么第一站应该是 OpenAPI 规范,以了解 API 对象是如何建模的。


参考:


Oreilly The Kubernetes API Server

官方 The Kubernetes API

什么是 Kubernetes API?


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。     相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
人工智能 API 开发工具
GitHub官方开源MCP服务!GitHub MCP Server:无缝集成GitHub API,实现Git流程完全自动化
GitHub MCP Server是基于Model Context Protocol的服务器工具,提供与GitHub API的无缝集成,支持自动化处理问题、Pull Request和仓库管理等功能。
3680 2
GitHub官方开源MCP服务!GitHub MCP Server:无缝集成GitHub API,实现Git流程完全自动化
|
Kubernetes API 网络安全
当node节点kubectl 命令无法连接到 Kubernetes API 服务器
当Node节点上的 `kubectl`无法连接到Kubernetes API服务器时,可以通过以上步骤逐步排查和解决问题。首先确保网络连接正常,验证 `kubeconfig`文件配置正确,检查API服务器和Node节点的状态,最后排除防火墙或网络策略的干扰,并通过重启服务恢复正常连接。通过这些措施,可以有效解决与Kubernetes API服务器通信的常见问题,从而保障集群的正常运行。
1297 17
|
人工智能 JavaScript 测试技术
构建智能 API 开发环境:在 Cursor 中连接 Apifox MCP Server
本文介绍了如何将Apifox MCP Server与Cursor结合,通过AI直接获取和理解API文档,大幅提升开发效率。首先需配置Apifox的Access Token和项目ID,并在Cursor中设置MCP连接。实际应用场景包括快速生成模型代码、同步更新接口文档与代码、生成CRUD操作、搜索API文档及自动生成测试用例。此外,还提供了管理多项目、安全性实践和优化AI响应质量的技巧。这种组合可显著减少从API规范到代码实现的时间,降低错误率并加速迭代过程,为开发者带来更高效的体验。
|
Kubernetes 安全 Cloud Native
云上攻防-云原生篇&K8s安全-Kubelet未授权访问、API Server未授权访问
本文介绍了云原生环境下Kubernetes集群的安全问题及攻击方法。首先概述了云环境下的新型攻击路径,如通过虚拟机攻击云管理平台、容器逃逸控制宿主机等。接着详细解释了Kubernetes集群架构,并列举了常见组件的默认端口及其安全隐患。文章通过具体案例演示了API Server 8080和6443端口未授权访问的攻击过程,以及Kubelet 10250端口未授权访问的利用方法,展示了如何通过这些漏洞实现权限提升和横向渗透。
2555 0
云上攻防-云原生篇&K8s安全-Kubelet未授权访问、API Server未授权访问
|
API 开发者
【API管理 APIM】APIM集成内部VNet后,自我访问出现(Unable to connect to the remote server)问题,而Remote Server正是APIM它自己
【API管理 APIM】APIM集成内部VNet后,自我访问出现(Unable to connect to the remote server)问题,而Remote Server正是APIM它自己
751 5
|
Kubernetes 负载均衡 API
在K8S中,api-service 和 kube-schedule 高可用原理是什么?
在K8S中,api-service 和 kube-schedule 高可用原理是什么?
|
JSON Kubernetes API
k8s技术预研14--kubernetes API详解
1、kubernetes API概述 Kubernetes API是集群系统中的重要组成部分,Kubernetes中各种资源(对象)的数据通过该API接口被提交到后端的持久化存储(etcd)中,Kubernetes集群中的各部件之间通过该API接口实现解耦合,同时Kubernetes集群中一个重要且便捷的管理工具kubectl也是通过访问该API接口实现其强大的管理功能的。
4785 0
|
10月前
|
缓存 监控 前端开发
顺企网 API 开发实战:搜索 / 详情接口从 0 到 1 落地(附 Elasticsearch 优化 + 错误速查)
企业API开发常陷参数、缓存、错误处理三大坑?本指南拆解顺企网双接口全流程,涵盖搜索优化、签名验证、限流应对,附可复用代码与错误速查表,助你2小时高效搞定开发,提升响应速度与稳定性。
|
11月前
|
数据可视化 测试技术 API
从接口性能到稳定性:这些API调试工具,让你的开发过程事半功倍
在软件开发中,接口调试与测试对接口性能、稳定性、准确性及团队协作至关重要。随着开发节奏加快,传统方式已难满足需求,专业API工具成为首选。本文介绍了Apifox、Postman、YApi、SoapUI、JMeter、Swagger等主流工具,对比其功能与适用场景,并推荐Apifox作为集成度高、支持中文、可视化强的一体化解决方案,助力提升API开发与测试效率。
|
10月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南

热门文章

最新文章