能够把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一块儿就是豆荚(一个Pod)。在k8s中咱们不会直接操做容器,而是把容器包装成Pod再进行管理.node
a. 使用Replication Controller 来部署、升级Pod b. Replica Set – 下一代Replication Controller c. Deployment – 更加方便的管理Pod和Replica Set
例子1: 提出疑惑python
先举个例子,假设咱们有一个Pod在提供线上服务,如今有以下几个场景,你们想一想如何应对: 1.节日活动,网站访问量突增 2.遭到攻击,网站访问量突增 3.运行Pod的节点发生故障 第1种状况,活动前预先多启动几个Pod,活动结束后再结束掉多余的,虽然要启动和结束的Pod有点多,但也能有条不紊按计划进行 第2种状况,正在睡觉忽然手机响了说网站反应特慢卡得要死,赶忙爬起来边扩容边查找攻击模式、封IP等等…… 第3种状况,正在休假忽然手机又响了说网站上不去,赶忙打开电脑查看缘由,启动新的Pod
解决办法:引入rcnginx
Pod须要手动管理,好累……可否在Pod发生问题时自动恢复呢,咱们先来看下Replication Controller(如下简称RC) 先说RC是什么。RC保证在同一时间可以运行指定数量的Pod副本,保证Pod老是可用。若是实际Pod数量比指定的多就结束掉多余的,若是实际数量比指定的少就启动缺乏的。
当Pod失败、被删除或被终结时RC会自动建立新的Pod来保证副本数量。因此即便只有一个Pod也应该使用RC来进行管理。
这个文件定义了RC的属性,咱们先关注以下字段: spec.replicas:副本数量3 spec.selector:RC经过spec.selector来筛选要控制的Pod spec.template:这里写Pod的定义(但不须要apiVersion和kind) spec.template.metadata.labels:Pod的label,能够看到这个label与spec.selector相同 这个文件的意思是定义了一个RC对象,它的名字是hello-rc(metadata.name:hello-rc),保证有3个Pod运行(spec.replicas:3),
Pod的镜像是index.tenxcloud.com/tailnode/hello:v1.0(spec.template.spec.containers.image: index.tenxcloud.com/tailnode/hello:v1.0)
关键在于spec.selector与spec.template.metadata.labels,这两个字段必须相同,不然下一步建立RC会失败。
(也能够不写spec.selector,这样默认与spec.template.metadata.labels相同)
如今经过kubectl来建立RC:docker
解决办法:引入rs,官方推荐使用RS代替RC数据库
1.RC只支持基于等式的selector(env=dev或environment!=qa)但Replica Set还支持新的基于集合的selector(version in (v1.0, v2.0)或env notin (dev, qa)),
这对复杂的运维管理带来很大方便 2.使用Deployment升级Pod只须要定义Pod的最终状态,k8s会为你执行必要的操做,虽然可以使用命令kubectl rolling-update完成升级,
但它是在客户端与服务端屡次交互控制RC完成的,因此REST API中并无rolling-update的接口,这为定制本身的管理系统带来了一些麻烦。 3.Deployment拥有更加灵活强大的升级、回滚功能
Replica Set目前与RC的区别只是支持的selector不一样,后续确定会加入更多功能。Deployment使用了Replica Set,是更高一层的概念。除非须要自定义升级功能或根本不须要升级Pod,因此推荐使用Deployment而不直接使用Replica Set。api
step.1 kubectl 向 k8s api server 发起一个create pod 请求(即咱们使用Kubectl敲一个create pod命令) 。 step.2 k8s api server接收到pod建立请求后,不会去直接建立pod;而是生成一个包含建立信息的yaml。 step.3 apiserver 将刚才的yaml信息写入etcd数据库。到此为止仅仅是在etcd中添加了一条记录, 尚未任何的实质性进展。 step.4 scheduler 查看 k8s api ,相似于通知机制。 首先判断:pod.spec.Node == null? 若为null,表示这个Pod请求是新来的,须要建立;所以先进行调度计算,找到最“闲”的node。 而后将信息在etcd数据库中更新分配结果:pod.spec.Node = nodeA (设置一个具体的节点) ps:一样上述操做的各类信息也要写到etcd数据库中中。 step.5 kubelet 经过监测etcd数据库(即不停地看etcd中的记录),发现 k8s api server 中有了个新的Node; 若是这条记录中的Node与本身的编号相同(即这个Pod由scheduler分配给本身了); 则调用node中的docker api,建立container。
4.ReplicaSet建立流程网络
step.1 kubectl 发起 create replicaSet 请求 step.2 k8s api server 接受 replicaSet 建立请求,建立yaml。 step.3 k8s api server将yaml的信息写入etcd数据库。 step.4 Controller-Manager中的ReplicaSetController,在etcd数据库中读到了新的replicaSet 信息后, 向k8s api server发起请求,建立3个Pod(个数能够本身指定)。 step.5 scheduler 在etcd中读到相应信息 若 3pod.spec.Node == null 则执行调度计算,找到最“闲”的若干个Node(若是有一个Node真的太闲,可能3个Pod都会被起在这个Node上面) pod1.spec.Node = nodeA (更新记录) pod2.spec.Node = nodeB pod3.spec.Node = nodeA (Node都是随机分配的) 将这些信息写回etcd数据库中。 step.6 nodeA 的 kubelet 读etcd时读到apiserver的信息,调用docker api;建立属于本身的pod1/pod3的container step.7 nodeB kubelet 读到 k8s api server的信息,调用docker api,建立pod2的container。
挂起(Pending):Pod 已被 Kubernetes 系统接受,但有一个或者多个容器镜像还没有建立。等待时间包括调度 Pod 的时间和经过网络下载镜像的时间,这可能须要花点时间。 运行中(Running):该 Pod 已经绑定到了一个节点上,Pod 中全部的容器都已被建立。至少有一个容器正在运行,或者正处于启动或重启状态。 成功(Succeeded):Pod 中的全部容器都被成功终止,而且不会再重启。 失败(Failed):Pod 中的全部容器都已终止了,而且至少有一个容器是由于失败终止。也就是说,容器以非0状态退出或者被系统终止。 未知(Unknown):由于某些缘由没法取得 Pod 的状态,一般是由于与 Pod 所在主机通讯失败。
Always: 当容器失效时, 由kubelet自动重启该容器 OnFailure: 当容器终止运行且退出码不为0时, 由kubelet自动重启该容器 Never: 不论容器运行状态如何, kubelet都不会重启该容器
kubelet重启失效容器的时间间隔以sync-frequency乘以2n来计算, 例如1丶2丶4丶8倍等, 最长延时5min, 而且在重启后的10min后重置该时间
pod的重启策略与控制方式息息相关app
RC和DeamonSet必须设置为Always,须要保证该容器持续运行
Job: OnFailure或Never, 确保容器执行完成后再也不重启
Always: 表示每次都尝试从新拉取镜像 IfNotPresent: 表示若是本地有镜像, 则使用本地的镜像, 本地不存在时拉取镜像 Never: 表示仅使用本地镜像
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment namespace: default labels: app: nginx spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: restartPolicy: Always containers: - name: nginx image: nginx:1.12 imagePullPolicy: IfNotPresent ports: - containerPort: 80