基于官方文档v1.14版本

什么是Kubernetes

Kubernetes是一个跨主机集群的开源的容器调度平台,它可以自动化应用容器的部署、扩展和操作,提供以容器为中心的基础架构.

Kubernetes 项目由 Google 公司在 2014 年启动.Kubernetes 建立在 Google 公司超过十余年的运维经验基础之上,Google 所有的应用都运行在容器上, 再与社区中最好的想法和实践相结合,也许它是最受欢迎的容器平台.

为什么我需要Kubernetes以及它能做什么?

Kubernetes有许多特性,你可以认为它是:

  • 一个容器平台
  • 一个微服务平台
  • 一个便携式云平台等等

Kubernetes提供以容器为中心的管理环境.它代表用户工作负载协调计算,网络和存储基础架构.这提供了平台即服务(PaaS)的大部分简单性,具有基础架构即服务(IaaS)的灵活性,并支持跨基础架构提供商的可移植性.

Kubernetes怎样成为一个平台?

尽管Kubernetes提供了许多功能,但总会有新的方案可以从新功能中受益.可以简化特定于应用程序的工作流程,以加快开发人员的速度.最初可接受的特殊编排通常需要大规模的自动化自动化.这就是为什么Kubernetes还可以作为构建组件和工具生态系统的平台,以便更轻松地部署,扩展和管理应用程序. Labels(标签)使用户可以随意组织他们的资源.Annotations(注释) 使用户能够使用自定义信息来装饰资源,以便于他们的工作流程,并为管理工具提供检查点状态的简便方法. 此外,Kubernetes控制平面基于开发人员和用户可用的相同API构建 .用户可以使用自己的API编写自己的controller控制器(例如 调度程序),这些API 可以通过通用命令行工具进行定位. 这种 设计 使得许多其他系统能够在Kubernetes上面构建

Kubernetes不是什么?

Kubernetes不是一个传统的,包罗万象的PaaS(平台即服务)系统.由于Kubernetes在容器级而非硬件级运行,因此它提供了PaaS产品常用的一些通用功能,例如部署,扩展,负载平衡,日志记录和监控.但是,Kubernetes不是monolithic(整体的),而且这些默认解决方案是可选的和可插拔的.Kubernetes为构建开发人员平台提供了构建模块,但在重要的地方保留了用户选择和灵活性.

Kubernetes:

  • 不限制支持的应用程序类型.Kubernetes旨在支持各种各样的工作负载,包括Deployment(无状态),StatefulSet(有状态)和Workload数据处理工作负载.如果应用程序可以在容器中运行,那么它应该在Kubernetes上运行得很好.
  • 不部署源代码并且不构建您的应用程序.持续集成,交付和部署(CI / CD)工作流程由组织文化和偏好以及技术要求决定.
  • 不提供应用程序级服务,例如中间件(例如,消息总线),数据处理框架(例如,Spark),数据库(例如,mysql),高速缓存,也不提供集群存储系统(例如,Ceph).在服务中.这些组件可以在Kubernetes上运行,或可以通过便携式机制(例如Open Service Broker)在Kubernetes上运行的应用程序访问.
  • 不规定记录,监视或警报解决方案.它提供了一些集成作为概念证明,以及收集和导出指标的机制.
  • 不提供或授权配置语言/系统(例如, jsonnet).它提供了一个声明性API,可以通过任意形式的声明性规范来实现.
  • 不提供或采用任何全面的机器配置,维护,管理或自我修复系统.

此外,Kubernetes不仅仅是一个编排系统.事实上,它消除了编排的需要.业务流程的技术定义是执行已定义的工作流程:首先执行A,然后运行B,然后执行C.相反,Kubernetes由一组独立的,可组合的控制流程组成,这些流程将当前状态持续推向所提供的所需状态.如何从A到C无关紧要.集中控制也不是必需的.这使得系统更易于使用,功能更强大,更强大,更具弹性,并且可扩展.

为什么使用Containers(容器)?

why_containers

部署应用程序的旧方法是使用操作系统软件包管理器在主机上安装应用程序.这样做的缺点是将应用程序的可执行文件,配置,库和生命周期彼此纠缠在一起并与主机操作系统纠缠在一起.可以构建不可变的虚拟机镜像以实现可预测的部署和回滚,但虚拟机是重量级且不可移植的

而新方法是基于操作系统级虚拟化,而不是硬件虚拟化部署的容器.这些容器彼此隔离并与主机隔离:它们具有自己的文件系统,它们无法看到彼此的进程,并且它们的计算资源使用受到限制.它们比虚拟机更容易构建,并且因为它们与底层基础架构和主机文件系统分离,所以它们可以跨云和操作系统分发进行移植.

由于容器小而快,因此可以在每个容器镜像中打包一个应用程序.这种一对一的应用程序到镜像关系解锁了容器的全部优势.使用容器,可以在构建/发布时而不是部署时创建不可变容器镜像,因为每个应用程序不需要与应用程序堆栈的其余部分组合,也不需要与生产基础结构环境结合.在构建/发布时生成容器镜像可以实现从开发到生产的一致环境.同样,容器比VM更加透明,这有利于监控和管理.当容器的流程生命周期由基础架构管理而不是由容器内的流程管理器隐藏时,尤其如此.最后

总结一下容器的好处:

  • 敏捷地创建和部署应用程序:与VM使用相比,增加了容器镜像创建的简便性和效率.
  • 持续开发,集成和部署:通过快速简便的回滚(由于镜像不变性)提供可靠且频繁的容器镜像构建和部署.
  • 开发(Dev)和运维(Ops)关注点分离:在构建/发布时而不是部署时创建应用程序容器镜像,从而将应用程序与基础架构分离.
  • 可观察性:不仅可以显示操作系统级别的信息和指标,还可以显示应用程序运行状况和其他信号.
  • 开发,测试和生产的环境一致性:在笔记本电脑上运行与在云中运行相同.
  • 云和操作系统分发可移植性:在Ubuntu,RHEL,CoreOS,本地,Google Kubernetes引擎以及其他任何地方运行.
  • 以应用程序为中心的管理:提高在虚拟硬件上运行OS的抽象级别,以及使用逻辑资源在OS上运行应用程序.
  • 松散耦合,分布式,弹性,解放的微服务:应用程序被分解为更小,独立的部分,可以动态部署和管理 - 而不是在一台大型单一用途机器上运行.
  • 资源隔离:可预测的应用程序性能.
  • 资源利用:高效率和高密度

Kubernetes是什么意思,为什么叫K8s?

Kubernetes这个名字源自希腊语,意思是舵手或 飞行员,是governor(州长?)和cybernetic(控制论)的根源.K8s 是将中间8个字母“ubernete”替换为“8”而得到的缩写.


Kubernetes 组件

Master Componenets

master组件提供群集的控制平面.做出关于集群的全局决策(例如,调度),以及检测和响应集群事件(当replication controller(复制控制器)的replicas(副本)字段不满足时启动新的pod).

master组件可以在群集中的任何计算机上运行.但是,为简单起见,设置脚本通常会在同一台计算机上启动所有主组件,并且不在此计算机上运行用户容器.有关示例多主VM设置,请参阅 构建多主高可用性群集.

kube-apiserver

暴露Kubernetes API的master上的组件.它是Kubernetes控制平面的前端(接入).

它的设计就是为了水平扩展,参考构建多主高可用性群集.

etcd

一致且高可用的键值存储,用作Kubernetes的所有群集数据的后备存储.

始终为您的Kubernetes集群提供etcd数据的备份计划.有关etcd的详细信息,请参阅etcd文档.

kube-scheduler

master节点上的组件,用于监视未创建节点的新创建的pod,并选择一个节点供其运行.

调度决策所考虑的因素包括个人和集体资源需求,硬件/软件/策略约束,亲和力和反亲和性规范,数据位置,工作负载间干扰和最后期限.

kube-controller-manager

master上负责运行controllers的组件

controllers 控制循环,通过apiserver监视集群的共享状态,并进行更改,尝试将当前状态移至所需状态.

逻辑上,每个控制器是一个单独的进程,但为了降低复杂性,它们都被编译成单个二进制文件并在单个进程中运行.

这些控制器包括:

  • Node Controller(节点控制器):负责在节点出现故障时注意和响应.
  • Replication Controller(复制控制器):负责为系统中的每个复制控制器对象维护正确数量的Pod.
  • Endpoints Controller(端点控制器):填充端点对象(即,连接ServicePod).
  • Service Account & Token Controllers(服务帐户和令牌控制器):为新的命名空间创建默认帐户和API访问令牌.

cloud-controller-manager

cloud-controller-manager运行与底层云提供商交互的控制器.cloud-controller-manager二进制文件是Kubernetes 1.6版中引入的alpha功能.

cloud-controller-manager仅运行特定于云提供程序的控制器循环.您必须在kube-controller-manager中禁用这些控制器循环.您可以通过在启动kube-controller-manager时将--cloud-provider标志设置为external禁用控制器循环.

cloud-controller-manager允许云供应商代码和Kubernetes代码相互独立地发展.在以前的版本中,核心Kubernetes代码依赖于特定于云提供程序的功能代码.在未来的版本中,云供应商特有的代码应由云供应商自己维护,并在运行Kubernetes时链接到云控制器管理器.

以下控制器具有云提供程序依赖项:

  • Node Controller(节点控制器):用于检查云提供商,以确定节点在停止响应后是否已在云中删除
  • Route Controller(路由控制器):用于在底层云基础架构中设置路由
  • Service Controller(服务控制器):用于创建,更新和删除云提供商负载均衡器
  • Volume Controller(卷控制器):用于创建,附加和装载卷,以及与云提供商交互以协调卷

Node Components

节点组件在每个节点上运行,维护正在运行的pod并提供Kubernetes运行时环境.

kubelet

在群集中的每个节点上运行的代理.它确保容器在pod中运行.

kubelet采用通过各种机制提供的一组PodSpecs,并确保那些PodSpecs中描述的容器运行且健康.kubelet不管理不是由Kubernetes创建的容器.

kube-proxy

kube-proxy通过维护主机上的网络规则并执行连接转发来启用Kubernetes服务抽象.

Container Runtime

容器运行时是负责运行容器的软件.Kubernetes支持多个运行时:Docker,containerd,cri-o,rktlet以及Kubernetes CRI(容器运行时接口)的任何实现.

Addons (插件)

插件是实现集群功能的pod和服务.可以通过Deployments,ReplicationControllers等管理pod.命名空间的插件对象在kube-system命名空间中创建.

默认选定的插件如下所述,有关可用插件的扩展列表,请参阅插件.

DNS

虽然其他插件并非严格要求,但所有Kubernetes集群都应具有集群DNS,因为许多示例都依赖于它.集群DNS是DNS服务器,除了您环境中的其他DNS服务器之外,它还为Kubernetes服务提供DNS记录.Kubernetes启动的容器会在DNS搜索中自动包含此DNS服务器.

Web UI (Dashboard)

Dashboard是Kubernetes集群的基于Web的通用UI.它允许用户管理和解决群集中运行的应用程序以及群集本身.

Container Resource Monitoring 容器资源监控

容器资源监控记录有关中央数据库中容器的通用时间序列,并提供用于浏览该数据的UI.

Cluster-level Logging

一个集群级别的日志记录机制,负责保存容器日志与搜索/浏览界面中央日志存储.


The Kubernetes API

所有的api约定及规范在这里API约定

API端点,资源类型和示例在这里API参考

接口文档写了10万行

Controlling API Access文档中讨论了对API的远程访问.

Kubernetes API还可用作系统声明性配置架构的基础.kubectl命令行工具可以用来创建,更新,删除,并获得API对象.

Kubernetes还根据API资源存储其序列化状态(当前在etcd中).

Kubernetes本身被分解为多个组件,通过其API进行交互.

API 修改

根据我们的经验,任何成功的系统都需要随着新用例的出现或现有用例的变化而增长和变化.因此,我们希望Kubernetes API能够不断变化和发展.但是,我们打算在很长一段时间内不破坏与现有客户端的兼容性.通常,可以预期频繁添加新的API资源和新的资源字段.消除资源或字段将需要遵循API弃用策略.

API更改文档详细说明了兼容更改的内容以及如何更改API.

OpenAPI and Swagger 定义

使用OpenAPI记录完整的API详细信息

从Kubernetes 1.10开始,Kubernetes API服务器通过/openapi/v2端点提供OpenAPI规范.通过设置HTTP请求头指定请求的格式

Header 可以设置的值
Accept application/json,application/com.github.proto-openapi.spec.v2@v1.0+protobuf (the default content-type is application/json for / or not passing this header)
Accept-Encoding gzip (not passing this header is acceptable)

在1.14版本之前,格式分隔式端点(/swagger.json,/swagger-2.0.0.json,/swagger-2.0.0.pb-v1,/swagger-2.0.0.pb-v1.gz)服务以不同的格式的OpenAPI规范.这些端点已弃用,将在Kubernetes 1.14中删除.

获取OpenAPI规范的示例:

1.10之前 1.10之后
GET /swagger.json GET /openapi/v2 Accept: application/json
GET /swagger-2.0.0.pb-v1 GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf
GET /swagger-2.0.0.pb-v1.gz GET /openapi/v2 Accept: application/com.github.proto-openapi.spec.v2@v1.0+protobuf Accept-Encoding: gzip

Kubernetes为API实现了另一种基于Protobuf的序列化格式,主要用于集群内通信,在设计提案中有记录,每个模式的IDL文件都位于定义API对象的Go包中.

在1.14之前,Kubernetes apiserver还公开了一个API,可用于检索Swagger v1.2 Kubernetes API规范/swaggerapi.该端点已弃用,将在Kubernetes 1.14中删除.

API versioning API版本控制

为了更容易消除字段或重构资源表示,Kubernetes支持多个API版本,每个版本位于不同的API路径,例如/api/v1/apis/extensions/v1beta1.

我们选择在API级别而不是在资源或字段级别进行版本控制,以确保API提供清晰,一致的系统资源和行为视图,并支持控制对生命周期和/或实验API的访问.JSON和Protobuf序列化模式遵循相同的模式更改指南 - 以下所有描述都涵盖两种格式.

请注意,API版本控制和软件版本控制仅间接相关.该API和发行版本的提案描述API版本和软件版本之间的关系.

不同的API版本意味着不同级别的稳定性和支持.API更改文档中更详细地描述了每个级别的标准.总结:

Alpha level:

  • 版本名称包含alpha(例如v1alpha1).
  • 默认关闭,打开可能会出现某些bug
  • 可随时删除对功能的支持,不另行通知.
  • API可能会在以后的软件版本中以不兼容的方式更改,不另行通知.
  • 由于错误风险增加和缺乏长期支持,建议仅在短期测试集群中使用.

Beta level:

  • 版本名称包含beta(例如v2beta3).
  • 代码经过了充分测试.启用该功能被认为是安全的.默认情况下启用.
  • 虽然细节可能会有所变化,但不会删除对整体功能的支持.
  • 在随后的beta版或稳定版中,对象的模式和语义可能以不兼容的方式发生变化.发生这种情况时,我们将提供迁移到下一版本的说明.这可能需要删除,编辑和重新创建API对象.编辑过程可能需要一些思考.对于依赖该功能的应用程序,可能需要停机时间.
  • 建议仅用于非关键业务用途,因为后续版本中可能存在不兼容的更改.如果您有多个可以独立升级的群集,您可以放宽此限制.
  • 请尝试我们的测试版功能并提供反馈!一旦他们退出测试版,我们可能无法进行更多更改

Stable level:

  • 该版本名称是vX这里X是一个整数
  • 许多后续版本的已发布软件中将出现稳定版本的功能.

API Groups

为了更容易扩展Kubernetes API,我们实现了API组.API组在REST路径和apiVersion序列化对象的字段中指定.

目前有几个API Group正在使用中:

  1. 核心组,常常被称为遗留组,是在REST路径/api/v1,以及文件中apiVersion: v1.

  2. 命名组处于REST路径/apis/$GROUP_NAME/$VERSION,并使用apiVersion: $GROUP_NAME/$VERSION (例如apiVersion: batch/v1).在Kubernetes API参考中可以看到支持的API组的完整列表.

使用自定义资源扩展API有两种受支持的路径:

  1. CustomResourceDefinition适用于基本CRUD操作

  2. 需要完整Kubernetes API语义的用户可以实现自己的apiserver并使用聚合器来使得客户端可以无缝集成

启用API组

默认情况下启用某些资源和API组.可以通过设置--runtime-config apiserver来启用或禁用它们.--runtime-config接受逗号分隔值.例如:要禁用批处理/v1,请设置 --runtime-config=batch/v1=false,以启用批处理/v2alpha1,设置--runtime-config=batch/v2alpha1.该标志接受逗号分隔的一组key=value对,描述了apiserver的运行时配置.

重要信息:启用或禁用组或资源需要重新启动apiserver和controller-manager来获取--runtime-config的改动.

启用组中的资源

默认情况下启用DaemonSet,Deployments,Horizo​​ntalPodAutoscalers,Ingresses,Jobs和ReplicaSet.可以通过设置apiserver的--runtime-config来启用其他扩展资源.--runtime-config接受逗号分隔值.例如:要禁用Deployments和Ingresses,请设置--runtime-config=extensions/v1beta1/deployments=false,extensions/v1beta1/ingresses=false


Kubernetes Objects

Understanding Kubernetes Objects 理解Kubernetes对象

Kubernetes Objects 是Kubernetes系统中的持久实体.Kubernetes使用这些实体来表示集群的状态.具体来说,他们可以描述:

  • 正在运行的容器化应用程序(以及在哪些节点上)
  • 这些应用程序可用的资源
  • 有关这些应用程序行为方式的策略,例如重新启动策略,升级和容错

Kubernetes对象是一个“目的记录” - 你创建对象,Kubernetes系统将不断努力确保对象存在.通过创建一个对象,您可以有效地告诉Kubernetes系统您希望集群的工作负载看起来像什么; 这是您的集群所期望的状态

要使用Kubernetes对象 - 无论是创建,修改还是删除它们 - 您需要使用Kubernetes API.例如,当您使用kubectl命令行界面时,CLI会为您进行必要的Kubernetes API调用.您还可以使用其中一个客户端库在您自己的程序中直接使用Kubernetes API .

Object Spec and Status 对象的说明(规格,规范)和状态

每个Kubernetes对象都包含两个嵌套对象字段,用于控制对象的配置:对象spec(说明,规范,规格)和对象status(状态).spec是描述了对象的期望状态 - 也就是希望对象具有的特征.status描述了对象的实际状态,并且通过Kubernetes系统提供和更新.在任何时间,Kubernetes控制平面都会主动管理对象的实际状态,来匹配提供的期望状态.

例如,Kubernetes Deployment是一个对象,可以表示在您的集群上运行的应用程序.创建Deployment(部署)时,您可以设置Deployment spec(部署说明)以指定您希望运行应用程序的三个副本.Kubernetes系统读取部署说明并启动所需应用程序的三个实例 - 更新status(状态)以符合您的规范.如果这些实例中的任何一个失败(status(状态)改变),Kubernetes系统进行更正spec和status之间的差异 - 在这种情况下,启动替换实例.

有关对象sepc规范,status状态和metadata元数据的更多信息,请参阅Kubernetes API约定.

Describing a Kubernetes Object 描述一个Kubernetes对象

在Kubernetes中创建对象时,必须提供描述其所需状态的对象spec(规格,说明),以及有关该对象的一些基本信息(例如名称).当您使用Kubernetes API创建对象(直接或通过kubectl)时,该API请求必须在请求体中将该信息包含为JSON.通常,会使用kubectl,并且在.yaml文件中提供信息. kubectl在发出API请求时将信息转换为JSON.

这是一个示例.yaml文件,显示Kubernetes Deployment所需的字段和对象规范:

apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

使用上述.yaml文件创建部署的一种方法是kubectl apply在命令行界面中使用该命令,并将该.yaml文件作为参数传递.这是一个例子:

kubectl apply -f https://k8s.io/examples/application/deployment.yaml --record

输出类似于:

deployment.apps/nginx-deployment created

Required Fields 必填字段

.yaml要创建的Kubernetes对象的文件中,您需要为以下字段设置值:

  • apiVersion - 您正在使用哪个版本的Kubernetes API来创建此对象
  • kind - 您想要创建什么样的对象
  • metadata - 有助于唯一标识对象的数据,包括name字符串,UID和可选项namespace

您还需要提供对象spec字段.spec对于每个Kubernetes对象的格式是不同的,并且包含特定于该对象的嵌套字段.该Kubernetes API参考可以帮助你找到所有你可以创建使用Kubernetes对象的规范格式.例如,spec对于Pod这个对象来说是这样的,spec对于Deployment对象是这样的.

Names 名字

Kubernetes REST API中的所有对象都由Name和UID明确标识 对于非唯一的用户提供的属性,Kubernetes提供label标签和annotation注释.

有关名称和UID的精确语法规则,请参阅标识符设计文档.

Names 名字

客户端提供的字符串,用于引用资源URL中的对象,例如/api/v1/pods/some-name.

只有给定类型的一个对象一次可以有一个给定的名称.但是,如果删除该对象,则可以创建具有相同名称的新对象.

按照惯例,Kubernetes资源的名称应最多为253个字符,并且由小写字母,数字,以及”-“,还有”.“组成,但某些资源具有更具体的限制.

UIDs

Kubernetes系统生成的字符串,用于唯一标识对象.

在Kubernetes集群的整个生命周期中创建的每个对象都具有不同的UID.它旨在区分类似实体的历史事件.

Namespaces 命名空间

Kubernetes支持由同一物理集群支持的多个虚拟集群.这些虚拟集群称为名称空间.

When to Use Multiple Namespaces 何时使用多个命名空间

命名空间旨在用于多个用户分布在多个团队或项目中的环境中.对于具有几个到几十个用户的集群,您根本不需要创建或考虑名称空间.当您需要命名空间提供的功能时,请开始使用. 命名空间提供名称作用域.资源名称在名称空间中必须是唯一的,跨名称空间可以重复.命名空间不能彼此嵌套,并且每个Kubernetes资源只能位于一个命名空间中. 命名空间是一种在多个用户之间划分集群资源的方法(通过资源配额). 在Kubernetes的未来版本中,默认情况下,同一名称空间中的对象将具有相同的访问控制策略. 没有必要使用多个命名空间来分隔略有不同的资源,例如同一软件的不同版本:使用标签来区分同一命名空间中的资源.

Working with Namespaces 使用命名空间

命名空间的管理指南文档中描述了命名空间的创建和删除

Viewing namespaces 查看命名空间

您可以使用以下命令列出集群中的当前命名空间:

kubectl get namespace
NAME          STATUS    AGE
default       Active    1d
kube-system   Active    1d
kube-public   Active    1d

Kubernetes以三个初始命名空间:

  • default 没有其他命名空间的对象的默认命名空间
  • kube-system Kubernetes系统创建的对象的命名空间
  • kube-public此命名空间是自动创建的,并且所有用户(包括未经过身份验证的用户)都可以读取.此命名空间主要用于集群使用,用于某些资源在整个集群中可见且可公开读取.此命名空间的公共方面只是一个约定,而不是一个要求.

Setting the namespace for a request 设置请求的命名空间

要临时设置请求的命名空间,请使用该--namespace

例如

kubectl --namespace=<insert-namespace-name-here> run nginx --image=nginx
kubectl --namespace=<insert-namespace-name-here> get pods

Setting the namespace preference 设置命名空间首选项

您可以在该上下文中为所有后续kubectl命令永久保存命名空间.

kubectl config set-context $(kubectl config current-context) --namespace=<insert-namespace-name-here>
# Validate it
kubectl config view | grep namespace:

Namespaces and DNS 命名空间和DNS

创建Service服务时,它会创建相应的DNS条目.是这样的..svc.cluster.local,这意味着如果容器只是使用,它将解析为当前命名空间本地的服务.这对于在多个名称空间(如开发,分段和生产)中使用相同的配置非常有用.如果要跨命名空间访问,则需要使用完全限定的域名(FQDN)

Not All Objects are in a Namespace 并非所有对象都在命名空间中

大多数Kubernetes资源(例如pod,service,replication controllers,等)都在某些名称空间中.但是,命名空间资源本身并不在命名空间中.并且低级资源(例如node(节点)和pv(persistentVolumes))不在任何名称空间中.

要查看哪些Kubernetes资源在命名空间中,哪些不在:

# In a namespace
kubectl api-resources --namespaced=true

# Not in a namespace
kubectl api-resources --namespaced=false

Labels and Selectors 标签和选择器

Labels标签是附加到对象(例如pod)的键/值对.标签旨在用于指定对用户有意义且相关对象的标识属性,但不会直接暗示核心系统的语义.标签可用于组织和选择对象的子集.标签可以在创建时附加到对象,随后可以随时添加和修改.每个对象都可以定义一组键/值标签.每个Key对于给定对象必须是唯一的

"metadata": {
  "labels": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

标签允许高效的查询和监视,非常适合在UI和CLI中使用.应使用annotation注释记录非识别信息.

Motivation 目的,动机

标签使用户能够以松散耦合的方式将他们自己的组织结构映射到系统对象,而无需客户端存储这些映射. 服务部署和批处理流水线通常是多维实体(例如,多个分区或部署,多个release渠道,多个层,每层多个微服务).管理通常需要交叉操作,这打破了严格的层次表示的封装,特别是由基础设施而不是用户确定的严格的层次结构.

标签的例子:

  • “release” : “stable”, “release” : “canary”
  • “environment” : “dev”, “environment” : “qa”, “environment” : “production”
  • “tier” : “frontend”, “tier” : “backend”, “tier” : “cache”
  • “partition” : “customerA”, “partition” : “customerB”
  • “track” : “daily”, “track” : “weekly”

这些只是常用标签的例子; 你可以自由地制定自己的规范.请记住,标签Key对于给定对象必须是唯一的.

Syntax and character set 语法和字符集

标签是键/值对.有效标签键有两段:可选前缀和名称,用斜杠(/)分隔.名称段是必需的,必须是63个字符或更少,以字母数字字符([a-z0-9A-Z])开头和结尾,中间可以带有短划线(-),下划线(_),点(.)和字母数字.前缀是可选的.如果指定,前缀必须是DNS子域:由点(.)分隔的一系列DNS标签,总共不超过253个字符,后跟斜杠(/).

如果省略前缀,则假定标签Key对用户是私有的.自动化系统组件(例如kube-scheduler,kube-controller-manager,kube-apiserver,kubectl,或其他第三方自动化),对用户对象添加标签时都必须指定一个前缀.

kubernetes.io/k8s.io/前缀保留给Kubernetes核心组件.

有效标签值必须为63个字符或更少,并且必须为空或以字母数字字符([a-z0-9A-Z])开头和结尾,并带有短划线(-),下划线(_),点(.)和字母数字

Label Selector 标签选择器

不像名字和UID,标签并不具备唯一性,通常,我们希望许多对象携带相同的标签. 通过label selector标签选择器,客户端/用户可以识别一组对象.标签选择器是Kubernetes中的核心分组原语. 目前,API支持两种类型的选择:基于等于,和基于集和的.标签选择器可以由逗号分隔的多个要求组成.在多个要求的情况下,必须满足所有要求,因此逗号分隔符充当逻辑AND(&&)运算符. 空或非指定选择器的语义取决于上下文,使用选择器的API类型应记录它们的有效性和含义.

Equality-based requirement 基于等于

基于等于或不等于的要求允许按标签键和值进行过滤.匹配对象必须满足所有指定的标签约束,尽管它们也可能有其他标签.三种操作符都承认=,==,!=.前两个代表等于(简单地说是同义词),而后者代表不等于.例如:

environment = production
tier != frontend

还可以写成”,“分割,environment=production,tier!=frontend

使用基于等于的场景是给pod指定选择node的条件,例如下面的pod选择标签为accelerator=nvidia-tesla-p100的节点

apiVersion: v1
kind: Pod
metadata:
  name: cuda-test
spec:
  containers:
    - name: cuda-test
      image: "k8s.gcr.io/cuda-vector-add:v0.1"
      resources:
        limits:
          nvidia.com/gpu: 1
  nodeSelector:
    accelerator: nvidia-tesla-p100

Set-based requirement 基于集合

基于集合的标签要求允许根据一组值过滤.三种操作符的支持:in,notinexists(仅key).例如:

environment in (production, qa)
tier notin (frontend, backend)
partition
!partition

基于集合与基于等于可以结合使用,例如:partition in (customerA, customerB),environment!=qa

API

LIST 和 WATCH 过滤

LIST和WATCH操作可以指定标签选择器来过滤使用查询参数返回的对象集.这两个要求都是允许的(在此处显示为出现在URL查询字符串中):

  • 基于等于: ?labelSelector=environment%3Dproduction,tier%3Dfrontend
  • 基于集合: ?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29

两种标签选择器都可用于通过REST客户端列出或查看资源.例如,使用kubectl是这样的:

kubectl get pods -l environment=production,tier=frontend

或者基于集合的方式:

kubectl get pods -l 'environment in (production),tier in (frontend)'

如前所述,基于集合的要求更具表现力.例如,他们可以在值上实现OR运算符:

kubectl get pods -l 'environment in (production, qa)'

或者通过exists操作符限制负匹配:

kubectl get pods -l 'environment,environment notin (frontend)'

Set references in API objects 在API对象中设置引用

某些Kubernetes对象(例如services和replicationcontrollers)也使用标签选择器来指定其他资源集,例如pod.

Service and ReplicationController

service使用标签选择器定义目标的一组pod.类似地,replicationcontroller应该管理的pod的数量也用标签选择器定义.

两个对象的标签选择器在使用映射定义json或yaml文件中定义,并且仅支持基于等于的需求选择器:

"selector": {
    "component" : "redis",
}

或者

selector:
    component: redis
Resources that support set-based requirements 支持基于集合的需求的资源

较新的资源,如Job,Deployment,Replica Set,和Daemon Set,支持基于集合的要求也是如此.

selector:
  matchLabels:
    component: redis
  matchExpressions:
    - {key: tier, operator: In, values: [cache]}
    - {key: environment, operator: NotIn, values: [dev]}

matchLabels是{key,value}的一个map.在matchLabels中一对{key,value}相当于matchExpressions的一个元素,其key字段是“key”,则operator是“in”和values数组仅包含“value”.matchExpressions是一个pod选择器列表.有效的运算符包括In,NotIn,ExistsDoesNotExist.在InNotIn的情况下,设置的值必须是非空的.最终的结果必须满足这两个的所有条件才会返回

Selecting sets of nodes 选择节点集

用于选择标签的一个用例是约束pod可以调度的节点集.有关更多信息,请参阅有关节点选择的文档.

Annotations 注释,注解

您可以使用Kubernetes注释将任意非标识元数据附加到对象.工具和库等客户端可以检索此元数据.

Attaching metadata to objects 将元数据附加到对象

您可以使用标签或注释将元数据附加到Kubernetes对象.标签可用于选择对象和查找满足特定条件的对象集合.相反,注释不用于识别和选择对象.注释中的元数据可以是小的或大的,结构化的或非结构化的,并且可以包括标签不允许的字符.

"metadata": {
  "annotations": {
    "key1" : "value1",
    "key2" : "value2"
  }
}

以下是可以在注释中记录的一些信息示例:

  • 由声明性配置层管理的字段.将这些字段作为注释附加,可以将它们与客户端或服务器设置的默认值以及自动生成的字段和自动调整大小或自动调整系统设置的字段区分开来.
  • 构建,发布或镜像信息,如时间戳,版本ID,git分支,PR编号,哈希和注册表地址.
  • 指向日志记录,监视,分析或审计存储库的指针.
  • 可用于调试目的的客户端库或工具信息:例如,名称,版本和构建信息.
  • 用户或工具/系统出处信息,例如来自其他生态系统组件的相关对象的URL.
  • 轻量推出工具元数据:例如,配置或检查点.
  • 负责人的电话或寻呼机号码,或指定可在何处找到该信息的目录条目,例如团队网站.
  • 从最终用户到实现的指令,用于修改行为或使用非标准功能.

您可以将此类信息存储在外部数据库或目录中,而不是使用注释,但这会使生成用于部署,管理,内省等的共享客户端库和工具变得更加困难.

Syntax and character set 语法和字符集

注释是键/值对.有效的注释键有两个段:可选的前缀和名称,用斜杠(/)分隔.名称是必需的,必须是63个字符或更少,以字母数字([a-z0-9A-Z])开头和结尾,带有短横线(-),下划线(_),点(.)和字母数字之间.前缀是可选的.如果指定,前缀必须是DNS子域:由点(.)分隔的一系列DNS标签,总共不超过253个字符,后跟斜杠(/).

如果省略前缀,则假定注释的key对用户是私有的.自动化系统组件(例如kube-scheduler,kube-controller-manager,kube-apiserver,kubectl,或其他第三方自动化)对用户对象添加注释时都必须指定一个前缀.

kubernetes.io/k8s.io/前缀保留给Kubernetes核心组件

Field Selectors 字段选择器

字段选择器允许您根据一个或多个资源字段的值选择Kubernetes资源.以下是一些示例字段选择器查询:

  • metadata.name=my-service
  • metadata.namespace!=default
  • status.phase=Pending

使用kubectl查询所有status.phaseRunning的命令:

kubectl get pods --field-selector status.phase=Running

Supported fields 支持的字段

支持的字段选择器因Kubernetes资源类型而异.所有资源类型都支持metadata.name和metadata.namespace字段.使用不受支持的字段选择器会产生错误.例如:

kubectl get ingress --field-selector foo.bar=baz
Error from server (BadRequest): Unable to find "ingresses" that match label selector "", field selector "foo.bar=baz": "foo.bar" is not a known field selector: only "metadata.name", "metadata.namespace"

Supported operators 支持的操作符

可以使用=,==以及!=,例如使用kubectl选择不在default命名空间中的所有Kubernetes服务:

kubectl get services --field-selector metadata.namespace!=default

Chained selectors 链式选择器

与标签和其他选择器一样,字段选择器可以作为逗号分隔列表链接在一起.这个kubectl命令选择status.phase不等于Running且spec.restartPolicy字段等于Always的所有Pod :

kubectl get pods --field-selector=status.phase!=Running,spec.restartPolicy=Always

Multiple resource types 多种资源类型

您可以跨多种资源类型使用字段选择器.此kubectl命令选择不在default命名空间中的所有Statefulsets和Services :

kubectl get statefulsets,services --field-selector metadata.namespace!=default

您可以使用比kubectl和dashboard更多的工具来可视化和管理Kubernetes对象.可以设置一组通用的标签允许工具互相操作的方式工作,用所有工具都能理解的通用方式描述对象.

除支持工具外,推荐标签还以可查询的方式描述应用程序

元数据围绕应用程序的概念进行组织.Kubernetes不是一个服务平台(PaaS),也没有或强制执行正式的应用程序概念.相反,应用程序是非正式的,并使用元数据来描述 应用程序包含的内容的定义是松散的.

推荐的标签都不是必须的,它只是让你管理应用程序更方便,对于任何工具来说都不是必要的

共享标签和注释共享一个共同的前缀:app.kubernetes.io.没有前缀的标签对用户是私有的.共享前缀可确保共享标签不会干扰自定义用户标签.

Labels 标签

Key Description Example Type
app.kubernetes.io/name 应用程序的名字 mysql string
app.kubernetes.io/instance 标识应用程序实例的唯一标识 wordpress-abcxzy string
app.kubernetes.io/version 应用程序当前版本 5.7.21 string
app.kubernetes.io/component 在架构中作为什么组件 database string
app.kubernetes.io/part-of 更高级别应用程序的名称 wordpress string
app.kubernetes.io/managed-by 用于管理的工具 helm string

用于描述上面这个信息的StatefulSet,是下面这样

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "5.7.21"
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/managed-by: helm

Applications And Instances Of Applications 应用程序和应用程序实例

应用程序可以一次或多次安装到Kubernetes集群中,在某些情况下,可以安装在同一名称空间中.例如,wordpress可以不止一次安装,其中不同的网站是wordpress的不同安装. 应用程序的名称和实例名称分别记录.例如,在WordPress具有app.kubernetes.io/name的wordpress,同时它有一个实例名,被表示为app.kubernetes.io/instance具有值 wordpress-abcxzy.这使得应用程序的应用程序和实例可以识别.应用程序的每个实例都必须具有唯一的名称

Examples 例子

为了说明使用这些标签的不同方式,以下示例具有不同的复杂性.

A Simple Stateless Service 简单的无状态服务

考虑使用Deployment和Service对象部署的简单无状态服务的情况.以下两个代码段表示如何以最简单的形式使用标签.

这个Deployment是用来配置运行应用程序本身的pod.

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

这个Service用来暴露应用:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: myservice
    app.kubernetes.io/instance: myservice-abcxzy
...

Web Application With A Database 有一个数据库的Web应用程序

考虑一个稍微复杂的应用程序:使用Helm安装的使用数据库(MySQL)的Web应用程序(WordPress).以下代码段说明了用于部署此应用程序的对象

以下Deployment内容用于WordPress:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

用Service暴露应用:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: wordpress
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/version: "4.9.4"
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: server
    app.kubernetes.io/part-of: wordpress
...

使用StatefulSet来部署MySQL,并且在metadata中添加它所属的应用:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/version: "5.7.21"
...

使用Service暴露MySQL服务:

apiVersion: v1
kind: Service
metadata:
  labels:
    app.kubernetes.io/name: mysql
    app.kubernetes.io/instance: wordpress-abcxzy
    app.kubernetes.io/managed-by: helm
    app.kubernetes.io/component: database
    app.kubernetes.io/part-of: wordpress
    app.kubernetes.io/version: "5.7.21"
...