资源对象管理基础

K8S系统的API Server基于HTTP/HTTPS接收并响应客户端的操作请求,它提供了RESTful风格的编程接口,将集群的各种组件都抽象成标准的REST资源,如Node,Namespaces,和Pod等,并支持通过标准的HTTP方法以JSON为数据序列化方案进行资源管理操作,通俗点理解就是,API Server将集群内的组件抽象成一个一个的HTTP客户端,客户端请求API Server都是以HTTP或者https的形式发送json数据格式的请求给API Server来完成请求和响应

资源对象及API群组

REST是representation state transfer的缩写,意为“表征状态转移”它是一种程序架构风格,基本元素为(resource)、表征(representation)和行为(action)。资源即对象,一个资源通常意味着一个附带类型和关联数据、支持的操作方法以及与其他对象的关系的对象,它们是有状态的事务,即REST中的(S),REST组件通过使用“表征”来捕获资源的当前或预期状态并再组件之间传输该表征从而对资源执行操作,表征是一个字节序列,由数据,描述数据的元数据以及偶尔描述元素及的元素据组成(通常用于验证消息的完整性),表征还有一些其他常用但不太精确的名称,如文档,文件和HTTP消息实体等 Kubernetes系统将一切事物都抽象为API资源,其遵循REST架构风格组织并管理这些资源及其对象,同时还支持通过标准的HTTP方法(POST,PUT,DELETE,PATCH,GET)对资源进行增、删、改、查等管理操作。不过,在k8s系统的语境中,“资源”用于表示“对象”的集合。例如,Pod资源可用于描述所有Pod类型的对象

K8S的资源对象

依据资源的主要功能作为分类标准的话,K8S的API对象大体可以分为“工作负载(workerload)”、“发现和负载均衡(discovery & LB)”、“配置和存储(config & storage)”、“集群(cluster)”以及元素据(metadata)五个类别。它们基本上都是围绕着一个核心目的而设计:如何更好的运行和丰富Pod资源,从而为容器化应用提供更灵活,更完善的操作与管理组件 如下图: K8S资源对象管理(一)之资源对象管理基础 - 图1 工作负载型资源用于确保Pod资源对象能够更好的运行容器化应用,具有同一种负载均衡的各Pod对象需要以负载均衡的方式服务于各请求,而各种容器化应用彼此之间需要“彼此发现”以完成工作协同,Pod资源具有生命周期,存储型资源能够为重构的Pod对象提供持久化的数据存储机制,共享同一配置的Pod资源可从配置资源中统一获取配置改动信息,这些资源作为配置中心为管理容器化应用的配置文件提供了极为便捷的管理机制,集群型资源为管理集群本身的工作特性提供了管理接口,而元数据型资源则用于配置集群内部的其他资源的行为

  • 工作负载型资源
  • Pod是工作负载型资源中的基础资源,它负责运行容器,并为其解决环境依赖的问题,例如向容器注入共享的或持久化的存储卷,配置信息或密钥数据等。但Pod可能会因为资源超限或节点故障等原因而终止,这些非正常终止的Pod资源需要被重建,不过,这类工作将由工作负载型的控制器来完成,它们通常也被称为Pod控制器
  • 应用程序分为无状态有状态两种类型,它们对环境的依赖及工作特性有很大的不同,因此需要由两种不同类型的Pod控制器来管理,ReplicationController、replicaSet和Deployment负责管理无状态的应用,StatefulSet负责管理有状态类的应用。ReplicationController 是上一代的控制器,其功能已由ReplicaSet、Deployment负责实现,因此几近于废弃。还有些应用较为独特,它们需要在集群中的每个节点上运行单个Pod资源,负责收集日志或运行系统服务等任务,这些Pod资源的管理则属于DaemonSet控制的分内之事。另外,有些容器化应用需要继续运行以守护进程不间断的提供服务,而有些则应该在正常完成后退出,这些在正常完成后就应该退出的容器化应用则由Job控制器来负责管控
  • ReplicationController:用来确保容器应用的副本数始终保持在用户定义的期望副本数,如果容器异常退出,则会自动创建新的Pod来代替,而异常退出的容器也会自动回收,典型的应用场景包括确保健康Pod的数量,弹性伸缩,滚动升级以及应用多版本发布跟踪等
  • ReplicaSet:新一代的RC,它与RC的唯一不同之处仅在于支持的标签选择器不同,RC只支持等值选择器,而ReplicaSet还额外支持用于集合式的选择器
  • Deployment:用于管理无状态的持久化应用,如HTTP服务器,它用于为Pod和ReplicaSet提供声明式更新,是建构在ReplicaSet之上的更为高级的控制器,Deployment的典型应用场景有,定义Deployemtn来创建Pod和ReplicaSet,滚动升级和回滚应用,扩容和缩容,暂停和继续Deployment
  • StatefulSet:用于管理有状态的持久化应用,如databases服务,其与Deployment的不同之处在于StatefulSet会为每个Pod创建一个独有的持久性标识符,并会确保各Pod之间的顺序性,statefulSet的应用场景有:1.稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现。2.稳定的网络标志,即Pod重新调度后,其PodName和HostName不变,基于headless Service(无头服务)(没有ClusterIP的Service)来实现。3.有序部署,有序扩展,即Pod是有顺序的,在部署或扩展的时候要依据定义的顺序进行(从0到N+1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现。4.有序收缩,有序删除
  • daemonSet:用于确保每个节点都运行了某Pod的一个副本,新增的节点一样会被添加此类Pod,节点移除时,此类Pod会被回收,DaemonSet常用于运行集群存储守护进程,如glusterd和ceph,还有日志收集进程,fluentd和logstash以及监控进程,如Promethues的Node exporter colletcd,datadog agent
  • Job:用于管理运行完成后即可终止的应用,例如一些批处理作业任务,换句话说就是专门用于处理那些短暂的一次性任务
  • 发现和负载均衡
  • Pod资源可能会因为任何意外故障而被重建,于是它需要固定的可被“发现”的方式。另外Pod资源仅在集群中可见,它的客户端也可能是集群内的其他Pod资源,若要开放给外部网络中的用户访问,则需要实现将其暴漏到集群外部,并且要为同一种工作负载的访问流量进行负载均衡,K8S使用标准的资源对象来解决此类问题,它们是用于为工作负载添加发现机制及负载均衡功能的Service资源和Endpoints资源,以及通过七层代理实现请求流量负载均衡的Ingress资源
  • k8s在设计之初就充分考虑了针对容器的服务发现和负载均衡机制,提供了Service资源,并通过kube-proxy配合cloud provider来适应不同的应用场景,随着K8S用户的激增,用户场景的不断丰富,又产生了一些新的负载均衡机制。目前K8s中的负载均衡可以分为以下几种机制,每种机制都有其特定的应用场景
  • Service:直接用Service提供集群内部的负载均衡,并借助cloud provider提供的LB提供外部访问
  • Ingress Controller:还是用Service提供集群内部的负载均衡,但是通过自定义Ingress Controller提供外部访问
  • Service LoadBanlancer:把load banlancer直接跑在容器中,实现bare metal的服务负载均衡
  • Custom LoadBanlancer:自定义负载均衡,替代kube-proxy,一般在物理部署K8S时使用,方便接入公司已有的外部服务
  • Service是对一组提供相同功能的Pod的抽象,并为它们提供一个统一的访问入口,借助Service,应用可以很方便的实现负载均衡于服务发现,并实现应的零宕机升级,Service通过标签来选取后端服务,一般配合Deployment来保证后端容器的正常运行,这些匹配标签的Pod IP和端口列表组成endpoints,由kube-proxy负载将服务IP负载均衡到这些endpoints上
  • 配置与存储
  • docker容器分层联合挂载的方式决定了不宜在容器内部存储需要持久化的数据,于是它通过引入挂在外部的存储卷的方式来解决此类问题,而K9S则为此设计了volume资源,它支持众多类型的存储设备和存储系统,另外,新版本的K8S还支持CSI(container storage interface)统一存储接口以及扩展支持更多类型的存储系统。
  • 另外,基于镜像构建容器应用时,其配置信息需要在镜像制作时配置,从而为不同的环境定制配置就变得较为困难,Docker使用环境变量等方式作为解决方案,但这么一来就需要在容器启动时将变量值传入,且无法在运行时修改。configmap资源能够以环境变量或存储卷的方式接入到Pod资源的容器中,并且可被多个同类的Pod所共享引用,从而实现”一次修改,多处生效”。不过,这种方式不适用于存储敏感数据,如,私钥,密码等,所以就有了secret的功能
  • Secret:Secret解决了密码,token,密钥等敏感数据的配置问题,而不需要把这些敏感数据暴漏到镜像或者Pod Spec中。Secret可以以Volume或者环境变量的方式使用
  • 集群级资源
  • Pod、Deployment、Service和ConfigMap等资源属于名称空间级别,可由相应的项目管理控制,然而,kubernetes还村在一些别的集群级别的资源,用于定义集群自身配置信息的对象,它们仅应该由集群管理管进行操作,集群级资源对象包含以下几种类型:
  • Namespace:资源对象名称的作用范围,绝大多数对象都隶属于某个名称空间,默认时隶属于“default”
  • Node:Kubernetes集群的工作节点,其标识符在当前集群中必须是唯一的
  • Role:名称空间级别的由规则组成的权限集合,可被RoleBinding引用
  • ClusterRole:Cluster级别的由规则组成的权限集合,可被RoleBinding和ClusterRoleBinding引用
  • RoleBinding:将Role中的许可授权权限绑定在一个或一组用户至上,它隶属于且仅能用于一个名称空间,绑定时,可以引用同一名称空间的role,也可以引用全局名称空间中的ClusterRole
  • ClusterRoleBinding:将ClusterRole中定义的许可权限绑定在一个或一组用户至上,它能够引用全局名称空间中的ClusterRole。并能通过subeject添加相关信息
  • 元素据类型,此类资源对象用于为集群内部的其他资源配置其行为或者特性,如HorizontalPodAutoscaler资源可以用于自动伸缩工作负载类型的资源对象的规模,Pod模板资源可以用于为Pod资源的创建预制模板,而LimitRange则可以为名称空间的资源设置其CPU和内存等系统级资源的数量限制
  • 小提示:一个应用通常需要多个资源的支撑,例如,使用Deployment资源对象管理应用实例,使用ConfigMap资源保存应用配置,使用Service或Ingress资源暴漏服务,使用Volume资源提供外部存储

资源及其在API中的组织形式

在K8S中,资源对象代表了系统上的持久实体类,K8S用这些持久实体类实体来表达集群的状态,包括容器化应用正在运行于哪个节点,每个应用程序有哪些资源可用,以及每个应用程序各自的行为策略,如重启,升级及容错策略等。一个对象可能会包含多个资源,用户可对这些资源进行增、删、改、查等管理操作。K8S通常利用标准的RESTful术语来描述API概念

  • 资源类型(resource type)是指在URL中使用的名称:如Pod、Namespace、和Service等。其URL格式为GROUP/VERSION/RESOURCE,如apps/v1/deployment
  • 所有资源类型都有一个对应的JSON表示格式,称为“种类(kind)”;客户端创建对象必须以JSON提交对象的配置信息
  • 隶属于同一资源类型的对象组成的列表称为“集合(collection)”如Podlist
  • 某种类型的单个实体称为“资源(resource)”或“对象(object)”,如名为Pod-daemon的Pod对象
    Kind代表着资源对象所属的类型,如Namespace、Deployment、Service及Pod等,而这些资源类型大体可以分为三个类别
  • 对象(object)类:对象表示K8S系统上的持久化实体,一个对象可能包含多个资源,客户端可用它执行多种操作。Namespace、Deployment、Service及Pod等属于这个类型
  • 列表(list)类:列表通常是指同一类型资源的集合,如Podlist、Nodelist等
  • 简单(simple)类:常用于在对象上执行某种特殊操作,或者管理非持久化的实体,如/binding或/status等
    k8s绝大多数的API资源类型都是“对象”,他们代表着集群中某个概念的实例。有一小部分的API资源类型为“虚拟(Virtual)类型”,他们用于表达一类“操作(operation)”。所有的对象型资源都拥有一个独有的名称标识以实现其幂等的创建及获取操作,不过,虚拟型资源无需获取或不依赖于幂等性时也可以不使用专用标识符
    有些资源类型隶属于集群范畴、如Namespace和PersistenVolume,而多数资源类型则受限于名称空间,如Pod、Deployment和Service等。名称空间级别的资源的URL路径中含有其所属名称空间的名称,这些资源对象在名称空间被删除会被一并删除,并且这些资源对象的访问也将受限于其所属的名称空间级别的授权审查
    K8S将API分割为多个逻辑组合,称为API群组,它们支持单独禁用或启用,并能够再次分辨。API Server支持在不同的群组中使用不同的版本,允许各组以不同的速度演进,而且也支持同一群组同时存在不同的版本,如apps/v1、app2/v1beta2和apps/v1beta1,也因此能够在不同的群组中使用同名的资源类型,从而能在稳定版本的群组及新的实验群组中以不同的特性同时使用同一个资源类型。群组化管理的API使得其可以更轻松的进行扩展。当前系统的API Server上的相关信息通过kubectl api-versions命令获取。
  1. [root@k8s-master01 ~]# kubectl api-versions
  2. admissionregistration.k8s.io/v1
  3. admissionregistration.k8s.io/v1beta1
  4. apiextensions.k8s.io/v1
  5. apiextensions.k8s.io/v1beta1
  6. apiregistration.k8s.io/v1
  7. apiregistration.k8s.io/v1beta1
  8. apps/v1
  9. authentication.k8s.io/v1
  10. authentication.k8s.io/v1beta1
  11. authorization.k8s.io/v1
  12. authorization.k8s.io/v1beta1
  13. autoscaling/v1
  14. autoscaling/v2beta1
  15. autoscaling/v2beta2
  16. batch/v1
  17. batch/v1beta1
  18. certificates.k8s.io/v1beta1
  19. coordination.k8s.io/v1
  20. coordination.k8s.io/v1beta1
  21. events.k8s.io/v1beta1
  22. extensions/v1beta1
  23. networking.k8s.io/v1
  24. networking.k8s.io/v1beta1
  25. node.k8s.io/v1beta1
  26. policy/v1beta1
  27. rbac.authorization.k8s.io/v1
  28. rbac.authorization.k8s.io/v1beta1
  29. scheduling.k8s.io/v1
  30. scheduling.k8s.io/v1beta1
  31. storage.k8s.io/v1
  32. storage.k8s.io/v1beta1
  33. v1
  34. [root@k8s-master01 ~]#

k8s的API以层级结构组织在一起,每个API群组表现为一个“/apis”为根路径的REST路径,不过核心群组core有一个专用的简化路径”/api/v1”。目前,常用的API群组可以归为如下两类

  • 核心群组(core group):REST路径为/app/v1,在资源的配置信息,apiVersion字段中引用时可以不指定路径,而近给出版本,如apiVersion: v1
  • 命名的群组(named group):REST路径为apis/$GROUP_NAME/$VERSION,例如/apis/apps/v1,它在apiVersion字段中引用的格式为apiVersion: $GROUP_NAME/VERSION如:apiVersion: apps/v1
    总结起来,名称空间级别的每一个资源类型在API中的URL路径表示都可简单抽象为如/apis/<group>/namespaces/<namespace>/<kind-plural>的路径,如default名称空间中Deployment类型的路径为/apis/apps/v1/namespaces/default/deployments,通过此路径可获取到名称空间中所有deployment对象的列表
  1. [root@k8s-master01 ~]# kubectl get --raw /apis/apps/v1/namespaces/default/deployments
  2. {"kind":"DeploymentList","apiVersion":"apps/v1","metadata":{"selfLink":"/apis/apps/v1/namespaces/default/deployments","resourceVersion":"44025"},"items":[{"metadata":{"name":"my-nginx","namespace":"default","selfLink":"/apis/apps/v1/namespaces/default/deployments/my-nginx","uid":"3e0173cc-71d6-4b61-bd10-3c3292c48642","resourceVersion":"44013","generation":1,"creationTimestamp":"2020-05-31T17:40:16Z","annotations":{"deployment.kubernetes.io/revision":"1","kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"apps/v1\",\"kind\":\"Deployment\",\"metadata\":{\"annotations\":{},\"name\":\"my-nginx\",\"namespace\":\"default\"},\"spec\":{\"replicas\":5,\"selector\":{\"matchLabels\":{\"app\":\"my-nginx\"}},\"template\":{\"metadata\":{\"labels\":{\"app\":\"my-nginx\"}},\"spec\":{\"containers\":[{\"image\":\"daocloud.io/library/nginx:1.13.0-alpine\",\"name\":\"my-nginx\",\"ports\":[{\"containerPort\":80}]}]}}}}\n"}},"spec":{"replicas":5,"selector":{"matchLabels":{"app":"my-nginx"}},"template":{"metadata":{"creationTimestamp":null,"labels":{"app":"my-nginx"}},"spec":{"containers":[{"name":"my-nginx","image":"daocloud.io/library/nginx:1.13.0-alpine","ports":[{"containerPort":80,"protocol":"TCP"}],"resources":{},"terminationMessagePath":"/dev/termination-log","terminationMessagePolicy":"File","imagePullPolicy":"IfNotPresent"}],"restartPolicy":"Always","terminationGracePeriodSeconds":30,"dnsPolicy":"ClusterFirst","securityContext":{},"schedulerName":"default-scheduler"}},"strategy":{"type":"RollingUpdate","rollingUpdate":{"maxUnavailable":"25%","maxSurge":"25%"}},"revisionHistoryLimit":10,"progressDeadlineSeconds":600},"status":{"observedGeneration":1,"replicas":5,"updatedReplicas":5,"readyReplicas":2,"availableReplicas":2,"unavailableReplicas":3,"conditions":[{"type":"Progressing","status":"True","lastUpdateTime":"2020-05-31T17:40:18Z","lastTransitionTime":"2020-05-31T17:40:16Z","reason":"NewReplicaSetAvailable","message":"ReplicaSet \"my-nginx-854bbd7557\" has successfully progressed."},{"type":"Available","status":"False","lastUpdateTime":"2020-06-07T06:46:23Z","lastTransitionTime":"2020-06-07T06:46:23Z","reason":"MinimumReplicasUnavailable","message":"Deployment does not have minimum availability."}]}}]}
  3. [root@k8s-master01 ~]#

另外,K8S还支持用户自定义资源类型,目前常用的方式有三种

  • 修改K8S源码自定义类型
  • 创建一个自定以的API Server,并将其聚合至集群中
  • 使用自定资源(Custom Resource Definition CRD)

访问K8S REST API

以变成的方式访问K8S REST API 有助于了解其流式化的集群管理机制,一种常用的方式是使用curl命令作为HTTP客户端直接通过API Server在集群上操作资源对象模拟请求和响应的过程。不过,由kebeadm部署的集群默认仅支持HTTPS的访问接口,它需要进行一系列的认证检查,好在用户可以借助kubectl proxy命令在本地主机上为API Server启动一个代理网关,由它支持使用http进行通信

  1. [root@k8s-master01 ~]# kubectl proxy --port=8080
  2. F0607 12:53:03.034737 6560 proxy.go:160] listen tcp 127.0.0.1:8080: bind: address already in use
  3. [root@k8s-master01 ~]#
  4. 因为我在本机已经监听了8080端口,使用proxy代理会提示端口已存在

而后即可用curl一类的客户端工具对此套接字发起访问请求,例如,请求K8S集群上的NamespaceList资源对象,即列出集群上所有的namespace对象

  1. [root@k8s-master01 ~]# curl http://192.168.1.16:8080/api/v1/namespaces
  2. {
  3. "kind": "NamespaceList",
  4. "apiVersion": "v1",
  5. "metadata": {
  6. "selfLink": "/api/v1/namespaces",
  7. "resourceVersion": "44824"
  8. },
  9. "items": [
  10. {
  11. "metadata": {
  12. "name": "default",
  13. "selfLink": "/api/v1/namespaces/default",
  14. "uid": "f3a0a4fd-0f05-46a4-8336-f1bd9112edf5",
  15. "resourceVersion": "143",
  16. "creationTimestamp": "2020-05-31T07:55:45Z"
  17. },
  18. "spec": {
  19. "finalizers": [
  20. "kubernetes"
  21. ]
  22. },
  23. "status": {
  24. "phase": "Active"
  25. }
  26. },
  27. {
  28. "metadata": {
  29. "name": "kube-node-lease",
  30. "selfLink": "/api/v1/namespaces/kube-node-lease",
  31. "uid": "7d991eb1-4356-4d37-889b-c136e1932cfe",
  32. "resourceVersion": "6",
  33. "creationTimestamp": "2020-05-31T07:55:44Z"
  34. },
  35. "spec": {
  36. "finalizers": [
  37. "kubernetes"
  38. ]
  39. },
  40. "status": {
  41. "phase": "Active"
  42. }
  43. },
  44. {
  45. "metadata": {
  46. "name": "kube-public",
  47. "selfLink": "/api/v1/namespaces/kube-public",
  48. "uid": "da40cfe9-55a9-4538-8dc6-62780455aeb9",
  49. "resourceVersion": "5",
  50. "creationTimestamp": "2020-05-31T07:55:44Z"
  51. },
  52. "spec": {
  53. "finalizers": [
  54. "kubernetes"
  55. ]
  56. },
  57. "status": {
  58. "phase": "Active"
  59. }
  60. },
  61. {
  62. "metadata": {
  63. "name": "kube-system",
  64. "selfLink": "/api/v1/namespaces/kube-system",
  65. "uid": "116236ba-88c7-47c6-afa2-a6b9ea4885ae",
  66. "resourceVersion": "4",
  67. "creationTimestamp": "2020-05-31T07:55:44Z"
  68. },
  69. "spec": {
  70. "finalizers": [
  71. "kubernetes"
  72. ]
  73. },
  74. "status": {
  75. "phase": "Active"
  76. }
  77. }
  78. ]
  79. [root@k8s-master01 ~]#

或者使用json的命令行处理器jq命令对响应的json数据流进行过滤,例如下面的命令仅用于显示相关的NamespaceList对象中的各成员对象

  1. [root@k8s-master01 ~]# curl http://192.168.1.16:8080/api/v1/namespaces |jq .items[].metadata.name
  2. % Total % Received % Xferd Average Speed Time Time Time Current
  3. Dload Upload Total Spent Left Speed
  4. 100 1760 100 1760 0 0 828k 0 --:--:-- --:--:-- --:--:-- 859k
  5. "default"
  6. "kube-node-lease"
  7. "kube-public"
  8. "kube-system"
  9. [root@k8s-master01 ~]#

给出特定的Namespace资源对象的名称则能够直接获取相应的资源洗洗,以kube-system名称空间为例

  1. [root@k8s-master01 ~]# curl http://192.168.1.16:8080/api/v1/namespaces/kube-system
  2. {
  3. "kind": "Namespace",
  4. "apiVersion": "v1",
  5. "metadata": {
  6. "name": "kube-system",
  7. "selfLink": "/api/v1/namespaces/kube-system",
  8. "uid": "116236ba-88c7-47c6-afa2-a6b9ea4885ae",
  9. "resourceVersion": "4",
  10. "creationTimestamp": "2020-05-31T07:55:44Z"
  11. },
  12. "spec": {
  13. "finalizers": [
  14. "kubernetes"
  15. ]
  16. },
  17. "status": {
  18. "phase": "Active"
  19. }
  20. }[root@k8s-master01 ~]#

上述命令响应的结果中展现了K8S大多数资源对象的配置格式,它是一个json序列化的数据结构,具有kind、apiVersion、metadata、spec和staus五个一级字段

对象类资源格式

K8S API仅接受及相应json格式的数据,同时,为了便于使用,它也允许用户yaml格式的POST对象,但API Server需要实现自行将其转换为JSON格式后才能提交。API Server接受和返回的所有json对象都遵循同一个模式,它们都具有kind和apiVersion字段,用于标识对象所属的资源类型,API群组及相关的版本。 大多数的对象或列表类型的资源还需要三个嵌套型的字段,metadata、spec、status,其中metadata字段为资源提供元数据信息,如名称,隶属的名称空间和标签等;spec则用于定义用户的期望状态,不同的资源类型,其状态的意义也各不相同,例如Pod资源最为核心的功能在于运行容器;而status字段则记录着活动对象的当前状态信息,它由k8s系统自行维护,对用户来说它是只读字段 每个字段通常仅接受并返回单一类型的数据,而一种类型可以被多个反映特定用例的资源所接受或返回。例如对于Pod类型的资源来说,用户可以创建、更新或删除Pod对象,然而,每个Pod对象的metadata、spec、status字段的值却又是各自独立的对象型数据,它们可以被单独操作,尤其是status字段,是由K8S系统单独进行自动更新,而不能由用户手动操作

资源配置清单

之前有使用curl [http://192.168.1.16:8080/api/v1/namespaces/kube-system](http://192.168.1.16:8080/api/v1/namespaces/kube-system)命令的方式在API Server上请求到了kube-system这个名称空间的状态信息,事实上,用户也可以直接使用kubectl get TYPE/NAME -o yaml命令获取任何对象的yaml格式的配置清单,或者使用’kubectl get TYPS/NAME -o json’命令和过去json格式的配置清单,例如,可以使用下面的命令获取kube-system名称空间的状态信息

  1. [root@k8s-master01 ~]# kubectl get ns kube-system -o yaml
  2. apiVersion: v1
  3. kind: Namespace
  4. metadata:
  5. creationTimestamp: "2020-05-31T07:55:44Z"
  6. name: kube-system
  7. resourceVersion: "4"
  8. selfLink: /api/v1/namespaces/kube-system
  9. uid: 116236ba-88c7-47c6-afa2-a6b9ea4885ae
  10. spec:
  11. finalizers:
  12. - kubernetes
  13. status:
  14. phase: Active
  15. [root@k8s-master01 ~]#

除了极少数的资源之外,K8S 系统的绝大多数资源都是由它的使用者创建创建的,创建时,需要以上述描述输出结果中类似的方式以YAML或json序列化的方式定义资源的相关配置,然后再由K8S的底层组件确保活动对象的运行时状态与用户提供的配置清单中定义的状态无限接近,因此,资源的创建要通过用户提供的资源配置清单来进行,其格式类似于kubectl get命令获取到的yaml或json形式的输出结果,不过,status字段对用户来说为只读字段,它由K8S集群自行维护,例如,下面的例子就是创建一个名称为dev的namespace资源时提供的配置清单实例

  1. [root@k8s-master01 nginx]# cat dev.yaml
  2. apiVersion: v1
  3. kind: Namespace
  4. metadata:
  5. name: dev
  6. spec:
  7. finalizers:
  8. - kubernetes
  9. [root@k8s-master01 nginx]#

将上述的配置清单保存到文件中,使用kubectl create -f /PATH/FILENAME命令即可将其创建到集群中。创建完成后查看YAML或json格式的输出结果,可以看到K8S会自动不全大部分的字段,并提供相应的数据,事实上,K8S的大多数资源都能够以类似的方式进行创建和查看,而且他们几乎都遵循类似的组织结构

  1. [root@k8s-master01 nginx]# kubectl create -f /etc/kubernetes/nginx/dev.yaml
  2. namespace/dev created
  3. [root@k8s-master01 nginx]#
  4. [root@k8s-master01 nginx]# kubectl create -f /etc/kubernetes/nginx/dev.yaml
  5. namespace/dev created
  6. [root@k8s-master01 nginx]# kubectl get ns dev
  7. NAME STATUS AGE
  8. dev Active 19s
  9. [root@k8s-master01 nginx]# kubectl get ns dev -o yaml
  10. apiVersion: v1
  11. kind: Namespace
  12. metadata:
  13. creationTimestamp: "2020-06-07T07:27:21Z"
  14. name: dev
  15. resourceVersion: "47495"
  16. selfLink: /api/v1/namespaces/dev
  17. uid: e4cb1150-2401-4f37-9992-66373953b7b0
  18. spec:
  19. finalizers:
  20. - kubernetes
  21. status:
  22. phase: Active
  23. [root@k8s-master01 nginx]#
  24. [root@k8s-master01 nginx]# kubectl get ns dev -o json
  25. {
  26. "apiVersion": "v1",
  27. "kind": "Namespace",
  28. "metadata": {
  29. "creationTimestamp": "2020-06-07T07:27:21Z",
  30. "name": "dev",
  31. "resourceVersion": "47495",
  32. "selfLink": "/api/v1/namespaces/dev",
  33. "uid": "e4cb1150-2401-4f37-9992-66373953b7b0"
  34. },
  35. "spec": {
  36. "finalizers": [
  37. "kubernetes"
  38. ]
  39. },
  40. "status": {
  41. "phase": "Active"
  42. }
  43. }
  44. [root@k8s-master01 nginx]#

例如再查看一个deployment资源对象名为my-nginx的状态

  1. [root@k8s-master01 nginx]# kubectl get deployment
  2. NAME READY UP-TO-DATE AVAILABLE AGE
  3. my-nginx 5/5 5 5 6d13h
  4. [root@k8s-master01 nginx]# kubectl get deployment my-nginx -o yaml
  5. apiVersion: apps/v1
  6. kind: Deployment
  7. metadata:
  8. annotations:
  9. deployment.kubernetes.io/revision: "1"
  10. kubectl.kubernetes.io/last-applied-configuration: |
  11. {"apiVersion":"apps/v1","kind":"Deployment","metadata":{"annotations":{},"name":"my-nginx","namespace":"default"},"spec":{"replicas":5,"selector":{"matchLabels":{"app":"my-nginx"}},"template":{"metadata":{"labels":{"app":"my-nginx"}},"spec":{"containers":[{"image":"daocloud.io/library/nginx:1.13.0-alpine","name":"my-nginx","ports":[{"containerPort":80}]}]}}}}
  12. creationTimestamp: "2020-05-31T17:40:16Z"
  13. generation: 1
  14. name: my-nginx
  15. namespace: default
  16. resourceVersion: "44538"
  17. selfLink: /apis/apps/v1/namespaces/default/deployments/my-nginx
  18. uid: 3e0173cc-71d6-4b61-bd10-3c3292c48642
  19. spec:
  20. progressDeadlineSeconds: 600
  21. replicas: 5
  22. revisionHistoryLimit: 10
  23. selector:
  24. matchLabels:
  25. app: my-nginx
  26. strategy:
  27. rollingUpdate:
  28. maxSurge: 25%
  29. maxUnavailable: 25%
  30. type: RollingUpdate
  31. template:
  32. metadata:
  33. creationTimestamp: null
  34. labels:
  35. app: my-nginx
  36. spec:
  37. containers:
  38. - image: daocloud.io/library/nginx:1.13.0-alpine
  39. imagePullPolicy: IfNotPresent
  40. name: my-nginx
  41. ports:
  42. - containerPort: 80
  43. protocol: TCP
  44. resources: {}
  45. terminationMessagePath: /dev/termination-log
  46. terminationMessagePolicy: File
  47. dnsPolicy: ClusterFirst
  48. restartPolicy: Always
  49. schedulerName: default-scheduler
  50. securityContext: {}
  51. terminationGracePeriodSeconds: 30
  52. status:
  53. availableReplicas: 5
  54. conditions:
  55. - lastTransitionTime: "2020-05-31T17:40:16Z"
  56. lastUpdateTime: "2020-05-31T17:40:18Z"
  57. message: ReplicaSet "my-nginx-854bbd7557" has successfully progressed.
  58. reason: NewReplicaSetAvailable
  59. status: "True"
  60. type: Progressing
  61. - lastTransitionTime: "2020-06-07T06:50:22Z"
  62. lastUpdateTime: "2020-06-07T06:50:22Z"
  63. message: Deployment has minimum availability.
  64. reason: MinimumReplicasAvailable
  65. status: "True"
  66. type: Available
  67. observedGeneration: 1
  68. readyReplicas: 5
  69. replicas: 5
  70. updatedReplicas: 5
  71. [root@k8s-master01 nginx]#

从命令结果可以看出,它也遵循K8S API标准的资源组织格式,由apiVersion,Kind,metadata,spec,和status五个核心字段组成,只是spec字段中嵌套的内容与Namespace资源几乎完全不同 事实上,对几乎所有的资源来说,apiVersion、kind、和metadata字段的功能基本上都是相同的,但spec则用于定义资源的期望状态,而资源之所以存在类型上的不同,也在于他们的嵌套属性存在显著差别,它由用户定义和维护。而status字段则用于记录活动对象的当前状态,它需要与用户再spec中定义的期望状态相同,或者正处于转换为其相同的过程中