Kubernetes系统将一切事物都抽象为API资源,其遵循REST架构风格组织并管理这些资源及其对象,同时还支持通过标准的HTTP方法(POST、PUT、PATCH、DELETE和GET)对资源进行增、删、改、查等管理操作。 Kubernetes的资源对象大体可分为
- 工作负载(Workload)
- 服务发现和负载均衡(Discovery & LB)
- 配置和存储(Config & Storage)
- 集群(Cluster)
- 元数据(Metadata)
资源对象及API群组
工作负载
Pod是工作负载型资源中的基础资源,它负责运行容器,并为其解决环境性的依赖。它被Pod控制器管理,但由于应用程序有无状态和有状态的区分,它们对环境的依赖及工作特性有很大的不同,因此分属两种不同类型的Pod控制器来管理。 管理无状态应用的控制器:
- ReplicationController
- ReplicaSet
- Deployment
ReplicationController和ReplicaSet的作用都是确保每个Pod副本在任一时刻都符合目标数量。但ReplicationController是上一代的控制器,已基本废弃。 Deployment用于管理无状态的持久化应用,例如HTTP服务器;它用于为Pod和ReplicaSet提供声明式更新,是建构在ReplicaSet之上的更为高级的控制器。
管理有状态应用的控制器:
- StatefulSet
StatefulSet用于管理有状态的持久化应用,如database服务程序;其与Deployment的不同之处在于StatefulSet会为每个Pod创建一个独有的持久性标识符,并会确保各Pod之间的顺序性。
另外还有两个比较特别的Workload控制器:
- DaemonSet
- Job控制器
DaemonSet常用于运行集群存储守护进程——如glusterd和ceph,还有日志收集进程——如fluentd和logstash,以及监控进程——如Prometheus的Node Exporter、collectd、Datadog agent和Ganglia的gmond等。
Job控制器用于管理运行完成后即可终止的应用,例如批处理作业任务。
服务发现和负载均衡
Kubernetes使用标准的资源对象来负责服务发现和负载均衡,包括:
- Service资源
- Endpoint资源
- Ingress资源
配置与存储
Docker使用Volume来进行数据的持久化,K8S也为此提供了 Volume资源,而且它基于标准的CSI(Container Storage Interface)接口,支持多种类型的存储系统。
另外,Docker在启动容器时需要注入环境变量,K8S也为此提供了ConfigMap资源,它可以环境变量或存储卷的方式接入到Pod资源的容器中,并且可被多个同类的Pod共享引用。Secret资源则用于提供密码等敏感配置信息。
集群级资源
上述资源都属于名称空间级别,可由相应的项目管理员所管理。Kubernetes还存在一些集群级别的资源,用于定义集群自身配置信息,它们仅应该由集群管理员进行操作。
- Namespace: 资源对象名称的作用范围,绝大多数对象都隶属于某个名称空间,默认属于default.
- Node: Kubernetes集群的工作节点,其标识符在当前集群中必须是唯一的.
- Role: 名称空间级别的由规则组成的权限集合,可被RoleBinding引用.
- ClusterRole: Cluster级别的由规则组成的权限集合,可被RoleBinding和ClusterRoleBinding引用.
- RoleBinding: 将Role中的许可权限绑定在一个或一组用户之上,它隶属于且仅能作用于一个名称空间.
- ClusterRoleBinding: 将ClusterRole中定义的许可权限绑定在一个或一组用户之上;它能够引用全局名称空间中的ClusterRole,并能通过Subject添加相关信息.
元数据型资源
元数据型资源用于为集群内部的其他资源配置其行为或特性,如HorizontalPodAutoscaler资源可用于自动伸缩工作负载类型的资源对象的规模,Pod模板资源可用于为pod资源的创建预制模板,而LimitRange则可为名称空间的资源设置其CPU和内存等系统级资源的数量限制等。
资源在API中的组织形式
除了kubectl,也可以使用curl、postman等工具作为HTTP客户端直接通过API Server在集群上操作资源对象,但是Kubernetes集群默认仅支持HTTPS的访问接口,它需进行一系列的认证检查,所以首先需要在本地主机上为API Server启动一个代理网关
kubectl proxy --port=8080
然后就可以发起请求了,比如获取集群的namespace list:
curl localhost:8080/api/v1/namespaces
与执行这样的命令得到的结果相同:
kubectl get namespaces -o json
所有的response都包含相同的一级字段:kind、apiVersion、metadata、spec、status。 其中kind、apiVersion分别表示对象所属的资源类型和API的版本。
metadata字段
metadata字段用于描述对象的属性信息,其内嵌多个字段用于定义资源的元数据,例如name和labels等。这些字段分为必要字段和可选字段两大类。比如名称空间级别的资源的必选字段包括有
- namespace:指定当前对象隶属的名称空间,默认值为default。
- name:设定当前对象的名称,在其所属的名称空间的同一类型中必须唯一。
- uid:当前对象的唯一标识符,其唯一性仅发生在特定的时间段和名称空间中
可选字段通常是指由Kubernetes系统自行维护和设置,或者存在默认值,或者本身允许留空。用户通过配置清单创建资源时,通常仅需要给出必选字段,可选字段可按需指定,对于用户未明确定义的嵌套字段,则需要由一系列的finalizer组件自动予以填充。
spec和status字段
spec来描述所期望的对象应该具有的状态,status字段则用来记录对象的当前状态。在定义资源配置清单时,spec是必须定义的字段,status字段则由Kubernetes负责填充或更新,用户不能手动进行定义。
上述字段的子节点的内容随资源的种类不同而有较大的区别,可以使用kubectl explain
来具体查看,比如
kubectl explain pods
kubectl explain pods.spec
资源对象管理
整体来说,K8S提供了两类资源管理的方式:陈述式和声明式 陈述式侧重于告诉计算机如何执行操作,run、expose、delete和get等命令都属于此类; 声明式侧重于构建程序逻辑而无须详细描述其实现流程,用户只需要设定期望的状态,系统即能自行确定需要执行的操作以确保达到用户期望的状态,所有的操作都通过apply命令来完成。
kubectl命令能够读取.yaml .yml或.json为格式的文件。-f
选项可以指定配置清单的路径、URL或目录,且可重复使用多次。如果指定的目录路径存在子目录中时,可使用-R
选项来递归获取子目录中的配置清单。
可以为每个资源使用专用的配置清单,也可以将多个相关的资源(例如,属于同一个应用或微服务)组织在同一个配置清单中。不过,如果是YAML格式的配置清单,多个资源彼此之间要使用“---”符号作为单独的一行进行资源分割
管理namespace资源
namespace资源属于集群级别的资源,用于将集群分隔为多个隔离的逻辑分区以配置给不同的用户、租户、环境或项目使用,namespace下又包含了pod、service等资源。 Kubernetes的namespace资源与Linux系统的名称空间是各自独立的概念。前者仅用于限制资源对象名称的作用域。 kubectl get namespaces
命令可查看所有的namespaces资源,kube-system主要用于运行系统级资源,而default下则包含那些未指定名称空间的资源。 kubectl describe namespaces <namespace>
命令可查看指定namespace的详细信息。 查看namespace级别的资源需要指定namespace名称,比如
kubect get pods -n kube-system
声明式创建namespace资源
使用apply命令基于以下配置清单创建namespace资源
3_namespace-example.yaml:
apiVersion: v1
kind: Namespace
metadata:
name: dev
spec:
finalizers:
- kubernetes
~ kubectl apply -f 3_namespace-example.yaml
namespace/dev created
创建namespace资源所需的属性较少,简单起见,kubectl为其提供了一个封装的专用陈述式命令kubectl create namespace <namespace>
删除Namespace资源
删除Namespace资源会级联删除其包含的所有其他资源对象
kubectl delete namespace dev
也可以为其指定--force --grace-period 选项
管理pod资源
首先定义如下资源清单: 3_pod-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-example
spec:
containers:
- name: myapp
image: ikubernetes/myapp:v1
创建Pod资源 陈述式对象配置方式:
kubectl create -f 3_pod-example.yaml
声明式对象配置方式:
kubectl apply -f 3_pod-example.yaml
查看pod状态
kubectl get -f 3_pod-example.yaml
或
kubectl get pod pod-example
同时可以使用-o yaml/json
选项获取详细的资源清单。 describe命令可查看活动对象的详细信息。
kubectl describe -f 3_pod-example.yaml
或
kubectl describe pod pod-example
更新Pod资源 对于活动对象,并非其每个属性值都支持修改,比如无法修改Pod资源对象的metadata.name字段,除非删除并重建它。对于那些支持修改的属性,比如,容器的image字段,可将其完整的配置清单导出于配置文件中并更新相应的配置数据,而后使用replace命令基于陈述式对象配置的管理机制进行资源对象的更新。
~ kubectl get pods pod-example -o yaml > pod-example-update.yaml
将image修改为ikubernetes/myapp:v2后执行:
~ kubectl replace -f pod-example-update.yaml
操作成功会提示:
pod/pod-example replaced
上述使用了陈述式对象配置方式更新活动对象的配置,replace命令要重构整个资源对象,所以它必须基于完整格式的配置信息才能进行活动对象的完全替换。若要基于此前的配置文件进行替换,就必须使用--force选项删除此前的活动对象,而后再进行新建操作。
~ kubectl replace -f 3_pod-example.yaml --force
pod "pod-example" deleted
pod/pod-example replaced
后面介绍会介绍更推荐的声明式管理方式。 删除Pod资源 陈述式命令方式:
kubectl delete pod pod-example
陈述式对象配置管理方式:
kubectl delete -f 3_pod-example.yaml
陈述式对象配置 VS 声明式
陈述式命令、陈述式对象配置、声明式三种管理K8S资源的方式中,后两种都是使用配置清单,但它们区别较大: 陈述式对象配置管理机制中,同时指定的多个资源必须进行同一种操作,而且其replace命令是通过完全替换现有的活动对象来进行资源的更新操作,对于生产环境来说,这并非理想的选择。 声明式对象配置操作在管理资源对象时将配置信息保存于目标对象的注解中,并通过比较活动对象的当前配置、前一次管理操作时保存于注解中的配置,以及当前命令提供的配置生成更新补丁从而完成活动对象的补丁式更新操作。 比如要更新pod镜像,只需要修改最初的3_pod-example.yaml,然后apply,系统就会进行补丁式更新操作。 而资源对象的删除操作依然可以使用apply命令,但要同时使用--prune选项,命令的格式为“kubectl apply -f <directory/> --prune -l <labels>”。但这个命令要慎用,因为它将基于标签选择器过滤出所有符合条件的对象,并检查由-f指定的目录中是否存在某配置文件已经定义了相应的资源对象,那些不存在相应定义的资源对象将被删除。因此,删除资源对象的操作依然建议使用陈述式对象配置方式。
学习资料
《Kubernetes实战进阶》 马永亮著