# 运维与DevOps面试指南
> 🎯 面向后端开发者的运维面试准备
> 涵盖:Linux、Docker、Kubernetes、Nginx、CI/CD、监控告警
---
## 📚 目录
1. [Linux面试题](#一linux面试题)
2. [Docker面试题](#二docker面试题)
3. [Kubernetes面试题](#三kubernetes面试题)
4. [Nginx面试题](#四nginx面试题)
5. [CI/CD面试题](#五cicd面试题)
6. [监控与故障排查](#六监控与故障排查)
---
# 一、Linux面试题
## 1.1 常用命令
### Q1:常用的Linux命令有哪些?
**答**:
**文件操作**:
```bash
# 查看文件
cat file.txt # 查看全部内容
head -n 100 file.txt # 查看前100行
tail -f file.txt # 实时查看文件末尾(看日志)
less file.txt # 分页查看
more file.txt # 分页查看
# 查找文件
find /path -name "*.log" # 按名称查找
find /path -mtime +7 -name "*.log" # 查找7天前的日志
find /path -size +100M # 查找大于100M的文件
# 文件权限
chmod 755 file.sh # 设置权限 rwxr-xr-x
chown user:group file # 修改所有者
```
**文本处理**:
```bash
# grep - 文本搜索
grep "ERROR" app.log # 搜索ERROR
grep -i "error" app.log # 忽略大小写
grep -C 5 "Exception" app.log # 显示上下5行
grep -r "keyword" /path # 递归搜索
# awk - 文本分析
awk '{print $1}' file.txt # 打印第一列
awk -F: '{print $1}' /etc/passwd # 指定分隔符
awk '/ERROR/{print}' app.log # 匹配打印
# sed - 文本替换
sed 's/old/new/g' file.txt # 替换文本
sed -i 's/old/new/g' file.txt # 直接修改文件
sed -n '10,20p' file.txt # 打印10-20行
```
**业务场景**:日志分析
```bash
# 统计ERROR出现次数
grep -c "ERROR" app.log
# 统计每个接口的调用次数
awk '{print $7}' access.log | sort | uniq -c | sort -rn | head -20
# 统计某个时间段的日志
sed -n '/2024-01-19 10:00/,/2024-01-19 11:00/p' app.log
# 查找最耗时的请求(假设最后一列是耗时)
awk '{print $NF, $0}' access.log | sort -rn | head -10
```
---
### Q2:如何查看系统资源使用情况?
**答**:
```bash
# CPU
top # 实时查看进程
htop # 更友好的top
mpstat 1 # CPU使用率(每秒刷新)
# 内存
free -h # 查看内存使用
vmstat 1 # 虚拟内存统计
# 磁盘
df -h # 磁盘使用情况
du -sh /path/* # 目录大小
iostat -x 1 # 磁盘IO
# 网络
netstat -tlnp # 查看监听端口
ss -tlnp # 更快的netstat
iftop # 网络流量监控
# 进程
ps aux # 查看所有进程
ps -ef | grep java # 查找Java进程
lsof -i :8080 # 查看端口占用
```
**业务场景**:排查Java应用问题
```bash
# 1. 找到Java进程
ps -ef | grep java | grep -v grep
# 2. 查看进程资源使用
top -p <pid>
# 3. 查看线程CPU使用(找到高CPU线程)
top -Hp <pid>
# 4. 将线程ID转为16进制
printf "%x\n" <tid>
# 5. 用jstack查看线程堆栈
jstack <pid> | grep -A 30 <tid_hex>
# 6. 查看GC情况
jstat -gc <pid> 1000
# 7. 生成堆转储
jmap -dump:format=b,file=heap.hprof <pid>
```
---
### Q3:Linux的文件权限是怎样的?
**答**:
```
-rwxr-xr-x 1 root root 4096 Jan 19 10:00 file.txt
│├─┤├─┤├─┤
│ │ │ └─ 其他用户权限
│ │ └──── 用户组权限
│ └─────── 所有者权限
└───────── 文件类型(- 普通文件,d 目录,l 链接)
权限数字:
r = 4 (读)
w = 2 (写)
x = 1 (执行)
755 = rwxr-xr-x(所有者全部权限,其他读和执行)
644 = rw-r--r--(所有者读写,其他只读)
```
```bash
# 修改权限
chmod 755 file.sh # 数字方式
chmod u+x file.sh # 符号方式(给所有者加执行权限)
chmod -R 755 /path # 递归修改
# 修改所有者
chown user file.txt
chown user:group file.txt
chown -R user:group /path
```
---
### Q4:如何管理后台进程?
**答**:
```bash
# nohup - 后台运行,不受终端关闭影响
nohup java -jar app.jar > app.log 2>&1 &
# 查看后台任务
jobs
# 把后台任务放到前台
fg %1
# systemd管理服务(推荐)
systemctl start app
systemctl stop app
systemctl restart app
systemctl status app
systemctl enable app # 开机自启
# 创建systemd服务文件 /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=app
ExecStart=/usr/bin/java -jar /opt/app/app.jar
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
---
### Q5:Shell脚本基础?
**答**:
```bash
#!/bin/bash
# 变量
NAME="app"
echo "Application: $NAME"
# 条件判断
if [ -f "/path/to/file" ]; then
echo "文件存在"
elif [ -d "/path/to/dir" ]; then
echo "目录存在"
else
echo "不存在"
fi
# 循环
for i in {1..5}; do
echo "Number: $i"
done
# 遍历文件
for file in /path/*.log; do
echo "Processing: $file"
done
# 函数
function deploy() {
local app_name=$1
echo "Deploying $app_name..."
}
deploy "my-app"
# 读取文件
while read line; do
echo "$line"
done < file.txt
```
**业务场景**:部署脚本
```bash
#!/bin/bash
APP_NAME="order-service"
JAR_FILE="/opt/app/${APP_NAME}.jar"
LOG_FILE="/var/log/${APP_NAME}.log"
PID_FILE="/var/run/${APP_NAME}.pid"
start() {
if [ -f "$PID_FILE" ]; then
echo "Application already running"
exit 1
fi
echo "Starting $APP_NAME..."
nohup java -jar -Xms512m -Xmx1024m $JAR_FILE > $LOG_FILE 2>&1 &
echo $! > $PID_FILE
echo "Started with PID: $(cat $PID_FILE)"
}
stop() {
if [ ! -f "$PID_FILE" ]; then
echo "Application not running"
exit 1
fi
PID=$(cat $PID_FILE)
echo "Stopping $APP_NAME (PID: $PID)..."
kill $PID
rm -f $PID_FILE
echo "Stopped"
}
restart() {
stop
sleep 2
start
}
case "$1" in
start) start ;;
stop) stop ;;
restart) restart ;;
*) echo "Usage: $0 {start|stop|restart}" ;;
esac
```
---
# 二、Docker面试题
### Q6:Docker的核心概念?
**答**:
| 概念 | 说明 |
|------|------|
| **镜像(Image)** | 只读模板,包含运行应用所需的所有内容 |
| **容器(Container)** | 镜像的运行实例,可以启动、停止、删除 |
| **仓库(Registry)** | 存储镜像的地方(Docker Hub、私有仓库) |
| **Dockerfile** | 构建镜像的脚本文件 |
| **数据卷(Volume)** | 持久化存储,容器删除数据不丢失 |
| **网络(Network)** | 容器间通信 |
```
关系图:
Dockerfile → (build) → Image → (run) → Container
↓
Registry(push/pull)
```
---
### Q7:Docker常用命令?
**答**:
```bash
# 镜像操作
docker images # 查看镜像
docker pull nginx:latest # 拉取镜像
docker build -t myapp:1.0 . # 构建镜像
docker push myrepo/myapp:1.0 # 推送镜像
docker rmi image_id # 删除镜像
# 容器操作
docker ps # 查看运行中容器
docker ps -a # 查看所有容器
docker run -d --name myapp -p 8080:8080 myapp:1.0 # 运行容器
docker start/stop/restart container # 启停容器
docker rm container # 删除容器
docker logs -f container # 查看日志
docker exec -it container /bin/bash # 进入容器
# 资源清理
docker system prune # 清理无用资源
docker image prune # 清理无用镜像
```
---
### Q8:Dockerfile最佳实践?
**答**:
```dockerfile
# ========== Java应用Dockerfile ==========
# 1. 使用多阶段构建,减小镜像体积
FROM maven:3.8-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
# 先下载依赖,利用缓存
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 2. 运行阶段使用精简镜像
FROM openjdk:11-jre-slim
WORKDIR /app
# 3. 创建非root用户运行
RUN groupadd -r app && useradd -r -g app app
USER app
# 4. 复制构建产物
COPY --from=builder /app/target/*.jar app.jar
# 5. 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 6. 暴露端口
EXPOSE 8080
# 7. 启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]
# 8. 传入JVM参数
CMD ["-Xms512m", "-Xmx1024m"]
```
**最佳实践要点**:
```
1. 使用多阶段构建 → 减小镜像体积
2. 合理利用缓存 → 先COPY依赖文件,再COPY源码
3. 使用.dockerignore → 排除不需要的文件
4. 最小化层数 → 合并RUN命令
5. 使用非root用户 → 安全
6. 添加健康检查 → 便于监控
7. 指定镜像版本 → 避免使用latest
```
---
### Q9:Docker网络模式有哪些?
**答**:
| 网络模式 | 说明 | 使用场景 |
|---------|------|---------|
| **bridge** | 默认模式,容器有独立网络命名空间 | 大多数场景 |
| **host** | 容器使用宿主机网络 | 需要高性能网络 |
| **none** | 无网络 | 安全隔离 |
| **container** | 共享其他容器网络 | 网络调试 |
| **overlay** | 跨主机网络 | Docker Swarm/K8s |
```bash
# 创建自定义网络
docker network create mynet
# 容器加入网络
docker run -d --name app1 --network mynet myapp:1.0
docker run -d --name app2 --network mynet myapp:1.0
# 同一网络内可以通过容器名通信
# app1可以访问app2: http://app2:8080
```
---
### Q10:Docker Compose是什么?
**答**:
Docker Compose用于定义和运行多容器应用。
```yaml
# docker-compose.yml
version: '3.8'
services:
# 应用服务
app:
build: .
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- MYSQL_HOST=mysql
- REDIS_HOST=redis
depends_on:
- mysql
- redis
restart: always
networks:
- app-network
# MySQL
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=root123
- MYSQL_DATABASE=myapp
volumes:
- mysql-data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app-network
# Redis
redis:
image: redis:6.2
command: redis-server --appendonly yes
volumes:
- redis-data:/data
ports:
- "6379:6379"
networks:
- app-network
# Nginx
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- app
networks:
- app-network
volumes:
mysql-data:
redis-data:
networks:
app-network:
driver: bridge
```
```bash
# 常用命令
docker-compose up -d # 启动所有服务
docker-compose down # 停止并删除
docker-compose ps # 查看服务状态
docker-compose logs -f app # 查看日志
docker-compose restart app # 重启服务
```
---
# 三、Kubernetes面试题
### Q11:K8s的核心概念?
**答**:
| 概念 | 说明 |
|------|------|
| **Pod** | 最小部署单元,包含一个或多个容器 |
| **Deployment** | 管理Pod副本,支持滚动更新 |
| **Service** | 服务发现和负载均衡 |
| **ConfigMap** | 配置管理(非敏感) |
| **Secret** | 敏感配置(密码、证书) |
| **Namespace** | 资源隔离 |
| **Ingress** | 外部访问入口(HTTP/HTTPS路由) |
| **PV/PVC** | 持久化存储 |
```
架构图:
┌─────────────┐
│ Ingress │ (外部访问)
└──────┬──────┘
│
┌──────▼──────┐
│ Service │ (负载均衡)
└──────┬──────┘
┌───────────────┼───────────────┐
│ │ │
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
│ Pod │ │ Pod │ │ Pod │
│ (app:v1) │ │ (app:v1) │ │ (app:v1) │
└───────────┘ └───────────┘ └───────────┘
│
┌──────▼──────┐
│ Deployment │ (管理Pod)
└─────────────┘
```
---
### Q12:常用的kubectl命令?
**答**:
```bash
# 查看资源
kubectl get pods # 查看Pod
kubectl get pods -o wide # 详细信息(含IP、节点)
kubectl get deploy,svc,pods # 查看多种资源
kubectl get all -n namespace # 查看命名空间所有资源
# 查看详情
kubectl describe pod <pod-name> # Pod详情
kubectl logs <pod-name> # 查看日志
kubectl logs -f <pod-name> -c <container> # 实时日志
# 进入容器
kubectl exec -it <pod-name> -- /bin/bash
# 应用配置
kubectl apply -f deployment.yaml # 应用配置
kubectl delete -f deployment.yaml # 删除资源
# 扩缩容
kubectl scale deployment <name> --replicas=5
# 滚动更新
kubectl set image deployment/<name> <container>=<image>:<tag>
kubectl rollout status deployment/<name> # 查看更新状态
kubectl rollout undo deployment/<name> # 回滚
# 调试
kubectl describe pod <pod-name> # 查看事件
kubectl logs <pod-name> --previous # 查看上一个容器的日志
kubectl port-forward <pod-name> 8080:8080 # 端口转发
```
---
### Q13:K8s的Deployment配置?
**答**:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
namespace: production
labels:
app: order-service
spec:
replicas: 3 # 副本数
selector:
matchLabels:
app: order-service
# 滚动更新策略
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 最多多出1个Pod
maxUnavailable: 0 # 最少保持全部可用
template:
metadata:
labels:
app: order-service
spec:
containers:
- name: order-service
image: myrepo/order-service:v1.0.0
ports:
- containerPort: 8080
# 资源限制
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
# 环境变量
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: password
# 配置文件挂载
volumeMounts:
- name: config
mountPath: /app/config
# 健康检查
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 10
periodSeconds: 5
volumes:
- name: config
configMap:
name: order-service-config
```
---
### Q14:K8s的Service类型有哪些?
**答**:
| 类型 | 说明 | 使用场景 |
|------|------|---------|
| **ClusterIP** | 集群内部访问(默认) | 内部服务 |
| **NodePort** | 通过节点端口访问 | 开发测试 |
| **LoadBalancer** | 云厂商负载均衡 | 生产环境 |
| **ExternalName** | DNS别名 | 外部服务 |
```yaml
# ClusterIP(内部服务)
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
type: ClusterIP
selector:
app: order-service
ports:
- port: 80
targetPort: 8080
---
# NodePort(外部访问)
apiVersion: v1
kind: Service
metadata:
name: order-service-nodeport
spec:
type: NodePort
selector:
app: order-service
ports:
- port: 80
targetPort: 8080
nodePort: 30080 # 30000-32767
```
---
### Q15:K8s如何实现滚动更新和回滚?
**答**:
```bash
# 滚动更新(自动)
kubectl set image deployment/order-service order-service=myrepo/order-service:v2.0.0
# 查看更新状态
kubectl rollout status deployment/order-service
# 查看更新历史
kubectl rollout history deployment/order-service
# 回滚到上一个版本
kubectl rollout undo deployment/order-service
# 回滚到指定版本
kubectl rollout undo deployment/order-service --to-revision=2
# 暂停/恢复更新
kubectl rollout pause deployment/order-service
kubectl rollout resume deployment/order-service
```
**滚动更新策略说明**:
```yaml
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 25% # 最多超出期望副本数的比例
maxUnavailable: 25% # 最多不可用副本数的比例
# 示例:3个副本
# maxSurge: 1 → 更新时最多4个Pod
# maxUnavailable: 0 → 更新时至少保持3个Pod可用
# 流程:新建1个v2 → 等待v2就绪 → 删除1个v1 → 重复
```
---
# 四、Nginx面试题
### Q16:Nginx的常用配置?
**答**:
```nginx
# nginx.conf 主配置
# 全局配置
worker_processes auto; # 工作进程数
error_log /var/log/nginx/error.log;
events {
worker_connections 1024; # 每个进程最大连接数
use epoll; # Linux使用epoll
}
http {
include mime.types;
default_type application/octet-stream;
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time';
access_log /var/log/nginx/access.log main;
# 性能优化
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Gzip压缩
gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;
# 上游服务器(负载均衡)
upstream backend {
least_conn; # 最少连接策略
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 backup; # 备用
keepalive 32; # 保持连接数
}
# 虚拟主机
server {
listen 80;
server_name www.example.com;
# 静态文件
location /static/ {
root /var/www;
expires 7d; # 缓存7天
}
# API反向代理
location /api/ {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 超时设置
proxy_connect_timeout 60s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
# 健康检查
location /health {
return 200 "OK";
}
}
}
```
---
### Q17:Nginx负载均衡策略有哪些?
**答**:
| 策略 | 说明 | 配置 |
|------|------|------|
| **轮询** | 默认,依次分配 | 无需配置 |
| **权重** | 按权重分配 | `weight=3` |
| **IP哈希** | 同一IP访问同一后端 | `ip_hash` |
| **最少连接** | 分配给连接最少的服务器 | `least_conn` |
| **URL哈希** | 同一URL访问同一后端 | `hash $request_uri` |
```nginx
# 权重轮询
upstream backend {
server 192.168.1.10:8080 weight=5;
server 192.168.1.11:8080 weight=3;
server 192.168.1.12:8080 weight=2;
}
# IP哈希(会话保持)
upstream backend {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
# 最少连接
upstream backend {
least_conn;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
```
---
### Q18:Nginx如何配置HTTPS?
**答**:
```nginx
server {
listen 80;
server_name www.example.com;
# HTTP重定向到HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example.com;
# SSL证书
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# SSL优化
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 安全协议和加密套件
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers on;
# HSTS(强制HTTPS)
add_header Strict-Transport-Security "max-age=31536000" always;
location / {
proxy_pass http://backend;
}
}
```
---
### Q19:Nginx如何限流?
**答**:
```nginx
http {
# 定义限流区域
# 按IP限流,10m共享内存,每秒10个请求
limit_req_zone $binary_remote_addr zone=ip_limit:10m rate=10r/s;
# 按接口限流
limit_req_zone $uri zone=api_limit:10m rate=100r/s;
server {
# 应用限流
location /api/ {
# burst=20:允许突发20个请求
# nodelay:不延迟处理
limit_req zone=ip_limit burst=20 nodelay;
proxy_pass http://backend;
}
# 限制连接数
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
location /download/ {
limit_conn conn_limit 5; # 每IP最多5个连接
limit_rate 100k; # 限速100KB/s
}
}
}
```
---
# 五、CI/CD面试题
### Q20:什么是CI/CD?
**答**:
```
CI(Continuous Integration)持续集成:
- 代码提交后自动构建、测试
- 快速发现问题,减少集成风险
CD(Continuous Delivery/Deployment)持续交付/部署:
- 持续交付:自动构建、测试、准备发布,手动部署
- 持续部署:完全自动化,代码提交后自动部署到生产
流程:
代码提交 → 自动构建 → 单元测试 → 代码扫描 → 构建镜像 → 部署测试环境 → 集成测试 → 部署生产
↑ │
└──────────────────────────────────────────────────────────────────────────────┘
反馈循环
```
---
### Q21:Jenkins Pipeline配置?
**答**:
```groovy
// Jenkinsfile
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'harbor.example.com'
IMAGE_NAME = 'order-service'
}
stages {
// 拉取代码
stage('Checkout') {
steps {
git branch: 'main', url: 'https://github.com/xxx/order-service.git'
}
}
// 编译构建
stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}
// 单元测试
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit '**/target/surefire-reports/*.xml'
}
}
}
// 代码扫描
stage('SonarQube') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn sonar:sonar'
}
}
}
// 构建Docker镜像
stage('Docker Build') {
steps {
script {
def imageTag = "${env.BUILD_NUMBER}"
sh "docker build -t ${DOCKER_REGISTRY}/${IMAGE_NAME}:${imageTag} ."
sh "docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${imageTag}"
}
}
}
// 部署测试环境
stage('Deploy to Test') {
steps {
sh """
kubectl set image deployment/${IMAGE_NAME} \
${IMAGE_NAME}=${DOCKER_REGISTRY}/${IMAGE_NAME}:${env.BUILD_NUMBER} \
-n test
"""
}
}
// 人工确认
stage('Approval') {
steps {
input message: '确认部署到生产环境?', ok: '部署'
}
}
// 部署生产环境
stage('Deploy to Production') {
steps {
sh """
kubectl set image deployment/${IMAGE_NAME} \
${IMAGE_NAME}=${DOCKER_REGISTRY}/${IMAGE_NAME}:${env.BUILD_NUMBER} \
-n production
"""
}
}
}
post {
success {
dingtalk(
robot: 'dingding-robot',
type: 'TEXT',
text: ["构建成功: ${env.JOB_NAME} #${env.BUILD_NUMBER}"]
)
}
failure {
dingtalk(
robot: 'dingding-robot',
type: 'TEXT',
text: ["构建失败: ${env.JOB_NAME} #${env.BUILD_NUMBER}"]
)
}
}
}
```
---
### Q22:GitLab CI/CD配置?
**答**:
```yaml
# .gitlab-ci.yml
stages:
- build
- test
- docker
- deploy
variables:
DOCKER_REGISTRY: harbor.example.com
IMAGE_NAME: order-service
# 构建
build:
stage: build
image: maven:3.8-openjdk-11
script:
- mvn clean package -DskipTests
artifacts:
paths:
- target/*.jar
expire_in: 1 hour
only:
- main
- develop
# 测试
test:
stage: test
image: maven:3.8-openjdk-11
script:
- mvn test
artifacts:
reports:
junit: target/surefire-reports/*.xml
only:
- main
- develop
# 构建Docker镜像
docker:
stage: docker
image: docker:latest
services:
- docker:dind
script:
- docker login -u $DOCKER_USER -p $DOCKER_PASSWORD $DOCKER_REGISTRY
- docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA .
- docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA
only:
- main
# 部署测试环境
deploy_test:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/$IMAGE_NAME $IMAGE_NAME=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA -n test
environment:
name: test
only:
- develop
# 部署生产环境(手动触发)
deploy_prod:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl set image deployment/$IMAGE_NAME $IMAGE_NAME=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA -n production
environment:
name: production
when: manual
only:
- main
```
---
# 六、监控与故障排查
### Q23:常用的监控方案?
**答**:
| 工具 | 用途 | 特点 |
|------|------|------|
| **Prometheus** | 指标采集 | 时序数据库,Pull模式 |
| **Grafana** | 可视化 | 丰富的Dashboard |
| **ELK** | 日志收集分析 | Elasticsearch+Logstash+Kibana |
| **Jaeger/Zipkin** | 链路追踪 | 分布式追踪 |
| **Alertmanager** | 告警管理 | 配合Prometheus |
**监控体系**:
```
┌─────────────────────────────────────┐
│ Grafana │
│ (可视化展示) │
└─────────────────┬───────────────────┘
│
┌───────────────────────────┼───────────────────────────┐
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐
│Prometheus │ │ Elasticsearch│ │ Jaeger │
│ (指标) │ │ (日志) │ │ (链路追踪) │
└─────┬─────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Exporter │ │ Filebeat │ │ Agent │
└───────────┘ └─────────────┘ └─────────────┘
│ │ │
┌─────▼──────────────────────────▼───────────────────────────▼─────┐
│ 应用服务 │
└──────────────────────────────────────────────────────────────────┘
```
---
### Q24:如何排查线上问题?
**答**:
**排查流程**:
```
1. 确认问题现象
└─ 接口慢?报错?服务不可用?
2. 查看监控指标
├─ CPU、内存、网络、磁盘
└─ QPS、响应时间、错误率
3. 查看日志
├─ 应用日志(ERROR、WARN)
├─ Nginx日志(5xx错误)
└─ 系统日志(/var/log/messages)
4. 定位问题服务
└─ 链路追踪(Jaeger/Skywalking)
5. 深入分析
├─ JVM问题:jstack、jmap、arthas
├─ 数据库问题:慢查询日志
└─ 网络问题:tcpdump、wireshark
```
**常见问题排查命令**:
```bash
# 1. CPU过高
top -Hp <pid> # 找到高CPU线程
printf "%x\n" <tid> # 转16进制
jstack <pid> | grep -A 30 <tid> # 查看线程堆栈
# 2. 内存问题
jmap -heap <pid> # 查看堆内存
jmap -histo:live <pid> # 对象统计
jmap -dump:format=b,file=heap.hprof <pid> # 堆转储
# 3. GC问题
jstat -gc <pid> 1000 # 每秒输出GC信息
jstat -gcutil <pid> 1000 # GC统计百分比
# 4. 线程死锁
jstack <pid> | grep -A 50 "deadlock"
# 5. 使用Arthas(推荐)
# 下载并启动
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
# Arthas常用命令
dashboard # 总览
thread -n 3 # 最忙的3个线程
trace com.xxx.Service method # 方法耗时追踪
watch com.xxx.Service method returnObj # 观察方法返回值
```
---
### Q25:如何进行容量规划?
**答**:
**评估公式**:
```
QPS估算:
日均PV / (24 * 3600 * 访问集中比例) = 平均QPS
峰值QPS = 平均QPS * 峰值倍数(通常2-10倍)
机器数量:
机器数 = 峰值QPS / 单机QPS * 冗余系数(1.5-2)
示例:
日均PV = 1000万
集中访问时间 = 8小时(比例=8/24=0.33)
平均QPS = 10000000 / (8 * 3600) ≈ 350
峰值QPS = 350 * 3 = 1050
单机QPS = 500(压测得出)
机器数 = 1050 / 500 * 1.5 ≈ 4台
```
**压测指标**:
```
关注指标:
- QPS/TPS
- 响应时间(P99、P95、P50)
- 错误率
- CPU、内存、网络使用率
压测工具:
- JMeter
- wrk
- ab (Apache Bench)
- Locust
```
---
## 📝 面试速记卡
```
【Linux】
文件搜索:find/grep/awk/sed
进程管理:ps/top/kill/nohup/systemctl
资源监控:top/free/df/iostat/netstat
【Docker】
核心:镜像(Image)、容器(Container)、仓库(Registry)
Dockerfile:多阶段构建、最小化层数、非root用户
网络:bridge(默认)、host、overlay(跨主机)
【Kubernetes】
核心对象:Pod、Deployment、Service、ConfigMap、Secret
Service类型:ClusterIP(内部)、NodePort、LoadBalancer
滚动更新:kubectl set image、kubectl rollout undo
【Nginx】
负载均衡:轮询、权重、ip_hash、least_conn
限流:limit_req_zone + limit_req
【CI/CD】
流程:代码→构建→测试→扫描→镜像→部署
工具:Jenkins、GitLab CI、GitHub Actions
【监控】
三大件:Prometheus(指标) + ELK(日志) + Jaeger(链路)
排查:top → jstack → jmap → arthas
```
---
**文档版本**:v1.0
**创建时间**:2026-01-19
**适用场景**:后端开发运维面试