Java面试秋招之云原生与容器化
第11章 云原生与容器化
面试重要程度:⭐⭐⭐⭐
常见提问方式:Docker原理、K8s架构、微服务治理
预计阅读时间:35分钟
开场白
兄弟,云原生和容器化绝对是当下最热门的技术趋势!现在的大厂面试,基本都会问到Docker、Kubernetes这些技术。这不仅是技术发展的必然,更是现代化应用部署和运维的标配。
今天我们就把云原生技术栈的核心知识点搞清楚,让你在面试中展现出对现代化架构的深度理解。
🐳 11.1 Docker容器技术
Docker核心原理
面试必问:
面试官:"Docker是如何实现容器隔离的?和虚拟机有什么区别?"
Docker vs 虚拟机对比:
虚拟机架构: ┌─────────────────────────────────────┐ │ 应用程序 + 依赖 │ ├─────────────────────────────────────┤ │ 客户操作系统 │ ├─────────────────────────────────────┤ │ Hypervisor │ ├─────────────────────────────────────┤ │ 宿主操作系统 │ ├─────────────────────────────────────┤ │ 物理硬件 │ └─────────────────────────────────────┘ Docker架构: ┌─────────────────────────────────────┐ │ 应用程序 + 依赖 │ ├─────────────────────────────────────┤ │ Docker Engine │ ├─────────────────────────────────────┤ │ 宿主操作系统 │ ├─────────────────────────────────────┤ │ 物理硬件 │ └─────────────────────────────────────┘ 优势对比: - 资源利用率:Docker > 虚拟机 - 启动速度:Docker(秒级) > 虚拟机(分钟级) - 镜像大小:Docker(MB级) < 虚拟机(GB级) - 性能开销:Docker(几乎无) < 虚拟机(5-15%)
Docker核心技术:
# 1. Namespace(命名空间隔离) # PID namespace - 进程隔离 docker run -it --pid=host ubuntu ps aux # 可以看到宿主机进程 # Network namespace - 网络隔离 docker run -it --network=host ubuntu netstat -tlnp # Mount namespace - 文件系统隔离 docker run -it -v /host/path:/container/path ubuntu # UTS namespace - 主机名隔离 docker run -it --hostname=mycontainer ubuntu hostname # IPC namespace - 进程间通信隔离 docker run -it --ipc=host ubuntu # User namespace - 用户隔离 docker run -it --user=1000:1000 ubuntu id # 2. Cgroups(资源限制) # CPU限制 docker run -it --cpus="1.5" ubuntu # 内存限制 docker run -it --memory="512m" ubuntu # IO限制 docker run -it --device-read-bps /dev/sda:1mb ubuntu # 3. Union FS(联合文件系统) # 查看镜像层 docker history nginx:latest docker inspect nginx:latest
Dockerfile最佳实践
高效Dockerfile编写:
# 多阶段构建示例
# 第一阶段:构建阶段
FROM maven:3.8.4-openjdk-17 AS builder
WORKDIR /app
# 先复制依赖文件,利用Docker缓存
COPY pom.xml .
RUN mvn dependency:go-offline -B
# 再复制源码并构建
COPY src ./src
RUN mvn clean package -DskipTests
# 第二阶段:运行阶段
FROM openjdk:17-jre-slim
# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
# 安装必要的工具
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# 从构建阶段复制jar包
COPY --from=builder /app/target/*.jar app.jar
# 创建日志目录
RUN mkdir -p /app/logs && chown -R appuser:appuser /app
# 切换到非root用户
USER appuser
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 暴露端口
EXPOSE 8080
# JVM参数优化
ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:+PrintGCDetails"
# 启动命令
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
Docker镜像优化技巧:
# 1. 选择合适的基础镜像
FROM openjdk:17-jre-slim # 而不是 openjdk:17
# 2. 合并RUN指令,减少镜像层
RUN apt-get update && apt-get install -y \
curl \
wget \
vim \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean
# 3. 使用.dockerignore文件
# .dockerignore内容:
# target/
# *.log
# .git/
# README.md
# 4. 利用构建缓存
# 把变化频率低的指令放在前面
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package
# 5. 清理不必要的文件
RUN apt-get update && apt-get install -y package \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& rm -rf /tmp/*
Docker Compose服务编排
复杂应用编排:
# docker-compose.yml
version: '3.8'
services:
# 应用服务
app:
build:
context: .
dockerfile: Dockerfile
args:
- BUILD_ENV=production
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=docker
- DB_HOST=mysql
- REDIS_HOST=redis
depends_on:
mysql:
condition: service_healthy
redis:
condition: service_started
volumes:
- ./logs:/app/logs
- ./config:/app/config:ro
networks:
- app-network
restart: unless-stopped
deploy:
resources:
limits:
cpus: '2.0'
memory: 1G
reservations:
cpus: '0.5'
memory: 512M
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# MySQL数据库
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=myapp
- MYSQL_USER=appuser
- MYSQL_PASSWORD=apppassword
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
networks:
- app-network
command: --default-authentication-plugin=mysql_native_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
# Redis缓存
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
- ./redis.conf:/usr/local/etc/redis/redis.conf:ro
networks:
- app-network
command: redis-server /usr/local/etc/redis/redis.conf
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
# Nginx反向代理
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
networks:
- app-network
restart: unless-stopped
# 监控服务
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
networks:
- app-network
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
volumes:
mysql_data:
driver: local
redis_data:
driver: local
prometheus_data:
driver: local
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
☸️ 11.2 Kubernetes容器编排
K8s核心概念
面试重点:
面试官:"Kubernetes的核心组件有哪些?Pod和Container的关系是什么?"
K8s架构图:
Master节点: ┌─────────────────────────────────────┐ │ kube-apiserver (API服务器) │ ├─────────────────────────────────────┤ │ etcd (分布式存储) │ ├─────────────────────────────────────┤ │ kube-scheduler (调度器) │ ├─────────────────────────────────────┤ │ kube-controller-manager (控制器) │ └─────────────────────────────────────┘ Worker节点: ┌─────────────────────────────────────┐ │ kubelet (节点代理) │ ├─────────────────────────────────────┤ │ kube-proxy (网络代理) │ ├─────────────────────────────────────┤ │ Container Runtime (容器运行时) │ └─────────────────────────────────────┘
核心资源对象:
# 1. Pod - 最小部署单元
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
labels:
app: my-app
version: v1.0
spec:
containers:
- name: app-container
image: my-app:v1.0
ports:
- containerPort: 8080
env:
- name: DB_HOST
value: "mysql-service"
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
- name: sidecar-container
image: nginx:alpine
ports:
- containerPort: 80
---
# 2. Deployment - 部署管理
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v1.0
ports:
- containerPort: 8080
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
---
# 3. Service - 服务发现
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
---
# 4. Ingress - 外部访问
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: my-app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app-service
port:
number: 80
---
# 5. ConfigMap - 配置管理
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app-config
data:
application.yml: |
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://mysql-service:3306/myapp
username: appuser
password: apppassword
---
# 6. Secret - 敏感信息
apiVersion: v1
kind: Secret
metadata:
name: my-app-secret
type: Opaque
data:
db-password: YXBwcGFzc3dvcmQ= # base64编码
api-key: bXlhcGlrZXk=
---
# 7. PersistentVolume - 持久化存储
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-app-pv
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: fast-ssd
hostPath:
path: /data/my-app
---
# 8. PersistentVolumeClaim - 存储声明
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-app-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: fast-ssd
K8s网络模型
网络通信原理:
# 1. Pod内容器通信 - 共享网络命名空间
apiVersion: v1
kind: Pod
metadata:
name: multi-container-pod
spec:
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080
- name: sidecar
image: nginx:alpine
ports:
- containerPort: 80
# 两个容器共享网络,可以通过localhost通信
---
# 2. Pod间通信 - 通过Service
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 8080
type: ClusterIP
---
# 3. 跨命名空间通信
apiVersion: v1
kind: Service
metadata:
name: cross-namespace-service
namespace: production
spec:
type: ExternalName
externalName: backend-service.development.svc.cluster.local
---
# 4. 外部访问 - NodePort
apiVersion: v1
kind: Service
metadata:
name: external-service
spec:
selector:
app: my-app
ports:
- port: 80
targetPort: 8080
nodePort: 30080
type: NodePort
---
# 5. 负载均衡 - LoadBalancer
apiVersion: v1
kind:
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
Java面试圣经 文章被收录于专栏
Java面试圣经,带你练透java圣经