【K8s】认识Kubernetes API:从CRD出发的一次梳理

这篇文章是我在学习K8s CRD(自定义资源)时,发现自己对"API到底是什么"还有点模糊,于是重新梳理了一遍的笔记。如果你也正处在这个阶段,希望这篇能帮你理清思路。

目录

为什么要认识API?

你每天都在用API,只是没意识到

[Kubernetes API长什么样?](#Kubernetes API长什么样?)

一个重要的概念:声明式API

API资源有哪些?

工作负载类(运行容器)

服务发现与负载均衡类(网络相关)

配置与存储类

集群与权限类

如何与API交互?

方式一:通过kubectl命令行(最常用)

方式二:通过编程语言客户端库

[方式三:直接调用REST API(最底层)](#方式三:直接调用REST API(最底层))

哪些组件可以和API交互?

集群内部组件

外部用户和工具

小结一下:交互关系图

扩展API:CRD是怎么回事?

[方式一:CustomResourceDefinition (CRD) ------ 最常用](#方式一:CustomResourceDefinition (CRD) —— 最常用)

[方式二:API聚合层 (API Aggregation) ------ 更灵活但更复杂](#方式二:API聚合层 (API Aggregation) —— 更灵活但更复杂)

为什么大家疯狂用CRD?

写在最后


为什么要认识API?

在K8s的世界里,API是绝对的核心。你可以这样理解:

Kubernetes API就是整个集群的"前台接待处"------所有想对集群做的事情,都得先经过它。

K8控制平面的核心是 kube-apiserver 组件,它暴露了一个 HTTP API。这个 API 是集群唯一的操作入口。无论是我们敲的 kubectl 命令,还是集群内部的各种组件(调度器、控制器),甚至是第三方的扩展程序,都是通过调用这个API来与集群交互的。

那为什么学习CRD之前要先搞懂API呢?因为CRD的本质,就是扩展Kubernetes API------在"前台接待处"增加一种新的业务可以办理。如果不先理解API本身,直接学CRD就像没搞懂银行柜台能办哪些业务,就直接去申请一个"新业务窗口"一样,容易一头雾水。

你每天都在用API,只是没意识到

我们天天都在和API打交道,只是可能没有意识到。

回想一下你在学K8s期间经常用到的一条命令:kubectl get pods

这条命令的背后,kubectl向kube-apiserver发起了这样一个请求:"GET /api/v1/namespaces/default/pods"。然后API服务器去etcd里查到Pod列表,返回给你。

又比如你执行 kubectl apply -f nginx.yaml

这背后是API服务器收到了一个POST请求,把YAML里描述的内容存到了etcd里。

所以可以这么说:每条kubectl命令,都是在调用API

Kubernetes API长什么样?

Kubernetes API是一个RESTful风格的HTTP API。我们平时写的YAML文件,实际上就是API请求的"身体"。比如这个部署Nginx的YAML:

Go 复制代码
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21

apiVersion 告诉API服务器:"我要用v1版本的apps组API";kind告诉它:"我要创建的是Deployment这种资源";spec则描述了具体期望的状态。

一个重要的概念:声明式API

K8s API是"声明式"的,这和我们平时习惯的"命令式"有很大区别:

命令式 声明式
告诉系统 "怎么做" "要什么"
好比 叫外卖时告诉骑手"左转、右转、上三楼" 在App里点餐,说"我要一份宫保鸡丁"
K8s中的体现 kubectl run、kubectl delete kubectl apply -f

声明式的好处是:你只需要提交一个描述"目标状态"的YAML文件,K8s自己会想办法把集群的当前状态调整成你描述的样子。而且kubectl apply可以反复执行,不用担心"重复执行会导致错误"------这在分布式环境中非常重要。

API资源有哪些?

"API资源"就是你可以通过API来操作的各种对象。执行 kubectl api-resources 这条命令,就能看到你的集群支持哪些资源 。

这些资源可以按功能分为几大类:

工作负载类(运行容器)

  • Pod:最小的部署单元,一个Pod里可以有一个或多个容器

  • Deployment:管理无状态应用,支持滚动更新和回滚

  • StatefulSet:管理有状态应用(如数据库),每个Pod有唯一标识

  • DaemonSet:保证每个节点上都运行一个Pod副本

  • Job / CronJob:处理一次性任务和定时任务

服务发现与负载均衡类(网络相关)

  • Service:为一组Pod提供统一的访问入口

  • Ingress:管理外部访问集群内部服务的路由规则

配置与存储类

  • ConfigMap:存明文配置数据(比如配置文件内容)

  • Secret:存敏感信息(比如密码、Token)

  • PersistentVolume(PV)PersistentVolumeClaim(PVC) :管理持久化存储

集群与权限类

  • Node:代表集群里的一个工作节点

  • Namespace:在集群内划分资源空间,实现隔离

  • ServiceAccountRoleClusterRole等:管理身份认证和权限控制

如何与API交互?

作为开发者,我们有三种主流方式与K8s API打交道。

方式一:通过kubectl命令行(最常用)

这是99%的情况下你会用的方式。

复制代码
# 查询资源
kubectl get pods
kubectl get deployments -n kube-system

# 创建资源
kubectl apply -f my-app.yaml

# 删除资源
kubectl delete pod my-pod

# 查看资源详细信息
kubectl describe pod my-pod

这种方式的优点是 简单直观,适合日常运维和调试;缺点是不适合在程序里调用。

方式二:通过编程语言客户端库

如果你在写一个Go应用或者Operator,需要用代码来操作Kubernetes,那么可以使用官方提供的客户端库。

Go语言的client-go是最成熟也最常用的:

Go 复制代码
import (
    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
)

func main() {
    // 加载kubeconfig
    config, _ := clientcmd.BuildConfigFromFlags("", "/path/to/.kube/config")
    clientset, _ := kubernetes.NewForConfig(config)
    
    // 查询default命名空间下的所有Pod
    pods, _ := clientset.CoreV1().Pods("default").List(context.TODO(), metav1.ListOptions{})
    for _, pod := range pods.Items {
        fmt.Println(pod.Name)
    }
}

除了Go,官方也提供了Python、Java、JavaScript等语言的客户端库。

方式三:直接调用REST API(最底层)

如果你需要最大的灵活性,或者想调试API本身,可以直接用curl等工具调用HTTP接口:

Go 复制代码
# 先获取一个Token
TOKEN=$(kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 -d)

# 调用API查询Pod
curl -k -H "Authorization: Bearer $TOKEN" https://<api-server-ip>:6443/api/v1/namespaces/default/pods

这种方式最灵活,但也最麻烦------你需要自己处理认证、证书、分页等细节。

哪些组件可以和API交互?

理解了"怎么用"之后,我们再来看看"谁在用"------这能帮你建立对整个K8s生态的全局认知。

集群内部组件

这些是Kubernetes自带的核心组件,它们时刻都在通过API相互通信:

  • kube-scheduler(调度器) :不停地通过API监听那些还没有被调度的Pod,然后选择一个合适的节点,再把调度结果写回API

  • kube-controller-manager(控制器管理器) :里面运行着各种控制器(如Deployment控制器、Job控制器),它们通过API不断检查"当前状态"和"期望状态",如果不一致就采取行动

  • kubelet(节点代理) :每个节点上的kubelet通过API获取分配给自己的Pod清单,然后把Pod的运行状态(比如容器是否启动成功)上报回API

外部用户和工具

  • 集群管理员和开发者:通过kubectl、kubectl插件或直接调用REST API来操作集群

  • CI/CD系统:Jenkins、GitLab CI、ArgoCD等工具通过API将应用部署到集群

  • 监控系统:Prometheus、Datadog等通过API采集集群和应用的指标数据

  • 云厂商管理工具:云服务商的控制台或CLI工具通过API管理托管Kubernetes集群

  • Operator:这是最值得单独说的一类------Operator本质上是运行在集群内部的程序,它通过API监听自定义资源的变化,然后执行相应的业务逻辑

小结一下:交互关系图

扩展API:CRD是怎么回事?

终于讲到CRD了------这也是我决定重新认识API的起点。

K8s的强大之处在于,它的API是可以扩展的。如果内置的资源(Pod、Service等)满足不了你的需求,你可以自己创建新的资源类型。

创建自定义资源有两种方式:

方式一:CustomResourceDefinition (CRD) ------ 最常用

CRD是Kubernetes内置的一种资源,用来定义"新的资源"。你只需要写一个YAML文件,声明你要新增一种资源类型,然后kubectl apply -f,Kubernetes就会在API里注册这种新资源。

比如,如果我想定义一个"数据库实例"这种资源:

Go 复制代码
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: databaseinstances.example.com
spec:
  group: example.com
  versions:
    - name: v1
      served: true
      storage: true
  scope: Namespaced
  names:
    plural: databaseinstances
    singular: databaseinstance
    kind: DatabaseInstance

定义好之后,我就可以像操作Pod一样来操作"数据库实例"了:

Go 复制代码
kubectl get databaseinstances
kubectl create -f my-database.yaml

方式二:API聚合层 (API Aggregation) ------ 更灵活但更复杂

聚合层允许你编写和部署一个独立的API服务器,然后在主API服务器后面"挂载"这个新的API组。这种方式更灵活(你可以自定义API的完整逻辑),但实现起来也更复杂。

为什么大家疯狂用CRD?

因为CRD把K8s变成了一个可编程的平台。通过CRD + Controller(控制器),你可以把任何复杂系统的运维逻辑"Kubernetes化":

工具/项目 CRD定义的资源 作用
Istio(服务网格) VirtualService、DestinationRule、Gateway 做流量管理、灰度发布、熔断等
Cert-Manager(证书管理) Certificate、Issuer、ClusterIssuer 自动申请和续签TLS证书
Prometheus Operator ServiceMonitor、PodMonitor、Alertmanager 简化监控配置和告警管理
TiDB Operator(数据库) TidbCluster、TidbBackup 让分布式数据库在K8s上像普通应用一样部署
ArgoCD(GitOps) Application、AppProject 实现声明式的持续交付

写在最后

回过头来看,我们梳理了这几件事:

  1. Kubernetes API是集群的统一入口,所有操作------不管是kubectl、内部组件还是外部工具------都得通过它

  2. API是声明式的,你告诉系统"要什么",而不是"怎么做"

  3. 资源是API操作的对象,Pod、Service、Deployment都是资源,kubectl api-resources可以查看所有资源

  4. 和API交互有三种方式:kubectl(最常用)、编程客户端库(适合写程序)、直接调用REST API(最灵活)

  5. 能和API交互的组件包括集群内部的调度器/控制器/kubelet、外部的用户/CI/CD/监控系统,以及运行在集群内的Operator

  6. CRD的本质就是扩展API,让你能定义自己的资源类型,这也是K8s成为云原生操作系统的基础

理解API,就是理解了K8s运作的底层逻辑。下次再看到CRD、Operator这些概念时,你会更清楚它们在整个体系中处于什么位置。

如果你还在学习阶段,不妨在自己的集群里执行一下kubectl api-resources,看看目前支持哪些资源------这会是一个不错的温习起点。

相关推荐
yanwumuxi2 小时前
Docker记录:误删宿主机挂载目录导致 PostgreSQL 数据丢失
docker·postgresql·容器
cui_hao_nan4 小时前
Docker 学习 5
docker·容器
A黄俊辉A5 小时前
两分钟上手docker
运维·docker·容器
努力努力再努力wz7 小时前
【Docker入门系列】:从架构演进到容器化:一文建立 Docker、虚拟化与 Namespace 的底层心智模型
运维·开发语言·数据结构·c++·docker·容器·架构
吴佳浩 Alben8 小时前
多智能体系统的通信风暴与死锁治理:生产级降级与容灾方案
人工智能·docker·ai·容器·架构
玉&心8 小时前
在dockers desktop上面部署k8s的前端和后端
云原生·容器·kubernetes
wdfk_prog8 小时前
Docker 29 与 containerd image store:镜像为什么会保存两种形态
运维·docker·容器
MC丶科8 小时前
软考架构师90天冲刺|DAY38·第二阶段综合测试-分布式与云原生
分布式·云原生·架构·serverless·service_mesh·软考架构师
hm宋8 小时前
ZooKeeper 容灾切换免重启实践:域名化配置与客户端自动迁移
分布式·zookeeper·云原生