Kubernetes笔记【历史学习文档】

Kubernetes笔记【历史学习文档】
XRKubernetes笔记【历史学习文档】
一、Kubernetes的前世
看似很新(相对于刚出现时来说),但它却是谷歌十几年以来大规模应用容器技术的经验积累和升华的重要成果。确切地说,Kubernetes是谷歌严格保密十几年的秘密武器——Borg的一个开源版本。Borg是谷歌的一个久负盛名的内部使用的大规模集群管理系统,它基于容器技术,目的是实现资源管理的自动化,以及跨过个数据中心资源利用率的最大化。十几年以来,谷歌一直通过Borg系统管理者数据庞大的应用程序集群,由于谷歌员工都签署了保密协议,即使离职也不能泄露Borg的内部设计,所以外界一直无法了解关于它的更多信息。直到 2015 年 4 月,传闻许久的Borg论文发布,伴随着Kubernetes的高调宣传被谷歌首次公开。
Borg就是一个喷气式飞机的驾驶系统,非常的专业和高大上,他适用于谷歌这样的大公司,它有几百万的机器。Kubernetes是一个它的简化版,它是一辆设计优良的轿车,它适合中小型公司,更方便的用它来调度自己的集群。
但即使是简化版,K8s的 go源代码量超过 430 万行(总代码量已经超过 520 万行)
二、Kubernetes 三问
2.1 Kubernetes具体是什么?
Kubernetes是用于自动部署,扩展和管理容器化应用程序的开源系统,它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。
Kubernetes,构建在 Docker 技术之上,为跨主机的容器化应用提供资源调度、服务发现、高可用管理和弹性伸缩等一整套功能,它提供了完善的管理工具,涵盖开发、部署测试、运维监控等各个环节。
2.2 为什么需要Kubernetes,不用Kubernetes可以吗?
1.** **传统部署时代:
互联网早期,会直接将应用程序部署在物理机上,例如直接将java程序部署到物理机中。像我有时候为了方便就 springboot项目一搭建,写好代码直接打成jar包。然后用 java -jar,直接就可以运行了(前提是linxu搭建了java环境)。可以说算是很方便了,不需要其他技术的参与。但是也有很多不足的点。
缺点:
(1)不能为应用程序定义资源使用边界,很难合理的分配计算资源,而且程序之间容易产生互相影响。
(2)当1个程序出现漏洞时,导致机器OOM或者宕机。另一个程序也受到影响。
总的说:无法为物理服务器中的应用程序定义资源边界,这会导致资源分配问题。 例如,如果在物理服务器上运行多个应用程序,则可能会出现一个应用程序占用大部分资源的情况, 结果可能导致其他应用程序的性能下降。 一种解决方案是在不同的物理服务器上运行每个应用程序,但是由于资源利用不足而无法扩展, 并且维护许多物理服务器的成本很高。
2.** **虚拟化部署时代:
作为解决方案,引入了虚拟化。虚拟化技术允许你在单个物理服务器的 CPU 上运行多个虚拟机(VM)。** 虚拟化允许应用程序在 VM 之间隔离(VMware、Hyper-V)**,并提供一定程度的安全,因为一个应用程序的信息 不能被另一应用程序随意访问。
虚拟化技术能够更好地利用物理服务器上的资源,并且因为可轻松地添加或更新应用程序 而可以实现更好的可伸缩性,降低硬件成本等等。每个 VM 是一台完整的计算机,在虚拟化硬件之上运行所有组件,包括其自己的操作系统。
缺点:
(1)资源开销大:每个虚拟机需要一个完整的操作系统,占用较多的硬件资源。
(2)启动速度慢:虚拟机启动需要时间,特别是操作系统启动时间较长。
(3)管理复杂:虚拟机管理相对复杂,维护成本较高。
这些缺点,也严重限制了其进行大规模应用部署和维护的可能。所以目前也极少数有微服务架构会选择使用虚拟机去部署应用。
3.** **容器化部署时代:
容器类似于 VM,但是它们具有被放宽的隔离属性,可以在应用程序之间共享操作系统(OS)。 因此,容器被认为是轻量级的虚拟机。容器与 VM 类似,具有自己的文件系统、CPU、内存、进程空间等。
容器的优势:
(1)轻量级和高效:容器共享宿主机的操作系统内核,启动速度快,资源开销小,非常适合微服务架构中频繁启动和销毁服务的需求。
(2)快速部署和扩展:容器可以快速部署和扩展,适应微服务架构的快速迭代和扩展需求。
(3)环境一致性:开发环境和生产环境一致,减少了环境差异带来的问题,提高了应用的稳定性和可靠性。
目前的时代就是属于容器化的时代。使用容器化方式进行部署应用带来了非常多的方便,我们几乎不用考虑环境的影响。github上很多项目都直接提供docker部署,往往一个命令就可以跑起来。但是一旦需要大规模使用容器化部署,我们还是会遇到一些问题:
● 一个容器故障停机了,怎么样让另外一个容器立刻启动去替补停机的容器?
● 如何将服务部署到多台物理机上,做到充分利用资源?
● 当并发访问量大的时候,怎么样做的横向扩展容器数量?
这些容器管理的问题统称为容器编排问题,为了解决这些容器编排问题,就产生了一些容器编排软件:
● Swarm:Docker自己的容器编排工具
● Mesos:Apache的一个资源统一管控的工具,需要和Marathon结合使用
● Kubernetes:Google开源的的容器编排工具
2.3 Kubernetes能做什么?
Kubernetes 提供的最简单的功能就是容器编排,其本质上是一组集群。它可以在集群的每个节点上运行容器化程序,并对这些节点中的容器进行管理。目的是实现资源管理的自动化,主要提供了如下的主要功能:
● 自我修复:一旦某一个容器崩溃,能够在1秒中左右迅速启动新的容器。
● 自动完成装箱计算:你告诉 K8s 每个容器需要多少 CPU 和内存 (RAM)。 K8s 可以将这些容器按实际情况调度到你的节点上,以最佳方式利用你的资源。
● 弹性伸缩:可以根据需要,自动对集群中正在运行的容器数量进行调整
● 服务发现:服务可以通过自动发现的形式找到它所依赖的服务
● 负载均衡:如果一个服务起动了多个容器,能够自动实现请求的负载均衡
● 版本回退:如果发现新发布的程序版本有问题,可以立即回退到原来的版本
● 存储编排:可以根据容器自身的需求自动创建存储卷。
三、** **Kubernetes 核心概念
Kubernetes的全部概念很多,且官方文档手册中覆盖比较全。这里我选一些核心和重要的概念。
官方文档https://kubernetes.io/zh-cn/docs/concepts/
3.1 kubernetes架构
一个Kubernetes集群至少包含一个控制平面(control plane),以及一个或多个工作节点(worker node)。
**1)控制平面(Control Plane) **
控制平面组件是整个集群的核心,负责控制和管理整个集群。它运行着一些关键的组件。master 节点可以有一个或多个,如果有多个 master 节点,那么它们之间需要通过 etcd 这个分布式键值存储来保持数据的一致性。
kube-apiserver(行政部门)
如果需要与Kubernetes 集群进行交互,就要通过 API。apiserver是 Kubernetes 控制平面的前端,用于处理内部和外部请求。
kube-scheduler(分管副总)
集群状况是否良好?如果需要创建新的容器,要将它们放在哪里?这些是调度程序需要关注的问题。scheduler调度程序会考虑容器集的资源需求(例如 CPU 或内存)以及集群的运行状况。随后,它会将容器集安排到适当的计算节点。
etcd(秘书)
是一种开源的分布式统一键值存储,用于分布式系统或计算机集群的共享配置、服务发现和的调度协调是一个键值对数据库。在K8s中用于存储配置数据和集群状态信息。
kube-controller-manager(CEO)
控制器负责实际运行集群,controller-manager控制器管理器则是将多个控制器功能合而为一,降低了程序的复杂性。
controller-manager包含了这些控制器:
● 节点控制器(Node Controller):负责在节点出现故障时进行通知和响应
● 任务控制器(Job Controller):监测代表一次性任务的 Job 对象,然后创建 Pods 来运行这些任务直至完成
● 端点控制器(Endpoints Controller):填充端点(Endpoints)对象(即加入 Service 与 Pod)
● 服务帐户和令牌控制器(Service Account & Token Controllers):为新的命名空间创建默认帐户和 API 访问令牌
2)工作节点(Worker Node) :
工作节点负责执行由控制平面分配的请求任务,运行实际的应用和工作负载。
kubelet(分公司负责人)
会在集群中每个节点(node)上运行。 它保证容器(containers)都运行在 Pod 中。当控制平面需要在节点中执行某个操作时,kubelet 就会执行该操作。
kube-proxy(联络员)
kube-proxy | Kubernetes 是集群中每个节点 | Kubernetes上运行的网络代理,是实现 Kubernetes 服务(Service) | Kubernetes 概念的一部分。kube-proxy 维护节点网络规则和转发流量,实现从集群内部或外部的网络与 Pod 进行网络通信。
容器运行时(Container Runtime)
容器运行环境是负责运行容器的软件。Kubernetes 支持许多容器运行环境,例如 containerd docs、docker等。
总结一下,Kubernetes主要就是由以下几个核心组件组成:
● etcd保存了整个集群的状态;
● apiserver提供了资源操作的唯一入口,并提供认证、授权、访问控制、API注册和发现等机制;
● controller manager负责维护集群的状态,比如故障检测、自动扩展、滚动更新等;
● scheduler负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上;
● kubelet负责维护容器的生命周期,同时也负责Volume(CVI)和网络(CNI)的管理;
● Container runtime负责镜像管理以及Pod和容器的真正运行(CRI);
● kube-proxy负责为Service提供cluster内部的服务发现和负载均衡;
3)多主节点架构:
3.2 核心概念
1)Pod
Pod是Kubernetes创建和管理的最小单元。一个Pod由单个或多个容器组成,这些容器共享存储和网络。
Pod的特点:
● 一个Pod可以理解为一个应用实例,提供服务。
● Pod中的容器部署在Node节点上。
● Pod中可以有一个或者多个容器。
● Kubernetes直接管理Pod,而不是容器。
疑问1:为什么需要Pod,直接用容器不行吗?
Pod主要用法:
● 运行单个容器:最常见的用法,在这种情况下可以将pod看作是单个容器的抽象封装。
● 运行多个容器:边车模式,通过在pod中定义专门容器,来执行主业务容器需要的辅助工作,这样的好处是将辅助功能同业务容器解耦,实现独立发布和能力重用。
实际使用场景有:日志收集和处理、监控和度量、服务代理和流量管理等等
边车模式通过将辅助功能与主应用解耦,使得 Kubernetes 中的应用程序更易于扩展、管理和监控。同样也增强了应用程序的灵活性和可靠性。
疑问2:Pod 如何实现的网络和存储的共享?
Pod的网络共享是默认的。每一个pod都有一个Infra Container容器,这个容器我们称之为网络容器,他负责一个pod内的所有容器的网络共享。
在pod中Infra容器永远是第一个被创建的容器,用户定义的其他容器则通过Join Network Namespace的方式与Infra容器关联在一起。
Infra容器占用极少的资源,使用的是一个非常特殊的镜像,叫做k8s.gcr.io/pause。这个镜像是一个汇编语言编写的,永远处于”暂停”状态的容器,解压后的大小仅有100-200KB。
对于pod中的容器A和容器B来说:
● 它们可以直接通过localhost(127.0.0.1)进行通信。
● 它们看到的网络设备和Infra容器看到的完全一样。
● 一个pod只有一个IP地址,也就是这个pod的Network Namespace对应的IP地址。
● pod中的网络资源一个pod一份,都是被pod中的容器共享。
● pod的生命周期只跟Infra容器一致,和容器A、B无关。
● pod中的多个容器不允许绑定相同的端口,因为所有容器共享网络协议栈,看到的网络信息一致。
对于同一个pod中的所有用户容器来说,它们的进出流量也可以认为都是通过Infra容器完成的。
与网络共享不同,pod内的存储共享不是默认的。
它是需要再pod的yaml文件去设置的。通过创建数据卷的方式,所有容器通过挂载同一个数据卷实现存储共享
2)Pod 的生命周期
概述:
我们一般将Pod对象从创建到终止的这段时间范围称为Pod的生命周期,它主要包含下面的过程:
Pod创建过程
运行初始化容器(init container)
运行主容器(main container)
容器启动后钩子(post start)、容器终止前钩子(pre stop)
容器的存活性探测(liveness probe)、就绪性探测(readiness probe)
Pod终止过程
在整个生命周期中,Pod会出现5种状态(相位),分别如下:
● 挂起(Pending):API Server已经创建了Pod资源对象,但它尚未被调度完成或者仍处于下载镜像的过程中
● 运行中(Running):Pod已经被调度到某节点,并且所有容器都已经被kubelet创建完成
● 成功(Succeeded):Pod中的所有容器都已经成功终止并且不会被重启
● 失败(Failed):所有容器都已经终止,但至少有一个容器终止失败,即容器返回了非0值的退出状态
● 未知(Unknown):API Server无法正常获取到Pod对象的状态信息,通常由于网络通信失败所导致
Pod的创建过程:
用户通过kubectl或其他的api客户端提交需要创建的Pod信息给API Server。
API Server开始生成Pod对象的信息,并将信息存入etcd,然后返回确认信息至客户端。
API Server开始反映etcd中的Pod对象的变化,其它组件使用watch机制来跟踪检查API Server上的变动。
Scheduler发现有新的Pod对象要创建,开始为Pod分配主机并将结果信息更新至API Server。
Node节点上的kubelet发现有Pod调度过来,尝试调度Docker启动容器,并将结果回送至API Server。
API Server将接收到的Pod状态信息存入到etcd中。
Pod的终止过程
用户向API Server发送删除Pod对象的命令。
API Server中的Pod对象信息会随着时间的推移而更新,在宽限期内(默认30s),Pod被视为dead。
将Pod标记为terminating状态。
kubelete在监控到Pod对象转为terminating状态的同时启动Pod关闭过程。
端点控制器监控到Pod对象的关闭行为时将其从所有匹配到此端点的service资源的端点列表中移除。
如果当前Pod对象定义了preStop钩子处理器,则在其标记为terminating后会以同步的方式启动执行。
Pod对象中的容器进程收到停止信号。
宽限期结束后,如果Pod中还存在运行的进程,那么Pod对象会收到立即终止的信号。
kubectl请求API Server将此Pod资源的宽限期设置为0从而完成删除操作,此时Pod对于用户已经不可用了。
3)Pod 检测探针
当容器进程运行时如果出现了异常退出,Kubernetes则会认为容器发生故障,会尝试进行重启解决该问题。但有不少情况是发生了故障,但进程并没有退出。比如访问Web服务器时出现了500的内部错误,可能是系统超载,也可能是资源死锁,但Nginx进程并没有异常退出,在这种情况下重启容器可能是最佳的方法。那如何来实现这个检测呢。
Kubernetes使用探针(probe)的方式来保障容器正常运行,实现零宕机。它通过kubelet定期对容器进行健康检查(exec、tcp、http),当探针检测到容器状态异常时,会通过重启策略来进行重启或重建完成修复。修复后继续进行探针检测,已确保容器稳定运行。
探针类型:
针对运行中的容器,kubelet可以选择以下三种探针来探测容器的状态:
● startupProbe 启动探针
用于检测容器中的应用是否已经正常启动。如果使用了启动探针,则所有其他探针都会被禁用,需要等待启动探针检测成功之后才可以执行。如果启动探针探测失败,则kubelet会将容器杀死,而容器依其重启策略进行重启。如果容器没有提供启动探测,则默认状态为Success。
● livenessProbe 存活探针
用于检测容器是否存活,如果存活探测检测失败,kubelet会杀死容器,然后根据容器重启策略,决定是否重启该容器。如果容器不提供存活探针,则默认状态为Success。
● readinessProbe 就绪探针
指容器是否准备好接收网络请求,如果就绪探测失败,则将容器设定为未就绪状态,然后将其从负载均衡列表中移除,这样就不会有请求会调度到该Pod上。如果容器不提供就绪态探针,则默认状态为Success
3)Pod 控制器
虽然说 Pod是最小的控制单元,但是kubernetes很少直接控制Pod,一般都是通过Pod控制器来完成的。Pod控制器用于Pod的管理,确保Pod资源符合预期的状态,当Pod的资源出现故障的时候,会尝试进行重启或重建Pod。
在kubernetes中Pod控制器的种类有不少,这里下介绍:ReplicaSet、Deployment、StatefulSet。Deployment 也是我们服务中最常用的。
更多的可以见官网:Deployments | Kubernetes
4)Pod的资源限制
在Kubernetes集群中,为了使系统能够稳定的运行,通常会对Pod的资源使用量进行限制。如果有一个程序出现异常,并占用大量的系统资源。如果未对该Pod进行资源限制的话,可能会影响其他的Pod正常运行,从而造成业务的不稳定性。
如何实现资源限制?
Kubernetes通过Requests和Limits字段来实现对Pod的资源进行限制。
● Requests:启动Pod时申请分配的资源大小
● Limits:限制Pod运行时最大可用的资源大小
在 Kubernetes 中,ReplicaSet 和 Deployment 是用于管理容器化应用程序的控制器。
ReplicaSet:
● ReplicaSet 是一种确保指定数量的 Pod 副本在任何给定时间运行的控制器。它的主要作用是保持 Pod 的数量一致。
● 如果一个 Pod 失败或被删除,ReplicaSet 会自动创建一个新的 Pod 来替换它。
● ReplicaSet 本身不会管理 Pod 的滚动更新或回滚。其不支持版本
Deployment:
● Deployment 是一种更高级别的控制器,它管理 ReplicaSet,从而间接管理 Pod。
● Deployment 提供了声明式的方式来更新应用程序,可以自动执行滚动更新、回滚以及暂停和恢复更新等操作。
● 当你创建一个 Deployment 时,它会自动创建一个 ReplicaSet 来维护 Pod 的副本数量。
StatefulSet
● 功能:StatefulSet 用于管理有状态应用程序的部署和扩展,保证 Pod 的顺序和稳定的网络标识。
● 使用场景:用于有状态的应用程序,例如数据库、分布式缓存和分布式存储系统。
● 特点:每个 Pod 都有一个唯一的、稳定的标识符(hostname),即使 Pod 被删除和重新创建,这个标识符也不会改变。
○ Pod 按照固定的顺序启动、终止和更新。
○ 提供了持久化存储的支持,通过 Persistent Volume(PV) 来保证数据持久性。
Kubernetes 基本使用更高级的Controller的抽象层控制器,来管理Pod实例。这些控制器帮助用户在各种场景中有效地部署和管理容器化应用程序,使 Kubernetes 成为一个功能丰富且灵活的容器编排平台。例如,如果一个Node故障,Controller就能自动将该节点上的Pod调度到其他健康的Node上。
四、 实战K8s
1 | apiVersion: apps/v1 |
1 | --- |
1 | --- |
四、** **Kubernetes网络
4.1 Kubernetes网络模型
该模型定义了:
● 每个 pod 都有自己的 IP 地址,这个 IP 在集群范围内可达。
● Pod 中的所有容器共享 pod IP 地址(包括 MAC 地址),并且容器之间可以相互通信(使用 localhost)
● Pod 可以使用 pod IP 地址与集群中任一节点上的其他 pod 通信,无需 NAT
● Kubernetes 的组件之间可以相互通信,也可以与 pod 通信
● 网络隔离可以通过网络策略实现
上面的定义中提到了几个相关的组件:
● Pod:Kubernetes 中的 pod 有点类似虚拟机有唯一的 IP 地址,同一个节点上的 pod 共享网络和存储。
● Container:pod 是一组容器的集合,这些容器共享同一个网络命名空间。pod 内的容器就像虚拟机上的进程,进程之间可以使用 localhost 进行通信;容器有自己独立的文件系统、CPU、内存和进程空间。需要通过创建 Pod 来创建容器。
● Node:pod 运行在节点上,集群中包含一个或多个节点。每个 pod 的网络命名空间都会连接到节点的命名空间上,以打通网络。
同Pod内的容器间通信
同 pod 内的容器间通信最简单,这些容器共享网络命名空间,每个命名空间下都有 lo 回环接口,可以通过 localhost 来完成通信。
同节点上Pod间通信
curl 发出的请求根据容器内的路由表到达了 pod 内的 eth0 接口。然后通过与 eth0 相连的隧道 veth1 到达节点的根网络空间。veth1 通过网桥 cni0 与其他 pod 相连虚拟以太接口 veth0相连,网桥会询问所有相连的接口是否拥有原始请求中的 IP 地址(比如这里的 10.42.1.9)。收到响应后,网桥会记录映射信息(10.42.1.9 => veth0),同时将数据转发过去。最终数据经过 veth0 隧道进入 pod httpbin 中。
不同节点上的Pod间通信
跨节点的 pod 间通信会复杂一些,且 不同网络插件的处理方式不同,这里选择一种容易理解的方式来简单说明下。
前半部分的流程与同节点 pod 间通信类似,当请求到达网桥,网桥询问哪个 pod 拥有该 IP 但是没有得到回应。流程进入主机的路由寻址过程,到更高的集群层面。
在集群层面有一张路由表,里面存储着每个节点的 Pod IP 网段(节点加入到集群时会分配一个 Pod 网段(Pod CIDR),比如在 k3s 中默认的 Pod CIDR 是 10.42.0.0/16,节点获取到的网段是 10.42.0.0/24、10.42.1.0/24、10.42.2.0/24,依次类推)。通过节点的 Pod IP 网段可以判断出请求 IP 的节点,然后请求被发送到该节点。
整个通信的过程需要各种组件的配合,比如 Pod 网络命名空间、pod 以太网接口 eth0、虚拟以太网接口 vethX、网桥(network bridge) cni0 等。其中有些组件与 pod 一一对应,与 pod 同生命周期。虽然可以通过手动的方式创建、关联和删除,但对于 pod 这种非永久性的资源会被频繁地创建和销毁,太多人工的工作也是不现实的。
实际上这些工作都是由容器委托给网络插件来完成的,而网络插件所遵循的规范 CNI(Container Network Interface)。
网络插件都做了什么?
● 创建 pod(容器)的网络命名空间
● 创建接口
● 创建 veth 对
● 设置命名空间网络
● 设置静态路由
● 配置以太网桥接器
● 分配 IP 地址
● 创建 NAT 规则
● 等等
4.2 实践 K8s集群网络
kubectl get ippool -o yaml > k8s-ippool.yaml
cat /etc/kubernetes/manifests/kube-controller-manager.yaml
cluster-cidr=172.168.0.0/16,指定了集群中所有 Pod 可以使用的 IP 地址范围:
● 所有 Pod 的 IP 地址都将在 172.168.0.0 到 172.168.255.255 的范围内。
● 这个范围总共有 65,536 个 IP 地址(2^16 个)。
配置文件中是没有看到 node-cidr-mask-size,如果没有设置的话,node-cidr-mask-size默认是24。24位掩码长度,对于ipv4来说就是只有8位主机长度(256)。所以咱们每个节点最多可分配 256个ipv4(理论上,实际上会少些,因为有些IP地址会保留)。
因此可以看出,理论上,整个集群最多可以支持 256 个节点。每个节点最多可容纳 256 个 Pod。
cat /etc/kubernetes/manifests/kube-apiserver.yaml
Kubernetes集群中所有Service的ClusterIP地址的分配范围,简称为Service CIDR。
service-cluster-ip-range=10.96.0.0/12:
表示Service IP地址的范围从10.96.0.0到10.111.255.255,大概一共1,048,576个 ip地址。这个范围其实很大了,我们完全用不上那么多。官方默认也是用的12位掩码长度,不过也有些只配置了16位掩码长度(65,534个ip地址)
service-node-port-range=1-65535:
指定了NodePort类型的Service在分配端口时使用的端口范围。
指定业务应用部署的命名空间,查看容器是否正常运行。
1 | kubectl get pod -n finchina-dev |
1 | kubectl describe pod finchina-search-57c98cc8c-4sdkw -n finchina-dev |
1 | kubectl logs -f --tail 10 finchina-search-57c98cc8c-4sdkw -n finchina-dev |
1 | kubectl exec -it finchina-search-57c98cc8c-4sdkw sh -n finchina-dev |
五、落地应用
5.1 微服务灰度更新(Dev):
启动探针与滚动更新配置修改
5.2 微服务优雅上下线(内外网):
容器生命周期钩子函数 PreStop+主动通知Nacos下线+容器延迟关闭
5.3 kuboard打不开问题(dev)
这个问题最后定位到是 kuboard容器内etcd空间满了。这个问题,中台的k8s出现过这个问题,然后定位解决了。后来环保的K8s也出现了这个问题,我排查后发现是一样的问题。那么怎么去解决呢?当时记录下来啦,如下:
1 | 1.在k8s主节点找到 kuboard容器及容器id |
六、** **日常使用知识点
这里给大家介绍一点点日常使用 k8s的一些知识点
1、** **容器日志在哪?重启容器后日志是不是就丢了?
想要了解服务的日志,先要看 服务的 logback-custom.xml 配置文件。logback-custom.xml
日志级别过滤(LevelFilter):
● 每个日志文件 appender 都有一个 LevelFilter,用于过滤不同级别的日志。
● 例如,DEBUG_FILE 只接受 DEBUG 级别的日志,INFO_FILE 只接受 INFO 级别- 日志,WARN_FILE 只接受 WARN 级别的日志,ERROR_FILE 只接受 ERROR 级别的日志。
● 这确保了不同级别的日志被正确记录到相应的日志文件中。
日志滚动策略:
● 每个日志文件(DEBUG_FILE, INFO_FILE, WARN_FILE, ERROR_FILE)使用了 RollingFileAppender,并且指定了 TimeBasedRollingPolicy。
● 该策略允许日志按日期滚动,并结合文件大小限制(
日志保留天数:
● 在每个 RollingFileAppender 配置中,
● 这表示每个日志文件的备份最多保留 15 天。超过 15 天的日志文件会自动删除,以节省存储空间。
其实这里我们也没看到容器的日志具体是存在哪?
那么这个logger.logHome 是在哪呢,其实它是放在了 nacos的公共配置文件 finchina_middle_common.yml 中
这样就大概知道了文件的路径了。在容器中每个服务的日志文件是存储在
1 | /apps/logs/服务名/ |
我们知道当实例被重启或者销毁时,容器也会响应的销毁。那么是否容器里的日志文件都会没了。这就要看 服务容器组的yaml文件了
所以能知道,dev information实例容器里的 /apps/logs 目录是被持久化挂载在物理机的 /app/pod-logs/finchina-release 目录下的。
从上图可以看到 物理机ip是 10.10.18.244,那么我们就可以直接去这个物理机上看到日志。并且因为是持久化挂载,物理机可以保存容器的日志,并且容器销毁后日志依旧存在。
● 如果实例重启后,部署到其他物理机上后,旧物理机上的日志不会删除。如果部署在原物理机上,则日志会追加,并不会覆盖历史日志。
● 部署到新物理机上后,新日志会追加在新物理机对应目录上。
容器的服务日志都会存储在物理机上,不会丢失。那么时间旧了,那么多日志怎么办?我从目前我们的方案里,其实没有看到针对这个的特别处理。后来我问了下运维,因为那么多日志不能不去清理,线上应该是有定时清理任务的。
1 | */30 * * * * /bin/find /app/ -mtime +7 -iname "*.log"| /bin/xargs /bin/rm -rf |
我们dev节点服务器是没有定时清理的,所以会积攒历史日志。
2、** **镜像拉不下来?
由于政策原因,之前23年6月不允许访问官方镜像仓库 Docker Hub,所以大家都是用国内镜像站。但是今年6月国内Docker加速镜像也被要求全部关闭。后续各种包管理工具可能都会下架(npm等)。
这次解决是用了一些国外镜像站。
修改节点机器的docker仓库源配置:
vim /etc/docker/daemon.json
1 | { |
1 | # 重新加载配置文件,不行的话再重启docker |
如果存在机器依旧拉取慢,可以找有镜像的机器将镜像打包推送到我们私有的harbor库里。之前就有即使配置了加速源,也拉不动镜像。所以就把 calico插件镜像推送到仓库了。这样拉镜像就特别快,并且也可以防止加速源被废弃。
http://10.15.98.150/harbor/projects/44/repositories
3.** **** 容器网络问题,无法请求到其他容器?无法解析域名?**
3.1 网络ping不通
问题可以进去先进去容器 ping 其他节点上容器组ip,看pod之间网络通信是否正常。如果发现ping不同,那就基本可以确认是容器网络问题。
这种网络问题一般都是 calico网络插件问题,可以去看下对应节点的 calico-node 是否正常运行,可以尝试重启下。
3.2 外部域名解析不成功
这种问题一般是 coredns组件运行有问题。如果还有问题,可以再检查下 node-local-dns 在节点上是否正常运行。
- 节点磁盘满了怎么办?
docker system prune -a
sudo find /app/ -mtime +7 -iname “*.log” | sudo xargs rm -rf















































