Linux
Linux 系统启动流程是怎样的?
- BIOS/UEFI 加电自检,检查 CPU、内存、硬盘、网卡等硬件是否正常;
- 加载 Bootloader(GRUB),包含内核镜像(vmlinuz)和 initramfs(临时根文件系统);
- 内核初始化,内核解压缩并加载到内存、初始化硬件驱动(存储、网络、文件系统等)、启动第一个用户空间进程(systemd);
- 根据 /etc/fstab 挂载磁盘分区;
- 启动系统服务(syslog、network、sshd)和用户空间服务(nginx、docker…);
- 最后进入 ssh 登录界面。
如何排查一台 Linux 服务器的负载过高问题?
- 首先可以通过监控面板,或登录宿主机使用 w、uptime 等命令查看 1 分钟、5 分钟、15 分钟的平均负载(load average),如果 1 分钟的平均负载偏高,有可能是瞬时的,可以继续观察,如果如果 15 分钟的平均负载也高,则需要继续排查;
- 平均负载 > CPU核心数 = 高(CPU 和 IO 的排队时间)
- 使用 top、ps、iotop、nethogs 等命令获取占用 CPU 或 IO 高的进程;
- 最后通过查看服务日志、系统日志、内核日志等方式排查是否有报错。
- 系统日志:
/var/log/syslog
(Ubuntu)、/var/log/messages
(CentOS)。- 内核日志可以使用
dmesg
查看(重点关注 I/O error、OOM killer)。
请解释 top 命令输出中 load average 的含义。
- top 的 load average 表示在过去 1、5、15 分钟内,系统中处于运行态(R,正在运行或等待 CPU)和不可中断睡眠态(D,等待 I/O)的进程的平均数量;
- 是否算高要结合 CPU 核心数来看,正常应该 load < CPU 核数,超过太多说明有性能瓶颈。
如何查看和分析内存使用情况?
- free -h 查看内存和SWAP的总体使用情况,还可以使用 top 命令 + M 按内存使用率排序。
硬盘空间满了你会如何排查?
- 先使用
df -h
查看是哪块磁盘满了,以及对应的挂载点;- 然后使用
du -sh /挂载点/*
,逐级定位是哪个目录或者文件占用空间大,也可以使用find / -xdev -type f -size +1G
搜索大于指定大小的文件;- 解决方案:如果是日志等无用的文件,可以先使用
>文件名
立即释放磁盘空间,持久解决方案可以选择使用逻辑卷扩展。其他的优化手段,比如减少程序的日志写入量等;- 还可使用
lsof | grep 文件名
来定位文件对应的进程。
*磁盘空间还有,但数据无法写入是什么原因?
- inode 用尽,可以使用 df -i 检查;
- 文件系统只读,可以使用 mount | grep 挂载点 检查,ro 表示只读,rw 读写;
- 用户没有写权限。
删除文件后,磁盘空间并未释放,为什么?
- 是因为这个文件的 inode 仍然被其他进程持有,可以使用
lsof | grep 文件名
定位到进程后重启进程。
你如何查看某个进程打开了哪些文件?
- 可以使用
lsof -p <PID>
查看进程打开的所有文件。
软链接和硬链接的区别?
- 软连接相当于Windows下的快捷键方式,而硬链接本质上是同一个文件;
- 软连接与源文件的 inode 不同,而硬链接与源文件的 inode 是相同的;
- 软链接可跨分区,硬链接不可以;
- 源文件删除,软链接不可访问,硬链接可以;
- 软链接可以对文件、目录创建,而硬链接只能针对文件。
你如何限制某个用户的资源使用(CPU、内存等)?
- 可以用 ulimit 限制用户的 CPU 时间、内存、进程数和打开文件数;更精细的可以用 cgroups 限制 CPU、内存、IO;如果是 systemd 管理的服务,也可以在 service 文件里配置 CPUQuota 和 MemoryMax。
什么是文件描述符?如何查看和调整目前文件描述符的限制量?
- 文件描述符是一个非负整数,用于标识进程打开的文件或 I/O 资源(包括普通文件、目录、设备、管道、socket 等)。
- 查看进程打开的文件描述符,有两种方案,一种是
ls -l /proc/<pid>/fd
,另一种是lsof -p <pid>
。在较新的系统中,比如 Ubuntu 2404,还可以使用lsfd
命令查看。- 如果程序打开文件过多导致 “too many open files” 错误,可以通过 ulimit 临时调整上限,或编辑 /etc/security/limits.conf 永久修改。
- 临时查看进程能打开的文件描述符上限:
ulimit -n
/etc/security/limits.conf
中的软/硬限制含义:硬限制(hard)表示最高能开多高,软限制(soft)当前用户可调整的数量,但不能超过硬限制。
Linux 系统级优化你做过哪些?
内核参数级优化(通过 sysctl 或 /etc/sysctl.conf 配置,然后通过 sysctl -p 生效。):
net.ipv4.tcp_max_tw_buckets = 65536 # 减少TIME_WAIT连接 net.ipv4.tcp_tw_reuse = 1 # 复用TIME_WAIT连接 net.ipv4.tcp_fin_timeout = 30 # 缩短FIN等待时间 net.core.somaxconn = 65535 # 监听队列最大值
其他系统资源/环境级优化(配置文件、资源限制、包管理等):
- apt/yum 源指向内部仓库或国内镜像站。
- 修改打开文件描述符的最大数量(通常软硬限制都设置为 65535)。
- 时间同步,ntp源指向内部或国内NTP服务器。
- 服务器多 CPU 场景下,调整 NUMA node ,让 CPU 优先访问本地内存,以避免跨 NUMA 节点的远程内存访问带来的延迟损耗。
- 一般通过 BIOS/UEFI 配置调整。
- 假设服务器 2 个 CPU,每个 8 核,512 GB 内存。CPU 0-7 属于 node 0,CPU 8-15 属于 node 1,给每个 NUMA 节点 256 GB 内存。
- 可以用
numactl -H
、numastat -m
、lscpu
查看目前 NUMA 分配情况。- 关闭 Swap、SELinux
SQL
练习表
- 在数据库中执行该sql语句,创建练习表
-- 创建部门表 CREATE TABLE departments ( department_id INT PRIMARY KEY, department_name VARCHAR(100) NOT NULL ); -- 插入部门数据 INSERT INTO departments VALUES (1, 'Engineering'), (2, 'Human Resources'), (3, 'Marketing'), (4, 'Finance'); -- 创建员工表 CREATE TABLE employees ( employee_id INT PRIMARY KEY, first_name VARCHAR(50), last_name VARCHAR(50), gender CHAR(1), hire_date DATE, department_id INT, FOREIGN KEY (department_id) REFERENCES departments(department_id) ); -- 插入员工数据 INSERT INTO employees VALUES (101, 'Alice', 'Smith', 'F', '2015-03-01', 1), (102, 'Bob', 'Johnson', 'M', '2017-07-15', 1), (103, 'Carol', 'Williams', 'F', '2019-01-10', 2), (104, 'David', 'Brown', 'M', '2018-11-23', 3), (105, 'Eve', 'Davis', 'F', '2020-06-17', 4); -- 创建薪资表 CREATE TABLE salaries ( salary_id INT PRIMARY KEY, employee_id INT, salary DECIMAL(10,2), from_date DATE, to_date DATE, FOREIGN KEY (employee_id) REFERENCES employees(employee_id) ); -- 插入薪资数据 INSERT INTO salaries VALUES (1, 101, 80000, '2020-01-01', '2021-12-31'), (2, 101, 85000, '2022-01-01', '9999-12-31'), (3, 102, 75000, '2019-01-01', '9999-12-31'), (4, 103, 60000, '2019-01-10', '9999-12-31'), (5, 104, 72000, '2018-11-23', '9999-12-31'), (6, 105, 68000, '2020-06-17', '9999-12-31'); -- 创建项目表 CREATE TABLE projects ( project_id INT PRIMARY KEY, project_name VARCHAR(100), start_date DATE, end_date DATE ); -- 插入项目数据 INSERT INTO projects VALUES (1, 'Project Apollo', '2021-01-01', '2021-12-31'), (2, 'Project Zephyr', '2022-03-01', NULL), (3, 'Project Orion', '2020-06-01', '2021-06-30'); -- 创建员工-项目关系表(多对多) CREATE TABLE employee_projects ( employee_id INT, project_id INT, role VARCHAR(50), PRIMARY KEY (employee_id, project_id), FOREIGN KEY (employee_id) REFERENCES employees(employee_id), FOREIGN KEY (project_id) REFERENCES projects(project_id) ); -- 插入员工项目关系数据 INSERT INTO employee_projects VALUES (101, 1, 'Developer'), (101, 2, 'Lead Developer'), (102, 1, 'Tester'), (103, 2, 'HR Manager'), (104, 3, 'Marketing Lead'), (105, 2, 'Accountant');
练习题 1:查询所有员工的姓名及其所在部门名称
- 查询每位员工的 first_name、last_name 和其对应的 department_name。
SELECT e.first_name, e.last_name, d.department_name FROM employees e JOIN departments d ON e.department_id = d.department_id;
练习题 2:查询当前薪资最高的员工信息
- 找出当前薪资(to_date = ‘9999-12-31’)最高的员工的姓名和薪资。
SELECT e.first_name, e.last_name, s.salary FROM salaries s JOIN employees e ON s.employee_id = e.employee_id WHERE s.to_date = '9999-12-31' ORDER BY s.salary DESC LIMIT 1;
练习题 3:查询每个部门的平均薪资
- 统计每个部门当前员工的平均薪资。
SELECT d.department_name, AVG(s.salary) AS average_salary FROM employees e JOIN departments d ON e.department_id = d.department_id JOIN salaries s ON e.employee_id = s.employee_id WHERE s.to_date = '9999-12-31' GROUP BY d.department_name;
练习题 4:查询参与了“Project Zephyr”的员工及其角色
- 列出参与了名为“Project Zephyr”的员工的姓名和他们的角色。
SELECT e.first_name, e.last_name, ep.role FROM employee_projects ep JOIN employees e ON ep.employee_id = e.employee_id JOIN projects p ON ep.project_id = p.project_id WHERE p.project_name = 'Project Zephyr';
练习题 5:查询至少参与了两个项目的员工
- 列出参与两个或以上项目的员工的姓名和项目数量。
SELECT e.first_name, e.last_name, COUNT(ep.project_id) AS project_count FROM employee_projects ep JOIN employees e ON ep.employee_id = e.employee_id GROUP BY e.employee_id HAVING COUNT(ep.project_id) >= 2;
练习题 6:查询“Engineering”部门的所有员工当前薪资
- 显示 Engineering 部门所有员工的姓名及其当前薪资。
SELECT e.first_name, e.last_name, s.salary FROM employees e JOIN departments d ON e.department_id = d.department_id JOIN salaries s ON e.employee_id = s.employee_id WHERE d.department_name = 'Engineering' AND s.to_date = '9999-12-31';
练习题 7:查询所有项目的负责人(Lead Developer 或 Manager)
- 列出所有项目的名称、员工姓名及他们担任的领导角色(如包含“Lead”或“Manager”的角色)。
SELECT p.project_name, e.first_name, e.last_name, ep.role FROM employee_projects ep JOIN employees e ON ep.employee_id = e.employee_id JOIN projects p ON ep.project_id = p.project_id WHERE ep.role LIKE '%Lead%' OR ep.role LIKE '%Manager%';
练习题 8:查询未参与任何项目的员工
- 列出没有参与任何项目的员工。
SELECT e.first_name, e.last_name FROM employees e LEFT JOIN employee_projects ep ON e.employee_id = ep.employee_id WHERE ep.project_id IS NULL;
网络
主机网络不通,如何排查?
- 首先可以查看IP、子网掩码、网关、路由配置是否正确,相关的排查命令有ip、ping、traceroute;
- 然后还可以看防火墙策略是否对其限制,并结合tcpdump抓包测试;
- 最后可以看网卡、网线、路由器、交换机等硬件设备是否工作正常。
*访问一个网站背后的过程?
- 首先通过DNS解析,将域名解析为对应的IP地址,解析顺序依次为 “浏览器缓存” → “本地 hosts 文件” → “递归查询(本地 DNS)” → “迭代查询(根→顶级→权威)”;
- 获取到IP地址后,进行TCP三次握手建立连接;
- 如果请求的域名是HTTPS的,客户端和服务器还会通过 TLS 握手 建立加密通道,握手过程包括证书验证、密钥协商等;之后所有 HTTP 报文将通过 TLS 进行加密传输。
- 之后向服务端发送HTTP请求报文,请求报文中包含方法(GET/POST/PUT/DELETE等)、路径、HTTP版本号、首部字段(一组键值对,如 Host、User-Agent、Accept 等 )、请求体(可选,例如在 POST 请求中携带 JSON 数据);
- 服务端收到后,返回HTTP响应报文,其中包含版本号、状态码、短语、首部字段(Content-Type、Server等)、空行、数据实体;
DNS解析流程?
- 将域名解析为对应的IP地址,解析顺序依次为 “浏览器缓存” → “本地 hosts 文件” → “递归查询(本地 DNS)” → “迭代查询(根→顶级→权威)
- DNS相关的测试工具有 dig、nslookup
什么是递归查询?什么是迭代查询?
- 假设宿主机的 DNS 服务器指向了 223.5.5.5(阿里云DNS),本机向这个 DNS 服务器发起的查询就是递归查询;
- 而这个DNS服务器(223.5.5.5),如果没有命中缓存,它会向根服务器、顶级服务器、权威服务器发起的查询,就叫迭代查询。
迭代查询的细节简述?
- 访问 www.baidu.com 时,如果本地 DNS 没有缓存,它会向根服务器查询,根服务器返回 .com 的 DNS 地址;
- 接着去问 .com 顶级域服务器,它告诉你 baidu.com 的权威服务器地址;
- 最后向权威服务器请求 www.baidu.com 的 IP,获取成功后返回给客户端。这个过程就是迭代查询。
*TCP三次握手的过程?
- 第一次握手(SYN):客户端向服务器发送一个 SYN。此时,客户端进入 SYN_SENT 状态;
- 第二次握手(SYN-ACK):服务器收到客户端的 SYN 报文后,会发送一个 SYN-ACK(同步确认)报文段作为响应。此时,服务器进入 SYN_RCVD 状态;
- 第三次握手(ACK):客户端收到服务器的 SYN-ACK 报文后,发送一个 ACK(确认)报文段作为最终确认。此时,客户端进入 ESTABLISHED 状态。服务器收到客户端的 ACK 后也进入 ESTABLISHED 状态,连接正式建立。
*TCP和UDP的区别?
- 连接与可靠性:TCP是面向连接的,会通过三次握手、流量和拥塞控制、重传等机制使传输更可靠 ;而UDP仅提供最基本的数据传输能力,只管发送,不管对方是否收到。
- 传输速度:UDP要高于TCP。
- 首部结构:
- TCP首部最小为20字节,最大为60字节(其中包括源端口、目标端口、序列号、确认号、6个标志位、效验和、滑动窗口、紧急指针、数据实体等)
- UDP首部为8个字节(其中包括:源端口、目标端口、长度、效验和、数据实体)
- 通信方式:TCP 仅支持一对一通信(因为只能和一台主机建立三次握手);UDP支持一对一、一对多的方式通信。
- 应用场景:TCP 适合下载文件等对数据传输可靠性要求高的场景;而 UDP 更多的用于在线视频、语音等对数据实时传输效率要求高的场景,像 DNS、DHCP 协议是基于 UDP 的。
OSI七层模型指的是哪几层?分别有什么协议?
- xxx
常见服务的端口号
- 未特别说明的,均为TCP,但有些服务,既支持UDP,又支持TCP
Port Service 20
ftp-data 21
ftp 22
ssh 23
telnet 25
smtp 53/udp
dns 67/udp
dhcp 68/udp
dhcp-client 69/udp
tftp 80
http 110
pop3 119
nntp 123/udp
ntp 443
https 465
smtps 514/udp
syslog 873
rsync 995
pop3s 1521
oracle 2049
nfs 3306
mysql 3389
rdp 5432
postgresql 5672
RabbitMQ 6379
redis 8080
tomcat 9092
Kafka 9200
elasticsearch 11211
memcached
监控与告警
Prometheus 主要由哪些组件组成?
- Prometheus Server:负责数据采集、存储和查询。
- Exporter:指标暴露器,负责把应用/系统的监控数据转成 Prometheus 能识别的格式。
- Node Exporter:采集主机 CPU、内存、磁盘、网络等系统指标
- cAdvisor:采集容器运行时的资源指标
- MySQL/Redis/Kafka Exporter:采集中间件运行指标
- Pushgateway:用于 短生命周期任务 或 无法被主动拉取的任务。用于 短生命周期任务 或 无法被主动拉取的任务。
- 场景:一次性批处理任务(job 运行几秒就结束,Prometheus 来不及拉取)。Job 可以把指标主动 推送(push) 给 Pushgateway,Prometheus 再去拉取 Pushgateway。
- Alertmanager:处理告警通知。
- 去重(避免重复通知)
- 分组(相似告警合并)
- 抑制(例如主机宕机时抑制其子服务告警)
- 静默(临时屏蔽某些告警的通知)
- 路由(邮件、Slack、钉钉、企业微信等)
- Grafana(可选,用于可视化)
Prometheus 的数据模型是什么?
Prometheus 使用多维数据模型,每个时间序列由以下部分组成:
- 指标名称(Metric Name):说明“监控的是什么”。(如 http_requests_total)。
- 标签(Labels):区分相同指标的不同维度。(如 method=“GET”、status=“200”)。
- 时间戳(Timestamp):表示采样的时间点。
- 值(Value):表示该时间点的数值。
如何监控 K8s 集群?
- 通常的方案是 Prometheus + Grafana + Alertmanager,Prometheus作为时序数据库采集指标数据,Grafana 基于 Prometheus 的指标进行图形展示,Alertmanager 实现告警;
- 还可以通过 KubeSphere、Rancher 等 K8s 管理平台实现监控,这些平台都集成了监控告警功能;
- 常见的监控指标:
- Node:CPU、内存、磁盘使用率、磁盘IO
- Pod/容器:CPU、内存使用情况
- Pod 状态:Running、Pending、CrashLoopBackOff 等
- API Server 的每秒请求数、请求延迟
- 网络流量和带宽使用情况
- 存储类的使用情况
如何监控应用程序?
- Prometheus + 第三方或程序内部集成的 /metrics 端点。
如何设计一个有效的监控系统?
- 全面覆盖:监控系统应覆盖所有关键组件,包括服务器、网络设备、数据库、应用层等。
- 多维度监控:不仅要监控硬件资源(如CPU、内存、磁盘),还要监控应用性能(如请求延迟、错误率)和服务健康状态(如服务可用性)。
- 实时性:监控数据应尽可能实时更新,以便及时发现问题。
- 告警机制:设置合理的告警阈值和通知渠道(如邮件、短信、Slack等),确保问题能够被及时发现和处理。
- 可视化:通过仪表盘展示关键指标,便于快速了解系统状态。
- 历史数据分析:保留历史数据,便于分析趋势和排查问题。
如何设置合理的告警阈值?
- 基于历史数据:分析历史数据,了解系统的正常运行范围,确定合适的阈值。
- 区分紧急和非紧急告警:对于影响用户体验的关键指标(如请求失败率),设置较为严格的阈值;对于次要指标(如磁盘使用率),可以适当放宽。
- 动态调整:随着系统负载的变化,定期调整告警阈值,确保其始终处于合理范围内。
- 避免误报:设置合理的触发条件,避免频繁的误报。例如,可以通过多次采样确认异常后再触发告警。
CI/CD
容器
*容器与虚拟机的区别?
- 容器使用宿主机的内核,而每个虚拟机都有自己独立的内核。
- 容器更加轻量,迁移和部署都比虚拟机更加方便,并且启动速度也要比虚拟机快。
- 容器的隔离性不如虚拟机,因为容器是公用宿主机的内核 + 通过内核的 namespace 实现隔离。
namespace 有哪些?
- PID namespace:隔离进程 ID(每个 namespace 中的进程看到的 PID 是独立的)
- Network namespace:隔离网络资源(如网卡、IP 地址、端口等)
- Mount namespace:隔离文件系统挂载点
- UTS namespace:隔离主机名和域名
- User namespace:隔离用户和组 ID
- IPC namespace:隔离进程间通信(如信号量、消息队列等)
Dockerfile 的指令有哪些?
- FROM 指定基础镜像。
- LABEL 给镜像打标签。
- COPY 将宿主机文件。
- COPY 和 ADD,都可以将宿主机的文件拷贝至容器,但 ADD 还可以将压缩包解压缩拷贝,以及从 URL 下载文件拷贝至镜像。
- RUN 指定镜像构建时执行的shell命令,每个 RUN 指令都会在镜像中新增一层。
- ARG 和 ENV,ARG 是 “构建时变量”,ENV 是 “运行时变量”。
- USER 指定容器运行时的用户。
- WORKDIR 为后续的RUN、COPY、ADD、CMD、ENTRYPOINT等指令设置工作目录”(构建和运行阶段均生效)
- EXPOSE 声明容器运行时 “监听的端口”(仅为元数据说明,不实际映射端口)。
- VOLUME 定义容器中的 “匿名卷”(持久化数据的目录),避免容器内的数据随容器删除而丢失。
- ONBUILD 定义 “触发器”,当当前镜像被用作其他镜像的基础镜像时,自动执行ONBUILD后的指令。
- STOPSIGNAL 指定容器停止时发送的系统信号(默认是SIGTERM),用于优雅关闭应用。
- CMD 和 ENTRYPOINT,都是指定容器启动时的命令,但 ENTRYPOINT 不可变。CMD 通常作为容器启动时的参数,可以被覆盖。
Dockerfile 中的 COPY 和 ADD 有什么区别?
- COPY 和 ADD,都可以将宿主机的文件拷贝至容器,但 ADD 还可以将压缩包解压缩拷贝,以及从 URL 下载文件拷贝至镜像。
Dockerfile 中的 CMD 和 ENTRYPOINT 有什么区别?
- CMD 和 ENTRYPOINT,都是指定容器启动时的命令,但 ENTRYPOINT 不可变。CMD 通常作为容器启动时的参数,可以被覆盖。
使用 Dockerfile 制作镜像时,如何减少镜像的大小?
- 使用轻量级镜像,如 alpine。
- 清理无用的缓存文件。
- 尽量减少 RUN 指令的使用,以减少镜像分层。
- 使用多阶段构建,比如第一阶段使用nodejs镜像构建前端代码,第二阶段仅把前端构建结果拷贝至nginx镜像。
Overlay 与 Underlay 的区别?
Overlay 与 Underlay 的本质上都是为了解决容器跨宿主机通信的问题
- Overlay 是在底层网络之上构建一层虚拟网络(典型代表有 Calico 的 IPIP/VxLAN 模式),来实现容器跨宿主机通信。而 Underlay 是直接使用底层网络,来实现容器跨宿主机通信( K8s 的 hostNetwork 模式)。
- IP 方面,Overlay 网络下,容器 IP 有独立的地址段,而 Underlay 网络下,容器需要和宿主机处于同一网段。
- 性能开销方面,Overlay 封装 / 解封装会带来少量 CPU 开销,Underlay 无封装 / 解封装过程,转发效率接近物理网络。
Docker 的网络模式有哪些?containerd呢?
- bridge(默认),容器连接到一个虚拟网桥(docker0),容器间可互通,可通过端口映射与宿主机交互。
- host,容器与宿主机共用网络命名空间,没有隔离,性能好但安全性低。
- none,容器没有网络,只有 loopback。
- container,多个容器共享同一个容器的网络命名空间。
- overlay,用于多主机网络,常结合 Swarm 或 Kubernetes。 PS:containerd 本身不提供复杂网络模式,只负责容器运行。但它对外提供了 CNI 接口,可对接不同的网络插件。
K8s
Kubernetes 的核心组件有哪些?
Master 节点
- API Server:提供 Kubernetes API,是集群的前端接口。
- Controller Manager:管理各种控制器(如 Deployment、StatefulSet、DaemonSet等),确保实际状态与期望状态一致。
- 比如:Deployment Controller 会监控实际状态,发现副本数不匹配后,会自动创建一个新的 Pod,确保实际状态与期望状态一致。
- Scheduler:负责将 Pod 调度到合适的节点上。
- etcd:分布式键值存储,保存集群的所有配置数据。
Worker 节点
- Kubelet:管理节点上的 Pod,并定期向 API Server 报告 Pod 状态。
- Kube Proxy:负责 Service 的负载均衡和流量转发,确保客户端请求的流量转发到对应的 Pod 上,有 iptables 和 IPVS 两种模式。
- Container Runtime:运行容器的引擎(如 Docker、containerd)。
其他:
- CoreDNS:集群内部 DNS 服务。
kubernetes 中的 Pod 是什么?
- 在 Kubernetes 中,Pod 是最小的调度和运行单位,Pod 中可以包含一个或多个容器,这些容器共享网络和存储资源。
- 共享网络是指 Pod 内所有容器共享同一个网络命名空间,容器之间可以通过 localhost 直接通信。
- 共享存储是指 可以挂载同一个 Volume,多个容器可同时读写,常用于日志共享、配置共享等。
pause 容器是干嘛的??
- 每个 Pod 启动时,都会启动一个 pause 容器,这个容器相当于是 Pod 的“底座”,为 Pod 中的其他容器提供网络、命名空间等基础环境。
Pod 运行模式?
- 单容器应用:一个 Pod 就运行一个业务容器(最常见)。
- Sidecar 模式:在主应用容器旁边放一个辅助容器(如日志收集、监控代理)。
- Adapter 模式:主应用容器不变,旁边加一个数据转换容器。
- Ambassador 模式:通过代理容器来与外部服务通信。
Pod 控制器有哪些?
- 在 K8s 中,常见的 Pod 控制器有 Deployment、StatefulSet、DaemonSet、Job、CronJob;
- Deployment 是 ReplicaSet 增强版,主要用于运行无状态服务。
- StatefulSet 主要用于运行无状态服务。
- DaemonSet 确保在集群的每个节点上都运行一个 Pod,通常用于集群级别的服务,如日志收集器、监控代理等。
- Job 用于执行一次性任务,任务完成后 Pod 会被终止。
- CronJob 是周期性任务,任务会定时执行。
Deployment 和 StatefulSet 有什么区别?
- Deployment 通常用于运行无状态服务,而 StatefulSet 通常用于运行有状态服务;
- Pod 名称方面,Deployment 是随机分配的,而 StatefulSet 有固定的名称后缀,比如-0、-1、-2;
- 启动和删除顺序方面,Deployment 没有要求,而 StatefulSet 启动和删除都有严格的先后顺序要求;
ReplicaSet 和 Deployment 有什么区别?
- Deployment 是 ReplicaSet 增强版,增加了滚动更新和回滚功能。
Pod 创建过程?
- 首先 kubectl 或其他客户端会向 kube-apiserver 发送 PodTemplate;
- API Server 对请求进行 认证、鉴权、准入控制;
- 认证:你是谁?(比如通过证书验证身份)
- 鉴权:你有没有权限做这个操作?(比如基于角色的访问控制中,Alice 是否有 “create pods” 这个权限。)
- 准入控制:这个操作是否合法、合规?(namespace的Pod 数量、CPU、内存使用总量是否超限?PodSecurity、ResourceQuota、LimitRanger 这三种都属于准入控制器)
- 验证通过后,Pod 对象被转换成 json 格式存入 etcd;
- Controller Manager 监控到 etcd 中有新的 Pod 资源对象后,会将 Pod 状态置为 Pending;
- Scheduler 从 etcd 拿到 Pending 状态的 Pod 后,根据调度策略(资源量、亲和性/反亲和、污点/容忍、优先级等)选择合适的节点,把调度结果(Pod.Spec.NodeName) 通过 API Server 写回 etcd;
- kubelet 监听到本节点被分配了新的 Pod 后,根据 Pod 定义(PodSpec),就会开始调用 CNI 插件配置网络,CSI 插件挂载持久化存储,CRI拉镜像、启动 pause 容器和业务容器,以及启动、就绪、存活探针开始探测;
- 最后 kubelet 会定期向 API Server 上报 Pod 状态(Pending、Running、Succeeded、Failed…)。
Pod 删除过程?
- 首先 kubectl 或其他客户端向 kube-apiserver 发送 Pod 删除请求;
- API Server 将 Pod 标记为 Terminating 状态,并设置一个宽限期(默认30秒)。在宽限期内,kubelet 会尝试优雅地停止 Pod 中的容器;
- 如果定义了停止前钩子(preStop Hook),会在此期间执行。
- 如果宽限期内容器仍未停止,kubelet 会向容器发送 9(SIGKILL) 信号,强制终止进程;
- 最后 kubelet 会向 API Server 报告 Pod 已终止,API Server 收到后,最终会把 Pod 对象从 etcd 中移除。
Pod 状态有哪些?
- Pending:Pod 已创建,但还没有被调度到节点上。
- Running:Pod 中的所有容器都已启动并运行。
- Succeeded:在一次性任务中出现,表示任务已成功执行完毕。
- Failed:表示 Pod 中的容器以非零状态码退出。
- Unknown:Kubelet 无法获取 Pod 的状态。
- Terminating:Pod 已经收到了删除请求,但还没有完全删除,正在进行资源清理和容器终止的过程。
- CrashLoopBackOff(容器状态):表示容器启动失败并多次重启失败。
Pod 的探针有哪些?
- Startup Probe(启动探针):检查容器是否成功启动。
- Readiness Probe(就绪探针):检查容器是否已准备好接收流量,探测成功才会通过 Service 将流量路由到该容器。
- Liveness Probe(存活探针):周期性检查容器是否健康。
- PS:
- 探测方式有三种,分别是基于命令、基于 HTTP 状态码、基于 TCP 连接。
- 基于命令是根据命令执行的退出状态码判断是否执行成功,0表示成功,非0表示失败;
- 基于 HTTP 状态码,2xx、3xx表示成功,否则表示失败;
- 基于 TCP 连接,是根据能否建立 TCP 连接来判断(类似 telnet)
- 执行顺序上,启动探针是首先执行,启动探针探测成功后,就绪和存活探针并行执行。
- 启动探针成功后不再持续探测,存活和就绪探针会在容器运行期间进行周期性探测。
kubernetes 中的 Service 是什么?
- kubernetes 中的 Service 是 Pod 的代理,可以为 Pod 提供一个稳定的访问入口,并且 Pod 之间还可以通过 Service 的域名进行通信;
- Service 的代理是基于 iptables 或 ipvs 的。
Service 的类型有哪些?
- ClusterIP(默认):提供一个仅在集群内部可访问的虚拟 IP。
- NodePort:在每个节点上打开一个端口,通过 NodeIP:NodePort 的方式访问服务。
- 在生成 NodePort 的同时,也会生成一个 ClusterIP。可以通过 NodeIP:NodePort 从外部访问服务;但在集群内部,依然可以通过 ClusterIP 来访问。
- LoadBalancer:在公有云(如 AWS、GCP、Azure)中使用时,会自动创建一个云负载均衡器,将外部流量转发到 Service。常用于生产环境对外暴露服务。
- 会生成一个 ClusterIP + NodePort,然后再由云提供商创建一个外部的负载均衡器,转发流量到 NodePort。
- 请求流程:外部 → LoadBalancer 公网 IP → NodePort → ClusterIP → Pod。
- ExternalName:把集群外部服务引入到集群内。
什么是 Headless Service?它与普通 Service 有什么区别?
- Headless Service 是一种特殊的 Service 类型,它与普通的 Service 主要区别在于不分配 Cluster IP。
- Headless Service 的核心作用在于它改变了 DNS 解析的行为。
- 对于普通 Service:当你查询其 DNS 名称时,DNS 服务器会返回 Service 的 Cluster IP。
- 对于 Headless Service:当你查询其 DNS 名称时,DNS 服务器会返回与该 Service 相关联的所有 Pod 的 IP 地址。
- 说白了就是可以实现 Pod 间直接进行通信,而不使用 service 进行负载均衡,通常用于有状态服务需要通过 Pod IP 直接通信的场景。
- 定义方式是在 Service 的 clusterIP 处定义为 None。
kubernetes 中的 Ingress 是什么?
- “Kubernetes 中的 Ingress 是一种 API 对象,主要作用是管理集群外部到内部服务的 HTTP/HTTPS 流量路由。简单说,它就像集群的‘入口网关’,能根据域名、路径等规则,把外部请求转发到对应的内部 Service;
- Ingress 本身只是规则的定义,必须配合 Ingress 控制器(比如 Nginx Ingress Controller)才能生效,常见的控制器有 Nginx、Traefik、Istio。
Service 和 Ingress 的区别?
- 在 K8s 中,Service 和 Ingress 都是对外暴露流量的方式;
- Service 是给一个或多个 Pod 提供稳定访问入口,负责四层(TCP/UDP)负载均衡,有 ClusterIP、NodePort 和 LoadBalancer 类型,适合内部访问或者简单对外暴露;
- Ingress 是给一个或多个 Service 提供稳定访问入口,负责七层(HTTP/HTTPS)路由规则,需要依赖 Ingress Controller,比如 Nginx、Traefik、Istio,支持基于域名和路径的流量分发,还可以配置 TLS;
- 简单来讲,Ingress 通过七层代理转发到 Service,Service 通过四层代理转发到Pod。
外部请求 → Ingress Controller → Service → Pod
kubernetes 中的 Namespace 是什么?
- Namespace 实现了 K8s 中各种资源的逻辑隔离;
- 默认的 Namespace 有 default、kube-system、kube-public、kube-node-lease。
- kube-system 下默认运行了coredns、etcd、apiserver、controller-manager、kube-proxy、scheduler。
kubernetes 中的 Configmap 和 Secret 是什么?
- Configmap:用于存储非敏感的配置数据(如环境变量、配置文件)。
- Secret:用于存储敏感数据(如密码、密钥),内容经过 Base64 编码。
k8s 中 StorageClass、PV、PVC的关系是?
- 这三个是 K8s 中最常用的持久化存储解决方案,可以实现静态或动态供应持久化存储资源;
- 静态供应(Static Provisioning)
- 管理员手动创建好 PV;
- 用户创建 PVC;
- 系统自动将 PVC 和符合条件的 PV 绑定;
- StorageClass 可选。
- 动态供应(Dynamic Provisioning)
- 用户创建 PVC,并指定 StorageClass;
- StorageClass 的 Provisioner 插件会自动创建一个 PV,并且 PVC 会自动绑定这个 PV;
- 这是现代集群更常用的方式。
kubernetes 中的 Volume 有哪些?
- 临时卷:
- emptyDir:在 Pod 被分配到节点时创建,生命周期与 Pod 一致。当 Pod 从节点移除时,emptyDir 中的数据会被永久删除。常用于 Pod 内多个容器之间共享数据。
- 持久卷:
- PersistentVolume(PV):由管理员配置的集群级存储资源,独立于 Pod 生命周期。
- PersistentVolumeClaim(PVC):由用户申请的存储资源,类似 “存储需求订单”,Kubernetes 会自动匹配满足条件的 PV。
- 本地存储卷
- hostPath:宿主机的文件系统路径直接挂载到 Pod 中。
- local:与 hostPath 类似,但更强调稳定性,需要显式指定节点亲和性,适用于需要高性能本地存储的场景(如数据库)。
- 配置类卷:
- Configmap:用于存储非敏感的配置数据(如环境变量、配置文件)。
- Secret:用于存储敏感数据(如密码、密钥),内容经过 Base64 编码。
- downwardAPI:将 Pod 或容器的元数据(如 Pod 名称、IP、标签等)以文件形式暴露给容器。
- 网络存储卷
- nfs:挂载 NFS(网络文件系统)共享目录,适用于需要多节点共享数据的场景。
K8s 如何实现滚动更新?
- 通过 Deployment 的 strategy 字段定义滚动更新策略,并通过 maxUnavailable、maxSurge 控制速率。
- maxUnavailable 表示升级时最多有几个 Pod 不可用。
- maxSurge 表示升级时最多比期望副本数多出的 Pod 数量。
- 最常见配置(高可用):maxUnavailable = 0,maxSurge = 1,先多启动一个新 Pod,确认可用后再删旧的,不会出现服务空档。
K8s 如何实现蓝绿部署?
- 蓝绿部署是指存在A、B两套环境,平常A对外提供服务,当B升级测试完成后,把流量迁移到B环境中;
- K8s中要实现蓝绿部署,可以基于 service 的标签选择器,切换到不同的 Pod 控制器来实现。
K8s 如何实现金丝雀发布?
- 金丝雀发布又称灰度部署,指的是先进行小范围的升级,当运行一段时间没问题后,再进行增量或全量替换。
- K8s中要实现灰度部署,可以通过 service 的标签选择器控制转发的后端 Pod。也可以使用服务网格(如 Istio),通过基于权重的方式实现流量控制。
K8s 如何实现金丝雀发布?
- 金丝雀发布又称灰度部署,指的是先进行小范围的升级,当运行一段时间没问题后,再进行增量或全量替换。
- K8s中要实现灰度部署,可以通过 service 的标签选择器控制转发的后端 Pod。也可以使用服务网格(如 Istio),通过基于权重的方式实现流量控制。
K8s 中的 CRD 和 Operator 是什么?
- CRD 是自定义资源类型,Operator 是一个自定义的控制器,两者结合通常用于管理有状态应用。
什么是 Helm?
- Helm 是 Kubernetes 的包管理工具,类似于 Linux 的 apt 或 yum,也像 Node.js 的 npm。
- 它把一组 Kubernetes 资源(Deployment、Service、ConfigMap、Ingress 等)打包成一个 Chart,可以安装、升级、回滚和删除。
Helm 相关组件有哪些?
- Chart:类似于 yum/apt 里的软件包;
- Release:Chart 的一次部署实例,支持版本回滚;
- Repo:Chart 的仓库;
- Values:Chart 的配置文件;
- Templates:通过 Go 模板机制渲染生成最终的 K8s YAML。
数据库
事务特性有哪些?
- 原子性(Atomicity):整个事务中的所有操作要么全部成功执行,要么全部失败后回滚。
- 一致性(Consistency):事务做完后,数据得保持前后一致(比如转账时,A少了100块,B就必须多100块)。
- 隔离性(Isolation):事务在未提交前不可见,但有多种隔离级别:读未提交、读已提交、可重复读、串行化。
- MySQL 的 InnoDB 存储引擎默认是可重复读。
- 持久性(Durability):事务一旦提交,其所做的修改会永久保存于数据库中。 PS:事务还依赖于事务日志,其中包含 redo log 和 undo log,redo log保障事务的持久性,undo log保障事务的原子性。
MySQL 的锁有哪几种?
- 全局锁、表锁、行锁,行锁又分为共享锁(读锁)和排他锁(写锁)。
数据库如何做备份?
看数据量
- 较小:每日全量备份(每日定时任务,K8s 或系统 crontab) + 开启二进制日志(binlog),工具可以使用 mysqldump。
- 较大:每周或每月全量备份 + 每日增量备份 + 开启二进制日志(binlog),工具可以使用 xtrabackup(XtraBackup 本身只支持增量,不支持差异备份。)。
- 增量备份(Incremental Backup):仅备份自上次备份以来变化的数据,恢复时必须按顺序应用:全量 → 第1次增量 → 第2次增量 → …
MySQL最常用的高可用方案?
- 8.0 以上推荐用 MGR (MySQL Group Replication)
如果数据库 CPU 飙高怎么排查?
- SHOW PROCESSLIST 或 SHOW FULL PROCESSLIST(Info 列显示完整的 SQL 语句)
- 检查慢查询、是否有全表扫描、索引是否失效。
消息队列
Kafka的核心组件有哪些?
- Producer(生产者):负责将数据发布(写入)到 Kafka 的 Topic 中。
- Consumer(消费者):订阅并消费 Kafka 中的消息。
- Broker(代理):Kafka 集群中的每个节点称为 Broker,负责接收、存储和传输消息。
- Topic(主题):Kafka 中消息的逻辑分类单元。
- Partition(分区):Topic 的物理分片,可以提高并行处理和扩展性。
- Zookeeper(可选):早期版本用于管理集群元数据,Kafka 2.8+ 开始,使用 KRaft(Kafka Raft Metadata mode) 模式,作为 Zookeeper 的替代方案。
负载均衡
四层负载均衡中,常用的负载均衡算法有哪些?
- 轮询(Round Robin):流量均匀地分配到所有后端服务器上。
- 最少连接(Least Connection):将流量优先分配给连接数最少的服务器。
- 加权轮询(Weighted Round Robin):根据权重分配流量。
- 加权最少连接(Weighted Least Connection):根据权重和连接数分配流量。
- 基于源地址哈希(Source Hashing):根据源 IP 地址的哈希值分配流量。
七层负载均衡中,常用的负载均衡算法有哪些?
IPVS 是什么?
- IPVS (IP Virtual Server) 是 LVS (Linux Virtual Server) 的一种实现。它是 LVS 的一个增强版。
Web 服务
配置 Nginx 作为 Web Server 时,你常用的优化配置有哪些?
- 性能优化:
- 开启和 CPU 核心数相同的 worker 进程(worker_processes auto;)
- worker 进程与 CPU 亲缘性绑定(worker_cpu_affinity 0001 0010 0100 1000; # 假设4核CPU,绑定每个进程到特定核心)
- 增大 worker 进程的最大连接数(worker_connections 10240;)
- 使用 epoll 事件通知模型
- 开启 gzip 压缩
- 客户端频繁请求的场景下,开启 keepalive,并设置合理的 timeout
- 安全优化:
- 普通用户运行 worker 进程(user www-data; # master 进程还是以 root 身份运行,因为只有 root 身份才能绑定 <1024 的特权端口)
- 隐藏 Nginx 版本号(server_tokens off;)
- 防盗链(仅允许指定域名访问图片等静态资源)
- 反向代理:
- 开启缓存
- 开启客户端 IP 透传(proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;)
- 其他:
- 日志输出改为 json 格式(便于 ELK 分析)
Python
Python 的数据类型有哪些?
- 基本类型:int(整型), float(浮点型), complex(复数), bool(布尔型), 字符串;
- 容器类型:list(列表), tuple(元组), set(集合), dict(字典)。
列表和元组的区别?
- 列表可变,元组不可变;
- 定义方式上,列表使用方括号[],元组使用圆括号()或直接用逗号分隔;
Python 中 *args 和 **kwargs 的作用?
- *args:接收任意数量的位置参数,返回元组
- **kwargs:接收任意数量的关键字参数,返回字典
Python 中 is 与 == 的区别?
is
比较对象的id,即内存地址(是否是同一个对象),==
比较对象的值a = [1, 2] b = [1, 2] print(a == b) # True print(a is b) # False