K8S原理架构与实战(基础篇)
背景
容器时代的到来
在介绍K8S之前,先来看看服务器的演变过程:物理机时代、虚拟机时代、容器化时代
物理机时代的缺点:
- 部署慢 :每台服务器都要安装操作系统、相关的应用程序所需要的环境,各种配置
- 成本高:物理服务器的价格十分昂贵
- 资源浪费:硬件资源不能充分利用
- 扩展和迁移成本高:扩展和迁移需要重新配置一模一样的环境
虚拟机时代很好的解决了物理机时代的缺点,虚拟机时代的特点是:
- 易部署:每台物理机可部署多台虚拟机,且可以通过模板,部署快,成本低
- 资源池:开出来的虚拟机可作为资源池备用,充分压榨服务器性能
- 资源隔离:每个虚拟机都有独立分配的内存磁盘等硬件资源,虚拟机之间不会互相影响
- 易扩展:随时都能在一个物理机上创建或销毁虚拟机
虚拟机的缺点是:每台虚拟机都需要安装操作系统
容器化时代解决了虚拟机时代的缺点,容器化时代在继承了虚拟机时代优点的基础之上,还有以下优势
- 更高效的利用硬件资源:所有容器共享主机操作系统内核,不需要安装操作系统。
- 一致的运行环境:相同的镜像产生相同的行为
- 更小:较虚拟机而言,容器镜像更小,因为不需要打包操作系统
- 更快:容器能达到秒级启动,其本质是主机上的一个进程
容器编排的需要
容器技术的代表就是docker,关于docker可以参考之前的文章《都9102年了,还没听过docker?5分钟带你了解docker的前世今生!》,此处不再赘述,docker在单机上使用方便快捷,但在集群中表现如何呢?假设现在有5个节点,每个节点中都装有docker,现在要部署一个应用,要求要10个副本,有如下做法:
- 在5个节点上随机分配
- 平均分配,每台节点分配2个
- 根据不同节点的负载状态分配,负载低的优先分配
无论选择哪种方法都需要执行相同docker run命令10遍,如果是最后一种做法还需要挨个检查每个节点的负载,这种问题叫做不利于自动装箱
如果以后增加了1个副本还需要再重复上面的动作,如果增加10个呢?增加100个呢?人为去操作那就有点难受了,这种问题叫做不利于水平扩容与缩容,简称水平扩缩
如果现在要变更版本,更新或者回滚,需要停止容器,然后替换新版本镜像,再启动,这样的操作每个副本都要来一次,如果副本太多,简直是噩梦,这种问题叫做不利于自动化上线和回滚
如果现在一个容器停止运行了,docker的重启策略会将它拉起来继续运行,这没什么问题,如果节点宕机了呢?上面的所有容器都停止了,docker重启策略就没用了,这样副本的数量就会减少,这个问题叫做不能自我修复
假设需要负载均衡,那么得新增一个节点安装负载均衡器,并且配置5个节点的IP和端口,前提是容器的端口要映射到主机端口,而且容器之前网络是隔离的,不能相互访问,维护成本高,这个问题叫不利于服务发现与负载均衡
上面的这些操作,就是容器编排,既然存在如上问题,那么就需要一个技术进行自动化编排,这个技术就是K8S,K8S即kubernetes /kjubɚ’nɛtɪs/
Kubernetes,是一个工业级的容器编排平台。Kubernetes 这个单词是希腊语,它的中文翻译是“舵手”或者“飞行员”。在一些常见的资料中也会看到“ks”这个词,也就是“K8s”,它是通过将 8 个字母“ubernete ”替换为“8”而成为的一个缩写。
官网:https://kubernetes.io/zh/
项目Github地址:
https://github.com/kubernetes/kubernetes
根据官网描述,它有如下功能
|功能
|
描述
|
|
自动化上线和回滚
|
Kubernetes 会分步骤地将针对应用或其配置的更改上线,同时监视应用程序运行状况以确保你不会同时终止所有实例。如果出现问题,Kubernetes 会为你回滚所作更改。你应该充分利用不断成长的部署方案生态系统。
|
|
服务发现与负载均衡
|
无需修改你的应用程序即可使用陌生的服务发现机制。Kubernetes 为容器提供了自己的 IP 地址和一个 DNS 名称,并且可以在它们之间实现负载均衡。
|
|
存储编排
|
自动挂载所选存储系统,包括本地存储、诸如 GCP 或 AWS 之类公有云提供商所提供的存储或者诸如 NFS、iSCSI、Gluster、Ceph、Cinder 或 Flocker 这类网络存储系统。
|
|
Secret 和配置管理
|
部署和更新 Secrets 和应用程序的配置而不必重新构建容器镜像,且 不必将软件堆栈配置中的秘密信息暴露出来。
|
|
自动装箱
|
根据资源需求和其他约束自动放置容器,同时避免影响可用性。将关键性工作负载和尽力而为性质的服务工作负载进行混合放置,以提高资源利用率并节省更多资源。
|
|
批量执行
|
除了服务之外,Kubernetes 还可以管理你的批处理和 CI 工作负载,在期望时替换掉失效的容器。
|
|
IPv4/IPv6 双协议栈
|
为 Pod 和 Service 分配 IPv4 和 IPv6 地址
|
|
水平扩缩
|
使用一个简单的命令、一个 UI 或基于 CPU 使用情况自动对应用程序进行扩缩。
|
|
自我修复
|
重新启动失败的容器,在节点死亡时替换并重新调度容器,杀死不响应用户定义的健康检查的容器,并且在它们准备好服务之前不会将它们公布给客户端。
|
|
为扩展性设计
|
无需更改上游源码即可扩展你的 Kubernetes 集群。
|
为什么是K8S
当然容器编排不止有K8S,还有Docker Swarm、Apache Mesos、AWS ECS,下面是几个平台简单的比较:
| |Swarm
|
Kubernetes
|
Mesos
|
ECS
|
|
基本功能
|
Docker原生的集群管理工具
|
开源的容器集群工具,提供应用级别的部署,维护和扩张功能
|
基于数据中心的操作系统
|
基于云的高可用,高扩展容器集群
|
|
高层次抽象
|
无
|
Pod Job Service
|
无
|
Task Service
|
|
应用扩展性
|
无
|
支持
|
Framework 支持
|
支持
|
|
应用高可用性
|
无
|
支持
|
Framework 支持
|
支持
|
|
集群协调和服务发现
|
etcd ZooKeeper Consul
|
etcd
|
ZooKeeper
|
/
|
|
调度策略(Schedule)
|
内置,可扩展
|
内置
|
两级别,可扩展
|
可扩展
|
|
监控
|
Logging Driver
|
Heapter,ELK Addon
|
内置
|
CloudWatch
|
|
用户界面
|
CLI API UCP UI
|
CLI API UI
|
API UI
|
CLI API AWS Console
|
|
开发语言
|
Go
|
Go
|
Java
|
NA
|
|
开源
|
是
|
是
|
是
|
否
|
|
最大支持管理节点数
|
官方1000 非官方5000
|
官方1000 非官方2000
|
10000
|
/
|
那为什么是K8S,主要基于以下几点:
- Google、RedHat等开源基础设施公司共同发起了CNCF基金会,以Kubernetes为基础,建立一个由开源基础设施领域厂商主导、按照独立基金会方式运营的平台社区,来对抗以Docker公司为核心的容器商业生态
- Kubernetes脱胎于Google内部久负盛名的大规模集群管理系统Borg,是Google在容器化基础设施领域十余年实践经验的沉淀和升华
- Kubernetes采用了非常优雅的软件工程设计和开源开放的态度,使得用户可以根据自己的使用场景、通过灵活插拔的方式,采用自定义的网络、存储、调度、监控、日志等模块
架构
在K8S中,由Master控制节点和Worker节点共同构成一个集群,如下图所示:
Master节点
- etcd:分布式KV数据库,使用Raft协议,用于保存集群中的相关数据,项目地址:https://github.com/etcd-io/etcd
- API Server:集群统一入口,以restful风格进行操作,同时交给etcd存储(是唯一能访问etcd的组件);提供认证、授权、访问控制、API注册和发现等机制,可以通过kubectl命令行工具,dashboard可视化面板,或者sdk等访问
- Scheduler:节点的调度,选择node节点应用部署
- Controller Manager:处理集群中常规后台任务,一个资源对应一个控制器,同时监控集群的状态,确保实际状态和最终状态一致
Worker节点
- kubelet:相当于Master派到node节点代表,管理本机容器,上报数据给API Server
- Container Runtime:容器运行时,K8S支持多个容器运行环境:Docker、Containerd、CRI-O、Rktlet以及任何实现Kubernetes CRI (容器运行环境接口) 的软件
- kube-proxy:实现服务(Service)抽象组件,屏蔽PodIP的变化和负载均衡
流程样例
- 通过kubectl命令行工具向API Server发送一个请求:创建ReplicaSet,API Server会将此请求存储在etcd中
- Controller Manager会接受到一个通知
- Controller Manager发现现在的集群状态和预期的状态不一致,因此需要创建Pod,此信息会通知到Scheduler
- Scheduler会选择空闲的Worker节点,然后通过API Server更新Pod的定义
- API Server会通知到Worker节点的上的kubelet
- kubelet指示当前节点上的Container Runtime运行对应的容器
- Container Runtime下载镜像并启动容器
总体架构
核心概念
Pod
- Pod是最小调度单元
- Pod里面会包含一个或多个容器(Container)
- Pod内的容器共享存储及网络,可通过localhost通信
Pod本意是豌豆荚的意思,此处指的是K8S中资源调度的最小单位,豌豆荚里面的小豆子就像是Container,豌豆荚本身就像是一个Pod
Deployment
Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Depl