Kubernetes
前身:Google通过go语言对Borg进行编写开发出K8S,K8s采用HTTP协议进行C/S结构的开发
Kubernetes 特点
- 轻量级:消耗资源小
- 开源
- 弹性伸缩
- 负载均衡:IPVS
要掌握的知识点
-
基础概念:什么是Pod,控制器类型,K8s网络通讯模式,
-
Kubernetes安装:构建K8S集群
-
资源清单:资源,掌握资源清单的语法,编写Pod,掌握Pod的生命周期
-
Pod控制器:掌握各种控制器的特点以及使用定义方式
-
服务发现:掌握SVC原理及其构建方式
-
存储:掌握多种存储类型的特点,并且能够在不同环境中选择合适的存储方案。(有自己的见解)
-
调度器:掌握调度器原理,能够根据要求把Pod定义到想要的节点运行
-
安全:集群的认证、鉴权、访问控制原理及其流程
-
HELM:就像Linux yum命令,HELM是部署集群,掌握HELM原理,HELM模板自定义,HELM部署一些常用的插件
-
运维:修改Kubeadm 达到证书可用期限为10年,能够构建高可用的集群
服务分类
- 有状态服务:DBMS
- 无状态服务:LVS、APACHE
etcd的官方将它定位成一个可信赖的分布式键值存储服务务,它能够为整个分布式集群存储一些关键数据,协助分布式集群的正常运转
etcd v2会把数据写入到内存中
etcd v3会引入本地卷持久化操作
ETCD是K8s集群中一个重要的存储
kublet、kube proxy、container
kublet会与docker进行交互,操作docker去创建对应的容器,kublet会维持pod的生命周期。
kube proxy可以监听负载操作,操作防火墙,实现pod的映射。
高可用集群副本数据最好是 >=3
主要组件:
- API SERVER:所有服务访问统一入口
- CrontrollerManager:维持副本期望数目
- Scheduler:负责介绍人物,选择合适的节点进行分配任务
- ETCD:键值对数据库,存储K8S集群所有重要信息(持久化)
- Kublet:直接跟容器引擎交互实现容器的生命周期管理
- Kube-proxy:负责写入规则至IPTABLES、IPVS实现服务器映射访问的
其他插件说明
- COREDNS:可以为集群中的SVC创建一个域名IP的对应关系解析
- DASHBOARD:给K8s集群提供一个B/S结构访问体系
- INGRESS CONTROLLER:官方只能石实现四层代理,INGRESS可以实现七层代理
- FEDETATION:提供一个可以跨集群中心多K8S统一管理功能
- Prometheus:提供K8s集群的监控能力
- ELK:提供K8s集群日志统一分析介入平台
Pod概念
一个Pod封装多个容器,两个Pod共用Pause的网络栈(意味着两个Pod没有自己独立的IP地址)。
Pause是pod的根容器,pod中所有的container共享pod的网络栈和挂载存储
Pod控制类型
控制器概念
k8s中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为
生命周期不同分类
-
自主式Pod:Pod退出了,此类型的Pod不会被创建
-
控制器管理的Pod:在控制器的生命周期里,始终要维持Pod的副本数目
ReplicationController&ReplicaSet&Deplovment
ReplicationController(RC)用来确保容器应用的副本数始终保持在用户定义的副本数,即如果有容器异常退出,会自动创建新的Pod来替代;而如果异常多出来的容器也会自动回收。
在新版本的Kubernetes中建议使用ReplicaSet来取代ReplicationControlle
ReplicaSet跟ReplicationController没有本质的不同,只是名字不一样,并且ReplicaSet 支持集合式的 selector(创建pod的时候会打上标签,但有一天想删除,修改的时候,RS就支持这种方案。RC不支持。)
虽然ReplicaSet 可以独立使用,但一般还是建议使用Deployment来自动管理ReplicaSet,这样就无需担心跟其他机制的不兼容问题(比如ReplicaSet不支持rolling-update但Deployment 支持)
(达到滚动更新,回滚操作)
Deployment是通过rs去管理Pod的
★Deployment
Deployment为Pod和ReplicaSet提供了一个声明式定义(declarative)方法,用来替代以前的ReplicationController来方便的管理应用。典型的应用场景包括:
- 定义Deployment来创建Pod和ReplicaSet
- 滚动升级和回滚应用
- 扩容和缩容
- 暂停和继续 Deployment
声明式例子,如mysql创建数据库,无需告知具体步骤:
mysql的create database xx
声明式(Delpoyment):apply(优) create
命令式(rs):create(优) apply
Deployment是通过rs去管理Pod的
滚动更新和回滚操作原理图(删除的时候把副本数目降低)
HPA(HorizontalPodAutoScale)
Horizontal Pod Autoscaling 仅适用于Deployment和ReplicaSet,在V1版本中仅支持根据Pod的CPU利用率扩所容,在vlalpha版本中,支持根据内存和用户自定义的metric扩缩容
(达到水平自动扩展)
StatefullSet
Docker主要面对的是无状态服务,无状态服务即含义没有对应的存储需要实时保留,如Apache、LVS调度器。
有状态服务,MySQL,MongoDB,需要实时的进行数据的更新及存储。
StatefulSet是为了解决有状态服务的问题(对应Deployments和ReplicaSets是为无状态服务而设计),其应用场景包括:
- 稳定的持久化存储,即Pod 重新调度后还是能访问到相同的持久化数据,基于PVC来实现
- 稳定的网络标志,即Pod 重新调度后其PodName和HostName不变,基于Headless Service
(即没有ClusterIP的Service)来实现 - 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
(为什么不是start stop readiness实现?原因是它们需要更改pod内部容器的镜像,但对于init container来说是不需要更改的。只需要在pod容器运行之前加init C,并不会对原有Pod结构发生改变) - 有序收缩,有序删除(即从N-1到0)
DaemonSet
DaemonSet确保全部(或者一些)Node上运行一个Pod的副本。当有Node加入集群时,也会为他们新增一个Pod。当有Node 从集群移除时,这些Pod也会被回收。删除DaemonSet 将会删除它创建的所有Pod
使用DaemonSet的一些典型用法:
- 运行集群存储 daemon,例如在每个Node上运行glusterd、ceph。
- 在每个Node上运行日志收集daemon,例如fluentd、logstash。
- 在每个Node上运行监控daemon,例如Prometheus Node Exporter。(Zabbix监控每一个node)
Job,Cronjob
contab没有脚本纠错能力
Job会有自己的纠错能力,如果在运行的脚本没有以0状态码退出的话,会重新执行这个程序
Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束
Job的生命周期是等于Pod运行成功数目
Cron Job管理基于时间的Job(在特定的时间循环创建Job),即:
- 在给定时间点只运行一次
- 周期性地在给定时间点运行,例如:数据库备份、发送邮件
总结:
- 需要无状态服务部署到RS、Deployment
- 需要以node为节点的,部署到DaemonSet
- 需要批处理任务的,部署到Job和CronJob
- 需要有状态服务,部署到StatefulSet
- HPA就像是一个控制器的附属品,比如先部署了Deployment,再去创建个HPA去管理Deployment,可以实现自动的扩容收发,比如CPU大于60%的时候,扩容到10个节点。
(K8s默认是不支持这种的,需要有一个资源收集方案,给HPA提供一个性能指标)
Docker主要面对的是无状态服务,无状态服务即含义没有对应的存储需要实时保留,如Apache、LVS调度器。
有状态服务,MySQL,MongoDB,需要实时的进行数据的更新及存储。
服务发现
service去收集Pod是通过标签选择得到的
网络通讯模式
网络通讯模式说明
网络通讯模式 - 1
Kubernetes的网络模型假定了所有Pod都在一个可以直接连通的扁平的网络空间(所有的Pod都可以通过对方的IP直接到达)中,这在GCE(Google Compute Engine)里面是现成的网络模型,Kubernetes假定这个网络已经存在。
而在私有云里搭建Kubernetes集群,就不能假定这个网络已经存在了。我们需要自己实现这个网络假设,将不同节点上的Docker容器之间的互相访问先打通,然后运行Kubernetes
网络通讯模式 - 2
- 同一个Pod内的多个容器之间:lo,同一个Pod中的容器通过Pause容器网络栈的网卡lo进行访问
- 各Pod之间的通讯:Overlay Network
- Pod 与Service之间的通讯:各节点的Iptables规则
网络解决方案 Kubernetes + Flannel
Flannel是CoreOS团队针对Kubernetes设计的一个网络规划服务,简单来说,它的功能是让集群中的不同节点主机创建的Docker容器都具有全集群唯一的虚拟IP地址。而且它还能在这些IP地址之间建立一个覆盖网络(Overlay Network),通过这个覆盖网络,将数据包原封不动地传递到目标容器内
backend是访问池,图中的Destination是192.168.66.12
Flanneld开启网桥Flannel0,专门收集Docker0转发出来的数据报
ETCD之Flannel提供说明:
- 存储管理Flannel 可分配的IP地址段资源
(即Flannel启动之后会向ETCD去插入可以被分配的网段,记录分配网段的机器,防止已分配的网段被Flannel利用出现IP冲突。) - 监控ETCD中每个Pod的实际地址,并在内存中建立维护Pod节点路由表
(即根据Pod节点路由表,Pod网段10.1.15.0/24对应的物理主机是192.168.66.11)
不同情况下网络通信方式
同一个Pod内部通讯: 同一个Pod共享同一个网络命名空间,共享同一个Linux协议栈,共享Pause协议栈,通过localhost回环网卡通讯
Pod1至Pod2
Pod1与Pod2不在同一台主机,Pod的地址是与docker0在同一个网段的,但docker0网段与宿主机网卡是两个完全不同的IP网段,并且不同Node之间的通信只能通过宿主机的物理网卡进行。将Pod的IP和所在Node的IP关联起来,通过这个关联让Pod可以互相访问(上面图是其实就代表了不同主机之间的访问)
Pod1与Pod2在同一台机器,由Docker0网桥直接转发请求至Pod2,不需要经过Flannel
Pod1与Pod2在同一台机器的情况
Pod至Service的网络: 目前基于性能考虑,全部为iptables或LVS维护和转发
Pod 到外网: Pod向外网发送请求,查找路由表,转发数据包到宿主机的网卡,宿主网卡完成路由选择后,iptables执行Masquerade,把源IP更改为宿主网卡的IP,然后向外网服务器发送请求
MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat。
外网访问Pod: Service
组件通讯模式说明
真实的网络只有一个:节点网络
虚拟网络:Pod网络,Service网络