运维开发工程师面经(真实面试)

运维(开发)工程师面经

进程、线程、协程的区别

进程

  • 是操作系统进行资源分配和调度的一个独立单位,是应用程序运行的实例;
  • 每个进程都拥有自己的独立内存空间,一个进程至少包含一个主线程;
  • 进程间通信需要特定的机制,如管道、消息队列、套接字等;
  • 创建和销毁进程的开销比较大,因为操作系统需要分配和回收资源。

线程

  • 线程是进程中的一个实体,是被系统独立调度和分配的基本单位;
  • 同一进程内的线程共享进程的内存空间和资源,但每个线程拥有自己的栈空间;
  • 线程的创建和切换开销小于进程,因为他们共享同一进程资源;
  • 线程主要用于提高程序的并发性,允许多个线程并行执行以提高资源利用率

协程

  • 是一种程序组件,它允许挂起和恢复执行,通常应用于非抢占式多任务处理;
  • 协程在用户态管理,不需要操作系统内核支持,因此创建和切换开销小于线程;
  • 通常在同一线程内通过协程来实现并发,它们之间可以主动让出控制权;
  • 适用于IO密集型任务,可以简化异步编程模型;
  • 不是操作系统的原生概念,不同的编程语言可能有不同的协程实现

区别

  • 资源拥有
    • 进程拥有独立的内存和系统资源
    • 线程共享进程资源,但是拥有独立的栈和寄存器
    • 协程更轻量,通常在同一个线程内运行,共享更多资源
  • 开销
    • 创建和销毁进程的开销最大,其次是线程,最小的是协程
  • 通信方式
    • 进程需要特定的IPC机制
    • 线程间可以直接通过访问共享内存通信
    • 协程通常通过协作来共享数据
  • 操作系统支持
    • 进程和线程通过操作系统原生支持
    • 协程通常由编程语言运行时或库支持
  • 用途
    • 进程用于隔离不同的应用程序
    • 线程用于实现程序内部并发
    • 协程用于简化异步编程,提高性能和相应性
  • 调度
    • 进程和线程通过操作系统来调度
    • 协程由编程语言的运行时或框架调度

进程间的通信方式

  • 共享内存:是一种高效的IPC方式,允许两个或多个进程共享一个给定的存储区
  • 管道:管道是一种半双工的通信方式,允许一个进程和另一个进程之间的通信。
  • 消息队列:允许进程发送和接收消息,这些消息被存储在队列中,直到被接收。
  • 信号:是由操作系统提供的简单的通信方式,用于发送通知到进程。
  • 套接字:是一种通用的IPC方式,支持不同的通信协议,可用于进程间或网络中的节点通信。
  • 互斥锁:防止多个进程同时访问某个资源。
  • 文件映射:允许进程将文件或者设备映射到内存中,实现共享数据。
  • 事件:某些系统中,事件可以被用来作为进程间通信的一种机制。

软链接和硬链接的区别

  • 是否跨文件系统:软链接可以跨文件系统,而硬链接不可以。
  • 删除行为:删除硬链接目标不会影响链接本身,而软链接在目标被删除后会变得无效。
  • 存储内容:软链接存储目标的路径,而硬链接实际上是共享了目标的文件系统索引节点。
  • 对目录的处理:软链接可以链接到目录,硬链接通常不用于目录。
  • 文件权限:硬链接继承目标的文件权限,软链接作为一个独立的文件存在。

OSI七层模型每层的作用以及协议

  • 物理层:负责在物理媒介上传输原始比特流。常见协议:以太网、无线局域网、光纤通信。
  • 数据链路层:负责在相邻网络节点之间提供数据传输,将从物理层接收到的原始比特流组装成帧。常见协议:以太网、帧中继、点对点协议。
  • 网络层:负责在多个网络之间建立、维护和终止连接,负责数据包从源到宿的传递和路由选择。常见协议:互联网协议(IP)、ICMP、路由选择协议等。
  • 传输层:负责网络中两个节点之间提供可靠的数据传输服务,处理数据包的分割和重组。常见协议:TCP(传输控制协议)、UDP(用户数据报协议)
  • 会话层:负责建立、管理和终止应用程序之间的会话,提供数据交换的定界和同步功能。常见协议:远程过程调用(RPC)、套接字。
  • 表示层:负责数据的表示、压缩、安全和加密,确保从一个系统到另一个系统数据在表示格式上的兼容。常见协议:SSH、MIME。
  • 应用层:为应用软件提供网络服务,如远程登录、电子邮件、文件传输等。常见协议:HTTP、FTP、SMTP、DNS。

OSI模型和TCP/IP模型的区别

  • 设置和定制的机构:OSI是国际标准化组织制定的,TCP/IP是由美国国防部的高级研究计划局开发。
  • 层级划分:OSI是7层,TCP/IP通常被认为是4层(应用层、传输层、互联网层、网络接口层)或者5层。
  • 普及程度:OSI完美但是没有得到广泛应用;TCP/IP模型是互联网的基础,几乎所有的网络通信都是基于TCP/IP协议栈。
  • 实用性和灵活性:OSI比较复杂,不怎么实用;TCP/IP被广泛应用
  • 网络接口层:OSI模型中的网络接口层更多关注物理硬件的细节;TCP/IP模型中的网络接口层则更关注软件和硬件的接口,以及如何将数据帧正确地发送到物理介质上。
  • 协议分布: 在OSI模型中,会话层和表示层的概念比较明确,它们负责建立通信会话和数据的表示、安全等;在TCP/IP模型中,这些功能通常被归入应用层,或者通过其他协议实现,如SSL/TLS负责安全,FTP、SMTP等负责特定的应用层功能。

三次握手

在这里插入图片描述

  • 第一次握手:
    客户端将TCP报文标志位SYN置为1,随机产生一个序号值seq=J,保存在TCP首部的序列号(Sequence Number)字段里,指明客户端打算连接的服务器的端口,并将该数据包发送给服务器端,发送完毕后,客户端进入SYN_SENT状态,等待服务器端确认。
  • 第二次握手:
    服务器端收到数据包后由标志位SYN=1知道客户端请求建立连接,服务器端将TCP报文标志位SYN和ACK都置为1,ack=J+1,随机产生一个序号值seq=K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。
  • 第三次握手:
    客户端收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

四次挥手

在这里插入图片描述

  • 客户端发起fin位为1的FIN报文,此时客户端进入FIN_WAIT_1状态
  • 服务端接受到FIN 报文后,发送ack应答报文,此时服务端进入close_wait状态
  • 客户端接受到ack应答报文后,进入FIN_WAIT_2状态
  • 服务端处理完数据后,向客户端发送FIN报文,此时服务端进入LAST_ACK状态
  • 客户端接受到FIN报文后,客户端发送应答ack报文,进入TIME_WAIT阶段
  • 服务端接受到ack报文后,断开连接,处于close状态
  • 客户端过一段时间后,也就是2MSL后,进入close状态

TIME_WAIT的作用以及最长存在时间

作用:

  • 确保数据包传输完成:当TCP连接完成数据传输并准备关闭时,主动关闭方(通常是客户端或服务器)会进入 TIME_WAIT 状态,以确保所有数据包都已经被对方接收。
  • 防止旧连接的数据干扰:如果连接突然关闭,可能会有一些延迟的数据包在网络上徘徊。TIME_WAIT 状态确保这些“过时”的数据包在重新建立的新连接中不会造成干扰。
  • 避免连接混淆:如果相同的IP地址和端口号在短时间内重新建立连接,TIME_WAIT 状态可以防止新的连接与旧的连接混淆。
  • 实现TCP全双工可靠连接的关闭:TCP连接的关闭是四路握手过程,TIME_WAIT 状态是这个过程的一部分,确保双方都能独立地关闭连接

最长存在时间:TIME_WAIT 状态的持续时间通常是最大段生命周期(Maximum Segment Lifetime,MSL)的两倍。MSL是TCP段在网络中生存的最大时间,这个时间通常由网络环境决定。2MSL确保即使在最坏的情况下,即最后一个ACK在网络中丢失,重传的FIN也会被接收方接收到,从而允许连接可靠地关闭。

TCP和UDP的区别

  • 连接性:TCP是一种面向连接的协议,在数据传输之前需要先建立连接。UDP是一种无连接的协议,不需要事先建立连接,直接发送数据报文。
  • 速度:由于UDP不需要建立连接和进行数据确认,它的传输速度远高于TCP。
  • 可靠性:TCP提供可靠的、有序的数据传输适用于需要可靠传输的场景,如网页浏览、文件传输等。UDP不保证数据的可靠性和完整性,数据报文可能会丢失或者乱序,适用于对实时性要求较高、可以容忍部分数据丢失的场景。
  • 数据量:TCP的数据量通常较大,适用于需要可靠性和完整性保证的应用场景;UDP的数据量通常较小,因为它不进行连接的建立和数据的确认,直接发送数据报文。
  • 适用场景:TCP适用于大多数应用场景,尤其是需要数据传输的应用,如网页浏览、文件传输、电子邮件等。UDP适用于对数据传输速度要求较高、可以容忍部分数据丢失的场景,如实时音视频传输、网络游戏和物联网等。
  • 头部开销:TCP的头部开销较大,占用的字节数较多,包含源端口、目标端口、序列号、确认号、窗口大小等字段。UDP的头部开销较小,占用的字节数较少。

TCP可靠性机制有哪些

TCP(传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

  • 数据包编号:TCP给每个字节的数据包分配一个序号,确保数据能够正确地按序到达接收方。
  • 确认应答(ACK):接收方会发送确认应答给发送方,告知哪些数据已经成功接收。发送方根据这些确认应答来确定数据是否需要重传。
  • 数据校验:TCP使用校验和来检测数据在传输过程中是否出现错误。如果接收方检测到数据错误,它可以要求发送方重新发送损坏的数据。
  • 超时重传:如果发送方在一定时间内没有收到某个数据包的确认应答,它会认为该数据包丢失,并进行重传。
  • 流量控制:TCP使用滑动窗口机制来控制发送方的数据发送速率,以匹配接收方的处理能力,防止接收方被过多的数据淹没。
  • 拥塞控制:TCP通过拥塞控制算法(如慢启动、拥塞避免、快重传和快恢复)来调整数据的发送速率,以避免网络拥塞。
  • 有序传输:TCP确保数据包按照发送顺序到达接收方,如果出现乱序,接收方会缓存乱序的数据包,直到所有缺失的数据包到达后,再按序处理。
  • 最大报文段长度(MSS):TCP在连接建立时通过SYN报文交换双方的最大报文段长度,以确保数据包的大小适合网络环境,减少分片和重组的需要。
  • 保持活动(Keepalive):TCP可以配置保持活动机制,以检测连接是否仍然活跃,或者网络路径是否仍然可用。

资源无限大,如何确定TCP连接数量

在理论上,如果资源无限大,TCP连接的数量可以非常多。然而,在现实世界中,TCP连接的数量受到多种因素的限制,包括但不限于:

  • 最大端口号:TCP连接需要IP地址和端口号来标识。由于端口号范围是0到65535,每个IP地址理论上最多可以有65536个TCP连接(考虑到端口0通常不用于通信)。
  • 文件描述符限制:操作系统为每个进程设置了文件描述符的限制,TCP连接在内核中通常表示为文件描述符。这个限制可以通过ulimit命令在Linux中查看和设置。
  • 内存限制:每个TCP连接都需要分配内存以存储其状态信息,如缓冲区、控制块等。如果系统内存有限,这将限制可以建立的TCP连接数量。
  • 内核参数:操作系统的内核参数可能限制了TCP连接的数量,如Linux中的net.core.somaxconn参数控制着系统中最多可以创建的TCP连接数。
  • 网络设备容量:网络接口卡(NIC)和其他网络设备也有其处理能力的上限,这可能间接限制了TCP连接的数量。
  • 操作系统限制:操作系统可能通过安全策略或配置限制了TCP连接的数量,以防止资源耗尽。
  • 应用层限制:应用层的逻辑和性能也可能限制能够同时处理的TCP连接数量。
  • 拥塞控制和带宽:TCP协议的拥塞控制机制会根据网络带宽和拥塞情况调整数据传输速率,这也间接影响了可以维持的TCP连接数量。
  • 硬件限制:服务器的CPU核心数、网络带宽和其他硬件资源限制了可以处理的TCP连接数量。

ICMP是哪一层的协议?有什么作用?

ICMP是网络层协议,ICMP主要用于在IP主机、路由器或网络设备之间传递控制消息,例如错误报告和网络查询信息。
ICMP的作用包括

  • 错误报告:ICMP可以发送错误消息,通知发送方数据包在传输过程中遇到的问题,如“目的不可达”、“TTL超时”等。
  • 网络诊断:ICMP常用于网络诊断工具,如ping和traceroute(在某些系统中称为tracepath),它们使用ICMP回显请求和回显应答消息来测试网络连通性和路径。
  • 流量控制:ICMP可以携带有关网络拥塞的信息,帮助发送方了解网络状况并调整数据传输速率。
  • 路由器发现:ICMPv4支持路由器发现功能,允许主机确定其本地网络中的路由器。
  • 重定向:ICMP可以通知主机更优的路由选择,促使主机更新其路由表。
  • 时间戳:ICMP可以提供时间戳信息,帮助主机同步时间。
  • 地址掩码请求和通告:ICMPv4支持地址掩码请求和通告,有助于在不使用DHCP的情况下配置子网掩码。
  • 安全性:ICMP可以携带有关安全问题的信息,如“禁止访问的网络”。
  • 多播和多播侦听器发现:ICMPv6用于多播侦听器发现协议(MLD),类似于ICMPv4的IGMP(Internet Group Management Protocol)。

CPU满了,如何查看是哪些服务

  • 使用监控工具:tophtopnmonglances等工具实时监控系统资源使用情况
  • 查看CPU使用情况: 在tophtop中,按1可以高亮显示CPU使用率,从而快速看到占用CPU最多的进程。
  • 识别高CPU使用率的进程
  • 查看进程详细信息
  • 分析日志文件
  • 检查服务依赖
  • 资源使用率分析:使用更详细的工具,如Linux的perfpidstatatop,进行深入分析。
  • 检查系统配置:确保没有达到硬件限制,如CPU频率限制
  • 网络问题排查:如果怀疑是网络问题导致的CPU占用,可以使用iftop(Linux)或Wireshark等工具检查网络流量。
  • 检查服务依赖:检查服务依赖关系,有时候一个服务的高CPU使用可能是由另一个服务的问题间接引起的。
  • 更新和补丁
  • 重启服务或者系统
  • 性能调优

vi编辑器中,如何替换

vivim(Vi IMproved)编辑器中,替换文本是一个常见的操作。以下是一些基本的替换命令和技巧:

  • 单个字符替换:在普通模式下,按r,然后输入新字符,可以替换光标下的单个字符。

  • 使用替换命令:在普通模式下,输入:s:substitute开始替换操作。

  • 替换光标处的文本:命令格式::s/old/new,将光标处的old文本替换为new文本。

  • 替换行中所有匹配的文本: 命令格式::s/old/new/gg代表全局(global)。

  • 替换文件中所有匹配的文本:命令格式::%s/old/new/g%代表对整个文件进行替换。

  • 替换并忽略大小写:命令格式::%s/old/new/gii代表忽略大小写(ignore case)。

  • 确认替换:如果你想在替换前确认每个替换,可以使用c标志::%s/old/new/gc

  • 使用正则表达式替换vivim支持正则表达式,可以在替换命令中使用复杂的匹配模式。

  • 跨多个文件替换: 使用:arg:global命令结合替换,例如::arg *.txt然后:global/old/s//new/g

  • 替换并使用特殊字符:如果要替换的文本包含特殊字符(如/),可以使用反斜杠\进行转义。

  • 替换多个字符:将光标放在要替换的文本上,按v进入可视模式,选择文本,然后输入:s/new/进行替换。

  • 在普通模式下替换文本:使用:'<,'>范围来替换高亮选中的文本,例如::'<,'>s/old/new/

  • 使用寄存器存储替换文本:你可以将文本存储在寄存器中,并在替换命令中引用它,例如:"ayy:%s/old/<C-r>a/g

  • 替换并保留原字符串:如果需要在替换的同时保留原字符串,可以使用:%s/old/new/&,其中&代表保留原字符串。

常见的文件系统有哪些

  • ext4:用于Linux的第四代扩展文件系统(Fourth Extended File System),提供高性能、可靠性和大容量支持。
  • xfs: 用于Linux的高性能文件系统,设计用于大容量存储和高I/O负载。
  • ntfs:Windows操作系统的主流文件系统,提供数据恢复、大容量支持和文件加密等功能。
  • APFS:苹果公司开发的现代文件系统,用于macOS、iOS和其他Apple操作系统,提供安全性、性能和可靠性。
  • HFS+ (Hierarchical File System Plus):苹果公司早期的文件系统,曾用于macOS,现已被APFS取代。
  • ReiserFS:用于Linux的文件系统,以高性能和可靠性著称。
  • UFS (Unix File System):用于UNIX和类UNIX系统的文件系统,包括多种变体。
  • NFS:用于Linux和UNIX系统的网络文件系统,允许系统通过网络访问远程文件系统。
  • OCFS2:专为数据库应用设计的集群文件系统,用于Linux。

ceph属于哪种文件系统

分布式存储系统

常用的Linux命令

grep、ls、cat、top、ifconfig、echo、mv、cp、chmod、ps、cd、pwd、mkdir、rm、touch、du、df、curl、wget、ssh、history

TOP是如何获取到数据的

top 是一个常用的 Linux 命令行工具,用于实时监控系统的性能和资源使用情况。以下是 top 获取数据的一些主要方式:

  1. 读取 /proc 伪文件系统

    • Linux 的 /proc 伪文件系统包含了系统和进程的运行时信息。top 通过读取 /proc 中的文件(如 /proc/stat/proc/meminfo/proc/cpuinfo 等)来获取 CPU、内存、磁盘和网络等的使用数据。
  2. 解析 /sys 文件系统

    • /sys 文件系统提供了关于系统硬件和驱动的详细信息。top 可以读取 /sys 中的信息来获取额外的系统资源数据。
  3. 使用系统调用

    • top 可能使用一些系统调用来获取特定的性能数据,如 times() 来获取 CPU 时间。
  4. 解析 kmsg

    • top 可以通过解析内核日志(/var/log/messagesdmesg 命令的输出)来显示系统消息。
  5. 利用 libstatgrab

    • 在某些实现中,top 可能使用 libstatgrab 这样的库来获取系统和进程的统计信息。

df和du的定义和区别

df 和 du 是两个在类Unix系统中常用的命令行工具,它们都用于提供磁盘使用情况的信息,但它们的功能和使用场景有所不同:

df 命令

  • df(disk free)命令用于显示文件系统的磁盘空间使用情况。
  • 它显示的是文件系统级别的磁盘使用信息,包括每个文件系统的总容量、已用空间、可用空间以及挂载点。
  • df 可以显示所有文件系统的磁盘使用情况,也可以指定特定文件系统来查看。

du 命令

  • du(disk usage)命令用于查看指定文件或目录占用的磁盘空间。
  • 它显示的是文件或目录级别的磁盘使用信息,可以递归地查看子目录的磁盘使用情况。
  • du 通常用来找出哪些文件或目录占用了大量磁盘空间,帮助用户清理磁盘空间。

主要区别

  • 查看级别:df 查看的是文件系统的磁盘使用情况,而 du 查看的是文件和目录的磁盘使用情况。
  • 默认输出:df 默认显示所有文件系统的磁盘使用情况,du 默认显示当前目录的磁盘使用情况。
  • 使用场景:df 常用于检查整个文件系统的磁盘空间,du 常用于查找占用大量空间的特定文件或目录。
  • 递归与非递归:du 可以递归地查看目录的磁盘使用情况,而 df 通常不递归显示。
  • 输出格式:两者都可以使用 -h 参数以人类可读的格式输出结果。

Buffer和Cache的区别

Buffer(缓冲区)

  • 用途:缓冲区主要用于平滑和调节生产者和消费者之间的数据流。当生产者生产数据的速度和消费者处理数据的速度不一致时,缓冲区可以暂存数据,防止快速生产者压倒慢速消费者或慢速生产者饿死快速消费者。
  • 数据流向:缓冲区通常用于单向的数据流,如输入缓冲区和输出缓冲区。
  • 数据存储:缓冲区中的数据通常是按顺序存储的,并且按照先进先出(FIFO)的原则进行访问。
  • 应用场景:缓冲区常用于I/O操作,如网络通信、设备驱动程序、流处理系统等。

Cache(缓存)

  • 用途:缓存主要用于存储可能会被频繁访问的数据,以便快速访问。它利用了局部性原理,即最近访问过的数据很可能在不久的将来再次被访问。
  • 数据流向:缓存可以支持双向的数据流,即可以读取缓存中的数据,也可以向缓存中写入数据。
  • 数据存储:缓存中的数据存储通常是无序的,并且访问时不一定遵循FIFO原则。缓存可能会根据特定的替换算法(如最近最少使用,LRU)来移除和替换数据。
  • 应用场景:缓存广泛应用于CPU缓存、磁盘缓存、数据库缓存、Web服务器缓存等。

主要区别

  • 目的:缓冲区用于平滑数据流,而缓存用于加速数据访问
  • 数据访问模式:缓冲区通常按顺序访问数据,而缓存则可能根据访问模式进行优化,如随机访问。
  • 数据更新:缓冲区的数据通常是按照生产者和消费者的操作顺序更新的,而缓存的数据可能会根据算法进行预取或替换。
  • 数据存储时间:缓冲区中的数据可能只在短期内存储,而缓存中的数据可能会存储更长时间,直到被替换。
  • 大小和层级:缓存可能具有多层级结构(如CPU的L1、L2、L3缓存),而缓冲区通常没有这种层级结构。

shell语句:从文件中找出所有以x结尾的身份证号码

grep -E '[0-9]{17}[0-9X]' filename.txt

DNS的解析过程

Linux的启动流程

  • 上电自检(Power-On Self-Test, POST):计算机接通电源后,BIOS(基本输入输出系统)或UEFI(统一可扩展固件接口)进行上电自检,检测硬件是否正常工作。
  • 启动管理器(Bootloader):启动管理器(如GRUB)被加载,它允许用户选择启动哪个操作系统。
  • 内核加载:用户选择操作系统后,启动管理器加载Linux内核和初始内存映像(initramfsinitrd)。
  • 内核初始化:内核进行自我检查并初始化硬件设备、内存管理、文件系统等。
  • 挂载根文件系统:内核挂载根文件系统(通常是/),这是操作系统的顶层目录。
  • init进程:内核启动init进程,它是所有其他用户空间进程的祖先。init进程的PID(进程ID)为1
  • 系统初始化:init进程根据配置文件(如/etc/inittab/etc/init.d/systemd单元文件等)执行系统初始化脚本和服务。
  • 运行级别(Runlevel):传统上,init根据/etc/inittab配置文件将系统带入特定的运行级别(如单用户模式、多用户模式等)。
  • systemd初始化:在使用systemd的系统中,init进程实际上是systemd,它根据/etc/systemd/system/中的配置文件管理服务和目标(targets)。
  • 启动图形界面:如果配置了图形界面(如GNOME、KDE等),相关服务将启动图形会话。
  • 用户登录:系统准备就绪后,等待用户登录。用户可以通过图形界面或命令行界面登录。
  • 用户空间:用户登录后,进入用户空间,可以使用命令行或图形界面与操作系统交互。

python的内置函数

Python的内置函数是作为Python语言核心的一部分,无需导入任何模块即可直接使用的函数。以下是一些常用的Python内置函数:

  • abs(x) - 返回x的绝对值。
  • bool([x]) - 将x转换为布尔值,True或False。
  • chr(i) - 将整数i转换为对应的ASCII字符。
  • dict(**kwargs) - 创建一个字典。
  • dir([object]) - 返回对象的属性和方法列表。
  • enumerate(iterable, start=0) - 将iterable的元素和它们的索引包装在一个元组中。
  • float([x]) - 将x转换为浮点数。
  • format(value[, format_spec]) - 格式化值。
  • globals() - 返回当前全局符号表的字典。
  • input([prompt]) - 从用户那里获取输入。
  • int([x, base=10]) - 将x转换为整数。
  • isinstance(object, class) - 检查对象是否是类的一个实例。
  • iter(object[, sentinel]) - 返回对象的迭代器。
  • len(object) - 返回对象的长度。
  • list([iterable]) - 将可迭代对象转换为列表。
  • max(iterable, *[, key, default]) - 返回可迭代对象中的最大值。
  • min(iterable, *[, key, default]) - 返回可迭代对象中的最小值。
  • next(iterator[, default]) - 返回迭代器的下一个项目。
  • open(file, mode=‘r’, buffering=-1, encoding=None, errors=None, newline=None) - 打开文件并返回文件对象。
  • pow(x, y[, z]) - 幂运算,x的y次幂,如果提供了z,则对结果取模z。
  • print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False) - 打印对象。
  • range(start, stop[, step]) - 创建一个整数序列。
  • round(number[, ndigits]) - 四舍五入数字。
  • set([iterable]) - 创建一个可变集合。
  • slice(start, stop[, step]) - 创建一个切片对象。
  • sorted(iterable, *, key=None, reverse=False) - 排序可迭代对象。
  • str([object]) - 将对象转换为字符串。
  • sum(iterable, start=0) - 求和可迭代对象中的元素。
  • tuple([iterable]) - 将可迭代对象转换为元组。
  • import(name, globals=None, locals=None, fromlist=(), level=0) - 动态地导入模块。

python中的元祖和列表区别

python中有哪些数据类型

  • 数值类型
    • int
    • float
    • complex
  • 布尔类型
    • 表示逻辑值True或False。
  • 序列类型
    • list
    • tuple
  • 集合类型
    • set:可变的无序集合,元素唯一。
    • frozenset:不可变的无序集合。
  • 字典类型 (dict):通过键值对存储数据的集合,键必须是不可变类型。
  • 文本类型:string
  • None类型 (NoneType)
  • 类和实例 (class):类是创建对象的模板,实例是类的特定实例。
  • 装饰器:特殊类型的函数,用于修改或增强其他函数的功能。
  • 模块类型 (module):表示Python模块的对象。
  • 命名元组 (collections.namedtuple)
  • Counter
  • 异常类型:表示错误的类型,如ValueError、TypeError等
  • 二进制数据类型:
    • bytes: 不可变的二进制数据。
    • bytearray: 可变的二进制数据。
  • 迭代器和生成器:
    • 迭代器是可以实现迭代协议的对象。
    • 生成器是使用yield语句的函数,返回一个迭代器

python中装饰器的作用

Python中的装饰器是一种设计模式,用于修改或增强函数、方法或类的行为,而不需要永久修改其结构。装饰器本质上是一个函数,它接受一个函数作为参数并返回一个新的函数。以下是装饰器的一些主要作用:

  • 增加功能:装饰器可以在不修改原始函数代码的情况下给函数增加新的功能。
  • 日志记录:使用装饰器可以在函数执行前后添加日志记录,方便调试和追踪。
  • 性能测试:装饰器可以用来测量函数的执行时间,分析性能瓶颈。
  • 访问控制:装饰器可以用于实现访问控制,例如权限检查、条件访问等。
  • 参数验证:在函数执行前,装饰器可以对输入参数进行验证。
  • 资源管理:装饰器可以用于自动管理资源,如文件的打开和关闭。
  • 异常处理:装饰器可以统一处理函数可能抛出的异常。
  • 代码复用:通过装饰器,可以避免重复编写相同的代码片段。
  • 测试和调试:在测试和调试过程中,装饰器可以临时修改函数的行为。
def my_decorator(func):
    def wrapper(*args, **kwargs):
        # 在函数执行前进行的操作
        result = func(*args, **kwargs)
        # 在函数执行后进行的操作
        return result
    return wrapper

@my_decorator
def my_function():
    # 函数体
    pass

nodejs如何实现的多线程

Node.js 实现多线程的方式与传统的多线程编程有所不同。Node.js 采用的是单线程事件循环模型,但提供了一些机制来利用多核CPU的能力:

  1. Child Processes:Node.js 使用 child_process 模块允许你在单独的进程中运行 JavaScript 代码,从而实现真正的并行计算。fork() 方法可以用来创建子进程。

  2. Cluster Modulecluster 模块是 Node.js 的一个内置模块,允许你创建多个工作进程(worker processes),这些进程共享服务器端口,但运行在不同的CPU核心上。

  3. Worker Threads:Node.js 从版本 10 开始引入了 worker_threads 模块,允许在主线程之外创建和运行多个线程。这对于执行CPU密集型任务非常有用。

  4. Event Loop: Node.js 的事件循环是单线程的,用于处理所有的 I/O 操作和回调函数。尽管事件循环是单线程的,但它可以异步地调度任务,从而避免阻塞。

  5. Asynchronous I/O:Node.js 的 I/O 操作是异步的,这意味着即使在等待 I/O 操作完成时,事件循环也可以继续运行其他任务。

  6. Thread Pool: Node.js 内部有一个线程池,用于执行一些阻塞性操作,如文件系统读写、数据库操作等。这些操作在线程池中的工作线程上执行,而不会影响事件循环的运行。

  7. Atomics and SharedArrayBufferAtomicsSharedArrayBuffer API 允许在工作线程之间共享和操作内存,这对于实现复杂的多线程操作非常有用。

  8. Performance Hooksperformance 模块提供了性能相关的钩子,允许你监控和分析多线程应用程序的性能。

  9. External Libraries:社区提供了许多第三方库,如 better-queuegeneric-pool 等,用于简化多线程和资源池的管理。

  10. Message Passing:在使用 child_processworker_threads 时,进程间通信通常通过消息传递来实现。

Node.js 的多线程实现侧重于非阻塞和异步编程,即使在单线程的事件循环中也可以高效地处理大量并发任务。通过使用上述机制,开发者可以充分利用多核处理器的优势,同时保持代码的简洁性和可维护性。

nodejs中的事件循环

Node.js 中的事件循环是一个运行机制,用于处理 I/O 操作、事件回调、计时器等任务。它是 Node.js 非阻塞 I/O 架构的核心。以下是 Node.js 事件循环的基本组成部分和流程:

  1. 定时器(Timers):事件循环首先检查是否有需要触发的定时器,如 setTimeoutsetInterval 设置的时间到了。

  2. I/O 事件(I/O Events):接下来,事件循环处理所有的 I/O 事件,包括网络请求、文件读写等。这些事件通常是由操作系统完成的异步操作。

  3. Immediates(立即执行的回调): 事件循环处理 setImmediate 设置的回调函数。这些回调会在当前事件循环结束之前执行。

  4. 检查关闭的句柄(Check for Closing Handles):事件循环检查是否有需要关闭的句柄,例如关闭的网络连接或文件流。

  5. 闲置的回调(Idle Callbacks):如果没有其他任务,事件循环会执行空闲时的回调,例如 process.nextTick

  6. 轮询阶段(Poll Phase): 如果前面的阶段都没有执行任何任务,或者 setImmediate 队列为空,事件循环会进入轮询阶段。在这个阶段,Node.js 会等待并处理 I/O 请求。

  7. 关闭事件(Close Events):在事件循环的最后阶段,关闭的事件会被处理,例如 socket 的关闭事件。

  8. 结束事件(Exit Events):当 Node.js 准备退出时,会执行清理操作并最终退出。

事件循环的流程可以用以下伪代码表示:

while (true) {
  let event = poll()
  if (event === null) {
    runDefaultTimer()
  } else {
    runEvent(event)
  }
  runImmediates()
}

在这个循环中,poll() 函数负责从不同的事件队列中获取事件,runDefaultTimer() 检查并触发定时器,runEvent(event) 执行事件对应的回调函数,runImmediates() 执行 setImmediate 的回调。

如何自己搭建Mysql

Linux系统:

  • 更新包管理器
    sudo apt-get update # 对于基于Debian的系统,如Ubuntu
    sudo yum check-update # 对于基于RPM的系统,如CentOS
  • 安装Mysql
    sudo apt-get install mysql-server # 对于基于Debian的系统
    sudo yum install mysql-server # 对于基于RPM的系统
  • 安全配置(初始化安全配置,移除匿名用户,禁止root远程访问等)
    sudo mysql_secure_installation
  • 启动Mysql服务器
    sudo systemctl start mysqld
  • 设置开机自启动
    sudo systemctl enable mysqld
  • 登录Mysql(使用root用户登录,你可能需要输入安装过程中设置的密码)
    mysql -u root -p
  • 配置远程访问

Mysql的范式

  • 第一范式(1NF):确保每个列的值都是原子性的,即表中的所有列都是不可分割的最小数据单元。
  • 第二范式(2NF):在满足1NF的基础上,要求表中没有部分依赖,即非主属性完全依赖于候选键。
  • 第三范式(3NF):在满足2NF的基础上,要求非主属性不依赖于其他非主属性,即不存在数据间的传递依赖。

Mysql的事务

MySQL的事务是数据库操作的一个基本特性,它确保了一组数据库操作要么完全执行,要么完全不执行,从而维护了数据的完整性和一致性。以下是MySQL事务的关键特性和使用方式:
事务的ACID特性:

  • 原子性(Atomicity):事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个点。
  • 一致性(Consistency):事务必须保证数据库从一个一致的状态转移到另一个一致的状态。
  • 隔离性(Isolation):并发执行的事务之间不会互相影响。
  • 持久性(Durability):一旦事务提交,它对数据库的改变就是永久性的,即使系统发生故障也不会丢失
    MySQL事务的使用
  • 开始事务:
    START TRANSACTION;
  • 提交事务:
    COMMIT;
  • 回滚事务:
    ROLLBACK;

事务的隔离级别:

  • READ UNCOMMITTED(读未提交):最低的隔离级别,允许读取未提交的数据,可能会导致脏读。
  • READ COMMITTED(读已提交):只允许读取已提交的数据,可以避免脏读。
  • REPEATABLE READ(可重复读):保证在同一个事务中多次读取同一数据的结果是一致的,但可能无法避免幻读。
  • SERIALIZABLE(串行化):最高的隔离级别,完全串行执行事务,避免了脏读、不可重复读和幻读。

设置事务的隔离级别:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

Mysql的锁类型

  • 全局锁:全局锁对整个数据库实例生效,用于控制对整个数据库的访问。
  • 表级锁:表级锁对特定表生效,分为乐观锁和悲观锁两种。
    • 乐观锁通常通过版本号或时间戳实现,检查在读取数据后是否有其他事务修改了数据。
    • 悲观锁在事务开始时就锁定涉及的表,防止其他事务修改。
  • 行级锁:行级锁对表中的特定行生效,允许多个事务同时修改表中不同的行,提高并发性。
  • 共享锁(Shared Locks):共享锁允许多个事务读取同一资源,但不能修改。
  • 排他锁(Exclusive Locks):排他锁允许事务独占访问资源,其他事务不能读取或修改。
  • 意向锁:意向锁是一种表明事务想要在更高级别上请求锁的锁,分为意向共享锁和意向排他锁。
  • 显式锁和隐式锁:
    • 显式锁是通过LOCK TABLES语句显式请求的锁。
    • 隐式锁是数据库管理系统自动应用的锁,如行级锁。
  • 外键约束锁:外键约束在更新或删除数据时会自动应用锁,以维护数据的引用完整性。
  • 元数据锁(MDL, Metadata Lock):元数据锁用于保护数据库结构的变更,防止在读取表结构时发生结构变更。
  • 死锁:当两个或多个事务相互持有对方需要的锁,导致无法继续执行时,会发生死锁。
  • 间隙锁(Gap Locks):间隙锁用于锁定某个范围内的记录,但不包括记录本身,用于防止幻读。
  • 临键锁(Next-Key Locks):临键锁是行锁和间隙锁的组合,用于处理行的当前值和行之后的范围。
  • 悲观锁和乐观锁:
    • 悲观锁假设会发生冲突,通常通过锁定涉及的数据来避免。
    • 乐观锁假设冲突很少发生,通过检测数据在读取后是否被修改来处理。

Mysql如何实现的主从复制

是一个异步复制的过程,主要通过binlog来实现。

  • 主服务器记录二进制日志
  • 从服务器请求二进制日志
  • 主服务器发送二进制日志
  • 从服务器记录二进制日志:从服务器接收到事件后,将其记录到自己的中继日志(relay log)中
  • 从服务器应用中继日志

解释一下死锁

死锁是计算机科学中的一种情况,发生在多个进程(或线程)在执行过程中因争夺资源而造成的一种僵局。当两个或多个进程在运行过程中,因争夺资源而造成的一种互相等待的现象,如果这些进程不主动放弃所争夺的资源,那么它们都将无法继续执行下去。
死锁的产生原因:

  • 竞争有限资源:当多个进程竞争有限的资源时,可能会产生死锁。
  • 进程推进顺序不当:如果进程请求资源的顺序不当,可能导致循环等待。

死锁的预防和解决方法:

  • 资源分配图:通过资源分配图检测死锁的可能性。
  • 预防策略:例如,静态分配、动态分配但不剥夺资源、请求多种资源时一次性分配等。
  • 避免策略:例如,银行家算法,通过预分配资源和检测安全状态来避免死锁。
  • 检测和恢复:系统可以检测死锁的存在,并采取措施恢复,如终止进程或回滚操作。
  • 死锁避免算法:如银行家算法,通过确保即使所有进程同时请求最大资源需求,系统也能按某种顺序分配资源来避免死锁。

Redis支持的数据类型

  • 字符串(String)
  • 列表
  • 集合
  • 有序集合
  • 散列(Hash)

Redis的持久化存储方式

  • AOF:AOF是记录每次对服务器写的操作,以追加的方式保存到文件末尾,可以配置每秒同步一次,以保证数据的完整性。Redis还能对AOF文件进行后台重写,防止文件过大。
  • RDB:RDB是定时快照的方式,可以在指定的时间间隔内对数据进行全量备份。

Redis如何扫描前缀相同的key

  • 使用 SCAN 命令:SCAN 命令是一个基于游标的迭代器,它可以返回一组符合给定模式的键。使用 SCAN 可以避免阻塞主线程,因为它是渐进式的。
    redis-cli --scan --pattern 'yourprefix:*'
  • 使用 KEYS 命令:KEYS 命令可以返回所有匹配特定模式的键。但是,这个命令在大型数据库上使用时可能会非常慢,因为它会阻塞服务器直到完成。
    redis-cli KEYS 'yourprefix:*'
  • 使用 MATCH 命令(Redis 6.0.0 以上版本):MATCH 命令用于返回一个模式字符串,该字符串可以与 SCAN 命令一起使用来查找键。
    redis-cli MATCH 'yourprefix:*'

简单说一下Docker和k8s

Docker

Docker 是一个开源的应用容器引擎,它允许开发者打包应用及其依赖到一个可移植的容器中。以下是 Docker 的一些关键特点:

  • 容器化:Docker 可以将应用及其依赖打包到轻量级、可移植的容器中,实现“一次构建,到处运行”。
  • 隔离性:每个容器都是相互隔离的,拥有自己的文件系统、网络配置和进程空间。
  • 可移植性:Docker 容器可以在任何安装了Docker Engine的机器上运行,无论操作系统或基础架构如何。
  • 自动化部署:Docker 通过Dockerfile自动化构建流程,简化了部署过程。
  • 版本控制和组件重用:Docker Hub和其他注册中心可以用来分享和存储容器镜像,支持版本控制和组件重用。
  • 微服务架构:Docker 适合微服务架构,每个服务可以独立部署和扩展。

Kubernetes:

Kubernetes 是一个开源的容器编排系统,用于自动化容器化应用的部署、扩展和管理。以下是 Kubernetes 的一些关键特点:

  • 服务发现和负载均衡:Kubernetes 为应用提供内置的负载均衡器,并可以根据流量自动进行服务发现。
  • 自动扩展:Kubernetes 可以根据资源使用情况和其他信号自动扩展应用的副本数量。
  • 自我修复:Kubernetes 会替换失败的容器,确保应用始终以期望的状态运行。
  • 存储编排:Kubernetes 集成了持久化存储,可以为容器提供存储卷。
  • 配置管理:Kubernetes 允许你分离配置和应用,使得应用更容易配置和重新部署。
  • 多环境部署:Kubernetes 支持在不同环境中部署应用,包括公有云、私有云、混合云和边缘计算。
  • 声明式部署:Kubernetes 使用声明式配置,你只需定义应用的期望状态,Kubernetes 会负责实现这一状态。

Docker 为应用提供了容器化解决方案,而 Kubernetes 则为容器化应用提供了强大的编排能力。它们经常一起使用,Docker 作为容器化工具,Kubernetes 作为容器的管理和调度平台。这种组合提供了一种高效、可扩展和可靠的应用部署和管理方式。

Docker和虚拟机的区别

  • 架构:
    • Docker:使用Linux容器技术,在宿主机的内核上运行隔离的容器实例,共享宿主机的内核。
    • 虚拟机:通过虚拟化技术模拟整个计算机系统,每个虚拟机都有独立的操作系统和内核。
  • 启动时间:
    • Docker:容器几乎可以瞬间启动,因为它们共享宿主机的内核。
    • 虚拟机:虚拟机启动需要更长的时间,因为它需要加载完整的操作系统。
  • 资源消耗:
    • Docker:容器通常消耗较少的资源,因为它们共享宿主机的内核和资源。
    • 虚拟机:虚拟机消耗更多的资源,因为每个虚拟机都需要分配独立的内存和CPU资源。
  • 性能:
    • Docker:容器提供接近本机的性能,因为它们直接运行在宿主机上。
    • 虚拟机:虚拟机可能会有轻微的性能开销,因为需要通过虚拟化层来管理硬件资源。
  • 存储:
    • Docker:容器只包含必要的应用程序文件和库,通常使用联合文件系统(如OverlayFS或AUFS)。
    • 虚拟机:虚拟机通常包含完整的操作系统和应用程序,占用更多的存储空间。
  • 可移植性:
    • Docker:容器设计为高度可移植,可以在任何支持Docker的平台上运行。
    • 虚拟机:虚拟机的可移植性受到虚拟化平台和操作系统的限制。
  • 隔离性:
    • Docker:容器提供一定程度的隔离,但共享宿主机的内核。
  • 虚拟机:虚拟机提供更强的隔离性,每个虚拟机都有自己的内核和操作系统。
  • 管理和编排:
    • Docker:通常与Kubernetes等容器编排工具一起使用,以管理大规模的容器部署。
    • 虚拟机:可以使用虚拟机监控器(如VMware vSphere或OpenStack)进行管理。
  • 安全性:
    • Docker:容器安全性依赖于Docker平台和容器运行时的安全措施。
    • 虚拟机:虚拟机通过硬件级别的虚拟化提供更强的安全性。
  • 用途:
    • Docker:适用于微服务架构、持续集成/持续部署(CI/CD)和应用程序的快速迭代。
    • 虚拟机:适用于需要完整操作系统环境的场景,如运行特定的操作系统或需要隔离的应用程序。

Docker的网络架构

  • CNM(Container Network Model)

    • CNM 规定了 Docker 网络的基础组成要素:Sandbox、Endpoint 和 Network。其中 Sandbox 提供了容器的虚拟网络栈,Endpoint 是虚拟网络的接口,Network 是 Docker 内部的虚拟子网。
  • 网络类型

    • Docker 支持多种网络类型,包括桥接网络、主机网络、覆盖网络和无网络。
    • 桥接网络:默认网络类型,使用 Docker daemon 主机上的桥接接口将容器连接到主机网络。
    • 主机网络:容器直接连接到宿主机的网络接口,共享宿主机的网络资源。
    • 覆盖网络:允许跨多个 Docker 守护进程的容器进行通信的虚拟网络,使用 Swarm 模式。
    • 无网络:容器没有网络访问能力,适用于安全要求较高的场景。
  • 网络驱动程序

    • Docker 网络驱动程序负责创建和管理 Docker 网络。常见的驱动程序包括 bridge、host、overlay 等

容器的启动引擎有哪些

容器的启动引擎,通常指的是容器运行时或容器管理系统,它们负责容器的创建、启动、执行、监控和停止等生命周期管理。以下是一些主流的容器启动引擎和容器管理系统:

  • Docker Engine:Docker 是最流行的容器平台之一,Docker Engine 是其容器运行时,负责容器的创建和执行。
  • containerd:containerd 是一个行业标准的容器运行时,由 Docker 团队开发,用于 Linux 容器的运行和管理。
  • CRI-O:CRI-O 是一个基于 OCI 标准的容器运行时,专为 Kubernetes 设计,提供对 OCI 容器运行时的实现。
  • rkt (Rocket):rkt 是 CoreOS 开发的一个容器引擎,虽然目前已经停止开发,但它曾经是容器技术的一个重要贡献者。
  • LXC (Linux Containers):LXC 是 Linux 容器的早期实现之一,它提供了一种轻量级的虚拟化技术,用于隔离和运行应用程序。
  • OpenVZ:OpenVZ 是一种基于容器的虚拟化技术,它允许单个物理服务器运行多个隔离的容器实例。
  • Singularity:Singularity 是一个用于运行安全容器的开源平台,特别适用于高性能计算和数据密集型工作负载。
  • Podman:Podman 是 Red Hat 开发的无需守护进程的容器引擎,可以用于构建、运行和管理 OCI 容器。
  • Kubernetes:Kubernetes 不是一个容器运行时,而是一个容器编排系统,它提供了高级的容器管理功能,如服务发现、自动扩展和自我修复。
  • Apache Mesos:Mesos 是一个集群管理器,可以运行容器化和非容器化的应用,它支持 Docker 容器作为其任务之一。
  • Docker Swarm:Docker Swarm 模式允许 Docker Engine 管理多个 Docker 守护进程,形成一个虚拟的容器集群。
  • OpenShift:OpenShift 是 Red Hat 提供的一个基于 Kubernetes 的企业级容器应用平台。
  • Amazon ECS:Amazon Elastic Container Service (ECS) 是 AWS 提供的一个容器编排服务,允许用户运行和扩展 Docker 容器。
  • Google Kubernetes Engine (GKE):GKE 是 Google Cloud 提供的托管 Kubernetes 服务,简化了 Kubernetes 集群的部署和管理。

Docker和Containerd的区别

Docker和Containerd是两种容器技术,它们在容器化领域扮演着重要的角色,但具有不同的设计理念和应用场景。

  1. 起源和发展历程

    • Docker 是一个成熟的容器化平台,它在容器技术的普及过程中发挥了关键作用,提供了一整套用于开发、部署和运行容器化应用的工具。
    • Containerd 是由 Docker 团队开源的容器运行时,专注于提供轻量级、高性能的容器运行环境,被设计为更加符合 Kubernetes 架构和需求的容器运行时。
  2. 架构

    • Docker 采用 Client-Server 架构,Docker Daemon 负责管理容器生命周期、镜像构建和网络等功能,而 Docker CLI 作为命令行工具与 Daemon 交互。
    • Containerd 是一个轻量级的容器运行时,遵循 CRI(Container Runtime Interface)标准,设计为模块化和可扩展,主要负责容器生命周期管理和镜像管理。
  3. 功能和特性

    • Docker 提供了丰富的功能,包括容器编排、网络管理、数据卷、镜像构建等,适用于开发者和小规模部署。
    • Containerd 专注于核心容器管理功能,如容器生命周期管理、镜像管理和存储管理等,提供了精简和稳定的容器运行时,适用于大规模生产环境和与其他容器编排工具集成。
  4. 性能

    • Docker 在应用启动和容器管理方面有良好的性能表现,通过镜像分层、资源隔离和快速启动等机制实现高效的容器管理和运行。
    • Containerd 通过精简的架构和优化的代码实现了更快的容器启动速度、低内存占用和高度可靠的运行。
  5. 使用场景

    • Docker 适合开发者和小规模部署,特别是需要快速构建和测试应用、创建开发环境和实验性场景的情况。
    • Containerd 适合大规模生产环境,特别是需要高度稳定性、安全性和与其他容器编排工具集成的场景。
  6. 与 Kubernetes 的集成

    • Docker 作为 Kubernetes 的容器运行时,需要通过 Dockershim 与 kubelet 交互,调用链较长。
    • Containerd 可以直接通过 CRI 与 kubelet 交互,调用链更短,组件更少,占用节点资源更少。
  7. 资源占用和稳定性

    • Containerd 通常具有更低的资源占用和更高的稳定性,适合作为生产环境中的容器运行时。
  8. 命令行工具

    • Docker 提供了用户友好的命令行工具,用于容器的创建、运行和管理。
    • Containerd 提供了 ctr 作为其客户端工具,而 Kubernetes 环境中通常使用 crictl 来检查和调试容器运行时和应用程序。
  9. 存储位置和日志

    • Docker 的数据目录默认在 /var/lib/docker,而 Containerd 的数据目录默认在 /var/lib/containerd
    • 使用 Docker 作为运行时时,容器日志的落盘由 Docker 负责,而使用 Containerd 作为运行时时,容器日志的落盘由 kubelet 负责。

选择 Docker 或 Containerd 取决于具体的使用场景和需求。对于开发者和小规模部署,Docker 提供了丰富的功能和易用性;而对于大规模生产环境,Containerd 的性能和稳定性可能更加突出[59]。

如果不同节点的pod之间无法通信,如何排查

如果 Kubernetes 集群中不同节点上的 Pod 之间无法通信,可以按照以下步骤进行排查:

  1. 检查 Pod 网络策略: 确认没有网络策略(NetworkPolicy)阻止了 Pod 之间的通信。

  2. 检查 Service 是否正确配置:确保 Service 正确配置并且能够正确代理到目标 Pod。

  3. 检查 DNS 解析: 确认集群内的 DNS 服务是否正常工作,Pod 是否能够通过 DNS 解析彼此的名称。

  4. 检查 Pod 是否在同一网络命名空间:如果 Pod 在不同的网络命名空间中,它们可能无法直接通信。

  5. 检查网络插件/CNI 配置:确认集群使用的网络插件(如 Calico、Flannel、Weave 等)是否正确配置。

  6. 检查路由和网关设置: 确认节点上的路由规则是否允许 Pod 之间的流量。

  7. 检查节点间的网络连通性:使用 pingtraceroute 命令测试不同节点间的连通性。

  8. 检查 Pod 是否已经调度:确认 Pod 是否已经成功调度到节点上,并且状态为 Running

  9. 查看 Pod 和节点的日志:查看相关 Pod 和节点的日志,寻找可能的错误信息或警告。

  10. 检查 Kubernetes 集群事件:使用 kubectl get events 查看集群事件,可能会有关于网络问题的线索。

  11. 检查防火墜和安全组设置:确认云服务的安全组或防火墜规则没有阻止 Pod 之间的通信。

  12. 检查 Pod 的 Readiness 和 Liveness Probes:确认 Probes 是否配置正确,错误的配置可能导致 Pod 网络不可用。

  13. 检查集群的 NetworkPolicy 配置:如果集群配置了 NetworkPolicy,确保没有规则阻止了 Pod 之间的通信。

  14. 检查 Overlay 网络:对于使用 Overlay 网络的集群,检查是否有正确的 Overlay 网络配置和密钥。

  15. 使用 kubectl describe 命令:使用 kubectl describe pod <pod-name> 查看 Pod 的详细状态,包括网络信息。

  16. 检查 API Server 日志:检查 Kubernetes API Server 的日志,可能会有关于网络通信失败的错误信息。

  17. 检查 CNI 插件日志:检查 CNI 插件的日志,这些日志可能包含网络配置错误的信息。

  18. 重新创建 Pod:如果怀疑是 Pod 网络配置问题,尝试重新创建 Pod 以查看是否能够解决问题。

  19. 联系云服务提供商:如果你使用的是云服务提供商提供的 Kubernetes 服务,联系他们的支持团队获取帮助。

通过这些步骤,你应该能够诊断和解决 Kubernetes 集群中 Pod 之间无法通信的问题。如果问题依然存在,可能需要更深入地检查集群的网络配置或联系网络插件的维护者。

pod的创建过程

在Kubernetes中,Pod从创建到运行的过程涉及多个步骤和组件。以下是Pod从无到有的一般过程:

  • 定义Pod配置:用户编写Pod的配置文件,通常是一个YAML或JSON格式的文件,定义了容器的镜像、环境变量、存储卷、网络设置等。
  • 提交Pod配置到Kubernetes集群:用户通过kubectl命令行工具或Kubernetes API将Pod配置文件提交给Kubernetes集群。
  • API Server接收请求:Kubernetes的API Server接收到Pod的创建请求,并将其存储在etcd中,这是一个分布式键值存储,用于保存集群状态。
  • 调度决策:调度器(Scheduler)监听API Server以获取新创建的Pods,并根据调度策略(如资源需求、亲和性规则、污点和容忍度等)选择一个合适的节点(Node)来运行Pod。
  • 调度结果写入etcd:调度器将调度决策(即Pod应该在哪个节点上运行)写回etcd。
  • 节点接收Pod信息:被选定的节点上的Kubelet服务监听etcd中的变更,并获取到分配给它的Pod信息。
  • 容器创建:Kubelet在节点上创建Pod定义的容器。它使用容器运行时接口(CRI),如Docker或containerd,来拉取容器镜像并启动容器。
  • 容器网络配置:Pod网络配置被设置,确保Pod能够与集群中的其他Pod通信。
  • 存储卷挂载:如果Pod配置中定义了存储卷(如PersistentVolumeClaims),Kubelet会挂载这些卷到容器的指定目录。
  • Pod状态更新:容器启动后,Kubelet将Pod的状态(如Running、Completed或Error)更新到API Server。
  • 监控和健康检查:Kubelet会定期执行健康检查(如Liveness和Readiness探针),监控容器的状态。
  • Pod就绪:当Pod中的所有容器都成功启动,并且Readiness探针表明Pod准备好服务请求时,Pod的状态变为就绪。
  • 服务发现:如果Pod是某个Service的一部分,它将被注册到相应的Service中,从而实现服务发现和负载均衡。
  • 用户访问:用户可以通过Service或直接通过Pod的IP地址访问Pod中的应用程序。

pod的删除过程

  • 删除请求:用户通过kubectl delete pod命令或Kubernetes API发出删除特定Pod的请求。
  • API Server 接收请求:Kubernetes API Server接收到删除请求,并在etcd中标记该Pod为删除状态。
  • 调度器和Controller Manager:调度器和Controller Manager监听到Pod的删除事件,更新它们的状态信息。
  • Kubelet 接收指令:运行在Pod所在Node上的Kubelet监听到删除事件,开始执行删除操作。
  • 终止容器:Kubelet向Pod中的每个容器发送终止信号(如SIGTERM),通知它们即将被删除。
  • 容器优雅关闭:容器接收到终止信号后,会尝试优雅地关闭,完成所有挂起的操作,保存状态,并退出。
  • 容器终止:如果容器在指定的优雅关闭时间内没有退出,Kubelet将发送SIGKILL信号强制终止容器。
  • 清理资源:Kubelet清理Pod使用的资源,包括网络资源、存储卷等。
  • 更新Pod状态:Kubelet将Pod的状态更新为“Terminating”或“Unknown”(如果与Kubelet的通信出现问题)。
  • Pod从API Server中删除:一旦Pod的所有资源都被清理,Kubelet将向API Server报告Pod的状态,API Server随后将Pod从etcd中删除。
  • 更新相关对象:与Pod相关的其他Kubernetes对象,如Service、Deployment等,也会根据Pod的删除进行相应的更新。
  • DNS和Service Discovery更新:如果集群使用了CoreDNS等DNS服务,DNS记录和Service Discovery信息也会相应更新,以反映Pod的删除。
  • 用户查询:用户可以使用kubectl get pods等命令查询Pod的状态和详细信息。
  • 资源监控:集群的监控系统可能会继续监控被删除的Pod一段时间,直到它们完全从系统中消失。
  • 垃圾回收:对于由其他对象(如Deployment)管理的Pod,它们的副本将由相应的控制器自动替换。

Pod的删除过程是自动化的,但用户可以通过设置终止宽限期(termination grace period)来控制Pod优雅关闭的时间。如果Pod在宽限期内没有自行终止,Kubelet将强制终止Pod以确保集群资源可以被正确回收。

pod的重启策略

使用restartPolicy设置pod重启策略

  • always
  • onFailure
  • never

k8s的组织架构

Kubernetes 的架构由多个组件组成,这些组件协同工作以提供完整的容器编排功能。
主要组件包括:

  • API 服务器:Kubernetes 控制平面的前端,对外提供 Kubernetes API。
  • 调度器:负责决定在哪个节点上运行新的容器。
  • 控制器管理器:运行集群中的各种控制器,如节点控制器、副本控制器等。
  • etcd:用于存储集群状态的分布式键值存储系统。
  • 节点组件:包括 kubelet、kube-proxy 和容器运行时等,在每个节点上运行。

什么是k8s的高可用

Kubernetes(K8s)的高可用性(High Availability,简称 HA)是指在集群中的某些组件或节点发生故障时,Kubernetes 集群仍然能够继续运行,并且能够保证服务的连续性和数据的完整性。实现高可用性的主要目标是减少系统停机时间,确保服务的稳定性和可靠性。

以下是实现 Kubernetes 高可用性的几个关键方面:

  1. 多节点部署:在多个物理服务器或虚拟机上部署 Kubernetes 节点,以避免单点故障。

  2. 主节点(Master Node)冗余:Kubernetes 的主节点负责管理集群状态和运行集群控制平面组件。主节点的高可用性可以通过运行多个主节点实例并使用领导者选举机制来实现。

  3. 数据持久化:使用分布式存储系统和持久化卷来保证数据的持久化,即使在节点故障的情况下也不会丢失数据。

  4. 控制平面组件的冗余:关键的控制平面组件,如 API 服务器、调度器、控制器管理器和 etcd,应该以集群模式运行,确保它们具有冗余和故障转移能力。

  5. 使用 etcd 集群:etcd 是 Kubernetes 的关键持久化存储,用于存储集群状态。运行 etcd 集群可以提供数据的高可用性和一致性。

  6. 负载均衡:在主节点前使用负载均衡器可以分发 API 服务器的流量,提高系统的可用性和扩展性。

  7. 监控和自动恢复:实现监控系统来实时监控集群状态,以及自动化恢复机制来处理故障节点或组件。

  8. 灾难恢复计划:制定和测试灾难恢复计划,以应对大规模故障或数据丢失的情况。

  9. 网络和存储的高可用性:确保网络和存储基础设施也支持高可用性,以避免成为单点故障。

  10. 滚动更新和自动扩缩容:使用滚动更新来逐步部署应用更新,减少更新过程中的服务中断。自动扩缩容可以根据负载动态调整集群规模。

通过上述措施,Kubernetes 集群可以在面对组件故障、网络问题或其他类型的干扰时,保持服务的持续可用性和数据的完整性。

说一个在k8s中你最熟悉的组件

k8s中有哪些控制器类型?分别用于什么场景

  • Deployment:适合无状态的服务部署
  • StatefullSet:适合有状态的服务部署
  • DaemonSet:一次部署,所有的node节点都会部署,例如一些典型的应用场景:在每个Node上运行日志收集 daemon,例如 fluentd、 logstash
  • Job:一次性的执行任务
  • Cronjob:周期性的执行任务

如何做的k8s升级

Kubernetes 升级是一个重要的过程,旨在确保集群运行最新版本的 Kubernetes 组件,以利用新功能、性能改进和安全修复。

  1. 准备工作

    • 确保备份了当前集群的状态,特别是 etcd 的数据。
    • 阅读 Kubernetes 官方文档中关于升级的指南,了解版本间的变更和任何必要的先决条件。
  2. 检查兼容性

    • 确认新版本的 Kubernetes 与你的容器运行时、云服务提供商、第三方插件和应用程序兼容。
  3. 升级控制平面

    • 通常,控制平面组件(API 服务器、调度器、控制器管理器和 etcd)应该先于工作节点升级。
    • 如果使用 kubeadm 进行集群管理,可以使用 kubeadm upgrade 命令来升级控制平面。
  4. 升级 etcd

    • etcd 作为 Kubernetes 的后端存储,需要特别小心地升级。按照 etcd 的官方文档进行操作,确保数据的一致性和完整性。
  5. 升级 Kubernetes 版本

    • 对控制平面组件进行版本升级,这通常涉及到下载新版本的二进制文件或使用配置管理工具更新服务。
  6. 升级工作节点

    • 控制平面升级完成后,接下来升级工作节点。这可能涉及到更新 kubelet、kube-proxy 和容器运行时。
  7. 应用新版本的最佳实践

    • 根据新版本的 Kubernetes 文档,应用任何新的配置或最佳实践。
  8. 测试集群

    • 升级完成后,进行彻底的测试以确保所有组件正常工作,包括网络、存储和应用程序。
  9. 滚动更新

    • 为了减少服务中断,可以采用滚动更新的方式逐个升级工作节点。
  10. 监控和验证

    • 升级过程中和升级后,密切监控集群的健康状况和性能指标。
    • 验证所有的资源对象和应用程序是否按预期运行。
  11. 回滚计划

    • 准备一个回滚计划以应对升级过程中出现的任何问题。
  12. 文档记录

    • 记录升级过程中的所有变更和步骤,以备未来参考。
  13. 通知用户

    • 如果集群服务于多个用户或团队,确保他们知道升级计划和可能的影响。
  14. 遵循版本升级策略

    • 通常建议一次只跳过一个次要版本进行升级,以避免引入过多的变更。

网络插件Flannel和Calico的区别

Flannel 和 Calico 是 Kubernetes 集群中常用的两种网络插件,它们各自有不同的特点和用途。以下是它们的主要区别:

Flannel

  • Flannel 是一个流行的 CNI 插件,使用虚拟网络覆盖技术来连接不同节点上的容器。
  • 支持多种后端驱动,如 VXLAN、UDP、Host-GW 等。
  • 相对简单易用,适合初期部署或对网络要求不是特别高的场景。
  • 性能方面,由于使用 overlay 网络,可能会有额外的封装开销。
  • 可靠性依赖于底层网络和 etcd 的稳定性。

Calico

  • Calico 是一个开源的网络和安全解决方案,使用 BGP 协议来实现容器之间的路由。
  • 提供灵活的网络策略和安全规则,适用于大规模部署。
  • 功能更为全面,不仅提供主机和 Pod 之间的网络连接,还涉及网络安全和管理。
  • 与 Flannel 不同,Calico 不使用 overlay 网络,而是配置第三层网络,使用 BGP 路由协议在主机之间路由数据包。
  • 支持固定 IP 配置,可以与服务网格 Istio 集成,提供更高级的网络安全和管理功能。

简而言之,Flannel 提供了一个简单且轻量级的网络解决方案,适合基本的容器间通信需求。而 Calico 提供了一个更全面的网络解决方案,特别适合需要复杂网络策略和高级网络安全功能的场景。Calico 的网络策略功能是其最受追捧的特性之一,而且它还能提供与服务网格集成的高级网络管理能力。

Prometheus-metrics数据增长快的原因?如何解决

Prometheus metrics 数据增长快可能有几个原因,以及相应的解决方案:

  1. 高频率的数据采集:Prometheus 支持高频率地从监控目标中抓取(scrape)指标数据。如果采集频率过高,将导致数据点数量迅速增加。

    • 解决方案:根据实际需求调整 scrape 间隔,增加采集间隔时间,减少数据采集频率。
  2. 大量使用 Counter 类型的 metrics:Counter 是 Prometheus 中只增不减的指标类型,随着时间的推移,其值会持续增长。

    • 解决方案:合理设计 metrics,对于不需要持续增长的场景,考虑使用 Gauge 类型,它可以反映当前状态,而不是持续增长。
  3. Histogram 和 Summary 类型的误用:Histogram 和 Summary 可以提供丰富的数据分布信息,但它们可能会占用更多的存储空间。

    • 解决方案:优化 Histogram 和 Summary 的使用,例如调整 buckets 的大小和数量,以减少存储需求。
  4. 保留策略(Retention Policy)设置不当:如果 Prometheus 没有正确地设置数据保留策略,可能会导致大量旧数据未被清理。

    • 解决方案:设置合理的数据保留时间,例如只保留过去30天的数据,并通过配置文件调整 retention 时间。
  5. 大量未使用的 metrics:系统中可能存在大量不再使用或不再更新的 metrics,这些数据仍然占用存储空间。

    • 解决方案:定期审查和清理不再需要的 metrics,使用 Prometheus 的 metrics API 来识别和删除这些 metrics。
  6. 数据没有通过联邦(Federation)或远程存储(Remote Storage)进行聚合:如果 Prometheus 实例之间没有进行数据聚合,每个实例都独立存储所有数据。

    • 解决方案:使用 Prometheus 的联邦功能或远程存储集成,将数据聚合到一个中心位置,减少每个实例的数据存储需求。
  7. 存储解决方案的性能问题:如果使用的存储解决方案性能不佳,可能会导致数据写入瓶颈,影响整体性能。

    • 解决方案:评估和升级存储解决方案,确保它能够处理 Prometheus 的数据写入负载。
  8. 未充分利用索引和标签:如果 metrics 没有正确地使用标签进行索引,可能会导致查询效率低下,增加数据存储需求。

    • 解决方案:优化标签使用,确保查询能够高效地利用索引。

如何实现的CICD

  • 环境搭建:首先需要搭建 Jenkins 运行所需的环境,包括安装 Jenkins、配置 JDK、Git、Maven 等工具。
  • 安装插件:Jenkins 具有丰富的插件生态,可以根据需要安装 Git、Maven、Docker 等相关插件来扩展 Jenkins 的功能。
  • 配置源码管理:在 Jenkins 中配置源码管理(SCM),通常是 Git 仓库。这允许 Jenkins 能够拉取最新的代码变更。
  • 编写构建脚本:编写构建脚本(如 Maven 的 pom.xml 或 Shell 脚本),用于自动化构建和测试过程。
  • 创建 Jenkins 任务/Job:在 Jenkins 中创建一个新的任务或 Job,配置任务的触发条件、构建环境、构建步骤等。
  • 配置构建触发器:设置构建触发器,可以是基于时间的调度、SCM 变更(如 Git 仓库的更新)、或其他事件。
  • 自动化构建与测试:当触发条件满足时,Jenkins 会自动执行构建脚本,编译代码,运行自动化测试。
  • 部署:构建和测试成功后,Jenkins 可以自动将构建产物(如 WAR 文件)部署到测试或生产环境。
  • 集成 Docker:利用 Docker 插件,Jenkins 可以在 Docker 容器中运行构建环境,实现环境的一致性,并可以构建 Docker 镜像。
  • 配置 Webhook:配置 Git 仓库的 Webhook,当代码被推送到仓库时,自动触发 Jenkins 构建。
  • 监控与通知:Jenkins 可以配置邮件通知、测试报告、构建历史等,帮助团队监控 CI/CD 流程的状态。
    -持续优化:根据反馈和监控结果,不断优化 CI/CD 流程,提高自动化效率和质量。

CICD的工具有哪些?

CI/CD(持续集成和持续交付/部署)工具是自动化软件交付流程的关键组件。以下是一些流行的 CI/CD 工具:

  1. Jenkins: 一个开源的自动化服务器,可以用于自动化各种任务,包括构建、测试和部署。

  2. GitLab CI/CD: 与 GitLab 集成的 CI/CD 工具,提供自动化的构建、测试和部署功能。

  3. GitHub Actions: GitHub 提供的 CI/CD 工具,允许用户在 GitHub 仓库中直接创建、管理和执行工作流程。

  4. CircleCI: 一个流行的持续集成和持续部署平台,专注于简单的设置和快速的构建。

  5. Travis CI: 一个持续集成服务,支持多种编程语言,可以自动地在 GitHub 推送时运行测试。

  6. TeamCity: JetBrains 提供的一个商业 CI/CD 服务器,支持构建、测试和部署流程的自动化。

  7. Bamboo: Atlassian 提供的一个 CI/CD 工具,与其他 Atlassian 产品(如 Jira 和 Bitbucket)紧密集成。

  8. CodeShip: 一个 CI/CD 服务,支持多种语言和平台,提供快速的容器化构建。

  9. Bitbucket Pipelines: Bitbucket 的内置 CI/CD 功能,允许在 Bitbucket 存储库中直接自动化构建和部署流程。

  10. Azure DevOps: 微软提供的一套完整的 DevOps 工具集,包括 Azure Pipelines 用于 CI/CD。

  11. Ansible: 一个自动化平台,可以用于 CI/CD 流程中的配置管理和应用部署。

如何测评分布式存储的吞吐量

  • 确定测试目标:首先明确测试的具体目标,比如是评估顺序读写还是随机读写的吞吐量,或者是评估在特定负载下的性能表现。
  • 选择测试工具:选择合适的性能测试工具,如 fio、IOMeter、dd 等,这些工具能够模拟不同的 I/O 模式和负载情况。
  • 配置测试环境:搭建测试环境,包括分布式存储系统、客户端、网络等,确保测试环境能够模拟实际运行条件。
  • 设计测试用例:根据测试目标设计测试用例,包括数据块大小、队列深度、读写比例等参数的设置。
  • 执行测试:运行测试用例,收集数据。注意测试时间要足够长,以排除噪音并收集稳定的性能数据。
  • 数据收集与分析:收集测试过程中的各类数据,包括 IOPS、延迟、吞吐量等,并进行分析以识别性能瓶颈。
  • 结果评估:评估测试结果,与预期性能或其他存储系统的性能进行比较,确定是否满足性能要求。
  • 报告撰写:撰写测试报告,总结测试结果,提出性能优化建议或识别潜在问题。
  • 使用专业工具:考虑使用专业的分布式存储性能基准测试工具,如 elbencho,它支持对文件、对象以及块存储进行延时、吞吐量和 IOPS 的综合测评,并特别针对 GPU 支持进行了优化。
  • 考虑实际应用场景:确保测试覆盖实际应用场景,包括不同的工作负载模式和数据访问模式。
运维开发工程师面试题可以包括以下方面的内容: 1. 请描述一次你在工作中遇到的重大失误,并说明你是如何解决这个问题的。 2. 作为一个运维工程师,你认为自己的工作职责是什么,如何保证为公司和客户提供最高、最快、最稳定、最安全的服务? 3. 请列举项目交付的清单,并详细说明每个环节的内容和重要性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [运维经典面试真题汇总系列](https://blog.csdn.net/estarhao/article/details/115256936)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [运维工程师常见40道面试题必会](https://blog.csdn.net/weixin_46535174/article/details/124487812)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [项目经理的福音,刚做项目经理的时候整理的,项目交付也是参考了本交付清单进行整理的文档,希望对大家有用](https://download.csdn.net/download/weixin_44060454/88230735)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值