从docker到Kubernetes
序号 | 内容点 | 课程安排 |
1 | Docker解决了什么问题?如何合理的构建Dockerfile?需要注意哪些问题 | 1 |
2 | Kubernetes解决了什么问题? 当前版本,当前的社区发展状况;等等; | 1 |
3 | Kubernetes的POD的概念,以及POD的特性; POD的生命周期?POD跟容器的区别; 如何创建第一个POD? | 1 |
4 | Kubernetes的Deployment概念,Deployment的前世今生; Deployment如何扩容缩容?原理; Kubernetes的ReplicationController; Kubernetes的JOB,Cronjob等资源介绍; 如何创建自己的第一个deployment;什么时候使用deployment; |
1
|
1:Docker是什么? Docker 解决了什么问题? 如何合理构建的Dockerfile? 需要注意哪些问题?
首先容器!= Docker, Docker容器是容器技术的一种, 其显著特点有:
1 | 容器与宿主机共享内核 |
2 | 轻量级,启动速度快 |
3 | 交付产物image方式标准化 |
### docker出现之前的部署情况
在docker出现之前,比如说要部署一个django(一个流行的python web服务框架)应用,要做哪些事情?
· 首先得有个python环境,比如这个要部署的应用基于python3,而你机器上是python2,那ok,先装个python3吧,一看装起来还挺麻烦,要先装各种依赖,还要解决一些可能的软件依赖冲突。
· 装完python之后,发现还要装mysql,还用了redis。没办法,继续下载,安装,配置。费了九牛二虎之力终于搞完了,一天就这么过去了。
· 啥?你告诉我原来的服务器不用了,要换一台服务器?我靠,那重新来一遍吧。
· 啥?你说咱们的基础应用做的太好,要进行推广,需要指导其他厂商部署?
· 所以docker解决了什么问题? 最重要的是环境问题,第二是交付产物的标准化问题。
· 如何合理的构建Dockerfile?
关于Dockerfile编写的最佳实践,仁者见仁智者见智。但是基本遵照:
https://docs.docker.com/develop/develop-images/dockerfile_best-practices/
1 | 应用程序的切割,每container跑单职能进程; |
2 | 尽可能不安装不必要的软件; |
3 | 尽可能以官方image为基准; |
· 需要注意哪些问题?
1 | 时区问题 |
2 | CMD、Entrypoint问题 |
3 | java内存限制问题(http://dockone.io/article/2249) |
4 | 宿主机版本问题 |
5 | 仓库问题 |
· Docker没有解决哪些问题?
1):docker虽然提供了统一的 打包方式和产物交付方式;但是针对一个复杂的项目来说,各个组件依旧需要人来手动去部署,或者以某种领域性的脚本来启动,不具备普适性;举个例子;一个项目有 redis, mysql,dubbo,tomcat,rabbitmq这些组件,部署的时候虽然产物都是镜像,但是各个组件的配置;部署在哪台机器?高可用?宕机如何恢复?等等诸多问题依然是老问题,docker没有解决;
2): docker没有解决不通环境可能存在的网络互联问题,需要自研或者第三方的网络插件抑或是 人自己像没有使用docker的时候那样自己管理各个组件的 网络信息(比如ip和端口);所以docker 更侧重于 是一个单机容器的运行引擎;
2: Kubernetes横空出世
起源于Google的 Borg项目,Kubernetes的目标是让部署容器化的应用简单并且高效,K ubernetes提供了应用部署,规划,更新,维护的一种机制。
2017年是 Kubernetes一个重大年度,这一年 Kubernetes 带来了4个大版本的更迭,从3月份1.6到年底的1.9发布了4个版本,以及2018年的1.10,马上1.11即将发布。
其次,docker宣布原生支持 Kubernetes,而不再向之前那样一味的宣传自己的swarm生态。
为什么呢?
1: 理念先进,先进在哪,给你个眼神自己体会。。。随着我们学习k8s会慢慢体会到。。
2: 社区活跃,为什么活跃。。。别问我。。。
需要明确的一点的, Kubernetes 并不是依赖docker; 容器!=docker, k8s不仅仅能编排docker容器,事实上,k8s开发了其三大接口 CRI 容器运行时接口, 容器网络接口 CNI , 容器存储接口 CSI,这些接口使得k8s不仅仅能编排docker,使得其开放性最大化,而k8s本身只做其擅长的容器编排与调度。
举个例子 除了docker 容器 还有 frakti (基于HyperV), rkt (coreos 下的对抗docker的)等等。
迫于竞争对手压力,实际上,docker被迫在为开源努力,比如其在调整架构后,开源了containerd,对docker有研究的同学应该知道它从docker项目中剥离出来的一个CRI组件。
在容器编排领域, Kubernetes是 实际的事实标准。
3: 相对docker ,k8s引入了哪些东西,改变了哪些操作习惯
k8s的是一个 master-slaver的基本架构;设计图:https://www.kubernetes.org.cn/kubernetes%E8%AE%BE%E8%AE%A1%E6%9E%B6%E6%9E%84
其中左侧:master 架构图:
先说说 master:
K8S相比docker首先引入了其自身周边的一些运维工具以及组件:
我们用k8s一般管理的是多台机器的集群; k8s 每个版本都会发布 一个叫kubectl的工具,这是一个命令行工具,其作用就是供用户敲一些命令控制-运维集群的;它的基本原理是连接k8s的apiserver组件,然后把用户的声明式命令转换为 k8sapiserver识别的 k8s内部资源的操作(CRUD); kubectl 不需要在k8s集群内,只要在任何可以连接到k8s的apiserver都可以控制操作集群。
apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制,所有api都是 声明式的API;后面我们将会看到:
· scheduler 负责 k8s集群内的调度,比如用户通过kubectl 向 apiserver下发了创建一个应用的指令; scheduler负责将你的应用容器调度到符合条件的节点上运行;调度决策可以通过一些人为设定或者完全由scheduler本身确定容器将会在哪里运行。
· Controller-Manager 负责
负责维护集群的状态,比如故障检测、自动扩展、滚动更新等。
再看看 node基本架构:
· Kubelet: 负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;同时接管docker;
· Kubeproxy: 负责为Service提供cluster内部的服务发现和负载均衡
· POD: 实际运行的容器对K8S来说是最小的调度单元和基本单位;实际跑的是用户的应用容器等等。。
4: Kubernetes 中的 POD概念:
POD 豆荚的意思,一个pod应当有一个主要的职能, 当有多个容器的时候,多个容器写作共同对外提供这个主要的职能。
举个例子:
如果我有一个 tomcat容器中跑了一个web应用;现在我想通过一种方式把web应用产生的日志上传到某个地方;那么另一个容器我可能会用一个专门的 filebeat组件专门收集日志;web组件和filebeat是两个不同镜像运行后形成的不同的容器;我不会考虑将 filebeat工具打到web组件这个镜像里,因为这不符合docker一般跑一个主进程的原则;那么我们将web和 filebeat可以组成k8s最小单元pod。
pod有如下特性;
共享网络空间;共用localhost;如果pod分配得到一个podip,两者容器是共用这个ip的。
可共享存储; Pod中的所有容器都可以访问共享的volume。
POD状态: pending, running, succeseed, failed, unknown.
容器探针: 结合kubelet可以对pod容器以某种方式做定期的诊断,以判断pod中的容器是否存活。
统一pod中的容器只会调度到同一台node
具体pod怎么共享网络参见: https://jimmysong.io/kubernetes-handbook/concepts/pause-container.html
· 一个Pod中运行一个容器。“每个Pod中一个容器”的模式是最常见的用法;在这种使用方式中,你可以把Pod想象成是单个容器的封装,kuberentes管理的是Pod而不是直接管理容器。
· 在一个Pod中同时运行多个容器。一个Pod中也可以同时封装几个需要紧密耦合互相协作的容器,它们之间共享资源。
5:如何创建第一个POD?
结合 kubectl工具,然后写一个声明式的资源文件 helloworld.yml
然后使用 命令: kubectl create -f helloworld.yml 在集群上创建该pod
使用命令查看该pod:
如果需要查看其docker下的形态,需要登录到 这台节点 node去执行docker ps;
docker 形态下查看该 pod
这仅仅是个开始, 在上面,我们是使用声明式api创建了 一个pod,但在k8s集群中,
我们基本都将 pod创建权交给 各种控制器;
在早期版本的K8S ,有一种控制器叫做 ReplicationController;
我们使用如下声明式文件创建一个 demo
replication.yml
ReplicationController用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收
查看当前 replication的信息;
查看该replication的资源表述;
访问并查看查看其中一个nginx pod日志信息;
你可以通过kubectl 实时对此 replication手动扩容;
稍等几秒后:
Deployment是 ReplicationController的改良版本;基本拥有RC全部特性,并且有了一些更高阶的特性,比如滚动更新,回滚版本;
· 什么时候使用deployment
如果是服务类的 pod ,优先考虑使用Deployment
以上我们看到看到了k8s集群中如何创建一个helloworld pod,以及使用 ReplicationController来创建pod。
我们发现
· 我们抛弃了原有 通过ssh 连接到各个主机手动安装 nginx的方式;
· 我们抛弃了部署脚本(playbook), 对资源的声明本身即是k8s的 playbook;
· 我们可以很方便的通过连接 主控apiserver 扩展我们实例的副本数
还有很多重要特性没有演示:
· 当pod容器中 遇到错误挂掉, RC/或者deployment会重建该POD ,重启拉起容器并运行,并且孜孜不倦的保证 你的pod处于你的 一个期望状态(比如你希望 实例数增加,比如所有容器 runnig)
· 配合k8s的其他特性保证 pod的高可用,降低运维的复杂度;
下次课程我们将接触 K8S的service原理以及k8s的pod网络相关知识。
最后,小编携全体爱测的伙伴们祝大家端午节快乐啦!(手动撒花花~~)