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圣经