运维面试 高频10题 · 第四组

存储 / K8s调度 / 网络排错 / 安全加固 / 性能调优 · 点击展开答案

已展开 0 / 10 题
Q31
K8s PV / PVC / StorageClass 的关系?动态供给原理是什么?
K8s存储
+
  • PV(PersistentVolume):集群管理员预先创建的实际存储资源(NFS / 云盘 / Ceph)
  • PVC(PersistentVolumeClaim):开发者声明"我需要多大、什么访问模式的存储",不关心底层
  • StorageClass:存储模板,定义用哪个 provisioner 自动创建 PV,实现动态供给
# 1. 创建 StorageClass(以 NFS provisioner 为例)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: nfs-sc
provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
parameters:
  archiveOnDelete: "false"   # 删除 PVC 时不保留目录

---
# 2. PVC 声明,指定 storageClassName
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myapp-data
spec:
  storageClassName: nfs-sc   # 触发动态供给
  accessModes: [ReadWriteMany]
  resources:
    requests:
      storage: 5Gi
  • RWO(ReadWriteOnce):只能被一个节点挂载读写,云盘常用
  • RWX(ReadWriteMany):多节点同时读写,NFS / CephFS 支持
  • ROX(ReadOnlyMany):多节点只读
常见坑:PVC 一直 Pending → 先看 kubectl describe pvc,多半是 StorageClass 名字写错、provisioner Pod 没跑起来、或 NFS 服务端路径权限问题。
Q32
K8s 调度器如何选择节点?污点与容忍怎么用?
K8s调度
+
  • 过滤(Predicates):排除不满足条件的节点。检查资源是否足够、节点选择器、污点容忍、亲和性规则等
  • 打分(Priorities):对剩余节点打分,选最高分。综合考虑资源均衡、亲和性权重等
# 给节点打污点(effect 三种:NoSchedule / PreferNoSchedule / NoExecute)
kubectl taint nodes worker01 gpu=true:NoSchedule
# 含义:不允许调度,除非 Pod 声明容忍

# Pod 声明容忍,才能调度到该节点
tolerations:
- key: "gpu"
  operator: "Equal"
  value: "true"
  effect: "NoSchedule"

# 查看节点污点
kubectl describe node worker01 | grep Taints

# 删除污点(末尾加 -)
kubectl taint nodes worker01 gpu=true:NoSchedule-
  • nodeSelector:硬性要求,标签不匹配直接不调度,简单粗暴
  • nodeAffinity:支持软硬两种规则,requiredDuringScheduling(硬)/ preferredDuringScheduling(软,尽量调过去但不强制)
典型场景:GPU 节点打污点,只有声明了 GPU 容忍的 Pod 才能调过去,防止普通服务占用 GPU 资源。
Q33
Linux 内核参数调优:高并发场景下需要调哪些参数?
Linux性能调优
+
# === 文件描述符 ===
fs.file-max = 1000000          # 系统级最大文件描述符数

# === 网络连接 ===
net.ipv4.tcp_max_syn_backlog = 8192    # SYN 队列长度,防 SYN 攻击
net.core.somaxconn = 32768             # listen 队列最大长度
net.core.netdev_max_backlog = 16384    # 网卡接收队列

# === TIME_WAIT 优化 ===
net.ipv4.tcp_tw_reuse = 1              # 允许复用 TIME_WAIT socket
net.ipv4.tcp_fin_timeout = 15          # FIN_WAIT_2 超时时间(默认60s)
net.ipv4.tcp_max_tw_buckets = 200000   # 最大 TIME_WAIT 数量

# === 端口范围 ===
net.ipv4.ip_local_port_range = 10000 65535  # 可用本地端口范围

# === 内存 ===
vm.swappiness = 10             # 尽量不用 swap(0=禁用,生产建议10)
vm.overcommit_memory = 1       # 允许内存超分配(Redis 必须设)

# 立即生效
sysctl -p
# /etc/security/limits.conf
* soft nofile 1000000
* hard nofile 1000000

# 验证生效
ulimit -n
Nginx 优化关联:sysctl 调内核,worker_connections 调 Nginx,ulimit -n 调进程文件描述符,三个层次都要到位才能真正支撑高并发。
Q34
Linux 系统安全加固有哪些措施?SSH 如何加固?
Linux安全
+
# /etc/ssh/sshd_config 关键配置
Port 22222                    # 改默认端口,减少扫描
PermitRootLogin no            # 禁止 root 直接登录
PasswordAuthentication no     # 禁用密码登录,只允许密钥
PubkeyAuthentication yes      # 开启公钥认证
MaxAuthTries 3                # 最大尝试次数
LoginGraceTime 30             # 登录超时时间
AllowUsers deploy ops         # 白名单,只允许指定用户登录
ClientAliveInterval 300       # 300秒无操作断开

systemctl restart sshd
  • 账户安全:删除无用账号,设置密码复杂度(/etc/login.defs),锁定 root(passwd -l root
  • 最小化安装:关闭不需要的服务(systemctl disable xxx),移除不必要的软件包
  • 防火墙:firewalld / iptables 只开放必要端口
  • sudo 控制:用 visudo 精细化授权,不给整机 sudo ALL
  • 登录审计:配置 /var/log/secure 日志,配合 ELK 或 Zabbix 告警异常登录
  • fail2ban:自动封禁暴力破解 IP
# fail2ban 安装配置
yum install fail2ban -y
# /etc/fail2ban/jail.local
[sshd]
enabled = true
maxretry = 5        # 5次失败后封禁
bantime = 3600      # 封禁1小时
findtime = 600      # 10分钟内统计
Q35
DNS 解析流程是什么?如何排查 DNS 问题?
网络DNS
+
  1. 查本地 /etc/hosts(最高优先级)
  2. 查本地 DNS 缓存(systemd-resolved / nscd)
  3. 发给 /etc/resolv.conf 里的递归解析器(如 8.8.8.8)
  4. 递归解析器依次问:根域名服务器 → TLD 服务器(.com)→ 权威 DNS → 返回 A 记录
# 基础查询
nslookup baidu.com
dig baidu.com A               # 查 A 记录
dig baidu.com +trace          # 追踪完整解析链路(排查最有用)

# 指定 DNS 服务器查询(绕过本地缓存验证)
dig @8.8.8.8 baidu.com

# 查看本机 DNS 配置
cat /etc/resolv.conf

# K8s Pod 内 DNS 排查
kubectl exec -it <pod> -- nslookup kubernetes.default
kubectl exec -it <pod> -- cat /etc/resolv.conf
# K8s Pod 的 DNS 指向 CoreDNS ClusterIP(通常 10.96.0.10)

# 查看 CoreDNS 日志
kubectl logs -n kube-system -l k8s-app=kube-dns
K8s DNS 规则:Pod 访问同 namespace 的 Service 直接用 svc名,跨 namespace 用 svc名.namespace名,完整 FQDN 是 svc名.ns名.svc.cluster.local
Q36
MySQL 索引的数据结构是什么?联合索引最左前缀原则?
MySQL索引
+
  • InnoDB 使用 B+ 树:所有数据存在叶子节点,叶子节点之间有双向链表连接
  • 聚簇索引(主键索引):叶子节点存整行数据,一张表只有一个
  • 二级索引(普通索引):叶子节点存主键值,查到后再回表到聚簇索引取完整数据
  • 覆盖索引:查询字段全在索引里,不需要回表,性能最好
# 联合索引 idx(a, b, c) 相当于建了三个索引:
# (a)、(a,b)、(a,b,c)

-- 能走索引
SELECT * FROM t WHERE a=1;
SELECT * FROM t WHERE a=1 AND b=2;
SELECT * FROM t WHERE a=1 AND b=2 AND c=3;
SELECT * FROM t WHERE a=1 AND c=3;   -- a 能走,c 不走(跳过 b)

-- 不走索引(未从最左列开始)
SELECT * FROM t WHERE b=2;
SELECT * FROM t WHERE b=2 AND c=3;

-- 范围查询之后的列不走索引
SELECT * FROM t WHERE a=1 AND b>5 AND c=3;
-- a走、b走范围、c不走(b用了范围,c断掉)
设计索引口诀:等值列放前、范围列放后、选择性高的列放前。建索引前先 EXPLAIN 验证,避免无效索引。
Q37
Docker 网络模式有哪些?容器间如何通信?
Docker网络
+
  • bridge(默认):容器连接到 docker0 虚拟网桥,通过 NAT 访问外网。同宿主机容器可通过容器名互通(自定义网络下)
  • host:容器直接使用宿主机网络栈,无 NAT 性能好,但端口可能冲突
  • none:只有 lo 回环,完全隔离,需手动配网
  • container:共享另一个容器的网络命名空间(K8s Pod 的实现原理)
# 创建自定义网络(推荐,支持容器名 DNS 解析)
docker network create mynet

# 启动容器加入同一网络
docker run -d --name mysql --network mynet mysql:8
docker run -d --name app   --network mynet myapp:latest

# app 容器内直接用容器名访问 mysql
# mysql -h mysql -u root -p   ← 直接用 "mysql" 作为主机名

# 查看网络详情
docker network inspect mynet
# docker-compose 默认为所有服务创建同一网络
# 服务间直接用服务名通信,无需额外配置
services:
  web:
    image: nginx
  db:
    image: mysql
# web 容器内 ping db 直接通
记住:默认 bridge 网络不支持容器名解析,自定义网络才支持。生产用 docker-compose 或 K8s,别手动管网络。
Q38
K8s Ingress 是什么?与 Service 的区别?ingress-nginx 如何配置 HTTPS?
K8sIngressHTTPS
+
  • Service(NodePort/LB):四层(TCP/UDP),一个端口对应一个服务,端口多了难管理
  • Ingress:七层(HTTP/HTTPS),基于域名 / 路径路由,一个入口承载多个服务,支持 TLS 终止
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /  # 路径重写
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - api.yourdomain.com
    secretName: tls-secret         # 存放证书的 Secret
  rules:
  - host: api.yourdomain.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: api-svc
            port:
              number: 8080
      - path: /admin
        pathType: Prefix
        backend:
          service:
            name: admin-svc
            port:
              number: 3000
# 自签证书(测试用)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt -subj "/CN=api.yourdomain.com"

# 创建 Secret
kubectl create secret tls tls-secret \
  --cert=tls.crt --key=tls.key -n production
Q39
如何排查两台服务器之间网络不通的问题?
网络排错
+
# === 第1层:物理/链路层 ===
ip link show                   # 网卡是否 UP
ethtool eth0                   # 查看网卡速率、连接状态

# === 第2/3层:网络层 ===
ping <对端IP>                  # 基础连通性
ping -I eth0 <对端IP>          # 指定网卡
traceroute <对端IP>            # 路由路径,定位在哪跳丢包
ip route show                  # 查路由表,确认有到达对端的路由

# === 第4层:传输层(端口是否通)===
telnet <IP> <port>
nc -zv <IP> <port>             # 更推荐,可测 UDP
ss -tlnp | grep <port>        # 对端端口是否监听

# === 防火墙排查 ===
iptables -L -n | grep <port>  # 本地 iptables 是否拦截
firewall-cmd --list-all        # firewalld 规则
# 临时测试:关闭防火墙(生产谨慎)
systemctl stop firewalld

# === 抓包(最终手段)===
tcpdump -i eth0 host <对端IP> and port <port> -nn -w /tmp/cap.pcap
# 检查 Calico / Flannel 是否正常
kubectl get pods -n kube-system | grep calico
calicoctl node status

# 检查 BGP 路由是否下发
ip route | grep <对端Pod网段>
面试答法:说出"物理→网络层→传输层→应用层→防火墙"这个排查顺序,比直接说"ping一下"要专业得多。
Q40
Prometheus 的数据模型和 PromQL 基础?rate() 和 irate() 的区别?
PrometheusPromQL
+
  • 每条时间序列由 metric 名 + label 键值对 唯一标识
  • 例:http_requests_total{job="nginx", status="200", instance="10.0.0.1:9090"}
  • 四种指标类型:Counter(只增)/ Gauge(可增减)/ Histogram(分布)/ Summary(分位数)
# CPU 使用率(5分钟平均)
100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 内存使用率
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 某接口 QPS(每秒请求数)
rate(http_requests_total{path="/api/v1"}[1m])

# 错误率(5xx 比例)
rate(http_requests_total{status=~"5.."}[5m]) /
rate(http_requests_total[5m])

# P99 响应时间(需要 Histogram 类型指标)
histogram_quantile(0.99, rate(http_duration_seconds_bucket[5m]))
  • rate():时间窗口内所有样本的平均增长率,曲线平滑,适合告警规则(不被毛刺误触发)
  • irate():只取最近两个样本计算瞬时速率,反应灵敏,适合实时监控面板(Grafana 大屏)
记住:告警用 rate(),大屏用 irate()。Counter 类型指标必须用 rate()/irate() 换算,直接用原始值没意义(只会增不会减)。