Q120. 如何配置 Ansible 的清单(inventory)和 SSH 免密登录?

1. 是什么:Ansible 的清单(Inventory) 是一份定义「被管理主机」及其分组、变量、连接参数的清单文件(默认 /etc/ansible/hosts,也常用自定义路径);SSH 免密登录 是通过公私钥认证让控制端无需输入密码即可登录被管主机,是 Ansible 高效批量操作的前提。

2. 为什么用它:Ansible 是无 Agent 架构(通过 SSH 直连),必须先知道管哪些主机、怎么连过去,清单承担「主机清单 + 分组 + 变量」三重职责;SSH 免密避免每次执行要输密码,尤其批量执行上百台时是必需的体验和效率保障。

3. 怎么用它

① 配置 Inventory(支持多种写法)

# /etc/ansible/hosts —— 每行一个主机,用 [] 定义组
[webservers]
192.168.1.11 ansible_user=root
192.168.1.12
web.example.com

[db]
192.168.1.21 ansible_port=2222   # 可指定端口

[all:vars]          # 组通用变量
ansible_python_interpreter=/usr/bin/python3
# 也支持 YAML 格式 inventory:groups/hosts/vars
all:
  hosts:
    mail.example.com:
  children:
    webservers:
      hosts:
        192.168.1.11:
        192.168.1.12:
      vars:
        http_port: 8080
  • 指定清单运行:ansible -i myhosts -m ping webservers;不指定默认 /etc/ansible/hosts

② 配置 SSH 免密(控制端生成密钥 → 拷贝到被管端)

# 1) 生成密钥对(若还没有)
ssh-keygen -t rsa -b 4096        # 一路回车,生成 ~/.ssh/id_rsa(私钥) 和 id_rsa.pub(公钥)

# 2) 将公钥拷贝到目标主机(会提示输入密码一次)
ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.1.11

# 3) 验证免密
ssh root@192.168.1.11   # 无需密码即成功
  • 原理:控制端持有私钥,被管端 ~/.ssh/authorized_keys公钥;登录时服务端用公钥验签,验证通过即放行。
  • 多主机批量可用循环 ssh-copy-id,或用 sshpass -p '密码' 做首次注入(注意安全)。
  • 测试连通:ansible -i hosts all -m ping,返回 pong 即成功。

4. 使用场景:初始化一批新服务器、批量执行命令前准备连接;面试关键:答出「Inventory 三要素(主机/组/变量)」+「ssh-keygen 生成、ssh-copy-id 分发、authorized_keys 存公钥/控制端存私钥」这条完整链路,并说明 Ansible 无 Agent、靠 SSH 的特点。


Q121. 编写一个 playbook 来安装 Nginx 并启动服务。

1. 是什么:Ansible Playbook 是使用 YAML 编写的「一揽子任务清单」,按顺序在目标主机上执行安装、配置、启动等操作;本题要求把「装 Nginx + 启动」落地为一个可重复执行的 playbook(通常还含配置、设置开机自启)。

2. 为什么用它:Playbook 把一次次手动命令固化为幂等、可重复、可版本化的自动化步骤——同一台机器跑多次结果一致、不会反复安装,这正是自动化运维的核心价值,也是 Ansible 比手工 apt install 强的原因。

3. 怎么用它(以 CentOS/RHEL 的 yum 为例,Ubuntu 换成 apt):

---
- name: 安装并启动 Nginx
  hosts: webservers            # 作用于 inventory 里的 webservers 组
  become: yes                  # 提权执行(root)
  tasks:
    - name: 安装 nginx
      ansible.builtin.yum:
        name: nginx
        state: present

    - name: 复制(生成)自定义配置
      ansible.builtin.template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify: 重启 nginx          # 配置变更后触发 handler

    - name: 启动并设置开机自启
      ansible.builtin.systemd:
        name: nginx
        state: started
        enabled: yes

  handlers:
    - name: 重启 nginx
      ansible.builtin.systemd:
        name: nginx
        state: restarted
  • 运行:ansible-playbook -i hosts install_nginx.yml
  • 关键点:模块 ansible.builtin.yum(装包)、template(按模板生成配置)、systemd(管理服务,state: started + enabled: yes 表示启动且开机自启);handlers 在任务"变更"时才触发。
  • 校验:ansible-playbook -i hosts install_nginx.yml --syntax-check;跑完后 curl http://目标IP 验证。

4. 使用场景:批量初始化 Web 服务器、环境标准化、配合 CI/CD 发布。面试关键:能画出 playbook 骨架——hostsbecometasks(装包/配置/启服务)、handlers 触发重启;并点出 systemd 模块同时完成启动与开机自启、notify/handlers 只在配置变更时重启这一最佳实践。


Q122. 如何调试 Ansible 的 playbook?如何提高 Ansible 的执行效率?

1. 是什么调试指在 Playbook 报错或结果不符合预期时定位问题的手段;提效指通过并发、免密码、关闭事实收集等手段缩短批量执行时间,二者是把 Ansible 从「能跑」推向「好用、可维护、大规模可用」的能力。

2. 为什么用它:Playbook 错在哪一步、变量为何没生效、主机为何不通都需要有章法地定位,否则排查靠猜;而管理几十上百台主机时,串行执行或反复收集 Facts 会非常慢,提效手段直接影响运维人效与响应速度。

3. 怎么用它

① 调试手段

# 语法检查(不执行)
ansible-playbook -i hosts play.yml --syntax-check

# 只列出将执行哪些任务,不真正执行(dry-run 预演)
ansible-playbook -i hosts play.yml --check

# 逐步查看每台主机/任务结果,含省略输出
ansible-playbook -i hosts play.yml -v / -vv / -vvv / -vvvv

# 指定只跑某个 play/host / 某个 task
ansible-playbook -i hosts play.yml --limit webservers
ansible-playbook -i hosts play.yml --start-at-task="安装 nginx"

# 任务内打印变量定位
- debug:
    msg: "用户变量是 {{ user }}"
  • 常见调试点:模块参数拼错、变量未定义({{ }} 引号)、become 权限不足、模板路径错误。

② 提效手段

# 1) 关闭不必要的 Facts 收集(Gathering Facts 最耗时)
- name: 提效版
  hosts: all
  gather_facts: no
# 2) 并发控制:fork 并行执行(默认 5)
ansible -i hosts all -f 30 -m ping
ansible-playbook -i hosts play.yml --forks 30

# 3) 开启 SSH pipelining:减少 SSH 连接次数(需在 ansible.cfg 配置)
# [ssh_connection]  pipelining = True

# 4) 用 SSH 长连接 ControlMaster 复用连接
# [ssh_connection]  ssh_args = -o ControlMaster=auto -o ControlPersist=60s

# 5) 缓存 Facts 到内存/文件,跨 play 复用,避免每次重查
# [defaults]  gathering = smart  ; fact_caching = jsonfile ; fact_caching_connection = /tmp/facts_cache
  • 取舍:gather_facts: no 会丢掉节点信息,需按需再开;并发数要结合控制端性能与网络合理设置。

4. 使用场景:Playbook 上线前校验、生产大批量变更、几百台主机批量软件/配置同步。面试关键:调试答「--check 预演 → -vvv 看详细 → --syntax-checkdebug 打变量 + --limit 缩范围」;提效答「gather_facts 关闭 + fork 并发 + pipelining + ControlMaster 复连 + Facts 缓存」这五板斧。


Q123. Metrics(指标)、Sample(样本)、Time Series(时间序列)是什么?

1. 是什么:这三个是 Prometheus 数据模型的三层基本单位——Metrics(指标) 是描述被观测对象某一特性的命名项(如 node_cpu_seconds_total);Sample(样本) 是指标在某一时刻的一个具体测量值(时间戳 + 数值 的二元组);Time Series(时间序列) 是同一指标在同一组标签(labels)下随时间产生的一串样本的序列。

2. 为什么用它:抓一套监控不能只记"当前值",必须能追溯变化趋势、按标签区分不同实例;理解这三个层级才能看懂 PromQL 查询逻辑(按"指标名+标签"选取时间序列、再对序列里的样本做运算),是玩转 Prometheus 的地基。

3. 怎么用它

  • 指标(Metric) = 指标名 + 描述;命名规范通常用"库_对象_单位",如 node_memory_MemAvailable_bytes(字节)。

  • 样本(Sample):存储为 (timestamp, value)。Prometheus HTTP API 返回里体现为 [时间戳, 数值, [标签]]

  • 时间序列(Time Series):由 指标名 + 标签集唯一标识,例如:

    http_requests_total{method="GET", instance="10.0.0.1:9100"}
    http_requests_total{method="POST", instance="10.0.0.1:9100"}
    

    上面两个不同标签组合就是两条不同的时间序列;序列里每个时间点就是一个样本。

  • 本质:Series = Identifier(指标名+labels)+ 一组样本,PromQL 查询就是按"名字+标签"选 Series,再对 Series 内样本做聚合/速率计算。

4. 使用场景:设计 exporter 暴露指标、编写 PromQL、理解 rate() 为什么需要"序列内多个样本"。面试关键:用一个例子串起来——「指标名{标签}= 定位到时间序列,序列上每个时间点有一个样本(ts+value)」;强调标签不同 → 序列不同,这是很多人答不清的关键点。


Q124. 四种指标类型(Counter, Gauge, Histogram, Summary)的区别和用途。

1. 是什么:Prometheus 的指标在数据采集端分为四种类型——Counter(计数器) 只增不减、Gauge(仪表盘) 可增可减、Histogram(直方图) 记录观测值的分布桶、Summary(摘要) 在客户端直接计算分位数——它们适用不同的业务观测需求。

2. 为什么用它:不同被观测量性质不同——请求总量只会增长、当前在线人数会上下波动、请求耗时需要看分布和 P99;类型错了会导致监控语义错误(如对只增计数器做差值),选对类型才能正确表达业务并支撑 PromQL 的计算方式。

3. 怎么用它(对比):

类型特点典型例子PromQL 用法
Counter只增不减,重启会归零请求总数、总字节数、node_cpu_seconds_totalrate() / increase() 算速率/增量
Gauge可增可减,可设任意值当前温度、内存使用量、在线连接数直接取值/avg/maxdelta() 看变化
Histogram记录落入各桶(bucket) 的累计计数请求耗时、响应体大小histogram_quantile(0.99, ...) 算 P99 分位数
Summary客户端预计算分位数并暴露请求耗时(场景要求客户端算)直接用暴露的 _quantile;无 histogram_quantile
  • Histogram vs Summary 取舍:Histogram 在服务端算分位数,可跨实例聚合、标签可选但精确度受桶影响;Summary 在客户端算,分位值精确但不能跨实例聚合。默认生产多选 Histogram
  • 命名约定:Counter 加 _total 后缀(如 _requests_total),Histogram 有 _bucket/_sum/_count 三组指标。

4. 使用场景:设计监控指标、写告警规则(如"QPS 突增"用 counter 的 rate,"内存超 90%"用 gauge,接口 P99 用 histogram)。面试关键:三句话区分——Counter 只会涨、Gauge 会升降、Histogram/Summary 看耗时分布;Histogram 服务端算分位、可聚合,Summary 客户端算、不可聚合,两者核心差异这三点必答。


Q125. PromQL 的基本语法,如何做聚合、筛选、计算?

1. 是什么PromQL(Prometheus Query Language) 是 Prometheus 的查询语言,用「指标名 + 标签匹配」选取时间序列,再对序列做筛选、聚合、数学/函数计算,最终得到仪表盘或告警用的数值。分瞬时查询(Instant,看当前)和区间查询(Range,看一段时间)。

2. 为什么用它:监控值本身意义有限,往往要"算"才有价值——每秒速率、P99 延迟、CPU 使用率、最高/最低等都有现成语法;掌握 PromQL 才能写出正确的监控面板和告警规则,是监控使用的核心技能。

3. 怎么用它

① 筛选(标签匹配)

node_cpu_seconds_total                       # 全部同名序列
node_cpu_seconds_total{cpu="0"}              # 精确匹配(=)
node_cpu_seconds_total{mode!="idle"}         # 不等于(!=)
node_cpu_seconds_total{mode=~"user|system"}  # 正则匹配(=~)
node_memory_*}                                # 名字通配(支持 glob)

② 计算(函数与算术)

# 每秒速率:区间查询必需 rate()
rate(node_cpu_seconds_total{mode="idle"}[5m])
# 增量:一段时间内的增长量
increase(http_requests_total[1h])
# CPU 使用率(用空闲率倒推):
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# 瞬时值运算:内存使用率
(node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes) / node_memory_MemTotal_bytes * 100

③ 聚合(聚合函数 + by/without)

sum(rate(http_requests_total[5m]))                       # 求和(总 QPS)
sum(rate(http_requests_total[5m])) by (method)           # 按标签分组聚合
avg / max / min / count / topk(10, expr)                 # 均值/最大/最小/计数/前N
histogram_quantile(0.99, sum(rate(x_bucket[5m])) by (le)) # 算 P99 分位数
  • 常用聚合函数:sumavgminmaxcounttopk/bottomkcount_values;用 by(标签) 分组、without() 排除分组。
  • 常用函数:rate(Counter 速率,必配区间)、increaseirate(高灵敏度速率)、delta(Gauge 变化)、absroundclamp_max

4. 使用场景:Grafana 面板公式、Prometheus 告警规则(expr 里写 PromQL)、日常排障查询峰值/异常。面试关键:先分清瞬时区间查询(rate/increase 必须用区间 [5m]);再答 "筛选用标签 {},计算用函数+算术,聚合用 sum ... by(标签) 分组"三段式,能现场写一个 CPU 使用率/请求速率表达式即可加分。


Q126. 如何配置 Alertmanager 实现告警的分组、抑制、静默和路由(到钉钉/微信)?

1. 是什么Alertmanager 是 Prometheus 生态中负责处理告警的组件——接收 Prometheus 推送的告警,通过路由(route)、分组(group)、抑制(inhibit)、静默(silence) 四条机制整理后,再通过接收器(Webhook/钉钉/企业微信等)发送出去,避免告警风暴、减少重复打扰。

2. 为什么用它:直接让 Prometheus 推所有告警会"告警轰炸",同一个故障往往触发几十条告警淹没真正的问题;Alertmanager 的四种机制把海量告警收敛成"一条有代表性的通知 + 去重去抑制",实际运维中几乎必不可少的降噪层。

3. 怎么用它alertmanager.yml):

route:
  group_by: ['alertname']          # 按告警名分组(同类合并)
  group_wait: 30s                  # 组首告警后等 30s 再发,给后续合并留时间
  group_interval: 5m               # 已有组再触发时的发送间隔
  repeat_interval: 4h              # 未被确认的告警重复提醒间隔
  receiver: 'dingtalk'
  routes:                          # 更细的子路由
    - matchers: [ 'severity="critical"' ]
      receiver: 'wechat'
      continue: false

# 抑制:当某告警存在时,抑制另一些告警
inhibit_rules:
  - source_matchers: ['severity="critical"']
    target_matchers: ['severity="warning"']
    equal: ['alertname', 'instance']   # 同告警名同实例时,critical 抑制 warning

receivers:
  - name: 'dingtalk'
    webhook_configs:
      - url: 'https://oapi.dingtalk.com/robot/send?access_token=xxx'
        send_resolved: true
  - name: 'wechat'
    wechat_configs:
      - api_url: 'https://qyapi.weixin.qq.com/cgi-bin/'
        corp_id: '企业ID'
        agent_id: '应用ID'
        api_secret: '密钥'
        to_party: '部门ID'
  • 四个机制一句话
    • 分组(grouping):相同/相关告警合并成一条通知,减少轰炸;
    • 抑制(inhibition):较高层级(如 Critical)告警存在时,抑制相关低层级(Warning)告警;
    • 静默(silence):管理员手动屏蔽某类告警一段时间(如维护窗口),用 amtool silence add 或 Web UI;
    • 路由(routing):按 matcher 把不同告警发到不同接收器(钉钉/微信/邮件/值班组)。
  • 关联配置:Prometheus 侧 alertmanager: static_configs: - targets 把告警推到 Alertmanager;接收器里 Webhook 是通用通道,接入钉钉机器人/企业微信机器人通常都用 webhook_configs 或官方邮件/微信配置。

4. 使用场景:告警风暴降噪、不同严重级别/团队分级告警、大促护维护窗口静默。面试关键:四个机制逐个讲清含义+例子——分组按 group_by、抑制 inhibit_rules、静默维护窗口、路由按 matcher 分发到钉钉/微信;并给一个 Webhook→钉钉机器人的最小配置。


Q127. 如何用 Recording Rules 提升查询性能?

1. 是什么Recording Rules(预计算规则) 是 Prometheus 的一种预计算机制——把频繁执行、且计算量大的复杂 PromQL,按固定周期(默认 1m)提前算出结果存成新指标,查询时直接读这个"现成指标",而不是实时去扫原始时间序列

2. 为什么用它:仪表盘里反复查询同一个昂贵表达式(如跨多实例的 rate()+sum+by),每次都让 Prometheus 临时重算,会拖慢面板渲染、增加 CPU 负担并可能超时;预计算把 "重活"分摊为固定周期做一次,让查询即时返回,是 Grafana 大面板和超大规模采集时的标配优化。

3. 怎么用它rules/recording.yml):

groups:
  - name: recording_cpu
    rules:
      # 每条 SQL 预计算结果存为 job:xxx 新指标
      - record: job:cpu_usage:rate5m
        expr: |
          100 - (avg by (instance)(irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
      - record: job:http_requests:rate5m
        expr: |
          sum(rate(http_requests_total[5m])) by (job, method)
  • 命名约定:<level>:<metric>:<operation>,如 job:cpu_usage:rate5m,方便溯源。
  • 加载方式:在 Prometheus 配置 rule_files: - "rules/*.yml",重载 Prometheus(curl -X POST http://localhost:9090/-/reload 或重启)。
  • Prometheus -> Status -> Rules 查看规则执行状态;规则名以 __ 开头的也可用于告警。
  • 结合 Alerting Rules(告警规则):告警规则的 expr 有时也引用 recording rule 的指标,进一步减负。

4. 使用场景:Grafana 大看板、QPS/延迟等高频查询、成百上千实例的聚合查询优化。面试关键:一句话——“把高频、昂贵的表达式按周期预计算成新指标存起来,查询直接读结果”;并讲清命名规范 job:metric:操作 和 “只在查询确实慢/频繁时才用,别过度预计算淹没磁盘” 这个取舍。


Q128. 简述 Kubernetes 的架构(Master 和 Node 组件及其功能)。

1. 是什么:Kubernetes(K8s)采用 控制平面(Master/Control Plane)+ 工作节点(Worker Node) 主从架构,控制面负责"决策与调度",工作节点负责"真正运行容器";两类组件分别承担不同的管理职责。

2. 为什么用它:把"集群大脑"(决策:调度、控制循环、API)与"日常劳动力"(执行:跑 Pod、转发流量)分离,使集群可水平扩展、高可用、故障自愈,这是理解"Pod 为何能在某台节点上跑起来"的关键。

3. 怎么用它(组件与功能):

控制平面(Master)组件

组件功能
kube-apiserver集群唯一的 API 入口,所有交互(kubectl/各个组件)都经它,负责认证、授权、校验、状态存储
etcd分布式键值存储,保存集群全部状态数据(“集群的数据库”)
kube-scheduler调度器:决定新 Pod 调度到哪台节点(考虑资源/亲和/污点)
kube-controller-manager运行各类控制器(Node/Deployment/ReplicaSet…),维持期望状态
cloud-controller-manager(可选)对接云厂商(LB/存储/节点管理)

工作节点(Node)组件

组件功能
kubelet节点上的"小管家",负责拉镜像、起停容器、汇报状态、执行探针
kube-proxy维护 iptables/IPVS 规则,实现 Service 的负载均衡与转发
容器运行时containerd / CRI-O / Docker,真正创建运行容器的引擎
  • 数据流一句话:kubectlapiserver(校验+写入 etcd)→ scheduler 选节点 → 该节点 kubelet 拉镜像起容器 → controller-manager 不断检查让实际状态收敛回期望状态。

4. 使用场景:K8s 集群部署与排障(如 pod 调度异常查 scheduler、"control plane 组件负载"查 apiserver/etcd)。面试关键:控制面答齐 apiserver/etcd/scheduler/controller-manager 四大件,节点答 kubelet + kube-proxy + 运行时;并点出 “apiserver 是唯一入口、etcd 存状态” 这两个记忆锚点,能画出主从结构与数据流更佳。


Q129. Pod, Deployment, Service, Ingress 的概念和关系。

1. 是什么:这是 K8s 里最容易混的四个资源,它们分属不同层级:Pod(最小运行单元)、Deployment(管理无状态工作负载)、Service(Pod 的稳定访问抽象)、Ingress(集群入口的七层路由)。关系一句话:Deployment 管 Pod,Service 暴露 Pod,Ingress 路由到 Service

2. 为什么用它:K8s 里"一个应用能稳定对外访问"是四层协同的结果——没有它们各自的分工,就无法实现"Pod 随便换,但访问入口和路由却一直稳定"这一 K8s 的核心价值,因此这四个概念必须整体理解而非孤立背诵。

3. 怎么用它(逐个 + 关系链):

  • Pod:一个或多个共享网络/存储的容器集合,K8s 的最小调度单位;Pod IP 会随重建变化,不稳定。

  • Deployment声明式管理一组 Pod 副本,负责滚动更新、回滚、扩缩容、故障自愈;它创建并管理实现副本的 ReplicaSet

  • Service:为一组 Pod(靠 selector 标签选中)提供一个稳定访问入口 + 负载均衡;Pod IP 漂移没关系,Service 的 ClusterIP/域名不变。

  • Ingress:在 Service 之上的七层(HTTP/HTTPS)统一入口按域名/路径把外部请求路由到不同 Service,还带 TLS 证书、路径重写能力。

  • 关系链(对外访问流程):

    客户端 --HTTP--> Ingress(按域名/路径路由) --> Service(选中一组的Pod做LB) --> Pod(真正的容器)
    Deployment 负责这些 Pod 的副本数/更新/自愈
    
  • 没有 Ingress 也能用:小规模可直接用 NodePort/LoadBalancer 类型 Service 暴露,Ingress 是"更灵活的集中入口"选项。

  • 流量走向记忆Ingress -> Service -> (Endpoints -> Pod 的容器端口)

4. 使用场景:设计一个 Web 服务在 K8s 的对外暴露方案、排障"能进集群但访问不到 Pod"(依次查 Ingress 路由、Service selector、Pod 就绪探针)。面试关键:先逐个定义再给关系链,**背熟"Deployment 管 Pod、Service 暴露 Pod、Ingress 路由 Service"**这句话;能画出 Ingress→Service→Pod 的流量图,并补充 Deployment 在下层负责副本与自愈即为完整。


Q130. ReplicaSet 和 Deployment 的区别。

1. 是什么ReplicaSet(RS) 是保证指定数量 Pod 副本持续运行的控制器;Deployment更上层的控制器,它在内部管理 ReplicaSet,并提供高级、无损的部署能力(滚动更新、回滚、扩缩容、暂停/恢复)。两者不是并列而是"套娃"关系。

2. 为什么用它:只靠 ReplicaSet 只能保证"有 N 个副本",但版本升级时无法做到平滑(既要有旧又要逐步上新);Deployment 在其上封装了滚动更新/回滚等编排策略,让"变更版本"变成可控、可回退的过程,这是生产发布必需的能力。

3. 怎么用它(对比):

维度ReplicaSetDeployment
职责维持 Pod 副本数量管理 RS + 提供发布/回滚能力
是否直接操作 Pod是(selector + template 造副本)否(通过其下的 RS 间接管理)
更新方式替换整个 RS 或手动滚动更新(RollingUpdate) 渐进替换
回滚无原生回滚支持 kubectl rollout undo 回滚到历史版本
更新历史不保留保存 revision 历史,可查看/回退
典型使用极少直接使用日常部署首选
  • 归档与选择:Deployment 每次更新会创建一个新 RS(旧 RS 缩到 0 但保留供回滚),所以 kubectl get rs 常看到多个历史的 RS。
  • 使用示例:
kubectl set image deployment/myapp myapp=myapp:v2     # 触发滚动更新
kubectl rollout status deployment/myapp                # 查看更新进度
kubectl rollout undo deployment/myapp                  # 回滚到上一版
  • 还有 HPA(水平自动扩缩)也是基于 Deployment/RS 的副本数来伸缩,进一步体现 RS 是"副本量的底层实现"。

4. 使用场景:日常发布(Deployment)、需要按版本无损更新/回滚时;面试关键:一句话**“ReplicaSet 保证副本数量、Deployment 管理 ReplicaSet 并提供滚动更新与回滚”;强调二者是包含关系(外层套里层)**而非对等,并点出每次更新会新建 RS 保留历史以便回滚。


Q131. Service 的类型(ClusterIP, NodePort, LoadBalancer)及其使用场景。

1. 是什么Service 是 K8s 给一组 Pod 提供的稳定访问抽象,按是否需要对外暴露、暴露到哪一层,分为 ClusterIP、NodePort、LoadBalancer(还有 Headless),不同 type 决定访问入口和暴露范围。

2. 为什么用它:Pod IP 不稳定、数量会变,Service 用标签 selector 稳定暴露这组 Pod;但对"内部调用"、“单节点端口暴露”、"云负载均衡"三种诉求各不相同,所以要按场景选 type——选错要么暴露过大、要么访问不到。

3. 怎么用它(类型对比):

类型访问方式暴露范围使用场景
ClusterIP(默认)集群内虚拟 IP + 域名,svc名.命名空间集群内部服务间相互调用(如网关调后端服务)
NodePort每个节点开放一个端口(30000~32767),节点IP:端口集群外部(但限端口且依赖节点可达)测试、无 LB 环境对外暴露
LoadBalancer自动创建云负载均衡器(阿里云 SLB),分配公网 IP公网生产对外服务,交给云 LB 高可用
# ClusterIP(默认,内部调用)
apiVersion: v1
kind: Service
metadata:
  name: backend-svc
spec:
  selector:
    app: backend          # 选中 backend 的 Pod
  ports:
    - port: 80
      targetPort: 8080    # 转发到 Pod 的 8080

# NodePort:多一行 type 即可
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 8080
      nodePort: 32080     # 可显式指定,也可自动分配

# LoadBalancer:云厂商自动建 LB + 公网IP(底层仍走 NodePort)
spec:
  type: LoadBalancer
  • 关系:ClusterIP < NodePort < LoadBalancer(NodePort 在 ClusterIP 之上开节点端口,LoadBalancer 又在 NodePort 之上绑云 LB),生产公网入口常在它们之上再套 Ingress 做域名/路径路由。
  • 对应云场景(阿里云/腾讯云/AWS):LoadBalancer 会自动拉起 SLB/CLB/ELB,并可用 Annotations 配置带宽、证书等。

4. 使用场景:服务间内部通信用 ClusterIP、没有云 LB 的裸机/测试环境用 NodePort、生产公网服务用 LoadBalancer(再加 Ingress)。面试关键:一个递进记忆——“ClusterIP 对内 → NodePort 在每节点开端口对外 → LoadBalancer 在云上建 LB+公网IP”,并答出默认 ClusterIP、NodePort 端口范围 30000-32767、LoadBalancer 底层依赖 NodePort 这三点;能补充"公网入口常用 Ingress"更完整。

Q132. ConfigMap 和 Secret 的作用和区别?

1. 是什么ConfigMap 用于存储非敏感的配置数据(环境变量、配置文件内容);Secret 用于存储敏感信息(密码、Token、证书、私钥),二者都是把"配置/凭据"从镜像或 Pod 定义中解耦出来的 API 对象,可通过环境变量挂载文件/卷的方式注入到 Pod。

2. 为什么用它:把配置和业务代码/镜像分离,同一镜像可复用不同配置(开发/测试/生产);敏感信息不写死在镜像、不用明文环境变量,而是集中管理并加密存储,避免泄露;两者都能让配置变更无需重新构建镜像。

3. 怎么用它(对比):

对比项ConfigMapSecret
存储内容普通配置(明文)敏感信息(密码/证书)
存储编码明文Base64(再可叠加加密如 sops/KMS)
常见用途环境变量、配置文件密码、API Key、TLS 证书、镜像仓库凭据
注入方式env / envFrom / volume 挂载同左(三种方式皆可)
# ConfigMap:普通配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:                          # 用 data 存明文
  MYSQL_HOST: "10.0.0.5"
  LOG_LEVEL: "INFO"
  app.yaml: |                 # 多行文件内容
    server:
      port: 8080
---
# Secret:敏感信息(值需 Base64 编码)
apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
data:                          # 用 data 必须 Base64
  password: MTIzNDU2           # echo -n "123456" | base64
stringData:                    # 或用 stringData 写明文,apply 时自动编码
  username: admin

Pod 引用示例

spec:
  containers:
  - name: app
    envFrom:
    - configMapRef: { name: app-config }
    - secretRef: { name: db-secret }
    env:
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef: { name: db-secret, key: password }
    volumeMounts:
    - name: cfg
      mountPath: /etc/config
  volumes:
  - name: cfg
    configMap: { name: app-config }     # 也可以改 secret 同名挂载

4. 使用场景:应用分层配置、数据库密码/钱包私钥管理、TLS 证书注入、镜像拉取凭据(imagePullSecrets)。面试关键:一句话"ConfigMap 存明文配置、Secret 存敏感凭据,Secret 值用 Base64 编码(且生产应再加密)";并说明两者都通过 env 或 volume 注入、都用于把配置与镜像解耦。


Q133. kube-proxy 的 iptables 和 ipvs 模式原理区别?

1. 是什么kube-proxy 是运行在每个节点上的网络代理,负责实现 Service(ClusterIP、NodePort)的负载均衡与规则维护。它有两种主要实现模式:iptables(默认)和 IPVS,核心都是把访问 Service 的流量转发到后端 Pod。

2. 为什么用它:Service 的 ClusterIP 是虚拟 IP,必须由节点上某种机制把访问它的流量"重定向"到实际 Pod 上。iptables 基于内核包过滤实现;IPVS 基于内核 LVS/IPVS 体系、更专业。理解二者区别直接关系到大规模集群的网络性能与规则复杂度。

3. 怎么用它(对比):

对比项iptablesipvs
转发原理每新增一条 Service 生成大量 iptables 规则链,逐条匹配在内核生成 ipvs 服务与后端列表,hash 查找
性能匹配链多,规模大时延迟高、性能差O(1) hash 查找,延迟低、吞吐高
支持算法仅随机rr/lc/wrr/sh/dh 等多种调度算法
规则数量Service 多时规则爆炸规则紧凑(一条 service 对应一份后端表)
是否支持会话保持支持(source-hash 等)
特性通用、简单、兼容性好高级、高效,但对内核 ipvs 支持有要求
K8s 默认默认(kube-proxy --proxy-mode=iptables)手动开启 --proxy-mode=ipvs
# 查看 kube-proxy 用什么模式
kubectl get pod -n kube-system -l k8s-app=kube-proxy -o wide
# 或用 curl 访问节点上 kube-proxy 的 metrics 查看
# 更直接:hostPath 里 kube-proxy 的启动参数含 --proxy-mode
# 切换 ipvs:编辑 kube-proxy ConfigMap,将 mode 改为 ipvs
kubectl -n kube-system edit configmap kube-proxy
#   mode: "ipvs"     # 原来是 iptables/空
kubectl -n kube-system rollout restart daemonset kube-proxy

4. 使用场景:大规模集群(万级 Service/Pod)或对延迟敏感时用 ipvs;中小集群用默认 iptables 即可。面试关键:一句话"iptables 用规则链逐条匹配、规模大时慢;ipvs 用内核 hash 查找、O(1) 更快且支持多种调度算法与会话保持,适合大规模集群";并知道修改 kube-proxy 的 mode 字段切换。


Q134. kube-scheduler 的调度流程和常用预选/优选策略?

1. 是什么kube-scheduler 是控制平面负责调度新 Pod 到合适节点的组件。它把"待调度 Pod"与"集群候选节点"做匹配,经过**预选(Filter/Predicate)→ 优选(Score/Priority)→ 绑定(Bind)**三个阶段,选出最合适的一个节点。

2. 为什么用它:Pod 不能随便乱放——要考虑资源是否够用、亲和/反亲和、污点/容忍、跨区高可用等约束。scheduler 用一组可插拔的调度框架/策略,确保每个 Pod 被调度到既满足约束、又尽量合理的节点,是集群资源合理利用和稳定的关键。

3. 怎么用它(调度流程三步):

  • ① 预选(Filtering/Predicate):从所有节点中筛选出"能容纳该 Pod"的节点(不满足即淘汰)。常用预选:
    • PodFitsResources:节点剩余资源是否满足 requests。
    • PodFitsHostPorts:端口是否冲突。
    • NodeSelector/NodeAffinity:是否满足节点选择/亲和。
    • TaintToleration:是否容忍节点污点。
    • CheckNodeUnschedulable:节点是否可调度。
  • ② 优选(Scoring/Priority):对候选节点打分,分数高者优先。常用优选:
    • LeastRequested:优先调度到已用资源占比低(剩余多)的节点。
    • BalancedResourceAllocation:优先让 CPU/内存均衡。
    • NodeAffinityPriority:满足亲和加分。
    • ImageLocalityPriority:节点已有所需镜像优先。
  • ③ 绑定(Bind):把 Pod 绑定到得分最高的节点,写回 nodeName,该节点 kubelet 再拉镜像启动。
# 查看调度器调度失败的 Pod(Pending 常因无节点可调度)
kubectl describe pod <pod-name> | grep -A5 Events

# 手动查看节点可用资源
kubectl describe node <node-name> | grep -A5 "Allocatable"

# 查看调度器日志(在 Master)
journalctl -u kube-scheduler -f

# 手动指定调度到某节点(简单做法)
# 在 Pod spec 中加 nodeName / nodeSelector

4. 使用场景:排查 Pod Pending(无合适节点)、做资源均衡、实现亲和/反亲和(如让有状态服务分散到不同节点)。面试关键:背出"预选(过滤)→ 优选(打分)→ 绑定"三步;预选讲 2~3 个(资源、亲和、污点容忍)、优选讲 2~3 个(最空闲、均衡、镜像本地优先);并说明 Pending 通常是预选没通过(资源不够/污点不匹配)。


Q135. 描述 Pod 的生命周期和重启策略?

1. 是什么Pod 生命周期指 Pod 从创建到结束经历的状态集合(Pending、Running、Succeeded、Failed、Unknown),以及容器内的启动钩子、探针、终止钩子等阶段;重启策略(restartPolicy) 决定容器退出后 kubelet 是否重启它。

2. 为什么用它:理解生命周期才能解释"为什么 Pod 会重启/为什么会 Failed/为什么容器启动前有初始化";重启策略决定了故障容器的行为(一直重启还是停止),直接影响服务的可用性与人为干预时机。

3. 怎么用它(生命周期状态 + 阶段):

  • Pod 状态机(kubectl get pod 的 STATUS 列)
    • Pending:已创建但还没调度到节点(或镜像拉取中)。
    • Running:Pod 已被调度,容器已启动/运行中。
    • Succeeded:所有容器正常退出(不重启)。
    • Failed:所有容器异常退出(某个容器以非 0 退出)。
    • Unknown:节点失联,无法获取 Pod 状态。
  • 容器阶段(kubectl get pod -o jsonpath='{.status.containerStatuses}'WaitingRunningTerminated
  • 生命周期钩子/探针
    • postStart(容器启动后执行)、preStop(容器终止前执行)。
    • 三种探针:startupProbe(启动)、livenessProbe(存活)、readinessProbe(就绪)。
  • 重启策略 restartPolicy(Pod 级字段):
    • Always(默认):无论退出码如何,总是重启。
    • OnFailure:仅当容器以非 0 退出才重启(适合 job)。
    • Never:不重启(适合一次性 job)。
  • 注意:DaemonSet/Deployment 等控制的 Pod 通常 Always;Job/CronJob 用 OnFailure/Never
spec:
  restartPolicy: Always        # Always / OnFailure / Never
  containers:
  - name: app
    image: nginx
    lifecycle:
      postStart:
        exec: { command: ["/bin/sh","-c","echo start >> /tmp/log"] }
      preStop:
        exec: { command: ["/bin/sh","-c","echo stop >> /tmp/log"] }

4. 使用场景:排查 CrashLoopBackOff(Always 重启但反复崩溃)、服务发布/下线时的优雅终止(preStop 做清理)、区分 Job 与 Deployment 的重启行为。面试关键:说出 5 个状态 + 3 种重启策略;重点强调 CrashLoopBackOffrestartPolicy: Always 下容器反复崩溃的结果,以及 liveness/readiness 探针在生命周期中承担"存活/就绪"判断。


Q136. 如何编写一个 Deployment 和 Service 的 YAML 文件?

1. 是什么:用 YAML 定义一个 Deployment(管理工作负载、Deployment 副本数、滚动更新)和一个 Service(为这些 Pod 提供稳定访问入口)。这是 K8s 里最常用、必须手写的两个清单文件。

2. 为什么用它:K8s 是声明式的,用 YAML 描述"期望状态"再 kubectl apply 是标准用法;掌握 Deployment+Service 的写法,才能把应用(尤其 Web 服务)以容器化方式在集群内部署和暴露。

3. 怎么用它(模板示例,Deployment + Service 一体):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  labels: { app: my-app }
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:                  # Pod 模板
    metadata:
      labels:
        app: my-app          # 与 selector 匹配
    spec:
      containers:
      - name: my-app
        image: nginx:1.23
        ports:
        - containerPort: 80
        resources:
          requests: { cpu: "100m", memory: "128Mi" }
          limits:   { cpu: "500m", memory: "512Mi" }
---
apiVersion: v1
kind: Service
metadata:
  name: my-app-svc
spec:
  type: ClusterIP             # 可选 ClusterIP / NodePort / LoadBalancer
  selector:
    app: my-app               # 选中与 Deployment 相同的 Pod
  ports:
  - port: 80                  # Service 端口
    targetPort: 80            # 转发到 Pod 的容器端口(可写名字)
    protocol: TCP

关键点

  • selector 一致性:Service 的 selector 标签必须与 Deployment 的 template.metadata.labels(及 selector.matchLabels匹配,否则 Service 选不到 Pod。
  • 若用 NodePort,可在 ports 里加 nodePort: 32080(30000-32767)。
  • 若想 kubectl expose 自动生成,可用 kubectl expose deployment my-app --port=80 --target-port=80
# 应用 / 查看 / 删除
kubectl apply -f deploy.yaml
kubectl get deployment,service,pod -o wide
kubectl delete -f deploy.yaml

4. 使用场景:任何 Web/后端服务的标准部署;面试关键:背出 Deployment 的五大结构replicasselector.matchLabelstemplate.metadata.labelscontainersimage/ports)和 Service 的三大要素(typeselectorports),并强调"selector 标签匹配"这一最容易出错的点。


Q137. 如何实现应用的滚动更新和回滚?

1. 是什么滚动更新(Rolling Update) 是 Deployment 默认的升级策略——分批、渐进地用新版本 Pod 替换旧版本 Pod,过程中服务不中断;回滚(Rollback) 是把集群状态恢复到上一个(或某个历史)版本。二者都由 Deployment 的 strategyrevisionHistoryLimit 控制。

2. 为什么用它:直接删掉所有旧 Pod 再上新会瞬间"全断";滚动更新保证更新期间始终有可用副本、零/低停机;一旦新版本出问题,快速回滚到旧版能最大限度降低线上事故影响——这是生产发布的标配能力。

3. 怎么用它(配置 + 命令):

配置策略

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1       # 更新中最多可"不可用"的副本数(0~100%)
      maxSurge: 1             # 更新中最多可"超出期望副本数"的额外新副本
  revisionHistoryLimit: 10    # 保留多少个历史版本供回滚

触发滚动更新

kubectl set image deployment/my-app my-app=my-app:v2     # 改镜像触发
# 或 edit / apply 修改 YAML

查看进度

kubectl rollout status deployment/my-app                  # 查看 rollout 进度
kubectl rollout history deployment/my-app                 # 查看历史版本

回滚

kubectl rollout undo deployment/my-app                    # 回滚到上一个版本
kubectl rollout undo deployment/my-app --to-revision=2    # 回滚到指定版本

常见问题排查

  • 新版本起不来(镜像错/健康检查失败)→ rollout 会卡住,用 kubectl rollout history + kubectl describe pod 定位。
  • 想让"滚动更新"生效,要求 Deployment 带就绪探针(readinessProbe),否则新 Pod 即便就绪也影响切换时机。

4. 使用场景:线上发布、灰度渐进、故障快速回滚。面试关键:一句话"滚动更新用 maxUnavailable/maxSurge 控制分批替换、过程不断服;回滚用 rollout undo";并强调"新版起不来时 rollout 会暂停,需先看历史与 Pod 状态再决定回滚"。


Q138. 如何配置 Pod 的资源请求(requests)和限制(limits)?

1. 是什么requests(请求) 是 Pod 容器最少需要的资源量(调度时就按它预留);limits(限制) 是容器最多可用的资源量(超出会被限制/终止)。两者都针对 CPU 和内存,通过 resources 字段声明。

2. 为什么用它:不设 requests 会让调度器把 Pod 塞到资源不足的节点导致运行劣化;不设 limits 会让单个容器"吃爆"节点资源拖垮整台机器(内存尤其危险)。正确配置 requests/limits 是资源合理调度避免 OOM/CPU 争抢的关键。

3. 怎么用它

spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:                # 调度依据(下限)
        cpu: "250m"            # 250 毫核 = 0.25 CPU
        memory: "256Mi"        # 256 MiB
      limits:                  # 运行上限
        cpu: "1"               # 最多 1 核
        memory: "512Mi"        # 最多 512 MiB

关键点

  • 单位:CPU 用 m(milli,1 CPU = 1000m);内存用 Mi/Gi/M(Mi 是 MiB,M 是 MB)。
  • limits ≥ requests(通常 requests 设 60%~80% 的 limits 更合理)。
  • 调度与限制关系
    • 调度只依据 requests(预留)。
    • 运行超 limits CPU:被限流(throttle),不终止。
    • 运行超 limits 内存:容器被 OOMKill(内存超限会被杀掉,这是大坑)。
  • LimitRange / ResourceQuota:可对命名空间统一设置默认 requests/limits 和配额。
# 查看节点/命名空间资源
kubectl describe node <node> | grep -A5 "Allocatable"
kubectl get pod -n <ns> -o custom-columns=NAME:.metadata.name,CPU_REQ:.spec.containers[0].resources.requests.cpu,MEM_REQ:.spec.containers[0].resources.requests.memory

4. 使用场景:生产所有容器都宜配 requests/limits;排查 OOMKilled、节点资源被打满、批量 Pod 争抢 CPU。面试关键:点出"requests 是调度预留、limits 是运行上限";强调"CPU 超限只限流、内存超限杀容器",并说清单位与"limits 必须 ≥ requests"。


Q139. 如何配置 livenessProbe 和 readinessProbe?它们有何区别?

1. 是什么:两者都是 Kubernetes 探针,由 kubelet 周期性探测容器。livenessProbe(存活探针) 判断容器是否需要重启readinessProbe(就绪探针) 判断容器是否能接收流量

2. 为什么用它:光靠"容器进程在"不能代表"应用可用"。liveness 解决"卡死/假死但进程还在"的场景(自动重启恢复);readiness 解决"新 Pod 起来但还没准备好"的场景(先不被调度流量,避免 502)。二者让集群具备自愈和优雅上线能力。

3. 怎么用它(三种探测方式 + 区别):

spec:
  containers:
  - name: app
    image: myapp
    livenessProbe:              # 存活:失败则重启容器
      httpGet:
        path: /health
        port: 8080
      initialDelaySeconds: 10   # 启动后等 10s 再探测
      periodSeconds: 10         # 每 10s 探测一次
      timeoutSeconds: 3         # 单次超时 3s
      failureThreshold: 3       # 连续失败 3 次判定失败
    readinessProbe:             # 就绪:失败则从 Service 摘除
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5
      periodSeconds: 5

三种探测方式

  • httpGet:访问 HTTP 接口,2xx/3xx 视为健康。
  • tcpSocket:能否建立 TCP 连接。
  • exec:执行命令,退出码 0 视为健康。

区别(必答维度)

对比livenessProbereadinessProbe
判断什么容器存活(活没活)容器就绪(能不能接流量)
失败后果重启容器(Kill 后重建)从 Service Endpoint 剔除(不转发流量,不重启)
阶段整个运行期整阶段(含滚动更新时控制切换)
典型场景应用死循环/假死自动恢复应用启动慢、"预热"完成前不接流量

补充:还有 startupProbe(启动探针),用来保护启动慢的应用,避免它们被 liveness 误杀——启动成功前只运行 startupProbe,成功后才交还给 liveness/readiness。若配置了 startupProbe,建议把 liveness 的 failureThreshold 设大(如 30),防止启动慢被重启。

4. 使用场景:所有无状态服务建议配 readiness;关键业务配 liveness。面试关键:三句话——“liveness 失败重启容器、readiness 失败摘出流量、startupProbe 保护慢启动”;并用"重启 vs 摘流量"来区分 liveness 和 readiness 的核心差异。


Q140. 如何实现 Pod 的数据持久化?

1. 是什么:Pod 默认的容器文件系统是临时的,容器重启/重建后数据丢失;数据持久化 通过 Volume(卷) 把数据存储到 Pod 外的位置,Pod 重建数据仍在。常用类型有 emptyDirhostPathPersistentVolume(PV)+PersistentVolumeClaim(PVC)ConfigMap/Secret 挂载等。

2. 为什么用它:数据库、日志、配置文件等数据不能随容器销毁而丢失;有状态应用(DB、Redis、MQ)必须有持久存储。Volume 把"数据"与"容器生命周期"解耦,是 StatefulSet/有状态服务的基础。

3. 怎么用它(常用卷类型):

① emptyDir(临时,Pod 内共享)

spec:
  containers:
  - name: app
    volumeMounts:
    - { name: cache, mountPath: /data }
  volumes:
  - name: cache
    emptyDir: {}              # Pod 删除即清空,仅用于容器间共享临时数据

② hostPath(宿主机目录)

volumes:
- name: log
  hostPath: { path: /var/log/myapp }   # 挂到宿主机(有安全隐患,慎用)

③ PV + PVC(推荐,真正持久化 + 动态供给)

# PVC:声明需要什么存储
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data-pvc
spec:
  accessModes: [ReadWriteOnce]
  resources: { requests: { storage: 5Gi } }
---
apiVersion: v1
kind: Pod
spec:
  volumes:
  - name: data
    persistentVolumeClaim: { claimName: data-pvc }
  containers:
  - name: app
    volumeMounts:
    - { name: data, mountPath: /var/lib/mysql }

关键概念

  • PV:集群里真正的一块存储(静态 PV 或由 StorageClass 动态供给)。
  • PVC:用户"申请"存储的请求,绑定到 PV。
  • StorageClass:让存储动态供给(云盘/NFS/本地),省去手动建 PV。
  • StatefulSet:配合有状态应用,每个 Pod 有独立稳定的 PVC(如 db-0db-1 各自绑定一块卷)。
# 查看存储资源
kubectl get pv, pvc, storageclass

4. 使用场景:数据库/中间件(MySQL、Redis、ES)持久化、日志留存、有状态应用(StatefulSet)。面试关键:分层回答——临时共享用 emptyDir、单机用 hostPath、生产持久化用 PV/PVC(可加 StorageClass 动态供给);并指出"裸 containers 无卷则数据随 Pod 消失,StatefulSet 才能给每个 Pod 绑定独立稳定卷"。


Q141. 如何配置 Horizontal Pod Autoscaler (HPA)?

1. 是什么HPA(Horizontal Pod Autoscaler) 是 K8s 的水平自动扩缩容控制器——根据资源指标(如 CPU 使用率、内存,或自定义指标)或外部指标,自动增减 Deployment / StatefulSet 的副本数,实现"负载升高自动加 Pod、负载降低自动减 Pod"。

2. 为什么用它:手动扩缩容滞后且费人力;HPA 让副本数随实际负载动态伸缩,既保证高峰不被打垮,又避免低谷资源浪费,是弹性伸缩(尤其与 K8s 云环境结合)的核心能力。

3. 怎么用它(前提 + 配置):

前提:集群需安装 metrics-server(采集节点与 Pod 指标),否则 HPA 拿不到 CPU/内存数据。

# 安装 metrics-server(如未装)
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# 验证指标可用
kubectl top pod

创建 HPA

# 基于 CPU 自动伸缩(最常见),targets 语法(新版)
kubectl autoscale deployment my-app --cpu-percent=80 --min=2 --max=10
# 或写 YAML
cat <<EOF | kubectl apply -f -
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: my-app-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: my-app
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80   # 目标 CPU 平均使用率 80%
  behavior:                       # 可选:更精细的伸缩行为
    scaleUp:
      stabilizationWindowSeconds: 30
    scaleDown:
      stabilizationWindowSeconds: 300
EOF

源码要求(关键):HPA 基于 CPU 自动伸缩时,Deployment 的容器必须已配置 resources.requests.cpu(否则 HPA 无法计算"利用率",因为分母是 requests 而不是 limits)。

# 容器必须配 requests.cpu,HPA 才有分母
resources:
  requests: { cpu: "250m", memory: "256Mi" }
  limits:   { cpu: "500m", memory: "512Mi" }

查看 HPA 状态

kubectl get hpa
kubectl describe hpa my-app-hpa

4. 使用场景:Web 服务、API 网关等流量波动大的无状态应用弹性伸缩。面试关键:前提提醒——“要在集群装 metrics-server,且容器必须配 requests.cpu(否则 HPA 算不出利用率)”;并说清 HPA 只调节副本数(水平),垂直(调资源大小)是 VPA。让 Pod 数随 CPU 负载自动增减。


Q142. 如何使用 Namespace 实现多租户资源隔离?

1. 是什么Namespace(命名空间) 是 K8s 用来逻辑划分集群的机制,把一个物理集群切成多个虚拟的、相互隔离的"子集群"。多租户场景下,可用 Namespace 分配给不同团队/项目/环境(如 dev、test、prod),再配合 ResourceQuotaLimitRangeRBACNetworkPolicy 实现资源与权限的隔离。

2. 为什么用它:一个集群往往多个部门/租户共用,若不隔离会造成资源互相抢占、配置互相污染、权限失控、误删串扰。Namespace 从"资源/对象归属 + 配额 + 权限 + 网络"多个维度做边界,是最经济(不用起多套集群)的多租户方案。

3. 怎么用它
① 创建 Namespace

kubectl create namespace dev
kubectl create namespace prod
# 或 YAML
# apiVersion: v1
# kind: Namespace
# metadata: { name: prod }

② 在指定命名空间操作

kubectl get pods -n dev
kubectl apply -f app.yaml -n prod

③ 资源配额 ResourceQuota(限制命名空间总资源)

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev            # 只对 dev 生效
spec:
  hard:
    requests.cpu: "20"      # 该 ns 所有 Pod CPU requests 总和上限
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    pods: "100"             # Pod 总数上限

④ LimitRange(给命名空间内 Pod 设置默认/范围)

apiVersion: v1
kind: LimitRange
metadata: { name: dev-lr, namespace: dev }
spec:
  limits:
  - type: Container
    default: { cpu: "500m", memory: "512Mi" }
    defaultRequest: { cpu: "250m", memory: "256Mi" }
    max: { cpu: "4", memory: "8Gi" }

⑤ RBAC 权限绑定

# 创建给租户的用户/ServiceAccount,并只授予其 namespace 读写权限
kubectl create rolebinding dev-user --clusterrole=edit --user=alice -n dev

⑥ NetworkPolicy(网络层隔离,需 CNI 支持):控制不同 Namespace / Pod 之间的流量放行。

查看与切换默认命名空间

kubectl get namespace
kubectl config set-context --current --namespace=dev   # 切换默认 ns

4. 使用场景:多团队/多项目/多环境共用一套集群;面试关键:说出"Namespace 划分隔离 + ResourceQuota 限资源 + LimitRange 设默认 + RBAC 控权限 + NetworkPolicy 控网络"五板斧,并提"资源名在 ns 内唯一、跨 ns 可同名"。


Q143. 如何查看 Pod 的日志?如何进入 Pod 进行调试?

1. 是什么查看 Pod 日志kubectl logs进入 Pod 交互调试kubectl exec。这是排查 Pod 内部问题(应用报错、启动失败、配置错误)最常用的两个操作。

2. 为什么用它:Pod 内的容器是"黑盒",看不到内部运行;日志能反映应用运行与报错,exec 能像 SSH 一样进容器查看文件、执行命令、测连通,二者是诊断"应用为何异常/为什么起不来/为何访问不通"的利器。

3. 怎么用它

① 查看日志

kubectl logs <pod-name>                        # 查看指定 Pod 日志(单容器)
kubectl logs <pod-name> -c <container>         # 多容器时指定容器
kubectl logs <pod-name> --previous             # 查看上次崩溃前的日志(关键!)
kubectl logs <pod-name> -f                     # 持续跟踪(tail -f)
kubectl logs <pod-name> --tail=100             # 只看最近 100 行
kubectl logs -l app=my-app                     # 按标签看一组 Pod
kubectl logs <pod> --timestamps                # 带时间戳

重要:Pod 崩溃重启后,当前容器日志可能是新的(空白/无错),用 --previous上次崩溃的日志才能定位原因;CrashLoopBackOff 排查必用。

② 进入 Pod 交互

kubectl exec -it <pod-name> -- /bin/sh         # 进入容器(sh,若容器有 bash 则用 /bin/bash)
kubectl exec -it <pod-name> -c <container> -- /bin/sh   # 指定容器
kubectl exec <pod-name> -- env                  # 查看环境变量
kubectl exec <pod-name> -- cat /etc/nginx/nginx.conf    # 执行单条命令查看文件
kubectl exec -it <pod-name> -- nslookup 后端svc         # 容器内测 DNS/连通

③ 更完整的调试手段

  • describekubectl describe pod <pod> 看 Events、环境、挂载、容器状态。
  • debug 临时容器(无 exec 能力/无 shell 时):kubectl debug -it <pod> --image=busybox ...kubectl debug node/<node> --image=busybox(在节点侧调试)。
  • 看资源占用kubectl top pod
  • 副本/选择器kubectl get pods -o wide 看 Pod 在哪个节点。

4. 使用场景:任何 Pod 异常(Failure/CrashLoop/访问不通)的排查。面试关键:点出 --previous(看崩溃前日志)是 CrashLoopBackOff 排查的关键;并给"logs 看报错 → describe 看事件 → exec 进去看文件/环境/测连通 → 必要时 debug 临时容器"这条完整的 Pod 排查链路。

Q144. 如何管理集群的节点?

1. 是什么:节点管理指对集群中的 Node 进行查看、标记、调度控制、添加/删除、维护等操作,常用 kubectl 命令管理节点的 标签、污点/容忍、cordon/drain、状态与 kubelet 配置

2. 为什么用它:节点是承载 Pod 的物理/虚机,日常运维需要"让某节点不接新 Pod、维护时排空已有 Pod、给特定节点打标用于调度、下线不再用的节点"。掌握节点管理是集群容量规划、故障隔离、版本升级的基础。

3. 怎么用它

查看节点

kubectl get nodes                                    # 列出所有节点(状态/角色/版本)
kubectl get nodes -o wide                            # 显示节点 IP、容器运行时等
kubectl describe node k8s-node01                    # 查看节点详情(资源、污点、标签、事件)
kubectl top node                                      # 查看节点资源占用

标记与调度控制

# 给节点打标签(配合 nodeSelector / nodeAffinity 调度)
kubectl label node k8s-node01 disktype=ssd
kubectl label node k8s-node01 disktype-               # 删除标签(加 -)

# 污点/容忍:阻止普通 Pod 调度到某节点
kubectl taint node k8s-master01 key=value:NoSchedule   # 添加污点
kubectl taint node k8s-master01 key=value:NoSchedule-  # 删除污点(末尾 -)

# cordon:标记节点"不可调度"(新 Pod 不再来,已在跑的保持)
kubectl cordon k8s-node01
# drain:排空节点(先 cordon,并驱逐其上 Pod,常用于升级/下线)
kubectl drain k8s-node01 --ignore-daemonsets --delete-emptydir-data
# uncordon:恢复可调度
kubectl uncordon k8s-node01

添加/删除节点

# 添加:给新节点安装 kubelet/kubeadm/kubectl,再用 kubeadm join 加入
kubeadm join ... --cri-socket unix:///var/run/cri-dockerd.sock
# 下线:先 drain 排空,再删除该 Node 对象
kubectl delete node k8s-node02

4. 使用场景:节点升级/维护(cordon+drain)、下线故障节点、按标签做专用节点调度、节点角色隔离(Master 加 NoSchedule 污点)。面试关键:区分 cordon 与 drain——cordon 只"不再接收新 Pod",drain 会"排空已运行 Pod",两者常用于维护/升级前的顺序操作;并会打标签/污点来精细控制调度。


Q145. 如何备份和恢复 etcd 集群?

1. 是什么etcd 是 Kubernetes 的集群状态数据库,存所有对象、配置、证书等。备份/恢复都用 snapshot(快照)命令:备份 snapshot save 把 etcd 状态导出为快照文件,恢复 snapshot restore 把快照还原到 etcd 数据目录。

⚠️ 版本差异(重要):在 etcd 3.5+ / 3.6 中,snapshot 相关的子命令已从 etcdctl 迁移到独立工具 etcdutl(官方已提示 etcdctl snapshot ... 废弃)。因此分两版

  • 新版(3.5+/3.6,建议):用 etcdutl snapshot save/restore/status
  • 旧版(3.4 及之前,兼容):用 etcdctl snapshot save/restore/status
    注意:endpoint healthget/put在线操作仍用 etcdctl;只有 snapshot 这类"离线操作数据文件"的命令etcdutl

2. 为什么用它:etcd 丢失=集群元数据丢失,集群基本不可用。定期备份 etcd 是**灾难恢复(DR)**的最后防线,能应对节点故障、误删对象、etcd 数据损坏等场景——没有备份就是"裸奔"。

3. 怎么用它(下面给出新版 etcdutl旧版 etcdctl 两个版本)。

① 确认 etcd 信息(Master 上,kubeadm 部署的在 /etc/kubernetes/manifests/etcd.yaml):

# 在线检查 etcd 健康 —— 无论新旧版都用 etcdctl
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  endpoint health

③ 备份(snapshot save)

etcdutl(新版,etcd 3.5+/3.6):

ETCDCTL_API=3 etcdutl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /backup/etcd-$(date +%Y%m%d).db

# 查看快照(etcdutl)
ETCDCTL_API=3 etcdutl snapshot status /backup/etcd-$(date +%Y%m%d).db

etcdctl(旧版 / 兼容,etcd 3.4 及之前):把 etcdutl 换成 etcdctl 即可。

ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /backup/etcd-$(date +%Y%m%d).db

# 查看快照(etcdctl)
ETCDCTL_API=3 etcdctl snapshot status /backup/etcd-$(date +%Y%m%d).db

④ 恢复(snapshot restore)

etcdutl(新版,etcd 3.5+/3.6):

# 停掉 etcd(对 kubeadm 部署可先停止 kubelet,或直接清理静态 Pod)
# 恢复到新的数据目录(不建议直接覆盖原目录)
ETCDCTL_API=3 etcdutl snapshot restore /backup/etcd-20260828.db \
  --data-dir=/var/lib/etcd-restore \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key

etcdctl(旧版 / 兼容,etcd 3.4 及之前):同样把 etcdutl 换成 etcdctl

ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-20260828.db \
  --data-dir=/var/lib/etcd-restore \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key
  • 恢复后,把 etcd 的 data-dir 指向 /var/lib/etcd-restore,重启 etcd。
  • 生产常配合定时备份(cron 或 Velero),并异地/对象存储保存快照。

💡 新版本命令提示:在较新二进制中,etcdctl snapshot ... 会直接打印 Deprecated: Use "etcdutl snapshot ..." instead 的提示,请以 etcdutl 为准

⑤ 工具化方案:用 Velero(备份整个集群,含 etcd 与 PV 数据)做更高层的备份恢复。

4. 使用场景:灾备演练、etcd 数据损坏/误删、集群迁移、升级前快照。面试关键:背出 snapshot save(备份)与 snapshot restore(恢复)+ 那四个证书参数--cacert/--cert/--key/--endpoints);并答出"新版用 etcdutl、旧版用 etcdctl(3.5+ 已把 snapshot 命令迁移到 etcdutl)“这个版本差异,以及"恢复要换 data-dir、生产要定时 + 异地保存”。同时强调 etcd 备份是集群灾难恢复的兜底。


Q146. Pod 一直处于 Pending 状态,如何排查?

1. 是什么Pending 表示 Pod 已被 API 接受,但还没被调度到节点上运行(或调度后在等镜像/等待中)。它是调度失败的典型表现,通常由”没有合适的节点可以放”导致。

2. 为什么用它:Pod 卡在 Pending 会一直不工作,服务不就绪。Pendinning 常见根因集中在资源不足、节点选择/亲和不满足、污点不匹配、镜像拉取问题、端口冲突等,按序排查能快速定位是"哪个约束拦住了调度"。

3. 怎么用它(排查流程):

# 1) 看 Pod 状态与事件(最重要)
kubectl get pod <pod-name> -o wide                    # 确认 Pending + 所在命名空间/节点
kubectl describe pod <pod-name>                       # 看 Events 里的失败原因(关键!)

常见原因与对策

原因现象/事件解决
资源不足0/1 nodes are available: Insufficient cpu扩容节点 / 减小 requests / 清空闲 Pod
节点选择不匹配0/1 nodes available: node(s) didn't match node selector修正 nodeSelector/nodeAffinity / 给节点打正确标签
污点不匹配0/1 nodes available: node(s) didn't tolerate ...给 Pod 加对应 toleration / 去掉节点污点
端口冲突PodFitsHostPorts 相关事件避免 hostPort 冲突 / 换端口
镜像拉取image pull back off / ErrImagePull检查镜像名/仓库/认证
# 2) 看节点是否有足够资源(Pendinning 常因资源不够)
kubectl get nodes                                    # 查看各节点分配/容量
kubectl describe node <node> | grep -A5 Allocatable  # 看可分配资源

# 3) 看是否整体无节点可调度 / 节点状态
kubectl get nodes -o wide
kubectl cluster-info

4. 使用场景:新部署 Pod 一直 Pending;排障重点看 describe 的 Events。面试关键:第一反应 kubectl describe pod 看事件;再按"资源不够、节点/亲和不匹配、污点不容忍、端口冲突、镜像拉取失败"五类原因逐一排查;并知道 0/3 nodes are available 就是"没有任何节点满足调度要求"。


Q147. Pod 一直处于 ContainerCreating 状态,如何排查?

1. 是什么ContainerCreating 表示 Pod 已调度到节点并建立了 Pod 层,但容器还没创建成功,卡在拉镜像、挂卷、启动容器或网络(CNI)配置等阶段。

2. 为什么用它:ContainerCreating 比 Pending 更进一步(节点已确定),说明问题出在节点上的容器运行时层。常见根因:镜像拉取慢/失败、CNI 网络插件问题、存储卷挂载失败、权限/端口配置错误,逐层排查能定位到 kubelet/containerd 侧。

3. 怎么用它(排查流程):

# 1) 看 Pod 事件(同样先 describe)
kubectl describe pod <pod-name>                       # Events 里看 ContainerCreating 的具体报错

# 2) 看节点上容器运行时与 kubelet 日志
journalctl -u kubelet -f                              # 节点上跟踪 kubelet 日志
journalctl -u containerd -f                           # 若是 containerd
journalctl -u cri-docker -f                           # 若是 cri-docker

# 3) 看镜像拉取状态
kubectl get pods -o jsonpath='{.status.containerStatuses}' <pod-name>

常见原因

原因解决
镜像拉取慢/失败检查网络/镜像加速器 / 提前去节点 docker pull 预拉
CNI 网络插件未就绪检查 Calico/flannel 是否 Running、crictl/kubelet 网络配置
挂载卷失败检查 PV/PVC 是否 Bound、StorageClass、mount 权限
sandbox/pause 镜像问题检查该节点是否已导入 pause 镜像、版本是否一致
容器运行时权限/参数检查 kubelet 的 --cri-socket、cgroup 驱动是否一致
cgroup 驱动不一致确保 docker/containerd 用 systemd 且与 kubelet 一致
# 在节点上直接用 crictl 查看容器运行时状态
crictl ps -a
crictl images
# 查看节点网络插件 Pod 是否正常
kubectl get pod -n kube-system

4. 使用场景:Pod 调度成功但容器起不来;重点查镜像与 CNI 网络。面试关键:先 describe 看事件,再去节点看 kubelet/containerd 日志;按"镜像拉取、CNI 网络、卷挂载、pause 镜像、cgroup/CRI 配置"五类排查;并强调"容器运行时(cri-docker/containerd)的 socket 与 cgroup 驱动必须和 kubelet 对齐"。


Q148. Pod 不断重启,如何查看日志和排查原因?

1. 是什么:Pod 不断重启(典型状态为 CrashLoopBackOff)表示容器启动后又崩溃,被 kubelet 反复重启,形成一个"崩溃-重启-再崩溃"的死循环。

2. 为什么用它:CrashLoopBackOff 是最常见的 Pod 故障,通常源于应用启动报错、启动命令/配置错误、OOMKilled、liveness 探针失败等"容器内本身的错误"。关键是拿到崩溃那次的日志(而非重启后空白的新日志)才能定位。

3. 怎么用它(排查流程):

# 1) 看容器重启次数与状态
kubectl get pod <pod-name>                            # RESTARTS 列看重启次数
kubectl describe pod <pod-name>                       # 看 Last State / Reason(如 OOMKilled、Error)

# 2) 看"崩溃前"的日志(关键!重启后的当前日志可能为空)
kubectl logs <pod-name> --previous                    # 查看上次崩溃的日志
kubectl logs <pod-name> -c <container> --previous    # 多容器指定容器
kubectl logs <pod-name> --tail=50                     # 看最近 50 行
kubectl logs <pod-name> --timestamps                  # 带时间戳便于定位时序

常见崩溃原因

原因表现排查/解决
启动命令/入口错误CMD/ENTRYPOINT 不对、缺少依赖kubectl logs --previous 的报错
配置/环境变量缺失连接不到 DB、读不到配置检查 ConfigMap/Secret、env
OOMKilledStatus 为 OOMKilled提高内存 limits / 优化应用内存
liveness 探针失败Liveness probe failed调大 initialDelay/failureThreshold / 修探针路径
端口/权限端口被占用、无权限检查端口、容器用户/权限
资源不足启动即被调度问题检查 requests/节点资源
# 应用启动后立即崩溃,可以利用 debug 临时容器进入排查
kubectl debug -it <pod-name> --image=busybox -- sh

4. 使用场景:任何 CrashLoopBackOff 的定位;核心工具是 --previous。面试关键:强调 kubectl logs --previous 看崩溃前日志;再按"启动报错、配置缺失、OOMKilled、探针失败"排查;点出 describeLast Reason(如 OOMKilled)能快速定性,比只看重启次数更准。


Q149. 如何实现 Kubernetes 的权限控制?

1. 是什么:Kubernetes 权限控制基于 RBAC(基于角色的访问控制),核心三要素:Subject(主体:User/Group/ServiceAccount)→ Role/ClusterRole(角色:权限集合)→ RoleBinding/ClusterRoleBinding(绑定:把角色授予主体)。管理员用 RBAC 精确控制"谁能对哪些资源做什么操作"。

2. 为什么用它:K8s 默认所有操作都是白名单,需要明确授权。若不做权限隔离,任何能访问 apiserver 的人都拥有集群管理权,极其危险。RBAC 让不同团队、用户、ServiceAccount 各司其职、最小权限,是集群安全的基础。

3. 怎么用它(RBAC 四件套):

# 1) 创建 ServiceAccount(给 Pod/CI 用的身份)
kubectl create serviceaccount ci-robot

# 2) 创建角色(Namespace 内生效用 Role;集群级用 ClusterRole)
kubectl create role pod-reader --verb=get,list,watch --resource=pods

# 3) 创建集群角色(集群范围,可管理 node/namespaces 等)
kubectl create clusterrole cluster-admin --verb=* --resource=*

RBAC 四要素的关系

  • Subject:谁能操作(用户、组、ServiceAccount)。
  • Role / ClusterRole:能做什么(一组 verb + resource 规则)。
  • RoleBinding / ClusterRoleBinding:把角色授予主体(roleRef + subjects)。
  • 区别Role/RoleBinding 授权某个命名空间ClusterRole/ClusterRoleBinding 授权整个集群(所有命名空间)。
# 示例:把"pod-reader"角色绑定给 ci-robot 这个 SA(在 dev 命名空间)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-read-pods
  namespace: dev
subjects:
- kind: ServiceAccount
  name: ci-robot
  namespace: dev
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

常用校验命令

kubectl auth can-i list pods --as=ci-robot -n dev     # 模拟某用户是否有权限
kubectl get role,rolebinding,clusterrole,clusterrolebinding -A   # 查看授权

其他权限机制(补充):

  • ServiceAccount + 挂载 token:Pod 内应用用 SA 访问 API。
  • NetworkPolicy:网络层访问控制(不让 Pod 任意互访)。
  • 准入控制器(Admission Control):如 ResourceQuota、PodSecurityPolicy(已被 Pod Security 替代)。
  • kubectl config / kubeconfig:用 --user 指定不同用户身份。

4. 使用场景:给不同团队/CI 账号最小权限、限制某个用户只能读 Pod、隔离多租户。面试关键:背出 RBAC 四件套"Subject + Role/ClusterRole + RoleBinding/ClusterRoleBinding + API 规则(verb/resource)";说明 Role 限命名空间、ClusterRole 限整个集群;并知道 kubectl auth can-i 验证权限。


Q150. Kubernetes 的资源服务质量(QoS)有哪几类?如何保证关键服务的资源?

1. 是什么QoS(Quality of Service,服务质量) 是 K8s 根据容器是否声明了资源 requests/limits,把 Pod 划分为三档:Guaranteed(有保证)→ Burstable(有波动)→ BestEffort(尽力而为),档次越高,在资源紧张时越不容易被驱逐。

2. 为什么用它:当节点内存不足触发**驱逐(eviction)**时,K8s 会优先杀掉低优先级(低 QoS)的 Pod,以保护关键业务。合理设置 QoS 能让核心服务(如数据库、网关)在资源紧张时存活,而让临时/批处理 Pod 先被清理,是"资源保障 + 合理腾挪"的关键。

3. 怎么用它(三档判定规则):

QoS 等级判定条件特点淘汰优先级
Guaranteed每个容器都设置了 limits 且等于 requests(CPU/内存均有)最稳定,最不容易被驱逐最低
Burstable容器设置了 requestslimits(但非全部 = 最高档)大多应用属于这一档中间
BestEffort容器未设置任何 requests/limits资源无保证,最容易被驱逐最高(最先被杀)
# ① Guaranteed:requests == limits(最稳,保护关键服务)
resources:
  requests: { cpu: "1", memory: "2Gi" }
  limits:   { cpu: "1", memory: "2Gi" }

# ② Burstable:设置了 requests 但 limits 更大(通常应用)
resources:
  requests: { cpu: "250m", memory: "256Mi" }
  limits:   { cpu: "500m", memory: "512Mi" }

# ③ BestEffort:什么都不写(临时/批处理 Pod)
# 不写 resources

保证关键服务的资源(进一步手段):

  • 高 QoS(Guaranteed):给关键服务设 requests == limits
  • PriorityClass(优先级类):结合 QoS,用高优先级 + 低 QoS 会被驱逐时先保高优先级;驱逐顺序 = 先低 QoS,再低 PriorityClass。
  • LimitRange / ResourceQuota:命名空间层面默认给 Pod 定 requests/limits,避免误建 BestEffort。
  • 节点预留与 Pod 优先级:给节点 system-reservedkube-reserved 预留系统资源。
  • 亲和/反亲和 + 污点:把关键服务调度到资源充足的专属节点。

4. 使用场景:保护关键无状态/有状态服务、合理规划临时 Pod 的淘汰顺序。面试关键:背出三档"Guaranteed(requests=limits,最稳)→ Burstable(有 requests/limits 但不等,最常见)→ BestEffort(无 requests/limits,最先被驱逐)“;并说"用 Guaranteed + PriorityClass + LimitRange 保护关键服务”。


Q151. 如何优化 Kubernetes 的调度?

1. 是什么:调度优化指通过合理配置资源、污染/容忍、亲和/反亲和、PriorityClass、节点选择、调度器配置等,让 Pod 被调度到"更合适"的节点,实现资源均衡、热节点分散、关键服务保障、性能提升

2. 为什么用它:默认调度器只按"资源够不够"做基础判断,可能导致热点节点、资源浪费、关键服务与高负载混跑等问题。优化调度能提升集群利用率、稳定性与性能,减少 Pending 和资源争抢。

3. 怎么用它(常用优化手段):

# ① 资源 requests 合理设置:让调度器有足够依据,避免把多个 Pod 塞到同一节点
resources:
  requests: { cpu: "250m", memory: "256Mi" }
# ② 节点亲和(nodeAffinity):把 Pod 调度到特定节点(如 GPU/SSD 专用节点)
nodeAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
    nodeSelectorTerms:
    - matchExpressions:
      - { key: disktype, operator: In, values: ["ssd"] }
# ③ 污点 + 容忍:默认 Master 有 NoSchedule 污点(普通 Pod 不去);也可用污点隔离专用节点
#    给关键工作节点加污点,仅允许带容忍的关键服务上去
# ④ Pod 亲和/反亲和:让 Pod 聚合同一节点(性能)或分散到不同节点(高可用/容灾)
podAntiAffinity:
  requiredDuringSchedulingIgnoredDuringExecution:
  - labelSelector:
      matchLabels: { app: db }
    topologyKey: kubernetes.io/hostname    # 让 db 副本分散到不同节点
# ⑤ PriorityClass:高优先级 Pod 优先生成,低优先级(批处理)可被抢占
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata: { name: high }
value: 1000000
globalDefault: false
# ⑥ 资源均衡(BalancedResourceAllocation)等优选策略,在 kube-scheduler 配置中调整
# ⑦ 自定义调度器 / 多调度器(default-scheduler 之外再起一个,Pod 用 schedulerName 指定)
# 查看调度情况
kubectl describe pod <pod> | grep -i node
kubectl get happenings | grep -i "successfully assigned"

4. 使用场景:让关键服务分散到不同节点避免单点、让 GPU 任务到 GPU 节点、避免热点节点、保护核心业务不被抢占。面试关键:按"资源设置 + 亲和/反亲和 + 污点容忍 + 优先级 + 多调度器"分层讲;重点说清"反亲和(podAntiAffinity)用拓扑键把副本分散到不同节点实现高可用";并强调合理 requests 是调度质量的前提。


Q152. 如何限制用户和命名空间的资源配额?

1. 是什么:通过 ResourceQuota(资源配额) 限制某个命名空间内可创建的资源总量(CPU/内存/PVC/对象数量等),用 LimitRange(范围限制)命名空间内每个 Pod/容器设定默认与最大/最小的资源值。二者配合,在多租户场景下防止某个团队/用户"滥用"集群资源。

2. 为什么用它:不加限制时,某个团队可能创建大量 Pod/请求过量资源,耗尽整个集群资源、影响其他租户。配额和范围限制把"资源上限"和"单对象默认值"固定下来,实现多租户的资源公平与隔离,防止"一个 namespace 吃垮集群"。

3. 怎么用它

① ResourceQuota(限总量)

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    requests.cpu: "20"        # 命名空间内所有 Pod CPU requests 总和上限
    requests.memory: "40Gi"
    limits.cpu: "40"
    limits.memory: "80Gi"
    count/pods: "100"         # Pod 总数上限
    count/deployments.apps: "20"
    persistentvolumeclaims: "10"   # PVC 数量上限

② LimitRange(设单对象默认/范围)

apiVersion: v1
kind: LimitRange
metadata:
  name: dev-lr
  namespace: dev
spec:
  limits:
  - type: Container          # 对每个容器生效
    default:          { cpu: "500m", memory: "512Mi" }   # 未写时的默认 limits
    defaultRequest:   { cpu: "250m", memory: "256Mi" }   # 未写时的默认 requests
    max:              { cpu: "4", memory: "8Gi" }         # 上限
    min:              { cpu: "50m", memory: "64Mi" }       # 下限
  - type: PersistentVolumeClaim
    max: { storage: "20Gi" }

③ 资源配额与限额的应用顺序

# 创建配额与范围限制到命名空间
kubectl apply -f dev-quota.yaml
kubectl apply -f dev-lr.yaml
# 查看
kubectl get resourcequota,limitrange -n dev
# 验证:当请求超过配额时会报错(如 "exceeded quota")
kubectl apply -f big-deploy.yaml -n dev   # 会因超配额被拒

④ 结合 RBAC 与 namespace 隔离:给不同租户的 ServiceAccount/Role 仅授权自己 namespace 的权限 + 对该 namespace 建 ResourceQuota,实现"权限 + 资源"双重隔离。

4. 使用场景:多团队/多租户共用集群、限制某项目资源规模、防止失控的批量部署。面试关键:区分 ResourceQuota(管"命名空间总量")与 LimitRange(管"单个容器默认/范围");说清"配额从总量卡上限、范围限制从单对象兜底默认值",二者配套使用实现多租户资源隔离。


Q153. 解释 Sidecar 模式及其应用场景。

1. 是什么Sidecar(边车)模式是在 K8s 中让主容器旁边运行一个辅助容器(sidecar),二者同属一个 Pod,共享网络命名空间(localhost 互通)与存储卷,但职责分离——主容器做核心业务,sidecar 做辅助功能(日志采集、代理、监控、配置同步等)。

2. 为什么用它:把"跨业务的横切关注点"(日志、链路、代理、熔断、监控)抽成独立容器,而不需要修改主应用代码,从而做到业务容器"纯净"、辅助能力可独立扩展/升级/复用,也便于统一管理和实现服务网格(Service Mesh)。

3. 怎么用它(同 Pod 多容器):

apiVersion: v1
kind: Pod
metadata:
  name: app-with-sidecar
spec:
  containers:
  - name: app                      # 主业务容器
    image: myapp:v1
    ports: [ { containerPort: 8080 } ]
  - name: log-sidecar              # 边车容器
    image: fluentd                 # 收集日志
    volumeMounts:
    - { name: log, mountPath: /var/log/myapp }
  - name: proxy                    # 也可再放一个代理/边车
    image: envoy
  volumes:
  - name: log
    emptyDir: {}

核心要点

  • 同 Pod 共享网络:sidecar 与主容器通过 localhost 互访(共享 Pod 网络命名空间),且端口不能冲突。
  • 共享存储:sidecar 通过 volume 与主容器共享数据(如日志目录)。
  • 生命周期与 Pod 一致:sidecar 随 Pod 创建/销毁,一起调度到同一节点。
  • 服务网格典型应用:Istio/Linkerd 把 Envoy 作为 sidecar 自动注入,做流量治理、mTLS、可观测性。

典型应用场景

场景sidecar 作用
日志采集fluentd/filebeat 读取主容器的日志并转发到 ELK
服务网格Envoy sidecar 做代理、熔断、mTLS 加密
监控/指标采集应用指标(prometheus-exporter)
配置同步从配置中心拉取并热更新配置
SSH/调试/代理提供调试 shell、入站/出站代理
数据库/缓存代理本地代理连接池、读写分离

4. 使用场景:微服务统一接入日志/监控/服务网格、给旧应用无侵入加能力。面试关键:一句话"Sidecar 是与主容器同 Pod 共享网络和存储的辅助容器,把日志/代理/监控等横切功能独立出来’**;强调"共享 localhost 网络 + 共享卷",并举例 Istio 的 Envoy 注入是典型场景。


Q154. 如何保障 Kubernetes 集群的安全?

1. 是什么:Kubernetes 安全是多维度纵深防御,覆盖:访问控制(RBAC/认证/授权)→ 镜像安全 → 运行时安全 → 网络隔离(NetworkPolicy)→ 秘钥管理 → 审计与监控等层面。从"谁能进集群、哪些镜像能跑、Pod 间能否互访、敏感信息是否泄露"几个关键点加固。

2. 为什么用它:K8s 集群是核心基础设施,一旦被攻破影响整个应用。默认配置通常不够安全(如宽松 RBAC、无网络策略、弱口令、常见默认配置),必须按安全基线加固,防横向渗透、防滥用、防数据泄露。

3. 怎么用它(各层安全措施):

① 访问控制(认证 + 授权)

  • RBAC 最小权限授权(避免给宽泛的 cluster-admin)。
  • 严格管理 ServiceAccount、证书、kubeconfig 的颁发与轮换。
  • Admission Controller / OIDC 等对接企业身份认证。

② 镜像与供应链安全

  • 使用私有可信仓库(Harbor),启用镜像签名/扫描(Trivy、Docker image scan)。
  • ImagePolicyWebhook / Admission 只允许可信镜像运行。
  • 不拉公共不可信镜像;加 imagePullSecretsalwaysPullImages(强制校验)。

③ 运行时安全

  • Pod 应以非 root(runAsNonRoot)只读根文件系统(readOnlyRootFilesystem)、**drop 特权(capabilities)**运行。
  • 使用 Pod Security Admission(PSA,替代 PodSecurityPolicy)privileged / baseline / restricted 三档限制。
  • 安全上下文(securityContext):限制资源、禁用特权容器、限制 syscall。
securityContext:
  runAsNonRoot: true
  runAsUser: 1000
  allowPrivilegeEscalation: false
  capabilities: { drop: ["ALL"] }
  readOnlyRootFilesystem: true

④ 网络隔离(NetworkPolicy):默认 Pod 可任意互访,用 NetworkPolicy 控制"谁能访问谁"(默认拒绝 + 白名单放行),减少横向渗透面。

⑤ 秘钥管理:用 Secret + 加密(etcd 加密、KMS、外部 secret 如 vault/sealed-secrets),避免明文存储。

⑥ 审计与监控

  • 开启 API 审计日志(audit log) 记录敏感操作。
  • Kube-bench(按 CIS 基线检查集群安全)。
  • Falco / 运行时安全 检测异常行为。
  • 监控集群异常(apiserver 异常访问、异常 Pod)。

4. 使用场景:生产集群安全加固、等保要求、安全检查。面试关键:分层列出"访问控制(RBAC)→ 镜像供应链 → 运行时非 root → 网络隔离 → 秘钥加密 → 审计监控";重点讲 NetworkPolicy 默认拒绝、Pod Security Admission 限制特权、rbac 最小权限,这几个是 K8s 安全的抓手。


Q155. 如何实现跨集群的应用部署和故障转移?

1. 是什么:跨集群部署与故障转移指在多个 Kubernetes 集群(如主备集群、多可用区/多云集群)上部署同一应用,并在集群故障时自动切换到存活集群,实现更高的可用性(多集群容灾)与地区级容灾。常用手段:GitOps 多集群配置分发、kubeconfig 多集群切换、DNS/负载均衡引流、Velero/跨集群资源同步等。

2. 为什么用它:单集群存在单点故障(集群级宕机、region 故障、etcd 损坏)。跨集群部署 + 故障转移能在集群级别故障时保障业务不中断,是**生产高可用/容灾(DC 双活、跨地域容灾)**的进阶要求。

3. 怎么用它(常见方案):

① 多集群配置分发(GitOps / 多集群管理)

  • Argo CD / Flux / KubeVela / Rancher 把同一套 yaml 部署到多个集群(通过多集群上下文),实现配置统一、声明式发布
  • Helm 管理多环境/多集群的模板。

② 多集群切换(kubeconfig / kubectl ctx)

kubectl config get-contexts            # 查看所有集群上下文
kubectl config use-context prod-a      # 切换集群
kubectl get pods --context prod-b      # 指定集群
# 用 kubectl 别名/脚本管理多集群;或用 kubectx 工具快速切换

③ 故障转移(流量/入口切换)

  • DNS 切换:把应用域名解析切换到存活集群的负载均衡入口(如云 LB / Ingress / External-DNS)。
  • 全局负载均衡(GSLB):智能 DNS / 云 CDN 做地域性、健康检查驱动的流量引导。
  • 多云/多集群 LB(如 Ingress 多播、服务网格多集群、service.clusterIP 跨集群)做流量灾备。

④ 数据层跨集群同步

  • 数据库主从/异地(如 MySQL 主备、跨 region 复制)。
  • 存储与卷:用 Velero / Kasten 跨集群备份恢复;对象存储多region复制。

⑤ 自动故障转移(主动切换为主)

# 用 GitOps 工具(如 Argo CD)配合集群健康检查,实现"主集群故障 → 切到备集群"的自动化
# 或:监控集群健康(Prometheus/uptime),触发切换脚本/更新 DNS 记录

⑥ 更多理念

  • 服务网格多集群(Istio multicluster) 实现跨集群服务发现与流量灰度。
  • KubeFed / Karmada:多集群管理平台,统一管理多个集群的部署与策略(Karmada 较主流)。

4. 使用场景:同城双活 / 跨区域容灾 / 多云备份、集群级别故障演练。面试关键:按"配置分发(GitOps/Argo CD + Hel)→ 多集群切换(kubeconfig/context)→ 流量切换(DNS/GSLB/LB)→ 数据同步(DB 主备 + Velero 备份)→ 自动故障转移(健康检查驱动切换)"讲;并提到 Karmada / Argo CD / GSLB 是跨集群与故障转移的常用工具。

更多推荐