小白成长之路-k8s原理(一)
文章目录
- 前言
- 一、k8s组件
- 1.1master部分
- 1.2node节点
- 二、网络
- 2.1网络模型
- 2.2CNI
- 2.3流程
- 2.4网络解决方案
- 2.5网络模式
- 三、资源清单
- 3.1概述
- 3.2常见的资源
- 3.3资源清单的编写
- 四、Pod
- 4.1概念图
- 4.2pause
- 4.3概述
- 4.4pod生命周期
- 4.5pod探针
- 4.6钩子
- 4.7pod控制器
- 1.RC 控制器案例:
- 2.RS控制器
- 3.deployment控制器
- 4.Daemonset控制器
- 总结
前言
提示:主包第一次学k8s,有些难以理解,这篇文档是我对k8s的一个理解,如果不对之处,还望私信更正
一、k8s组件
1.1master部分
apiserver:相当于编程的接口api,按照我们的要求,执行并返回对应的数据和结果
我们想要和k8s集群进行沟通,那么这个api就是入口,他会将接收的请求存储在etcd数据库中
本身还是一种范式,基于rest风格
web ui:这里打的虚线,就是说明官方没有应用这个图形化界面,可以去安装插件,比如dashboard
etcd:是一种基于键值对存储的数据库,基于go语言实现的,整个集群的信息都会存储在这个数据库中
kubectl:客户端工具或者命令行工具,这个命令下发给了apiserver
scheduler:调度器,会去绑定我们的容器和节点之间的关系
controller:集群管家,主要作用就是保障整个集群的高可用
1.2node节点
Kubectl:通过容器引擎管理真正的管理容器,并不会真的去穿管容器,还是会通过apiserver,通过docker等来实现容器的创建
kubeproxy:监听apiserver,检查是否有防火墙规则或者负载均衡规则
总体:如果我们要通过命令行工具去下发容器的创建运行,这个请求会被发送到apiserver,apiserver先进行审核,如果没有问题,会把这个数据保存在etcd中,调度器会定期的获取我们需要运行的任务是否跟节点绑定,控制管理器会定期的检查集群运行的状态
二、网络
2.1网络模型
在不使用网络地址转换(NAT)的情况下,集群中的Pod 能够与任意其他 Pod 进行通信
在不使用网络地址转换(NAT)的情况下,在集群节点上运行的程序能与同一节点上的任何Pod 进行通信
每个 Pod 都有自己的IP 地址(IP-per-Pod),并且任意其他 Pod 都可以通过相同的这个地
址访问它
封装网络:
非封装网络:
2.2CNI
借助 CNI标准,Kubernetes 可以实现容器网络问题的解决。通过插件化的方式来集成各种网络插件,实现集群内部网络相互通信,只要实现CNI标准中定义的核心接口操作(ADD,将容器添加到网络;DEL,从网络中删除一个容器;CHECK,检查容器的网络是否符合预期等)。CNI插件通常聚焦在容器到容器的网络通信。
CNI通过 JSON 格式的配置文件来描述网络配置,当需要设置容器网络时,由容器运行时负责执行 CNI 插件,并通过 CNI 插件的标准输入(stdin)来传递配置文件信息,通过标准输出(stdout)接收插件的执行结果。从网络插件功能可以分为五类:
Main 插件,创建具体网络设备(bridge:网桥设备,连接container和 host;ipvlan:为容器增加 ipvlan 网卡;loopback:I0设备;macvlan:为容器创建一个MAC地址;ptp:创建一对VethPair;vlan:分配一个vlan设备;host-device:将已存在的设备移入容器内)
IPAM 插件:负责分配IP地址(dhcp:容器向 DHCP服务器发起请求,给Pod发放或回收IP地址:host-local:使用预先配置的IP地址段来进行分配;static:为容器分配一个静态IPy4/IPv6 地址主要用于 debug)
META 插件:其他功能的插件(tuning:通过 sysctl 调整网络设备参数;portmap:通过 iptables配置端口映射;bandwidth:使用Token Bucket Filter 来限流:sbr:为网卡设置 source basedrouting;firewal:通过iptables 给容器网络的进出流量进行限制)
Windows 插件:专门用于 Windows 平台的CNI插件(win-bridge与 win-overlay 网络插件)
第三方网络插件:第三方开源的网络插件众多,每个组件都有各自的优点及适应的场景,难以形成统一的标准组件,常用有 Flannel、Calico、Cilium、OVN 网络插件
2.3流程
2.4网络解决方案
Calico 是一个纯三层的虚拟网络,它没有复用 docker 的docker0 网桥,而是自己实现的,calico 网络不对数据包进行额外封装,不需要 NAT 和端口映射
Felix
管理网络接口
编写路由编写 ACL
报告状态
bird(BGP Client)
BGP Client 将通过 BGP 协议广播告诉剩余calico 节点,从而实现网络互通confd
通过监听 etcd 以了解 BGP 配置和全局默认值的更改。
Confd 根据 ETCD 中数据的更新,
动态生成BIRD文件,当配置文件更改时,confd触发BIRD重新加载
2.5网络模式
什么是VXLAN?
VXLAN,即 VirtuaLExtensibleLAN(虚拟可扩展局域网),是Linux本身支持的一网种网络虚拟化技术。VXLAN 可以完全在内核态实现封装和解封装工作,从而通过“隧道”机制,构建出覆盖网络(Overlay Network)
基于三层的”二层“通信,层即 vxlan 包封装在 udp 数据包中,要求 udp 在 k8s 节点间三层可达:一层即 vxlan 封包的源 mac 地址和目的 mac 地址是自己的 vxlan 设备 mac 和对端 vxlan 设备 mac 实现通讯。
三、资源清单
3.1概述
k8s所有内容都抽象为资源,资源实例化后就叫对象
3.2常见的资源
3.3资源清单的编写
# yaml格式的pod定义文件完整内容:
apiVersion: v1 #必选,版本号,例如v1
kind: Pod #必选,Pod
metadata: #必选,元数据name: string #必选,Pod名称namespace: string #必选,Pod所属的命名空间labels: #自定义标签- name: string #自定义标签名字annotations: #自定义注释列表- name: string
spec: #必选,Pod中容器的详细定义containers: #必选,Pod中容器列表- name: string #必选,容器名称image: string #必选,容器的镜像名称imagePullPolicy: [Always | Never | IfNotPresent] #获取镜像的策略 Alawys表示下载镜像 IfnotPresent表示优先使用本地镜像,否则下载镜像,Nerver表示仅使用本地镜像command: [string] #容器的启动命令列表,如不指定,使用打包时使用的启动命令args: [string] #容器的启动命令参数列表workingDir: string #容器的工作目录volumeMounts: #挂载到容器内部的存储卷配置- name: string #引用pod定义的共享存储卷的名称,需用volumes[]部分定义的的卷名mountPath: string #存储卷在容器内mount的绝对路径,应少于512字符readOnly: boolean #是否为只读模式ports: #需要暴露的端口库号列表- name: string #端口号名称containerPort: int #容器需要监听的端口号hostPort: int #容器所在主机需要监听的端口号,默认与Container相同protocol: string #端口协议,支持TCP和UDP,默认TCPenv: #容器运行前需设置的环境变量列表- name: string #环境变量名称value: string #环境变量的值resources: #资源限制和请求的设置limits: #资源限制的设置cpu: string #Cpu的限制,单位为core数,将用于docker run --cpu-shares参数memory: string #内存限制,单位可以为Mib/Gib,将用于docker run --memory参数requests: #资源请求的设置cpu: string #Cpu请求,容器启动的初始可用数量memory: string #内存清楚,容器启动的初始可用数量livenessProbe: #对Pod内个容器健康检查的设置,当探测无响应几次后将自动重启该容器,检查方法有exec、httpGet和tcpSocket,对一个容器只需设置其中一种方法即可exec: #对Pod容器内检查方式设置为exec方式command: [string] #exec方式需要制定的命令或脚本httpGet: #对Pod内个容器健康检查方法设置为HttpGet,需要制定Path、portpath: stringport: numberhost: stringscheme: stringHttpHeaders:- name: stringvalue: stringtcpSocket: #对Pod内个容器健康检查方式设置为tcpSocket方式port: numberinitialDelaySeconds: 0 #容器启动完成后首次探测的时间,单位为秒timeoutSeconds: 0 #对容器健康检查探测等待响应的超时时间,单位秒,默认1秒periodSeconds: 0 #对容器监控检查的定期探测时间设置,单位秒,默认10秒一次successThreshold: 0failureThreshold: 0securityContext:privileged: falserestartPolicy: [Always | Never | OnFailure]#Pod的重启策略,Always表示一旦不管以何种方式终止运行,kubelet都将重启,OnFailure表示只有Pod以非0退出码退出才重启,Nerver表示不再重启该PodnodeSelector: obeject #设置NodeSelector表示将该Pod调度到包含这个label的node上,以key:value的格式指定imagePullSecrets: #Pull镜像时使用的secret名称,以key:secretkey格式指定- name: stringhostNetwork: false #是否使用主机网络模式,默认为false,如果设置为true,表示使用宿主机网络volumes: #在该pod上定义共享存储卷列表- name: string #共享存储卷名称 (volumes类型有很多种)emptyDir: {} #类型为emtyDir的存储卷,与Pod同生命周期的一个临时目录。为空值hostPath: string #类型为hostPath的存储卷,表示挂载Pod所在宿主机的目录path: string #Pod所在宿主机的目录,将被用于同期中mount的目录secret: #类型为secret的存储卷,挂载集群与定义的secre对象到容器内部scretname: string items: - key: stringpath: stringconfigMap: #类型为configMap的存储卷,挂载预定义的configMap对象到容器内部name: stringitems:- key: stringpath: string
apiversion:v1 (组:版本号)
kind:类别
metdata:元数据
spec:期望
status:状态
四、Pod
4.1概念图
4.2pause
4.3概述
Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。
Pod(就像在鲸鱼荚或者豌豆荚中)是一组(一个或多个) 容器; 这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod 中的容器总是并置(colocated)的并且一同调度,在共享的上下文中运行。 Pod 所建模的是特定于应用的 “逻辑主机”,其中包含一个或多个应用容器, 这些容器相对紧密地耦合在一起。 在非云环境中,在相同的物理机或虚拟机上运行的应用类似于在同一逻辑主机上运行的云应用。
除了应用容器,Pod 还可以包含在 Pod 启动期间运行的 Init 容器。 你也可以在集群支持临时性容器的情况下, 为调试的目的注入临时性容器。
Pod 的共享上下文包括一组 Linux 名字空间、控制组(cgroup)和可能一些其他的隔离方面, 即用来隔离容器的技术。 在 Pod 的上下文中,每个独立的应用可能会进一步实施隔离。
Pod 类似于共享名字空间并共享文件系统卷的一组容器。
4.4pod生命周期
initc-1:
init 容器与普通的容器非常像,除了如下两点◆init 容器总是运行到成功完成为止
◆每个 init 容器都必须在下一个 init 容器启动之前成功完成
如果 Pod 的 Init 容器失败,Kubernetes 会不断地重启该 Pod,直到 Init 容器成功为止。然而,如果 Pod 对应的restartPolicy为 Never,它不会重新启动
initc-2:
InitC 与应用容器具备不同的镜像,可以把一些危险的工具放置在 initC 中,进行使用init℃ 多个之间是线性启动的,所以可以做一些延迟性的操作initC 无法定义 readinessProbe,其它以外同应用容器定义无异
案例:
有两个容器,都没有启动成功,只有第一个容器成功了,第二个才会创建
从日志来看因为没有服务,所以不会创建成功,证明其阻塞性
而且只有当第一个容器的返回结果为0,initc1才会进行下一步
4.5pod探针
探针是由 kubelet 对容器执行的定期诊断。要执行诊断,kubelet 调用由容器实现的 Handler。有三种类型的处理程序:
ExecAction:在容器内执行指定命令。如果命令退出时返回码为0则认为诊断成功
TCPSocketAction:对指定端口上的容器的IP 地址进行 TCP 检查。如果端口打开,则诊断被认为是成功的
HTTPGetAction:对指定的端口和路径上的容器的IP 地址执行 HTTP Get 请求。如果响应的状态码大于等于200 且小于 400,则诊断被认为是成功的每次探测都将获得以下三种结果之一:
》成功:容器通过了诊断。
》失败:容器未通过诊断。
》未知:诊断失败,因此不会采取任何行动
探针的类型:
-
livenessProbe(存活探针):判断容器是否正常运行。如果存活探测失败,那么kubelet就会把老的容器删除,然后根据重启策略对容器做操作。如果容器没有存活探针,默认状态为Success。
-
readinessProbe(就绪探针):判断容器的是否就绪。比如:应用在启动时可能需要加载大量的数据或配置文件,或是启动后要依赖等待外部服务。在这种情况下,既不想杀死应用,也不想给它发送请求。这个时候就需要用到这个探针。当就绪探测失败,端点控制器将从与 Pod匹配的所有服务的端点列表中删除该 Pod 的 IP 地址(如果是用nodeport映射端口到外网,这个时候就不能访问网站了,但是容器不会被删除),初始延迟之前的就绪态的状态值默认为 Failure。 如果容器不提供就绪态探针,则默认状态为 Success。
-
startupProbe(启动探针):指示容器中的应用是否已经启动。如果提供了启动探针,则所有其他探针都会被禁用,直到此探针成功为止。如果启动探测失败,kubelet 将删除容器,而容器依其重启策略进行重启。如果容器没有提供启动探测,则默认状态为 Success。
注意:startupProbe 和 livenessProbe 最大的区别就是startupProbe在探测成功之后就不会继续探测了,而livenessProbe在pod的生命周期中一直在探测!
就绪探针:
就绪探测
如果pod部的c不添加就绪探测,默认就绪。如果添加了就绪探测,只有就绪通过以后,才标记修改为就绪状态。当前pod内的所有的c都就绪,才标记当前 Pod 就绪
成功:将当前的C标记为就绪
失败:静默未知:静默
就绪探针案例:
1.负载均衡:
pod1
image镜像可以自己用其他的
pod2:
创建svc:
验证:
2.就绪检测:基于HTTP Get
在这里我是没有Index.html这个文件的,所以他的状态无法启动
现在我们手动创建
验证负载均衡:
2.基于exec
验证:在文件没有被删除的时候状态已就绪,文件被删除后,状态发生改变
存活探针:
介绍:k8s 通过添加存活探针,解决虽然活着但是已经死了的问题。
选项说明
*initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位“秒”,默认是 0秒,最小值是
periodSeconds:执行探测的时间间隔(单位是秒),默认为 10s,单位“秒”,最小值是 1>timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位“秒”,最小值是 1successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为1。必须为1才能激活和启动。最小值为1。
failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为3,最小值为1
就绪探测
如果pod部的c不添加就绪探测,默认就绪。如果添加了就绪探测,只有就绪通过以后,才标记修改为就绪状态。当前pod内的所有的c都就绪,才标记当前 Pod 就绪
成功:将当前的C标记为就绪
失败:静默
未知:静默
就绪探针案例:
1.基于EXEC
启动探针:
介绍:k8s在1.16版本后增加 startupProbe 探针,主要解决在复杂的程序中 readinessProbe、livenessProbe 探针无法更好的判断程序是否启动、是否存活。
选项说明
initialDelaySeconds:容器启动后要等待多少秒后就探针开始工作,单位“秒”,默认是0秒,最小值是 0periodSeconds:执行探测的时间间隔(单位是秒),默认为10s,单位“秒”,最小值是1timeoutSeconds:探针执行检测请求后,等待响应的超时时间,默认为 1s,单位“秒”,最小值是1successThreshold:探针检测失败后认为成功的最小连接成功次数,默认值为1。必须为1才能激活和启动。最小值为1。
failureThreshold:探测失败的重试次数,重试一定次数后将认为失败,默认值为3,最小值为 1。
启动探针
保障存活探针在执行的时候不会因为时间设定问题导致无限死亡或者延迟很长的情况成功:开始允许存活探测就绪探测开始执行
失败:静默
未知:静默
案例:
因为当前没有Index2,所以他的状态不对
手动创建
依然没有是因为只有当启动探测成功后,就绪探测和存货探测才会开始执行
启动探测是存在index1,当启动探测满足后,这个pod的状态就对了
4.6钩子
案例:
验证:
在 k8s 中,理想的状态是 pod 优雅释放,但是并不是每一个 Pod 都会这么顺利Pod 卡死,处理不了优雅退出的命令或者操作优雅退出的逻辑有 BUG,陷入死循环
代码问题,导致执行的命令没有效果
对于以上问题,k8s的 Pod 终止流程中还有一个"最多可以容忍的时间",即 grace period(在pod.spec.terminationGracePeriodSeconds 字段定义),这个值默认是 30秒,当我们执行 kubectl delete的时候也可以通过 --grace-period 参数显示指定一个优雅退出时间来覆盖 Pod 中的配置,如果我们配置的grace period 超过时间之后,k8s 就只能选择强制 ki Pod。值得注意的是,这与preStop Hook和SIGTERM 信号并行发生。k8s不会等待 preStop Hook完成。如果你的应用程序完成关闭并在terminationGracePeriod 完成之前退出,k8s 会立即进入下一步
4.7pod控制器
工作流程:
1.RC 控制器
案例:
验证1:我们的期望值是3,我们把第一个容器删除,会发现还是会有三个容器
验证2:添加新的标签,依然归于RC,并没有重启新的容器
验证3:修改valu值,就不归于RC,会创建新的pod
验证4:修改期望值,会创建出等量的Pod
2.RS控制器
匹配运算符:
案例1:必须是符合的标签
3.deployment控制器
replace和apply的区别
常用命令:
查看历史版本:
kubectl rollout history deployment name
回滚操作:
kubectl rollout undo deployment name --to-revision=1
4.Daemonset控制器
案例:
每个节点只有一个pod
总结
控制器还有job,cronjob,这个主包没有介绍,小伙伴们可自行学习