共计 3636 个字符,预计需要花费 10 分钟才能阅读完成。
什么是 Docker
Docker 不是虚拟机。在很多的网络教案中喜欢将 Docker 与虚拟机进行类比,这种类比用于理解 Docker 的优势有着不错的作用,因为 Docker 与虚拟机有着相同的优势。但是从技术而言,虚拟机技术则是对硬件层的虚拟化,而 Docker 是一种进程隔离技术。简单的说,我们可以在宿主机(Host Machine)使用 ps aux 看到使用 Docker 启动的进程。这意味着 Docker 中的程序实际上是跑在宿主操作系统中。这是我不赞成将 Docker 与虚拟机进行类比的原因。
要去理解 Docker, 最避不开的是 Namespace 与 Cgroups。
Namespace 是 Linux 中对进程之间进行隔离保护的技术。通过 Namespace 技术,保证了不同 Docker Container 中看到的内容不一样,这也是 Docker 的基础。
cgroups(Control Groups)最初叫 Process Container,由 Google 工程师(Paul Menage 和 Rohit Seth)于 2006 年提出,后来因为 Container 有多重含义容易引起误解,就在 2007 年更名为 Control Groups,并被整合进 Linux 内核。顾名思义就是把进程放到一个组里面统一加以控制。本质上,Cgroups 是一种对进程资源控制(比如可访问内存,CPU 时间使用)的技术手段。
这里我们可以更加清楚的明白,Docker 只是一个基于操作系统提供的虚拟化能力的一个上层应用,其核心功能都是由内核实现。这也是与虚拟机最大的不同点。
什么是 Kubernetes
Kubernetes 是一个由 Google 主导开发的开源容器编排平台,通过数年的发展已经成为了容器编排的事实标准。各大云平台也都提供了完善的 Kubernetes 功能,我们可以在 Kubernetes 的源码中看到目前适配的云平台。
在 Kubernetes 的世界里,我们不在关心具体的服务器细节,我们看到的是一个一个 CPU,一条一条内存,一块一块的磁盘摆在眼前,服务器已经被完全的抽象为计算资源。应用服务器的无状态化带来的最大好处是扩容的便利性,我们可以借助云平台,在数分钟内完成百倍的吞吐量扩展。另一方面,对于应用开发者,所有的一切都在 kubectl 这一个工具中。
Kubernetes 基础服务
0. Master
Master 管理着整个集群的状态与访问。
1. 节点
节点(Node)代表着一台物理实例。所有集群中的容器都运行在节点中。一旦某一个节点发生故障,则运行在该节点的容器会自动的迁移到其他节点(注意,迁移的过程是销毁重建。事实上为了状态的一致性,在 Kubernetes 中没有容器的停止与重启的概念)。
在集群运行中,我们可以添加 / 减少节点。在节点新增之后,
2. 网络
在集群(Cluster)内部,Kubernetes 使用虚拟网络层进行网络通讯。这使得每一个容器都有一个自己独立的 ip。我们可以从任何一个容器通过这个 ip 访问到另一个容器内部。
对于 Web 应用,我们经常需要部署多个实例用于负载均衡,在 Kubernetes,可以通过 Service 服务非常快速的创建一个内部负载均衡(ELB)。对于每一个 Service, 仍然会分配一个 ip,使得我们可以从一个容器去访问另外一组容器而无需任何额外的程序(例如 Haproxy,Nginx)支持。
在虚拟网络之上,Kubernetes 还提供了针对虚拟网络的 DNS 系统,我们只需要按照特定的规则就可以访问不同的 Service,连 ip 都不需要知晓。
虚拟网络完全的避开了对于物理网络细节(例如 Ip 地址,端口号)的依赖,使得我们可以通过配置得到一个完全一致的集群环境。
3. 存储
我们永远不应该在容器中存储任何需要持久化存储的数据(Mysql,Redis),因为容器会崩溃重建,故障迁移等原因造成自动重新部署,这些动作都会造成数据的丢失。如果在容器中需要使用持久化存储,我们需要使用 Persistent Volume 服务。该服务通过将外部的持久化存储系统挂载到容器中进行使用。对于一块磁盘,可以挂载一个允许写操作的卷到一个容器,以及挂载多个只读权限给多个容器。
4. 配置
不建议将容器中应用程序的配置文件在构建镜像(Docker Image)的时候打包进去,这会造成配置文件的变更需要重新构建。在 Kubernetes 中,提供了 ConfigMap 服务进行配置文件的管理。
我们通过会通过 ConfigMap 来构建应用程序的配置管理,然后将其挂载到容器中使用。这可以非常容器的让我们的应用程序跑在不同的环境中。
5. 调度
当我们向集群新增加一个(些)容器的时候,集群会自动将容器部署到合适的节点。集群会根据不同节点(Node)的状态(节点状态,节点资源状态)来进行规划,并且自动部署。在新增容器的时候,我们还可以指定对应的 Node Label 将不同的服务部署到不同的物理实例中,以实现服务的物理隔离。
Kubernetes 核心概念
1. Pod
Pod 是一个或多个 Docker 容器的组合,它们之间具有共享的存储与网络。Pod 也是 Kubernetes 的最小单位,Pod 中的容器会保证永远运行于同一个节点。
比如对于 PHP-FPM 应用而言,需要 PHP-FPM 进程与对应的 Web Server(Nginx,Apache)。基于 Docker 最小部署原则,我们会将 PHP-FPM 与 Web Server 分为两个镜像。我们可以在一个 Pod 中同时部署 PHP-FPM 镜像与 Web Server 进程,并且它们之间仍然可以通过 fastcgi 的方式进行通讯。而 Kubernetes 又保证了这些容器具备相同的生命周期。我们将整体理解为一个应用程序即可。
2. Development
部署(Development)是一个针对如何管理 Pod 的工具。通过 Development 我们可以快速地创建多个 Pod 副本,并且支持滚动热更新,从而实现了应用程序的热更新。我们可以简单的将部署理解为应用的多服务器管理技术手段,在物理机时代,有 ansible 这样的工具来进行批量部署。
3. Service
我们已经使用部署将我们的应用部署在了多台节点中,尽管 Kubernetes 已经提供了虚拟 IP 来让我们进行不同容器之间的通讯,但是这个 IP 是不稳定的,因为我们的节点会进行故障迁移,宕机,从而可能更新 IP。那么我们如何访问这些服务?答案就是 Service。
Service 将一些 Pod 关联在一起,并且设定一些访问策略(比如端口映射),并且允许设定一个固定的 ip。当我们尝试去访问这些服务的时候,我们只需要访问 Service 的 ip 与端口(映射之后的 Service 端口)就可以访问这些服务,并且 Service 本身可以进行负载均衡与健康检查。
这意味着 Service 是一个内部负载均衡器(ELB)。
4. Ingress
Ingress 本质上和 Service 一样,也是一种流量代理的概念,但是与 Service 不一样的是:
a. Service 是 4 层代理,Ingress 是 7 层代理(Http)。
b. Service 是服务的集群内部访问方法,Ingress 则是通过一组规则来控制从外部系统(internet)到多个服务的访问方法。
我们可以设定不同的域名,不同的 Http url path 路由到不同的后端服务(Backend Service)。因此,Ingress 代表着流量入口和负载均衡(LB)的作用。
5. StatefulSet
从概念上,StatefulSet 与 Development 是非常的相似,但是不同点是:Development 是对无状态 Pod 的管理(比如 Http Server),而 StatefulSet 则是对有状态的 Pod 进行管理,比如(数据库 MySQL), 同时会遵循固定的顺序进行启动或销毁容器。
通常地,StatefulSet 服务都会搭配持久化存储服务一起工作,我们会将数据库的数据目录指向持久化存储中,这保证了容器在销毁、重建之后数据仍然不会丢失。
6. DaemonSet
Daemon Set 是一种独特的部署方式,它保证了容器会运行在所有指定的节点中,并且保证在节点生命周期内一直存活。这通常适用于一些节点监控程序或采集程序。比如 fluentd 或 logstash
7. Job
Job 是一种一次性工作程序的部署方式。它会在所有指定的 Pod 运行完之后结束生命周期。比如我们可以使用 Job 来运行数据库迁移程序。
8. CronJob
从名称可知,CronJob 是计划任务的方式来运行程序,并且使用 Cron 语法来描述间隔周期,但是 CronJob 会有一些需要注意的地方:
a. CronJob 是分布式的,它不会保证运行在某一个确定的节点中,除非在 YAML 中指定。
b. CronJob 可能因为调度的问题,造成运行多次,这需要我们保证 CronJob 程序的幂等性。
参考资料
http://man7.org/linux/man-pag…
https://www.kernel.org/doc/Do…