Kubernetes是什么
Kubernetes 是一个可移植的、可扩展的开源平台,用于管理容器化的工作负载和服务,可促进声明式配置和自动化。 Kubernetes 拥有一个庞大且快速增长的生态系统。Kubernetes 的服务、支持和工具被广泛使用。
Kubernetes 这个名字源于希腊语,意为“舵手”或“飞行员”。因为 k 和 s 之间有八个字符,所以Kubernetes也被缩写为 k8s 。Google在2014年开源了Kubernetes项目,现在的Kubernetes已经结合了Google超过15年大规模生产工作负载的经验和来自社区的最好的想法和实践。
早期,各个组织机构在物理服务器上运行应用程序,这属于传统的部署方式,比如我们自己的笔记本电脑,在个人电脑上运行多个应用程序,可能出现资源分配的问题,如一个应用程序占用大部分资源而其他应用程序的性能急剧下降。作为解决方案,引入了虚拟化。虚拟化技术允许你在单个物理服务器的 CPU 上运行多个虚拟机(VM),虚拟化技术能够更好地利用物理服务器上的资源,每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。但是虚拟化仍然存在环境笨重,耦合度高等缺点。因此,提出容器化的概念,容器类似于 VM,但是它们具有被放宽的隔离属性,可以在应用程序之间共享操作系统(OS)。 容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。 但是它们与基础架构分离,因此可以跨云和 OS 发行版本进行移植,因此,容器被认为是轻量级的。
Kubernetes不是什么
Kubernetes 不是传统的、包罗万象的 PaaS(平台即服务)系统。 由于 Kubernetes 在容器级别而不是在硬件级别运行,它提供了 PaaS 产品共有的一些普遍适用的功能, 例如部署、扩展、负载均衡、日志记录和监视。 但是,Kubernetes 不是单体系统,默认解决方案都是可选和可插拔的。 Kubernetes 提供了构建开发人员平台的基础,但是在重要的地方保留了用户的选择和灵活性。
不限制支持的应用程序类型。 Kubernetes 旨在支持极其多种多样的工作负载,包括无状态、有状态和数据处理工作负载。 如果应用程序可以在容器中运行,那么它应该可以在 Kubernetes 上很好地运行。
不部署源代码,也不构建你的应用程序。 持续集成(CI)、交付和部署(CI/CD)工作流取决于组织的文化和偏好以及技术要求。
不提供应用程序级别的服务作为内置服务,例如中间件(例如,消息中间件)、 数据处理框架(例如,Spark)、数据库(例如,mysql)、缓存、集群存储系统 (例如,Ceph)。这样的组件可以在 Kubernetes 上运行,并且/或者可以由运行在 Kubernetes 上的应用程序通过可移植机制(例如, 开放服务代理)来访问。
不要求日志记录、监视或警报解决方案。 它提供了一些集成作为概念证明,并提供了收集和导出指标的机制。
不提供或不要求配置语言/系统(例如 jsonnet),它提供了声明性 API, 该声明性 API 可以由任意形式的声明性规范所构成。
不提供也不采用任何全面的机器配置、维护、管理或自我修复系统。
此外,Kubernetes 不仅仅是一个编排系统,实际上它消除了编排的需要。 编排的技术定义是执行已定义的工作流程:首先执行 A,然后执行 B,再执行 C。 相比之下,Kubernetes 包含一组独立的、可组合的控制过程, 这些过程连续地将当前状态驱动到所提供的所需状态。 如何从 A 到 C 的方式无关紧要,也不需要集中控制,这使得系统更易于使用 且功能更强大、系统更健壮、更为弹性和可扩展。
Kubernetes的组件
当你部署完 Kubernetes, 即拥有了一个完整的集群,一个集群主要由两个部分组成:控制面板(Control Plane)和工作节点(Node),控制面板相当于集群的大脑,控制着Node如何运作,而Node相当于四肢,用于运行这些容器化应用。
控制面板
控制平面的组件对集群做出全局决策(比如调度),以及检测和响应集群事件。控制面板主要由四个部分组成:
kube-apiserver:上知天文下知地理,上连其余组件,下接ETCD,提供各类 api 处理、鉴权,和 Node 上的 kubelet 通信等,只有 apiserver 会连接 ETCD。
etcd:兼具一致性和高可用性的键值数据库,是整个集群的数据库。
kube-scheduler:调度,打分,分配资源。
kube-controller-manager:控制各类 controller,通过控制器模式,致力于将当前状态转变为期望的状态。有时也会碰到cloud-controller-manager,这里我们在本地计算机中运行学习环境, 所部署的环境中不需要云控制器管理器。
Node
kubelet:Node上运行的代理。 它保证容器(containers)都 运行在 Pod 中。kubelet 接收一组通过各类机制提供给它的 PodSpecs,确保这些 PodSpecs 中描述的容器处于运行状态且健康,管理容器的生命周期。
kube-proxy:Node上运行的网络代理,主要负责网络的打通。
container :负责运行容器的软件,如Docker、 containerd、CRI-O 以及任何实现 Kubernetes CRI (容器运行环境接口)。
Kubernetes的对象
Kubernetes 对象 是持久化的实体,Kubernetes 使用这些实体去表示整个集群的状态。一旦创建对象,Kubernetes 系统将持续工作以确保对象存在。
Kubernetes的对象包括:Pod、Node、Controller、ReplicationController、ReplicaSet、Deployment、StatefulSet、DaemonSet、Job、CronJob、HorizontalPodAutoscaling、Service、Volume、Secret、ConfigMap、Ingress、ThirdPartyResource、ServiceAccount、SecurityContext、ResourceQuota、LimitRange、etc.
每个 Kubernetes 对象包含两个嵌套的对象字段,它们负责管理对象的配置:*spec
(规约)* 和 status
(状态) 。 对于 spec
对象,你必须在创建时设置其内容,描述你希望它所具有的特征: 期望状态(Desired State) 。status
描述了它的 当前状态(Current State),它是由 Kubernetes 系统和组件 设置并更新的。在任何时刻,Kubernetes 控制平面 都一直积极地管理着对象的实际状态,以使之与期望状态相匹配。
Kubernetes 对象管理
对象的管理都是通过Kubernetes API,也就是 ApiServer 组件提供的 API 接口kubectl
命令行工具实际上就是在调用kubernetes api,从管理技术上来说kubectl
命令分为三种,我们目前主要先掌握第一种和第二种:
管理技术 | 作用于 | 建议的环境 | 支持的写者 | 学习难度 |
---|---|---|---|---|
指令式命令 | 活跃对象 | 开发项目 | 1+ | 最低 |
指令式对象配置 | 单个文件 | 生产项目 | 1 | 中等 |
声明式对象配置 | 文件目录 | 生产项目 | 1+ | 最高 |
指令式命令
这是在集群中运行一次性任务的推荐方法,例如创建一个deployment对象:
kubectl create deployment nginx --image nginx
指令式对象配置
通过至少一个文件名来完成kubectl
命令指定的操作。如使用.yaml
文件来创建 Kubernetes对象。
kubectl create -f nginx.yaml
对应的 .yaml
文件需要配置如下的字段:
apiVersion
- 创建该对象所使用的 Kubernetes API 的版本kind
- 想要创建的对象的类别metadata
- 帮助唯一性标识对象的一些数据,包括一个name
字符串、UID 和可选的namespace
spec
- 你所期望的该对象的状态
对象 spec
的精确格式对每个 Kubernetes 对象来说是不同的,包含了特定于该对象的嵌套字段。 Kubernetes API 参考 能够帮助我们找到任何我们想创建的对象的规约格式。
声明式对象配置
用户对本地存储的对象配置文件进行操作, kubectl
会自动检测每个文件的创建、更新和删除操作。
Kubernetes对象的常用属性
name和uid
Kubernetes中每个对象都有 uid ,uid 是Kubernetes自动为对象生成的,可以唯一标识该对象的字符串。uid 是用于给Kubernetes本身管理对象的标识,对人类来说其可读性太差,因此对象还具有另一个属性 —— 可读性相对更好的,有一定意义的 “名称” 。在创建对象时可以给对象指定名称。不属于同一类别的对象可以有相同的名称,而同一种类型的对象,想要赋予相同的名称,则需要用到 namespace。
NameSpace
namespace可以解决命名冲突的问题,即不同的 namespace 中可以存在同名的资源对象,即使这些对象是相同的类型。但Kubernetes中的 namespace,更多的是为了提高资源的管理效率。
namespace 用来在逻辑上对资源进行分组,Kubernetes集群搭建好后,会创建一个名为 default的 namespace,当没有为资源明确指定 namespace 时,会默认分配到default中。而kubernetes 的组件,会分配到名为 “kube-system” 的 namespace。
namespace为名称提供了一个范围。对象的名称需要在命名空间内是唯一的。命名空间不能相互嵌套,每个Kubernetes 对象只能在一个命名空间中。大多数 kubernetes 资源的对象(例如 Pod、Service、副本控制器等)都位于某些命名空间中。但是命名空间资源本身并不在命名空间中。还有一些底层资源,例如 nodes 和持久化卷不属于任何命名空间。可以使用命令查看哪些资源在 namespace 中:
kubectl get pods --namespace=default
kubectl api-resources --namespaced=true
label和selector
label (标签)是附加到 Kubernetes 对象(比如 Pods)上的键值对,用于区分对象(比如Pod、Service)。 label 旨在用于指定对用户有意义且相关的对象的标识属性,但不直接对核心系统有语义含义。label 可以在创建时附加到对象,随后可以随时添加和修改。可以像 namespace 一样,使用 label 来获取某类对象,label 可以与 selector 一起配合使用,用表达式对条件加以限制,实现更精确、更灵活的资源查找。每个对象都可以定义一组键/值标签。每个键对于给定对象必须是唯一的。
对象信息的获取方式
要查看当前 kubernetes 集群中存在的某一类资源,可以使用kubectl的 get 选项:
kubectl get <resource_type> --namespace=<namespace>
namespace后面的 =
可有可无,不指定–namespace时默认获取default的namespace,另外 --namespace
可以简写成 -n
,如果想获取所有 namespace 下的对象,则可以写成 --all-namespaces
。
kubectl get namespace
kubectl get node
kubectl get pods --all-namespaces
kubectl get svc -n kube-system
如果想要查看某个对象的具体信息,需要用 describe
kubectl describe <resource_type> <object_name> --namespace=<namespace>
namespace也一样可以简写为-n
,但是不能写作--all-namespaces
了,因为不同的namespace可能有同名同类别的对象
kubectl describe pod kube-apiserver -n kube-system
kubectl describe node hello
以上是从Kubernetes官网上了解的Kubernetes概述,下一步将继续了解Kubernetes的架构。