kubernetes-基础理论-1

devops概念

  • 应用程序交付在运维人员之前,一般来讲需要一个开发团队,做架构设计、做开发、开发完成之后还要做构建然后测试,回滚,测试,验收,上线等等流程,在交付给运维之前开发完成之后这个过程,如果它能够自动实现,我们就把它称为持续集成的过程,整个环境的需要人工的环节只有一个就是开发代码。
  • 集成完成之后就该交付给运维进行部署了,那么交付给运维是这样的,测试通过后自动打包到一个可以被运维拿到的一个共享的文件服务上,或者是一个仓库当中,让我们运维人员能够得到打包好的构建好的最终产品,把这一步也能自动实现,那这就叫做持续交付。
  • 我们运维拿到最终产品之后就是做部署的,假设我们运维人员拿到之后也不需要做部署,一旦交付完成之后,我们有一款工具能够自动把这套代码拖出来,把它自动发布到对应的线上环境,那么这就叫持续部署,而这一切能自动循环实现,就称之为Devops;
  • 正是因为这种自动持续的流水作业,使得容器技术的实现可以让这些流程得以落地,原因在于,我们构建好的产品,要能够部署在对应的平台上,如有些环境是 windows、linux或ubuntu,这种复杂的异构环境, 原始的方式会使得在构建部署真正的不同平台时,代码是无法通用的,而最终要实现交付部署是非常困难的;
  • 我们为了每一种目标环境,就不得不构建一种适用的目标版本来,但是有了容器之后,这就变得简单了,只要我们的目标平台能够适用容器,那么我们就可以直接将我们的应用程序打包成镜像直接启动起来,而后不管是什么平台,把镜像运行为容器即可,使得自动部署变得极为简单,因此正式容器技术的出现,使得devops在落地上,就完全实现了可能,这就是容器技术带来的好处;
  • 正是因为有了容器编排工具才有了devops, 但又因为devops才使得容器编排工具得以流行, 以打通开发与运维之间的瓶碍
  1. CI: 持续集成

​ 持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试,只要有一个测试用例失败,就不能集成。

  1. CD: 持续交付

​ **持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。**如果评审通过,代码就进入生产阶段, 持续交付可以看作持续集成的下一步。它强调的是,不管怎么更新,软件是随时随地可以交付的

  1. CD: 持续部署

​ **持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。**持续部署的目标是,代码在任何时刻都是可部署的,可以进入生产阶段, 持续部署的前提是能自动化完成测试、构建、部署等步骤

  1. 架构设计 --> 开发 --> 构建(测试env) --> 测试 --> 部署(线上env)

容器优势

  • **快速创建/部署应用:**与VM虚拟机相比,容器镜像的创建更加容易。
  • **持续开发、集成和部署:**提供可靠且频繁的容器镜像构建/部署,并使用快速和简单的回滚(由于镜像不可变性)。
  • **开发和运行相分离:**在build或者release阶段创建容器镜像,使得应用和基础设施解耦。
  • **开发,测试和生产环境一致性:**在本地或外网(生产环境)运行的一致性。
  • **云平台或其他操作系统:**可以在 Ubuntu、RHEL、 CoreOS、on-prem、Google Container Engine或其它任何环境中运行。
  • **Loosely coupled,分布式,弹性,微服务化:**应用程序分为更小的、独立的部件,可以动态部署和管理。
  • 资源隔离
  • **资源利用:**更高效

编排工具

  1. kubernetes
  2. docker swarm : docker公司开发的编排工具
  3. apache mesos and marathon: idc/os 数据中心管控工具

容器编排工具应当具有的功能

  • 服务自动发现
  • 负载均衡
  • 安全、配置、存储管理
  • 健康检查
  • 自动 [扫描/重启/心跳] 配置 节点
  • 零down机部署

K8S是什么

​ Kubernetes是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。 (容器本身仅提供托管运行应用的逻辑, 而容器编排才是真正产生价值的所在),Kubernetes是Google 2014年创建管理的,是Google 10多年大规模容器管理技术Borg的开源版本。 其中openshift是k8s的发行版, 下载地址

通过k8s可以

  • 快速部署应用
  • 快速扩展应用
  • 无缝对接新的应用功能
  • 节省资源,优化硬件资源的使用

Kubernetes 特性

  • 可移植: 支持公有云,私有云,混合云,多重云 (multi-cloud)
  • 可扩展: 模块化, 插件化, 可挂载, 可组合
  • 自动化: 自动部署,自动重启,自动复制,自动伸缩/扩展
    • 自动装箱: 基于资源极其依赖约束,能够自动完成容器的部署而且不影响其可用性;
    • 自我修复: 当某一个容器挂了, 它可以自动一秒重启一个新的容器, 假设有一个应用程序(容器)挂了, 我们可以直接删除它创建一个新的,不必要修复, 所以有了k8s这个编排工具后,我们更多关注于群体而不是个体了;
    • **自动发布和回滚:**当上线代码出现问题的时候,可以自动实现发布和回滚;
    • **密钥和配置管理:**容器化应用程序的最大的问题在于,我们所配置应用程序比较苦难,我们基于镜像启动一个容器之后,我们如果期望容器中的应用程序换一种配置文件,那么我们就可以使用配置管理来实现,类似我们的docker的环境脚本,实现云配置的集中化;
    • **存储编排:**把存储卷实现动态供给,也就意味着,某一个容器需要用到存储卷的时候,根据容器自身的需求创建能够满足它需要的存储卷,实现存储编排;

Kubernetes 架构

​ k8s其实就是一个集群,组合多台主机整合成一个大的资源池并统一对外提供计算,存储的集群,我们将N个主机在每台主机之上都安装上Kubernetes的相关应用程序,然后在这个程序之上进行通信,从而完成彼此间的协调,并通过这个应用程序协同工作,把多个主机当一个主机来使用;
​ 集群有两种常用模型,第一种是P2P没有中心节点,每一个节点都能够接受用户请求,第二种是有中心节点的集群,比如像MySQL的主从复制,只有一个是主节点,其他都与他进行同步,这就是中心节点。在Kubernetes就是属于这种有中心节点架构的集群系统,从这个维度上来讲,它被叫做master/nodes集群

  • master: 由一个或一组节点组成, 主节点是集群的唯一入口,
  • node: 每一个节点都会贡献一部分计算能力、存储能力等相关资源, node其实就是运行容器的节点;
  • 分布式必须最少满足 一个master, 二个node, 生产环境最少得要满足两个master,架构图如下
    在这里插入图片描述

​ 用户通过api server 将请求提交给master, master中有一个调度器会分析各node的可用资源状态,找一个最佳适配的node节点,然后由这个node本地的docker或其它容器引擎将这个容器启动,这个node会先判断检查本地是否有这个镜像,如果没有会先去docker register中Pull,而register也可以做为容器运行,所以我们的register也可以交给k8s,这就是所谓的k8s功能模型,接收请求的只能kubernetes Cluster, 对外提供服务的为API Server (curd)

k8s-master组件

提供的服务: API Server, Scheduler, Controller-manage, etcd

在这里插入图片描述

Api Server

接收并处理请求,提供对外的增删改查接口, 如果用户请求是CURD,那么这个请求不应该运行在master之上,而是在node, 具体那个node可用由调度器来决定, Kubernetes的API Server是一个restfull风格的API,通过http向外提供服务,因此restfull当中所有向外输出的都是对象,所有的对象都可以拥有标签,所有的标签都可以使用标签选择器进行筛选

Scheduler

  • 负责观察每个node的计算资源, 如(cpu/mem/disk), 调度容器的请求,
  • k8s不但能够设定资源上限还能设置资源下限,我们称为请求量,意思就是一旦请求那么必须确保对应的node上有能够支撑的资源量,所以调度器就需要进行评估,哪一个节点更合适;
  • 为此Kubernetes设计了一个两级调度的方式来做调度,第一步先做预选,哪些服务器是符合要求的,比如有10台服务器,选出来有3台符合,然后再对这三个进行优选,从这个三个中再选择一个最优的节点;

Controller-manage

​ Controller Manager作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。

每个Controller通过API Server提供的接口实时监控整个集群的每个资源对象的当前状态,当发生各种故障导致系统状态发生变化时,会尝试将系统状态修复到“期望状态”。

Replication Controller

副本控制器的作用即保证集群中一个RC所关联的Pod副本数始终保持预设值, 支持自动滚动更新以及回滚操作

  1. 只有当Pod的重启策略是Always的时候(RestartPolicy=Always),副本控制器才会管理该Pod的操作(创建、销毁、重启等)如果一个Pod失败重启,重启的Node由Replication Controller决定,不一定是原先的Node
  2. RC中的Pod模板就像一个模具,模具制造出来的东西一旦离开模具,它们之间就再没关系了。一旦Pod被创建,无论模板如何变化,也不会影响到已经创建的Pod。
  3. Pod可以通过修改label来脱离RC的管控,该方法可以用于将Pod从集群中迁移,数据修复等调试。
  4. 删除一个RC不会影响它所创建的Pod,如果要删除Pod需要将RC的副本数属性设置为0或直接删除控制器
  5. 不要越过RC创建Pod,因为RC可以实现自动化控制Pod,提高容灾能力。

RC职责

  1. 确保集群中有且仅有N个Pod实例,N是RC中定义的Pod副本数量。
  2. 通过调整RC中的spec.replicas属性值来实现系统扩容或缩容。
  3. 通过改变RC中的Pod模板来实现系统的滚动升级。

RC使用场景

使用场景 说明 使用命令
重新调度 当发生节点故障或Pod被意外终止运行时,可以重新调度保证集群中仍然运行指定的副本数。
弹性伸缩 通过手动或自动扩容代理修复副本控制器的spec.replicas属性可以实现弹性伸缩。 kubectl scale
滚动更新 创建一个新的RC文件,通过kubectl 命令或API执行,则会新增
一个新的副本同时删除旧的副本,当旧副本为0时,删除旧的RC。
kubectl rolling-update

etcd

kv存储数据库, 与redis差不多, 具有rest协议可实现节点选举, 类似于zk, 存储master状态信息, 内部端口https用于内部通信,  外口端口http用于客户端通信。

k8s-node组件

工作节点, kubelet, docker(或者说容器引擎), kube-proxy

服务名称 状态说明
kubelet pod对应的容器的创建、启停等任务,同时与master节点密切协作,实现集群管理的相关功能
docker docker引擎, 负责本机的容器创建和管理工作
kube-proxy 实现kubernetes service的通信与负载均衡机制

POD

​ k8s上调度最小的逻辑单元,pod主要就是用来放容器的,一个pod可以包含多个 容器,而容器之间可以共享名称空间( ipc, net, uts),而mount,pid,user相互隔离, pod存储卷也可以共享。 k8s通过label-select识别pod节点是否属于哪个控制器
​ node是 k8s集群node节点负责运行,并且是由k8s集群中master指派的任务,而最根本的是它的最核心的任务是以Pod的形式去运行容器的,理论上讲,node可以是任何形式的计算设备,只要有传统意义上的CPU、内存啊等并且能够装上Kubernetes集群的代理程序它都可以作为整个Kubernetes集群的一个份子来进行工作,因此Kubernetes的实现效果就类似于如图

在这里插入图片描述

名称 说明
label 为了统一管理在同一个集群的大量资源,添加的元数据,kv类型
label-select 定义过滤条件,来挑选出所符合条件的pod资源

一个容器加入到pod, 都会属于同一个infra, 服务发现:当一个pod生成之后,会自动注册到控制器上

自主式POD

​ 自我管理,提交给api server, 借助Scheduler到指定的node节点, 由node启动节点,如果节点故障该pod也会消失,无法实现全局调度

控制器管理的Pod

  1. Replication Controller: 副本控制器
  2. ReplicaSet 副本集 不直接使用
    • Depolyment: 只能管理无状态应用控制器
      • HPA: 水平Pod自动伸缩控制器
    • StatefulSet: 有状态控制器
    • DaemonSet: 每个node上都运行一个副本
    • job、Ctonjob: 特殊控制器, 如: 备份, 清理日志

Service

​ Kubernetes为每一组提供同类服务的Pod和客户端之间添加了一个中间层,这个中间层是固定的,这个中间层就叫Service,Service只要不删除,它的地址和名称就是固定的,而后当客户端需要写在配置文件当中访问某一个服务的时候也不需要发现,不用自动发现某一个功能,他只需要在配置文件当中写入服务的名称和服务的地址即可,而这个服务是一个调度器,还能提供调度的功能,不但能提供稳定的访问入口还能提供调度Pod,一旦Pod宕机,新建的Pod会立即加入Service里面来,并把这个Pod作为后端的可用访问入口之一;

​ Service是靠标签选择器来关联Pod对象的,所以只要Pod存在只要属于这一组标签选择器就能立即被Service作为后端组件存在,并且Service把Pod关联进来之后还会动态探测IP地址是什么,端口是什么,并作为自己调度的后端可用接口,因此客户端的请求到达Service,由Service代理至后端的Pod来实现;如图
在这里插入图片描述

服务访问流程

​ 客户端 访问 --> service 代理至后端的pod, 当pod故障, service会自动根据label-select加入pod, 而sevice最终也只是一个iptables的DNAT规则或ipvs的规则,客户端也可以直接访问service的名称, 该名称会通过dns解析,如果service的地址或名称发生改变 dns会实时修改状态。

总结

k8s是master/node框架,组件列表

组件 列表
master API Server、Scheduler、Controller-Manager
node kubelet、容器引擎(Docker)、kube-proxy
Pod Label、Label Selector

k8s三个核心: pod 、控制器、service
控制器三要素: replicas, template, selector
service要素: 各种转发
Kubernetes域名解析:服务名.命名空间.svc.cluster.local

k8s网络模型

pod通信: pod与pod之间,pod与容器,pod与serivce, pod与集群外

  1. 节点网络: 节点地址
  2. service: 集群网络,虚拟地址,存在于ipvs或iptables中
  3. pod: pod网络
    • 同一个pod内的多个容器间: lo通信
    • 各pod之间通信
    • pod与service之间的通信 service通过kube-proxy随时与api server通信, 当pod发生改变时,其结果会非常保存API server中, 而 api service通信内容发生改变时会立即生成一个事件,kube-proxy当发现改变时会直接修改客户端 的iptables、ipvs规则

在这里插入图片描述

pod与pod之间通信

Pod和Pod之间通信,在Kubernetes内还存在三种通信网络,

  1. 一个Pod内可能有多个网络,所以同一Pod内的多个容器直接通过lo进行通信就行了;
  2. 各Pod之间的通信可直接使用对应Pod的地址进行通信,但是如果Pod过多可能会产生广播风暴;
  3. 通过隧道的方式转发二层报文,使得两台主机虽然跨主机但好像工作在同一个二层网络中一样,叠加有二层叠加跟三层叠加,我们可以转发对方的二层报文或隧道转发对方的三层报文从而实现叠加网络,这样就能实现Pod与Pod之间通信了;

Pod与Service通信

​ Pod有Pod独立的网络,Service也有Service的独立网络,那他们之间的通信从原理上来讲是不可达的,因为Service只不过是主机之上的iptables的规则地址,所以只需要将容器的报文指向网关, 网关假如是我们的docker0桥, 因为我们当前宿主机就有iptabels规则, 而每台主机之上都会有iptables策略, 所以在创建Service时,这个Service要反映在Kubernetes的每个node上的,每个node都应该有相应的iptables或ipvs规则,如果有一个容器视图去访问Service地址时,它应该把请求送给网关,一般是docker0桥的地址,而docker0桥收到以后发现这个地址需要通过我们的iptables规则表进行检查就知道它到底在哪儿,就找到了它

  • 因为Service随时也会产生变动,比如删除了Service或Pod改变了,那么Service规则中的目标地址也会改变, 如果Pod发生改变那么Service就需要使用标签选择器进行匹配并且获取地址;
  • 但是Service如何改变所有node的相关规则呢,那这个就需要一个专门的组件来实现,所以每一个node节点上需要一个组件,这个组件在node之上做为一个守护进程,它被称为kube-proxy,它负责随时与Api Server进行通信;
  • 因为每一个Pod发生变化之后这个结果需要保存在API Server当中的,对于API Server来说Pod发生改变之后会生成一个通知事件,这个事件可以被任何关联的组件接受到,比如我们的kube-proxy,一旦发现某一个Service背后的Pod地址发生改变,对应的由kube-proxy负责反映在对应node的iptables或ipvs规则上;
  • 所以Service的管理是靠kube-proxy来实现的,创建一个Service需要靠kube-proxy在每一个node上创建规则,每一个Service的变动也需要kube-proxy来反应到规则上;

在这里插入图片描述
​ kube-proxy说白了,它也是我们的Kubernetes一个客户端,它随时wath,监视者Kubernetes ApiServer上的变动,尤其是Service的资源的变动,它会把每一个Service资源的变动反应在当前节点上的对应的iptables或Ipvs规则

​ 这样一来我们的API Service需要存储整个集群当中的各组件的状态信息,那我们其他的master如何进行数据同步呢,那就涉及到共享存储,对于master主机来讲,所有的数据并不放置在master本地,而是放在共享存储里面,这个存储我们叫做Kubernetes的DB,也就是etcd,而etcd是一个键值存储系统,还支持各种协调工作,比如实现节点的选举啊等,所以etcd更像zookeeper,那etcd如果宕机了,那么整个集群就宕机了,所以etcd需要集群;

​ etcd也是restfull风格的集群,可以通过http或https通信,etcd有三个端口 一个端口集群内部通信,一个端口向客户的提供服务,也就意味着其内部通信需要点对点通信的证书,

  1. 要想向客户的通信的需要另外一套证书来实习,而Kubernetes的API Server也需要使用https加密,所以从这个角度来讲,etcd自身需要一套证书,etcd作为服务端来讲它的客户端是API Server;
  2. 而API Server需要向外部通信也需要一套证书。每个node组件有三个组件,API Server与kubelet进行通信使用https通信,所以我们要手动搭建Kubernetes是极其复杂的需要五套证书;

网络插件

无论是哪个服务商提供的网络管理方案它都应该负责管理两种网络,Pod网络和Service网络,

CNI: container network interface 容器网络接口

  • flannel: 网络配置, (配置简单,不支持策略)
  • calico: 网络配置,网络策略 (配置复杂)
  • canel: flannel+calico 功能合集 , 也可以做为容器或daemon运行

​ 其实我们网络需要两个维度,第一就是提供网络功能,给Pod提供IP地址给Service提供IP地址,第二Kubernetes的网络解决方案还要求它能够提供Network策略功能,来进行网络策略管理,进行容器隔离等,实际上也就是一些访问规则,因此我们要引入Kubernetes另外一个逻辑组件,叫做名称空间,Kubernetes的名称空间,整个Kubernetes是作为一个集群存在,我们将来可以在集群内部运行无数个Pod,都在同一个网络中,这么多的Pod,极有可能互相干扰,所以我们可以把他们切割成多个名称空间(namespace),一类Pod只运行在一个空间中,实现网络策略的管理;

es的网络解决方案还要求它能够提供Network策略功能,来进行网络策略管理,进行容器隔离等,实际上也就是一些访问规则,因此我们要引入Kubernetes另外一个逻辑组件,叫做名称空间,Kubernetes的名称空间,整个Kubernetes是作为一个集群存在,我们将来可以在集群内部运行无数个Pod,都在同一个网络中,这么多的Pod,极有可能互相干扰,所以我们可以把他们切割成多个名称空间(namespace),一类Pod只运行在一个空间中,实现网络策略的管理;

猜你喜欢

转载自blog.csdn.net/u010304195/article/details/106652146