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

全部评论
考虑南京OD的宝子们看过来,你就是我们要找的人,一对一指导,******
点赞 回复 分享
发布于 08-09 16:23 贵州

相关推荐

评论
2
4
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务