- grep、sed、awk、cut 通常用来干什么的
grep 通常用来过滤,sed 通常用来替换、awk 可以正则处理过滤字段、cut 通常取分隔符字段,通常这些可以组合使用 如 grep 再 awk、grep 再 sed
- http 错误码和原因
http 错误码通常有
1xx 信息响应
2xx 成功
3xx 重定向
4xx 客户端错误
5xx 服务器内部错误
一般有
200 成功
201 创建成功
204 成功但无返回
301 永久重定向 http -》 https
302 临时重定向 登录跳转
304 未修改
400 请求错误
401 未认证
403 无权限
404 不存在
405 方法不允许
408 请求超时
429 请求过多
500 服务内部错误
502 网关错误
503 服务不可用
504 网关超时
- 长连接、短链接、websocket 区别和使用场景
短链接,一般要进行3次握手4次挥手 优点 简单、不占连接 缺点 性能差、高频请求不合适
三次握手 sync sync+ack ack
四次挥手 fin ack fin ack
长连接,tcp连接可复用,仍然是 http 协议 优点减少 tcp 建立成本、提升性能 缺点服务器需要维护连接、不能主动推送数据,http 需要配置 keepalive
websocket 基于 tcp 全双工 服务器可以主动推送 一次连接多次通信,优点实时性强,数据头部小 缺点连接占资源 实现复杂
- nginx 性能优化有哪些方式
worker_processes auto 进程 auto
worker_connections 调大
开启 sendfile
开启 keepalive_timeout
开启 gzip
静态资源缓存
反向代理缓存
日志优化
操作系统参数调优
- lvs、nginx、haproxy 哪些场景使用
lvs 四层、转发快、只管流量不管内容
nginx 七层、功能全、能代理还能做 web
haproxy 专职负载均衡 四层七层都支持
- 僵尸进程是什么
僵尸进程是指没有父进程管控,一般操作系统的根进程是 1, 然后再有一个进程 xxx, 他有子进程 xxxx,由于某种原因,xxx 进程被删除了,但是子进程却没有被删除导致一直留在系统当中
ps -ef |grep Z
- 进程、线程、协程区别
进程 是资源分配的基本单位
线程是 cpu 调度的基本单位
携程是 用户态的轻量线程
- 什么是 nginx 的异步非阻塞
Nginx 的“异步非阻塞” = 一个 worker 用事件驱动方式,同时处理成千上万个连接,而不会被某一个请求卡住。
- linux网络丢包怎么排查
ping 检测连通性和丢包率和延迟
traceroute 检测路由跳转节点
ss/netstat 查看 tcp 状态 重传情况
tcpdump 抓包分析
ethtool 查看网卡状态
dmesg 内核网络异常日志
- 性能分析常用工具与命令
top 查看 cpu 情况
htop 图形化 top
free 查看内存情况
vmstat 虚拟内存 交换 io统计
sar 历史内存统计
iostat 查看磁盘 io 使用情况
df -h 磁盘使用情况
du -sh 查看文件大小
ping 测试包连通性
traceroute 路径追踪
ps aux 查看经常状态
pidstatus 进程cpu、io使用统计
vmstatus 系统负载内存等
- 什么是进程中断/挂起
cpu需要处理更高级的任务,所以需要把当前任务的现在状态存存到寄存器中,具体包含上下文切换,当前处理内容等,等待高级任务执行完毕后会继续恢复寄存器中内容再次执行
- 什么是软中断、硬中断
硬中断由硬件设备发起,执行时间短,优先级高
软中断有软件触发,需要等待硬中断处理完才能处理软中断有优先级
- 什么是不可中断进程
等待某些不可中断的事件,通常是 io 完成的进程,在此期间信号不能被打断,也不能被 kill
- 什么是栈内存和堆内存
stack 栈内存 作用是存储函数调用相关信息,局部变量,函数参数
heap 堆内存 存储动态分配的数据,例如数组、对象、缓存等
- top 命令里面可以看到进程哪些状态
top 进程可以看到 load 负载、cpu 数量、cpu 使用率、看到进程状态 iowait、idle、僵尸、sleep 等、 看到内存使用情况
- linux 系统中 /proc 是做什么的
/proc 是linux 虚拟文件系统 用来暴露内核和进程状态信息的
可以看到 cpu、内存、内核版本、加载模块等
通常有
/proc/cpuinfo
/proc/meminfo
/proc/uptime
/proc/loadavg
/proc/version
/proc/stat
/proc/sys 可调内核参数
- load和cpu使用率区别
load 是系统使用负载,有 load1 load5 load15 表达 单位时间内平均正在运行等待cpu/io 的进程数
一般 load 负载数值不会超过 cpu 核心数量,如果超过了代表系统压力很大
cpu 使用率 表示了当前cpu 使用情况
- MAC地址IP地址如何转换
mac 是数据链路层信息 ip 是网络层信息,mac 是网卡唯一硬件地址,ip 是网络逻辑地址
通常在网络中找另一台机器,需要发送 arp 信息,此时对象会收到 mac 并且缓存到 arp 表里,一般是 ip 5元组 ,mac、ip、协议、ip、mac
- 常见的raid有哪些,使用场景是什么
raid0 条带化 无容错 最少2块实现
raid1 镜像 一块盘坏了可以继续使用 最少2块实现
raid5 条带+奇偶校验 一块盘坏了 容量利用率高,读性能较好,写性能略低 最少3块
raid6 条带+双奇偶校验 可同时换2快盘 最少4块
raid10 镜像+条带 高可用性+高性能 容量利用率低 最少4块
raid01 条带+镜像 高可用性+高性能 容量利用率低 最少4块
- lvm怎么划分
lvm 逻辑卷,有 pv vg lv 组成,pv 是物理卷、vg 是卷组 lv 是逻辑卷
- jvm内存如何查看
jvm 是java 内存管理系统,他认为系统的内存是不可靠的,一般在服务启动时他会自动分配内存,分为 堆、非堆、线程使用情况等
- 什么是进程最大数、最大线程数、进程打开的文件数,怎么调整
进程最大数 系统允许每个用户同时创建最大进程数
最大线程数 单个进程或整个系统允许最大线程数量
进程打开数 一个进程同时打开的文件、socket 或管道数量
一般通过 ulimit -u 一般查看,一般通过 /proc/sys/kernel 修改
- buffers与cached的区别
内存中 buffer 是内核写的缓存,是系统元数据,无法修改
cached 是页面缓存,是打开内容的缓存可以修改
通常 cached 在内存不足是会自动释放最大的,但是 buffer 通常不会
- lsof命令使用场景
lsof 查看是进程打开文件/资源的命令,一般系统磁盘不够时,rm 删除了文件夹,但是可能 df -h 查看系统的磁盘还是没有恢复,那就是因为有进程打开的这个文件,可以通过 lsof 查看到对于的进程,进行释放
- Linux中的进程间通信的方式及其使用场景
linux 系统中不同进程之间进行通信一般通过 管道、队列、共享内存、信号、套接字等进行
- 什么是内存分页和分段
内存分页是将进程的虚拟空间划分大小固定的页,物理内存也划分同样大小的页框,通过页表映射虚拟页到物理页框中,目的是为了解决 内存碎片
内存分段是将进程地址的空间按逻辑单位划分为若干段,每段大小不固定,每段有 段基址 和段界限 目的是 可变大小
- 如何创建和管理自定义systemd服务
systemd 是 linux 管理服务启动与关闭的
linux 不止有 systemd 还有 init.d
- ansible roles使用场景,现在有多台机器需要批量加入k8s集群,怎么实现
ansible 要划分多个 role,有些需要实现幂等,比如基础设置之类的,如 系统调优,基础包安装 等
有些分成一次性执行的,如 master 节点安装等
有些需要检查后再次执行的,如判断 有没有 join 到集群,没有 join 的可以执行 等
- 谈谈你对k8s的理解
Kubernetes 本质是一个分布式控制平面,而不是简单的容器管理工具。用户通过 API Server 向 etcd 声明期望状态,Controller 通过持续的 reconcile loop 将真实集群状态收敛到期望状态。Scheduler 负责在全局约束下为 Pod 选择最优节点,而 kubelet 则在节点侧将调度结果转化为具体的容器运行状态。容器运行时通过 CRI 解耦,使 Kubernetes 可以运行在 containerd、kata 等多种运行时之上。
- k8s集群架构是什么
k8s 中 master 只有 api-server 是无状态的,多个 api-server watch etcd 数据,通常 api-server 可以对接 proxy 对外暴露,通常 kube-controller, kube-scheduler 是不提供对外暴露的功能的,他们通过 lease 租约的形式,如果是一个高可用的 k8s 集群,那么只有一个 kube-controller 提供了服务,其他的都在等待租约过程中,kubelet 部署在 node 节点的,他是watch api-server 主动上报了当前节点资源情况,以及watch到 api-server 里 pod 需要创建,就会创建。
- 简述Pod创建过程
用户通过 kubectl apply 或者通过 api 提交了创建 pod 记录
api 会验证对象合法话后会将对象写入到 etcd 中,此时 kube-scheduler 调度器 watch 到 api server 有一个 pod 对象,并且没有分配node 节点时,就会根据策略找到对应的 node 节点,scheduler 会修改这个 对象信息,并发送给 api-server ,api-server 再次存到 etcd 中,此时 kubelet watch 到 一个 pod 对象打上了他 nodeselect 但是本地却没有部署,他就会去部署这个 pod 到节点里,当部署完了时候会再次完成发送消息给 api-server,api-server 会存到 etcd 中
- 简述删除一个Pod流程
当用户提交了一个删除请求后,api 会验证对象合法性,并且打上 deletion 状态, kubelet watch 到 pod 需要被删除,就会发送优雅关闭信号给pod,并且等待优雅退出,等到时间后,删除 pod,然后更新 api 对象信息, api 去 etcd 中删除该资源
- 不同node上的Pod之间的通信过程
如果是同一个节点上 pod 通信,他们是通过网桥实现的
如果是不同node 节点上通信, pod 通过 veth peer 从网络namespace里出来到 内核的veth 设备上,veth 设备通过网桥 传输到另一台 node 节点的网桥上,然后去进行通信
- pod创建Pending状态的原因
pod pending 分为
未调度,pending由于 资源不足、有节点选择器、有污点、亲和性约束
已调度,pending由于 镜像下载失败、volume 挂在失败、权限问题、cni 网络问题
- deployment和statefulset区别
deployment 是无状态服务,首先他没办法直接指定 storageclass,其次它部署的服务没有领导这一说法,它对应的 svc 可以分配到每一个 pod 中
statefulset 是有状态服务部署,通常部署 etcd、redis、kafka 之类,它可以直接指定 storageclass,它对应的 svc 是一个 handless svc,通常用来实现服务注册
- kube-proxy有什么作用
kube_proxy 是每个 node 节点上的网络代理插件,它负责通过 iptables、或者 ipvs 将 svc ip 对应到后端的 pod ip 实现 pod 访问 svc 的负载均衡
- kube-proxy怎么修改ipvs规则
ipvsadm -L
- ipvs为什么比iptables效率高
iptable 通过链表规则匹配实现流量转发,每个包都需要遍历,适合小规模集群
ipvs 通过维护哈希表,不依赖表链遍历,是高性能负载均衡器
- pod之间访问不通怎么排查
先检查 pod ip 和状态,在检查网络联通性,再检查 node 节点之间互通,在检查 cni 插件互通,在检查 networkpolick 网络策略,在检查安全组防火墙,再检查 kube-proxy 规则
- k8s中Network Policy的实现原理
networkpolicy 是命名空间级别网络策略,它可以定义 ingress 入流量 egress 出流量
加入 pod a 发起请求访问 pod b, 那么 b 有 policy, pod a 到 node 网络栈,cni 插件会检查 policy 是否有策略,如果没有就到 b
- 探针有哪些?探测方法有哪些?
探针有 readiness就绪检测 liveness存活检测 startup 检测容器是由启动成功
方法有 http get、tcp、exec 命令
一般readiness 是与 svc 对应,如果服务健康了,加入到 endpoint 中,此时 svc 负载均衡就有了,还有一个一种就是 liveness 判断服务有没有运行,如果没有就绪,直接重启 pod
- pod健康检查失败可能的原因和排查思路
有可能是 没有配置,有可能是中间件连接失败服务没起来,有可能是资源不够启动,有可能是服务启动慢,有可能是端口未正确监听,有可能是权限不足
- k8s的Service是什么
svc 是对于暴露 pod 的抽象,通常是提供稳定的访问入口,通常是由 svc.namespace.svc.cluster.local
svc 有 clusterIP、NodePort、LoadBalancer、ExternalName
- k8s服务发现有哪些方式?
常见有 环境变量、dns、endpoint
- pod几种常用状态
pending 未就绪
running 运行中
succeeded pod完成正常退出
failed 容器退出状态非 0
unknown pod 状态未知,node与 api server 通信异常
- Pod 生命周期的钩子函数
PostStart 启动完成时操作,通常时下载依赖,创建目录,服务注册等
preStop 优雅关闭 通知服务下线,清理资源
- Calico和flannel区别
flannel 比较简单的 cni 插件,不支持网络策略,通常是通过 vxlan、ipip 实现跨界点通信
calico 支持网络策略,高性能,通常有 bgp、vxlan、ipip 封装等实现
如果 calico跟 flannel 都用 vxlan、ipip 性能是不是一样
不一样,flannel vxlan 是封装通过隧道发送,calico vxlan 是通过路由发送
- calico网络原理、组网方式
calico 分成 daemonset 在每个节点运行 负责更新 ipam bgp 或者路由更新等情况
felix agent 主要是负责维护 iptables/ ebpf 规则
ipam 负责分配ip维护 node 子网池子
- kubectl exec 实现的原理
exec 是发送给 api server 请求, api 不直接执行命令,将命令转成 websocket 发给 node 节点 kubelet kubelet 调用 容器运行时执行命令,把容器运行时 标准输出、标准错误都给打印出来
- kubeconfig存放内容
kubeconfig 中存放了 cluster 信息 api-server 地址,ca 证书, user 信息,toke 用户名密码, contexts 上下文信息,对于的哪一套 namespace 或者 cluster
- 假设k8s集群规模上千,需要注意的问题有哪些?
注意 api server 高可用,多副本 开启缓存
etcd 性能问题
kube-controller-manager 可能出现延迟
node 节点通过 节点池、标签、污点分组减少调度压力
多采用亲和性
限制 cpu、memory limit
采用 calico bgp
service 采用 ipvs 模式
dns 扩容
监控
日志采集
rbac 租户隔离
pod 数量限制
定期备份
- 节点NotReady可能的原因?会导致哪些问题?
kubelet 进程异常、cni 不通、节点压力大 kubelet 无法正常上报、运行时不对、api 延迟无法正常接收
- service和endpoints是如何关联的?
service 跟 endpoint 通过名字关联的,但是 service 跟 pod 通过 label 关联的
- request limit底层是怎么限制的
k8s request limit 底层是通过 cgroup 限制的, cgroup 支持限制 cpu、内存、进程、网络、设备访问、挂载点限制
- HPA怎么实现的
HPA 是 Kubernetes 的水平 Pod 自动扩缩器,通过周期性获取 Pod 指标(CPU/内存/自定义),计算目标副本数,并更新 Deployment/ReplicaSet 的 spec.replicas,实现根据负载自动伸缩。HPA 本身不直接创建 Pod,而是通过 Controller 修改副本数,由 ReplicaSet 负责创建/删除 Pod。
- scheduler调度流程
调度器分为:预入队列,排队、过滤、打分、保留资源、批准、拒绝、等待、绑定
preEnqueue 预入队列,这些插件将在 Pod 被添加到内部活动队列之前,在此队列中 Pod 被标记为准备好调度
Sort 排队,提供比较大小进行队列排队
PreFilter 预过滤,过滤出不符合的
Filter 过滤,过滤出可用的节点
PreScore 前置打分,生成一个可共享状态共 Score 使用
Score 打分,明确分数,找到合适节点
NormlizeScore 确认最终分数
Reserve 保留资源,预先划掉 Node 节点资源,方便下一个 Pod 调度
Peermit 批准
PreBind 准备需要绑定的所有工作
Bind 绑定到 node 节点
postbind 在 pod 被调用后,清理相关资源
unreserve 释放保留的资源
- k8s证书过期怎么更新
k8s 默认证书 1 年过期,默认可以使用 kubeadm certs renew all 证书轮转更新
或者自己构建 kubeadm 二进制,通过修改 证书时间,一次性签10年,20年
或者整个证书体系都用自己的
- Kubernetes Pod的常见调度方式
默认调度,过滤-打分
节点选择器
节点亲和性
节点反亲和性
污点与容忍
自定义调度器
- kubernetes Ingress原理
客户端发起请求,dns 解析到后发送给 ingress-controller, ingress controller 接收到请求发送给 service,service根据 iptables 或者ipvs 发送给 pod,pod 响应返回给客户端
- crd 怎么开发
首先需要创建自定义 crd 资源这个是 api-resource
其次需要通过代码生成器根据 scheme 对应 自己crd 的配置
然后是通过生成器生成代码,使用自定义 client 去创建 sharedinformer,然后讲 informer 的信息通过 handlevent 发给实际处理逻辑,实际逻辑是死循环,通过 handlevent 发送的队列去换成 index cache里找到对应的数据,然后进行代码逻辑执行,知道完成与期望状态一致
CRD 开发就是:通过定义自定义资源(CRD)、生成客户端和 Scheme,再用 SharedInformer + 工作队列在 Controller 中监听和处理事件,实现集群状态收敛到 CR 期望状态的循环逻辑。
- k8s 监控流程
kubelet 提供了 cadvisor,同时还可以安装 kube-status-metrics
安装 kube-status-metrics 还可以支持 hpa
- k8s 日志收集流程
k8s 日志有 elk、loki 等各种方式,大部分都是通过部署 daemonset 到 node 节点,去采集 node 节点 /var/log/pods 的 pod 的标准输出日志,可以选择目录层级,如采集一下10层目录结构
如果需要采集 pod 内文件日志,可能就需要采用 sidecar 边车模式,通过在 pod 中注入一个 容器,共享文件目录的方式,采集到对于的文件内容。
- etcd 异常怎么恢复集群步骤
etcd 最好是独立部署,并且制作镜像快照
etcd 需要如果坏掉一半,只能够提供读操作不能够提供写操作,必须要一半以上正常才能够进行写操作
etcd 有备份恢复脚本,如果发现问题能够立刻恢复。
- 蓝绿部署、灰度发布、金丝雀发布区别
蓝绿:需要有2套环境,新版本部署到 绿环境,然后进行测试后直接流量全部切换到绿环境 优点点简单,缺点占用双倍资源
灰度发布:通过控制网关流量方式,先对一部分区域开放,查看新版本表现再逐步开放,流量按比例逐渐放开,风险可控
金丝雀:灰度强调分阶段控制用户群体,金丝雀更强调先小流量试点,再且回到全部流量
- GitOps和DevOps区别
gitops 强调基础设施应用配置都存储在 git 仓库中,强调 git 状态同步到集群,实现声明式运维
devops 强调开发与运维结合,通过自动化工具实现cicd 加快软件交付
sre 网站可靠性工程师,强调指标驱动运维,强调 sli/sla 错误预算、自动化、容量管理、事件响应
- 谈谈你对SRE理念的理解
核心思想,通过软件工程控制系统可靠性,可用性,保证 sla
可靠性优先,工程化运维,把重复的运维工作用代码自动化,降低人为错误
度量和数据驱动 通过 sla,slo,sli 量化服务可靠性
- 运维过程中遇到的最大的故障是什么?怎么解决的?
公司设备从阿里云迁移到腾讯云后,mqtt 服务 cpu 经常提示 85% 以上,有时甚至 90%,由于单台设备都是 60 w 设备在线,如果有一台机器 down 了,设备重连会导致雪崩事故,只能反复排查原因,最终确定 腾讯云 cpu 与 阿里云cpu 同型号情况下 cpu 虚标,但是由于不能随意down 机,只能反复测试服务参数,并且由 emqx-bench 工具压测,最终找到解决方案,定期清除 emqx 遗嘱。
- 最近工作中做过最有意义的事
把公司整体业务从阿里云迁移到腾讯云实现了降本增效,其中涉及了 虚拟机、k8s、负载均衡、数据库迁移、公司业务不断线切换,保障了 app 服务的可用性
- 运维体系建设包含哪些方面
核心目标
系统稳定性、交付效率、风险可控、团队协作高效、降本
基础设施管理、自动化配置管理、告警管理、备份恢复管理、安全访问权限管理、变更流程标准化管理、性能优化与容量管理、运维团队与知识管理
- 你的优点和缺点分别是什么
学习能力强,能够快速掌握新知识与新技能
责任心强,能够主动承担事情并解决
抗压能力强,遇到事情能够保持冷静
缺点
不擅长拒绝,容易接受过多任务,需要学会优先级管理
对于ai方面经验不足
过于谨慎,决策需要经常找领导确认
- 与上级意见不一致怎么办
可以说理解您的思路,但是我发现一点别的情况,这个可能也要考虑进去,如果坚决不同意,也要尊重,聚焦与结果和团队目标,而不是个人立场
- git分支冲突怎么解决?
一般本地 merge 或者 rebase 别人分支
cherypick 一般同于将 某一个commit 合并到分支
- pod 中 resource 常用资源
cpu、memory、ephemeral storage 本地临时存储、hugepages 大页内存请求、gpu
- k8s SharedInformer 原理
list + Watch
Informer 启动时,先调用 List API 拉取全量资源,初始化缓存
然后调用 Watch API,监听增删改事件,实时更新缓存
DeltaFIFO 队列
事件流入队列,按资源对象 key 分组
可以合并多个 Update 事件,保证最终状态一致
本地缓存 Store / Indexer
避免频繁访问 API Server
支持按 namespace/name 查找对象
自动重试与重同步(Resync)
ResyncPeriod 定期触发全量同步
防止 Watch 丢失事件或缓存不一致
共享缓存(SharedInformer)
多个 Controller 可以共享同一个缓存
节省 API Server 请求,保证事件一致性
- go slice 底层是什么组成
go 底层是 数组、长度、容量组成
- go map 底层是什么组成
Go map 底层是 哈希表 + 链表/数组 + 槽(bucket)
- go 中一个 go-routine 如何实现超时
通过新建一个超时的监听器,然后通过 chan 告诉 roroutine 超时了
通过 context.WithTimeout 实现
- go var 和 := 的区别
var 可以在包级别声明,支持初始化或者不初始化
:= 只能在函数内部声明并初始化
- go const 特点
编译器明确,支持 iota 自增
- go 循环有哪些形式
for switch select
- go 空接口 interface{} 有什么作用?
通常用了做泛型,或者传递任何数据,可以存储任意类型
- go 数组和切片区别
数组长度固定,值类型
切片是引用类型,可以动态扩容,底层指向数组
- go 数组
func main() {
a := make([]int, 0, 4) // len=0, cap=4
a = append(a, 1)
fmt.Println(a[0])
}
这个是分配了长度 0,容量 4 的 slice,append 是从索引 0 写入,所以输出 1
func main() {
a := make([]int, 4) // len=4, cap=4
a = append(a, 1)
fmt.Println(a[0])
}
这个是分配了长度 4,容量 4 的 slice,底层数组已经分配了 4 个元素,默认零值,append 是从索引 4 写入,所以输出 0
- jenkins pipline 怎么写
首先 jenkins 有多种流水线,有简易流水线,自由风格流水线
大部分场景使用自由风格流水线,其中有两种类型 pipeline,脚本式,声明式
pipeline {
agent any // 在任意可用节点执行
environment {
APP_NAME = "my-app"
}
stages {
stage('Checkout') {
steps {
git branch: 'main', url: 'https://github.com/example/repo.git'
}
}
stage('Build') {
steps {
sh 'go build -o myapp ./...'
}
}
stage('Test') {
steps {
sh 'go test ./...'
}
}
stage('Docker Build & Push') {
steps {
script {
docker.build("${APP_NAME}:latest").push()
}
}
}
stage('Deploy') {
steps {
sh 'kubectl apply -f k8s/deployment.yaml'
}
}
}
post {
success {
echo 'Pipeline executed successfully!'
}
failure {
echo 'Pipeline failed!'
}
}
}
- k8s 多个controller 之间是如何实现 同步的?
两个 Controller 可以同时 watch 同一个资源,但不会“打架”,靠的是:API Server 的 resourceVersion 乐观锁、字段归属(Field Ownership)、以及 Leader Election(全局操作)。
resourceVersion 乐观锁
每个对象有 metadata.resourceVersion
Controller 更新时必须带上最新版本
如果 API Server 发现版本不一致 → 返回 409 Conflict → Controller 重试
意味着同时修改不会覆盖掉别人的改动,而是失败后重试。
- 一个pod 如何保证不被另一个scheduler 调度到?
还是乐观锁
Pod 被调度后会写入 spec.nodeName,只有未绑定的 Pod 才会被 Scheduler 调度,再加上 Leader Election 和 resourceVersion 乐观锁,保证同一个 Pod 不会被多个 Scheduler 分配到不同节点。
- 进程有优先级,如果是你,你如何调度这些进程?底层用什么数据结构来实现?
Linux 调度器用红黑树存储就绪队列,根据每个进程的 vruntime(受静态优先级和运行历史影响)挑选最小的进程执行,实现优先级和公平调度;我会优先保证高实时性任务,同时动态调节低优先级任务,兼顾公平性和响应性。
通过 renice 命令修改对应的 pid 的一个 nice 值
- DHCP 服务器如何保证 ip 不冲突的
DHCP 基于 UDP 协议,客户端通过广播方式发起请求,DHCP 服务器接收后为客户端分配可用 IP,并在内部维护租约表,租约表通常包含 IP、MAC、租约时间和状态等信息。正常情况下 DHCP 不会产生 IP 冲突,问题多出现在客户端异常未释放租约,或同一网段存在多个 DHCP 服务器导致分配冲突。
- k8s 很小的集群,偶尔出现node 节点 not ready,可能是什么原因
Kubernetes 中 Node 变为 NotReady 的根本原因是 kubelet 在一段时间内无法向 apiserver 上报心跳。除节点 CPU、内存、磁盘 IO 等资源压力、网络异常及中间网络设备不稳定外,还可能由于 kubelet 或容器运行时异常、磁盘或 ephemeral-storage 压力、conntrack 等内核资源耗尽、节点时间不同步、CNI 或 kube-proxy 异常,以及控制面组件(apiserver、etcd)性能或状态问题,导致心跳无法被正常发送或处理。
- 如果你要设计一个上千节点的 k8s 集群,你要如何设计
1. 集群架构设计
Master 节点高可用:
部署多副本的 etcd 集群(奇数节点,推荐 3 或 5 个节点)。
API Server、Controller Manager 和 Scheduler 使用多副本部署,结合负载均衡(如 HAProxy 或云厂商的负载均衡器)实现高可用。
使用 Keepalived 或 VIP 提供高可用的 API Server 入口。
Node 节点分组:
按功能划分节点池(如计算节点、存储节点、边缘节点)。
使用 Taints 和 Tolerations 实现工作负载隔离。
为不同的工作负载设置 Affinity 和 Anti-Affinity 策略。
2. etcd 集群设计
独立部署:
将 etcd 从 Kubernetes Master 节点中拆分出来,独立部署。
性能优化:
使用高速 SSD 存储,确保低延迟。
调优 etcd 的 Raft 心跳、选举超时、快照和 WAL 管理。
监控 etcd 的写延迟、磁盘 IO 和节点健康状态。
数据分离:
将高频事件(如 Watch 数据)存储到单独的 etcd 集群,核心数据(如 Pod、Node、CRD)存储在主 etcd 集群。
3. API Server 调优
并发控制:
调整 --max-requests-inflight 和 --max-mutating-requests-inflight 参数,限制并发请求数量。
缓存优化:
启用 Watch Cache 减少对 etcd 的压力。
分页策略:
对大规模资源查询启用分页(--enable-aggregated-discovery)。
安全性:
配置 TLS 加密,启用审计日志。
4. Node 节点优化
系统参数调优:
提高 ulimit 文件句柄限制。
调整 inode 配置,避免文件系统瓶颈。
配置内存大页(HugePages),减少内存碎片。
硬件选择:
使用高性能 CPU、内存、磁盘和网络设备。
配置万兆网卡,减少网络延迟。
Kubelet 配置:
增加资源保留(--kube-reserved 和 --system-reserved)。
限制每个节点的 Pod 数量(--max-pods)。
5. 网络设计
CNI 插件选择:
使用高性能 CNI 插件(如 Calico、Cilium)。
如果使用 Calico,启用 BGP 模式,优化路由性能。
Service 模式:
配置 kube-proxy 使用 IPVS 模式,提升大规模集群的网络性能。
网络隔离:
使用 NetworkPolicy 实现命名空间级别的网络隔离。
6. 存储设计
分布式存储:
使用分布式存储(如 Ceph、GlusterFS)为有状态应用提供持久化存储。
StorageClass:
为不同的工作负载定义多个 StorageClass,支持动态存储分配。
7. 监控与日志
监控:
部署 Prometheus + Grafana 监控集群状态。
使用 kube-state-metrics 和 node-exporter 收集指标。
日志:
部署 ELK 或 Loki 日志系统,采集集群和应用日志。
使用 DaemonSet 部署日志采集器(如 Fluentd 或 Filebeat)。
8. 扩展性与容错
水平扩展:
使用 HPA(Horizontal Pod Autoscaler)和 Cluster Autoscaler 实现自动扩缩容。
容错机制:
定期备份 etcd 数据,确保集群可恢复。
配置 PodDisruptionBudget,避免升级或维护时影响服务可用性。
9. 安全与隔离
RBAC:
配置基于角色的访问控制(RBAC),限制用户权限。
租户隔离:
使用命名空间和 ResourceQuota 实现多租户隔离。
镜像安全:
配置私有镜像仓库,启用镜像签名验证。
10. 测试与演练
压力测试:
使用工具(如 Vegeta、k6)模拟大规模负载,验证集群性能。
故障演练:
定期进行故障注入测试(如 Chaos Mesh),验证集群的容错能力。
通过以上设计,能够确保 Kubernetes 集群在上千节点规模下具备高可用性、可扩展性和稳定性,同时满足生产环境的性能需求。
- calico bgp 网络路由表流程
Pod1 eth0
│
▼
veth peer (Node1)
│
▼
calico0 (Node1)
│
▼
Node1 路由表 (由 BGP 学到 Node2 Pod CIDR 下一跳)
│
▼
物理网络 / L3
│
▼
Node2 路由表 (由 BGP 学到 Node1 Pod CIDR 下一跳)
│
▼
calico0 (Node2)
│
▼
veth peer (Node2)
│
▼
Pod2 eth0
- 如果不想让某个节点再被调度新的 Pod
禁止新 Pod 调度到该节点,但不影响已有 Pod kubectl cordon <node-name>
禁止调度 + 把现有 Pod 赶走 kubectl drain <node-name> --ignore-daemonsets
如果你是 不想让“大部分 Pod”调度上来,但允许“特定 Pod”上来,用 taint。
- k8s 中 coredns 作用,pod 访问的是域名怎么到的后端
Pod 访问域名 → CoreDNS 解析成 Service IP → kube-proxy 把 Service IP 转发到后端 Pod → 请求完成