存储 / K8s调度 / 网络排错 / 安全加固 / 性能调优 · 点击展开答案
# 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
kubectl describe pvc,多半是 StorageClass 名字写错、provisioner Pod 没跑起来、或 NFS 服务端路径权限问题。
# 给节点打污点(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-
requiredDuringScheduling(硬)/ preferredDuringScheduling(软,尽量调过去但不强制)# === 文件描述符 === 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
worker_connections 调 Nginx,ulimit -n 调进程文件描述符,三个层次都要到位才能真正支撑高并发。
# /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),移除不必要的软件包/var/log/secure 日志,配合 ELK 或 Zabbix 告警异常登录# fail2ban 安装配置 yum install fail2ban -y # /etc/fail2ban/jail.local [sshd] enabled = true maxretry = 5 # 5次失败后封禁 bantime = 3600 # 封禁1小时 findtime = 600 # 10分钟内统计
# 基础查询 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
svc名,跨 namespace 用 svc名.namespace名,完整 FQDN 是 svc名.ns名.svc.cluster.local。
# 联合索引 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断掉)
# 创建自定义网络(推荐,支持容器名 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 直接通
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
# === 第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网段>
http_requests_total{job="nginx", status="200", instance="10.0.0.1:9090"}# 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]))