Kubernetes,简称K8s,是用8代替名字中间的8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用。
本文旨在分享我自己的知识笔记,帮助像我这样的初学者去初步了解K8S集群的一些基本概念,文章将按照容器——Docker——Kubernetes的顺序去梳理相关知识点。
可能很多初学者对容器这个概念比较陌生,所以这里先从大家都有一定了解的虚拟机开始讨论。
虚拟机 (VM),顾名思义,虚拟机就是可以远程连接的虚拟服务器。
而容器(Container),顾名思义,是用于容纳某些东西的,而容器技术就是有效的将单个操作系统的资源“装”到某个“容器”中。
现在假设你要在虚拟机上运行一个网络应用 —— 包括一个 MySQL 数据库、一个 Vue 前端和一些 Java 库,在 Ubuntu 操作系统 (OS) 上运行。
而一个应用程序由各种组件、服务和库组成,它们运行在操作系统上。
现在,将应用程序打包成一个虚拟机镜像,这个镜像中包括了Ubuntu 操作系统。这使得虚拟机变得非常笨重 —— 通常有几个 G 的大小。
虚拟机镜像包含了整个操作系统及所有的库,对应用程序来说,这个镜像过于臃肿,其中大部分组件并没有被应用程序直接调用。如果你需要重新创建、备份或扩展这个应用程序,就需要复制整个环境(虚拟机镜像),在新环境中启动应用通常需要几十秒甚至几分钟时间。如果你想单独升级应用中的某个组件,比如说 Vue 应用,就需要重建整个虚拟机镜像。另外,如果你的两个应用依赖同一个底层镜像,升级底层镜像会同时影响这两个应用,而有时候,你只需要升级其中一个应用的依赖而已。这就是所谓的 “依赖陷阱”。(参见下图)
总之,使用打包虚拟机镜像这种方式,将使应用的运行、配置、管理、所有生存周期将与当前操作系统绑定,不利于应用的升级更新/回滚等操作,可移植性也差。
解决这个问题的办法就是容器。容器是继虚拟机之后更高层次的抽象,在这层抽象中,整个应用程序的每个组件被单独打包成一个个独立的单元,这个单元就是所谓的容器。通过这种方式,可以将代码和应用服务从底层架构中分离出来,实现了完全的可移植性(在任何操作系统或环境上运行应用的能力)。
在上面的例子中,Ubuntu 操作系统就是一个单元(容器)。MySQL 数据库是另一个容器,Vue 环境和相关的库也是一个容器。
而每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。相对于虚拟机,容器能快速部署,由于容器与底层设施、机器文件系统解耦的,所以它能在不同云、不同版本操作系统间进行迁移。
容器占用资源少、部署快,每个应用可以被打包成一个容器镜像,每个应用与容器间成一对一关系也使容器有更大优势,使用容器可以在build或release 的阶段,为应用创建容器镜像,因为每个应用不需要与其余的应用堆栈组合,也不依赖于生产环境基础结构,这使得从研发到测试、生产能提供一致环境。类似地,容器比虚机轻量、更“透明”,这更便于监控和管理。
虚拟机属于虚拟化技术。而容器技术,也是虚拟化技术,属于轻量级的虚拟化。
Docker 是最常用的容器化工具,并且是一个开源项目,诞生于 2013 年初,最初是 dotCloud 公司(后由于 Docker 开源后大受欢迎就将公司改名为 Docker Inc )内部的一个开源的 PAAS 服务 (Platform as a ServiceService) 的业余项目。
它基于 Google 公司推出的 Go 语言实现。 项目后来加入了 Linux 基金会,遵从了 Apache 2.0 协议,项目代码在 GitHub 上进行维护。
Docker 相比虚拟机的交付速度更快,资源消耗更低,Docker 采用客户端 / 服务端架构,使用远程 API 来管理和创建容器,其可以轻松的创建一个轻量级的、可移植的、自给自足的容器,docker 的三大理念是 build (构建)、ship (运输)、 run (运行),Docker 遵从 apache 2.0 协议,并通过(namespace 及 cgroup 等)来提供容器的资源隔离与安全保障等,所以 Docke 容器在运行时不需要类似虚拟机(空运行的虚拟机占用物理机 6-8% 性能)的额外资源开销,因此可以大幅提高资源利用率。
容器和虚拟机的比较
. 快速部署:短时间内可以部署成百上千个应用,更快速交付到线上
. 高效虚拟化:不需要额外hypervisor支持,基于linux内核实现应用虚拟化,相比虚拟机大幅提高性能和效率
. 节省开支:提高服务器利用率,降低IT支出
. 简化配置:将运行环境打包保存至容器,使用时直接启动即可 . 环境统一:将开发,测试,生产的应用运行环境进行标准化和统一,减少环境不一样带来的各种问题 . 快速迁移和扩展:可实现跨平台运行在物理机、虚拟机、公有云等环境,良好的兼容性可以方便将应用从A宿主机迁移到B宿主机,甚至是A平台迁移到B平台
隔离性:多个容器共用宿主机的内核,各应用之间的隔离不如虚拟机彻底
容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
镜像
Docker 镜像(Image),就相当于是一个 root 文件系统。比如官方镜像 ubuntu:16.04 就包含了完整的一套 Ubuntu16.04 最小系统的 root 文件系统。
仓库
仓库可看成一个代码控制中心,用来保存镜像。
Kubernetes一词来自希腊语,意思是 “飞行员” 或 “舵手”。
这个名字很贴切,Kubernetes 可以帮助你在波涛汹涌的容器海洋中航行。
Kubernetes是谷歌十几年来大规模容器技术应用的重要成果,是谷歌严格保密十几年的秘密武器——Borg的一个开源版本。Borg是谷歌内部使用的久负盛名的大规模集群管理系统,基于容器技术来实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
总之,使用Kubernetes提供的解决方案,不仅节省开发成本,还可以将精力更加集中于业务本身,而且由于Kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅度降低。
Kubernetes是一个完备的分布式系统支撑平台。Kubernetes具有完备的集群管理能力,包括多层次的安全防护和准入机制、多租户应 用支撑能力、透明的服务注册和服务发现机制、内建的智能负载均衡器、强大的故障发现和自我修复能力、服务滚动升级和在线扩容能力、 可扩展的资源自动调度机制,以及多粒度的资源配额管理能力。同时, Kubernetes提供了完善的管理工具,这些工具涵盖了包括开发、部署测试、运维监控在内的各个环节。因此,Kubernetes是一个全新的基于容器技术的分布式架构解决方案,并且是一个一站式的完备的分布式系统开发和支撑平台。
Kubernetes 借鉴了 Borg 的设计理念。Kubernetes 的整体架构跟 Borg 非常像,如下图所示。
K8S属于主从设备模型(Master-Slave架构),由Master和Node节点组成。
Master 节点负责集群的管理。Master 协调集群中的所有行为/活动,例如应用的运行、修改、更新等。
Node 节点作为Kubernetes集群中的工作节点,可以是VM虚拟机、物理机。每个node上都有一个Kubelet,用于管理node节点与Kubernetes Master通信。每个Node节点上至少还要运行container runtime(比如docker或者rkt)。
Kubernetes Architecture
Kubernetes cluster
kube-APIserver:对外暴露了Kubernetes API
kube-Controller-Manager:是控制平面的组件, 负责运行控制器进程。
从逻辑上讲, 每个控制器都是一个单独的进程, 但是为了降低复杂性,它们都被编译到同一个可执行文件,并在同一个进程中运行。
这些控制器包括:节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)
服务帐户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌
Etcd:后端存储。负责保存Kubernetes Cluster的配置信息和各种资源的状态信息,始终为 Kubernetes 集群的 etcd 数据提供备份计划。
kube-Scheduler:调度新创建的Pod
Kubernetes Master
Kubelet:负责与管控组件沟通,并按照管控组件的指示,直接管理 Worker 节点
Kube-proxy:每个节点上运行的网络代理
容器运行时(Container Runtime) :容器运行环境是负责运行容器的软件
Kubernetes 支持许多容器运行环境,例如containerd、CRI-O以及Kubernetes CRI (容器运行环境接口)的其他任何实现。
插件(Addons):插件使用 Kubernetes 资源(DaemonSet、Deployment等)实现集群功能。 因为这些插件提供集群级别的功能,插件中命名空间域的资源属于kube-system
命名空间。 常用的插件有DNS、Web 界面(仪表盘)、容器资源监控等。
Kubernetes Node
Pod 是 kubernetes 中可以创建和部署的最小也是最简的单位。代表着集群中运行的进程。
Pod的意思是豌豆荚,就像一个豌豆荚里面有多个豆子,一个Pod有一组(一个或多个)容器。
Pod运行在Node中(参见上图Kubernetes Node),这个节点既可以是物理机,也可以是虚拟机,在一个Node上能够运行多个Pod;其次,在每个Pod中都运行着一个特殊的被称为Pause的容器,其他容器则为业务容器。
Pod 中封装着应用的容器(有的情况下是好几个容器),存储、独立的网络 IP,管理容器如何运行的策略选项。
Pod 中可以同时运行多个进程(作为容器运行)协同工作。同一个 Pod 中的容器会自动的分配到同一个 node 上。同一个 Pod 中的容器共享资源、网络环境和依赖,它们总是被同时调度。
注意在一个 Pod 中同时运行多个容器是一种比较高级的用法。只有当你的容器需要紧密配合协作的时候才考虑用这种模式。例如,你有一个容器作为 web 服务器运行,需要用到共享的 volume,有另一个 “sidecar” 容器来从远端获取资源更新这些文件,如下图所示:
Pod 中可以共享两种资源:网络和存储。
Kubernetes Service 定义了这样一种抽象:
逻辑上的一组 Pod,一种可以访问它们的策略 —— 通常称为微服务。 Service 所针对的 Pod 集合通常是通过选择算符来确定的。
举个例子,考虑一个图片处理后端,它运行了 3 个副本。这些副本是可互换的 —— 前端不需要关心它们调用了哪个后端副本。 然而组成这一组后端程序的 Pod 实际上可能会发生变化, 前端客户端不应该也没必要知道,而且也不需要跟踪这一组后端的状态。
Service 定义的抽象能够解耦这种关联。
概念上来讲,K8S 集群的服务,其实就是负载均衡、或反向代理。
在Kubernetes中,Service是分布式集群架构的核心。一个Service对象拥有如下关键特征。
◎ 拥有唯一指定的名称(比如mysql-server)。
◎ 拥有一个虚拟IP地址(ClusterIP地址)和端口号。
◎ 能够提供某种远程服务能力。
◎ 能够将客户端对服务的访问请求转发到一组容器应用上。
控制平面组件会为集群做出全局决策,比如资源的调度。 以及检测和响应集群事件,例如当不满足部署的replicas
字段时, 要启动新的pod)。
控制平面组件可以在集群中的任何节点上运行。 然而,为了简单起见,设置脚本通常会在同一个计算机上启动所有控制平面组件, 并且不会在此计算机上运行用户容器。
控制平面组件包括kube-apiserver、etcd、kube-scheduler、kube-controller-manager等,即Master节点组件。
Node节点组件则负责维护运行的 Pod 并提供 Kubernetes 运行环境,包括kubelet、kube-proxy、容器运行时(Container Runtime)等。
Kubelet是使用 Kubernetes API 与 Kubernetes 集群的控制面进行通信的命令行工具,负责与管控组件沟通,并按照管控组件的指示,直接管理 Worker 节点。
Kubernetes 在容器级别而不是硬件级别运行
比较 Kubernetes 和单机操作系统,Kubernetes 相当于内核,它负责集群软硬件资源管理,并对外提供统一的入口,用户可以通过这个入口来使用集群,和集群沟通。
文章参考自《Kubernetes权威指南》、《深入浅出Kubernetes项目实战手册》、《云原生新手入门指南》。
下一篇文件将会讲解Kubernetes集群学习环境——minikube的安装部署。
如果对你有所启发的话,希望能不吝点赞关注。