云原生技术正在重塑现代软件开发和部署的方式。从单体应用到微服务,从虚拟机到容器,从手动部署到自动化编排,这一系列转变背后是云原生理念的推动。理解容器技术和
Kubernetes 编排系统,已经成为现代 DevOps 工程师的必备技能。
本文将从云原生的核心理念出发,深入探讨 Docker
容器技术的实现细节,然后系统介绍 Kubernetes
集群的部署与管理,最后通过实战案例展示如何构建完整的云原生应用栈。无论你是刚开始接触容器技术,还是希望深入理解
Kubernetes 的底层机制,都能在本文中找到实用的内容。
云原生概念与 12 要素应用
什么是云原生
云原生( Cloud
Native)是一种构建和运行应用程序的方法,充分利用云计算的优势。 CNCF(
Cloud Native Computing
Foundation)将其定义为:云原生技术使组织能够在现代动态环境(如公有云、私有云和混合云)中构建和运行可扩展的应用程序。
云原生的核心特征包括:
- 容器化:应用打包在容器中,实现环境一致性
- 微服务架构:应用拆分为小型、独立的服务
- 动态编排:通过 Kubernetes
等工具自动管理容器生命周期
- DevOps 文化:开发与运维紧密协作,实现持续交付
12 要素应用( 12-Factor App)
12 要素应用是一套构建 SaaS
应用的最佳实践,这些原则同样适用于云原生应用:
- 代码库(
Codebase):一个代码库对应多个部署环境
- 依赖( Dependencies):显式声明并隔离依赖
- 配置( Config):将配置存储在环境变量中
- 后端服务( Backing
Services):将数据库、消息队列等视为附加资源
- 构建、发布、运行( Build, Release,
Run):严格分离构建和运行阶段
- 进程( Processes):应用作为无状态进程运行
- 端口绑定( Port
Binding):应用通过端口绑定提供服务
- 并发( Concurrency):通过进程模型进行扩展
- 易处理( Disposability):快速启动和优雅关闭
- 开发/生产环境等价( Dev/Prod
Parity):保持开发和生产环境尽可能相似
- 日志( Logs):将日志视为事件流
- 管理进程( Admin
Processes):将管理任务作为一次性进程运行
这些原则指导我们设计可扩展、可维护的云原生应用。
Docker 容器技术详解
Docker 架构与核心概念
Docker 采用客户端-服务器架构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| ┌─────────────┐ │ Docker CLI │ ← 客户端 └──────┬──────┘ │ │ API 调用 ▼ ┌─────────────────┐ │ Docker Daemon │ ← 服务端( dockerd) │ - 镜像管理 │ │ - 容器管理 │ │ - 网络管理 │ │ - 存储管理 │ └─────────────────┘ │ ▼ ┌─────────────────┐ │ Linux Kernel │ │ - Namespaces │ │ - Cgroups │ │ - Union FS │ └─────────────────┘
|
核心组件:
- 镜像( Image):只读的模板,用于创建容器
- 容器(
Container):镜像的运行实例,包含应用和运行时环境
- 仓库( Registry):存储镜像的地方,如 Docker
Hub
- Dockerfile:用于构建镜像的文本文件
镜像管理
镜像采用分层存储结构,每一层都是只读的。多个容器可以共享相同的镜像层,节省存储空间。
查看镜像:
1 2 3 4 5 6 7 8
| docker images
docker inspect nginx:latest
docker history nginx:latest
|
拉取和推送镜像:
1 2 3 4 5 6 7 8 9
| docker pull nginx:1.21
docker pull registry.example.com/myapp:v1.0
docker tag myapp:v1.0 registry.example.com/myapp:v1.0 docker push registry.example.com/myapp:v1.0
|
镜像构建:
1 2 3 4 5 6 7 8
| docker build -t myapp:v1.0 .
docker build -f Dockerfile.prod -t myapp:prod .
docker build --build-arg VERSION=1.0 -t myapp:v1.0 .
|
容器管理
容器是镜像的运行实例,具有独立的文件系统、网络和进程空间。
容器生命周期:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker run -d --name myapp nginx:latest
docker start myapp
docker stop myapp
docker restart myapp
docker rm myapp
docker rm -f myapp
|
容器交互:
1 2 3 4 5 6 7 8 9 10 11
| docker exec -it myapp /bin/bash
docker exec myapp ls /var/log
docker logs -f myapp
docker stats myapp
|
容器导出和导入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker export myapp > myapp.tar
docker import myapp.tar myapp:v1.0
docker save myapp:v1.0 > myapp.tar
docker load < myapp.tar
docker save myapp:v1.0 myapp:v2.0 nginx:latest > all-images.tar
|
容器监控和调试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| docker stats myapp
docker stats --no-stream myapp
docker top myapp
docker inspect myapp
docker inspect -f '{{ .NetworkSettings.IPAddress }}' myapp docker inspect -f '{{ .State.Status }}' myapp
docker events --filter container=myapp
docker logs -f --timestamps myapp
docker logs --tail 100 myapp
docker logs --since 2025-01-02T10:00:00 myapp docker logs --until 2025-01-02T12:00:00 myapp
|
容器故障排查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| docker ps --filter "health=unhealthy"
docker inspect -f '{{ .State.ExitCode }}' myapp
docker inspect myapp | grep -A 10 "State"
docker exec -it myapp /bin/bash
docker exec -it myapp /bin/sh
docker exec myapp ps aux docker exec myapp netstat -tlnp docker exec myapp env
docker cp local-file.txt myapp:/app/
docker cp myapp:/app/log.txt ./log.txt
docker network inspect bridge | grep -A 10 myapp
docker exec myapp ping -c 3 8.8.8.8 docker exec myapp curl http://another-container:8080
|
容器批量操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker stop $(docker ps -q)
docker rm $(docker ps -aq)
docker rm -f $(docker ps -aq)
docker container prune
docker system prune -a
docker stats --no-stream --format "table {{ .Container }}\t{{ .CPUPerc }}\t{{ .MemUsage }}"
|
容器性能优化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| docker run -d --name myapp \ --memory="512m" \ --cpus="1.0" \ --cpu-shares=1024 \ myapp:latest
docker run -d --name myapp \ --restart=always \ myapp:latest
docker run -d --name myapp \ --oom-kill-disable \ --memory="512m" \ myapp:latest
|
Docker 网络详解
Docker
提供了多种网络模式,满足不同的网络需求。理解这些网络模式对于构建复杂的容器化应用至关重要。
网络模式概览:
- bridge(桥接):默认模式,容器通过虚拟网桥连接
- host(主机):容器直接使用主机网络
- none(无):容器没有网络接口
- overlay(覆盖):用于多主机网络,常用于 Swarm 或
Kubernetes
- macvlan:容器获得 MAC 地址,直接连接到物理网络
Bridge 网络详解
Bridge 网络是 Docker 的默认网络模式,每个容器都连接到名为
docker0 的虚拟网桥。容器之间可以通过容器名称或 IP
地址通信。
Bridge 网络工作原理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ┌─────────────┐ ┌─────────────┐ │ Container1 │ │ Container2 │ │ 172.17.0.2 │ │ 172.17.0.3 │ └──────┬──────┘ └──────┬──────┘ │ │ └──────────┬───────────┘ │ ┌─────▼─────┐ │ docker0 │ │ 172.17.0.1 │ └─────┬─────┘ │ ┌─────▼─────┐ │ Host │ │ Interface │ └───────────┘
|
创建自定义 Bridge 网络:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| docker network create mynetwork
docker network create --driver bridge \ --subnet=172.20.0.0/16 \ --gateway=172.20.0.1 \ --ip-range=172.20.240.0/20 \ mynetwork
docker network create --driver bridge \ --subnet=172.20.0.0/16 \ --gateway=172.20.0.1 \ --dns=8.8.8.8 \ --dns=8.8.4.4 \ mynetwork
docker network create --driver bridge \ --internal \ isolated-network
|
Bridge 网络高级配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| docker network inspect mynetwork
docker network connect mynetwork myapp
docker network connect --ip=172.20.0.100 mynetwork myapp
docker network disconnect mynetwork myapp
docker network rm mynetwork
docker network rm -f mynetwork
|
Bridge 网络容器间通信:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| docker network create app-network
docker run -d --name mysql \ --network app-network \ --network-alias db \ -e MYSQL_ROOT_PASSWORD=secret \ mysql:8.0
docker run -d --name app \ --network app-network \ -e DB_HOST=mysql \ -e DB_HOST_ALT=db \ myapp:latest
docker exec app ping -c 3 mysql docker exec app ping -c 3 db
|
Host 网络模式
Host
网络模式下,容器直接使用主机的网络栈,没有网络隔离。性能最好,但安全性较低。
使用 Host 网络:
1 2 3 4 5 6 7
| docker run -d --name nginx \ --network host \ nginx:latest
|
Host 网络适用场景:
- 需要最佳网络性能的应用
- 需要直接访问主机网络服务的场景
- 网络密集型应用(如负载均衡器)
Host 网络注意事项:
- 容器端口直接绑定到主机,可能造成端口冲突
- 无法在同一主机上运行多个使用相同端口的容器
- 安全性较低,容器可以直接访问主机网络
Overlay 网络详解
Overlay 网络用于跨多个 Docker 主机连接容器,常用于 Docker Swarm 或
Kubernetes 集群。
创建 Overlay 网络( Swarm 模式):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| docker swarm init
docker network create \ --driver overlay \ --subnet=10.0.0.0/24 \ --attachable \ my-overlay-network
docker service create \ --name web \ --network my-overlay-network \ --replicas 3 \ nginx:latest
|
Overlay 网络特性:
- 跨主机容器通信
- 自动服务发现
- 加密通信(可选)
- 支持多子网
Overlay 网络配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13
| docker network create \ --driver overlay \ --opt encrypted=true \ secure-overlay
docker network create \ --driver overlay \ --subnet=10.1.0.0/24 \ --gateway=10.1.0.1 \ --ip-range=10.1.0.0/25 \ custom-overlay
|
Macvlan 网络
Macvlan 允许容器直接连接到物理网络,每个容器都有独立的 MAC 地址。
创建 Macvlan 网络:
1 2 3 4 5 6 7 8 9 10 11 12
| docker network create -d macvlan \ --subnet=192.168.1.0/24 \ --gateway=192.168.1.1 \ -o parent=eth0 \ macvlan-net
docker run -d --name app \ --network macvlan-net \ --ip=192.168.1.100 \ myapp:latest
|
Macvlan 网络管理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| docker network ls
docker network inspect mynetwork
docker network inspect mynetwork --format '{{ range .Containers }}{{ .Name }} {{ end }}'
docker network prune
docker network prune -a
|
网络故障排查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| docker inspect <container-name> | grep -A 20 "NetworkSettings"
docker exec <container1> ping <container2-ip>
docker exec <container> cat /etc/resolv.conf
docker exec <container> ip addr show
docker run --rm --privileged --network host \ nicolaka/netshoot tcpdump -i eth0
|
Docker 存储驱动与卷管理
Docker
提供了多种数据持久化方案和存储驱动,理解这些机制对于优化容器性能和确保数据安全至关重要。
存储驱动详解
存储驱动控制 Docker
如何在宿主机上存储和管理镜像层。选择合适的存储驱动可以显著影响性能。
Docker 支持的存储驱动:
- overlay2:推荐使用,性能好,支持最多 128
层,适合大多数场景
- devicemapper:基于设备映射,适合生产环境,但性能不如
overlay2
- aufs:早期版本使用,现在较少使用,兼容性较好
- btrfs:需要 btrfs 文件系统支持,支持快照和压缩
- zfs:需要 ZFS 文件系统支持,功能强大但配置复杂
查看和配置存储驱动:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker info | grep "Storage Driver"
docker system df -v
cat /etc/docker/daemon.json
{ "storage-driver": "overlay2", "storage-opts": [ "overlay2.override_kernel_check=true" ] }
|
Overlay2 存储驱动详解:
Overlay2 是推荐的存储驱动,使用 Linux 内核的 OverlayFS 文件系统。
工作原理: 1 2 3 4 5 6 7 8 9 10 11
| 镜像层结构: ┌─────────────────┐ │ Container │ ← 可写层(容器层) ├─────────────────┤ │ Upper Dir │ ← 容器修改的文件 ├─────────────────┤ │ Lower Dirs │ ← 只读镜像层(多个) │ (镜像层 1) │ │ (镜像层 2) │ │ (镜像层 3) │ └─────────────────┘
|
Overlay2 优势:
- 性能优异,接近原生文件系统
- 支持最多 128 层
- 支持页缓存共享,节省内存
- 支持硬链接,节省磁盘空间
检查 Overlay2 状态:
1 2 3 4 5 6 7 8
| mount | grep overlay
docker system df
docker system prune -a --volumes
|
数据卷( Volume)管理
数据卷是 Docker 推荐的数据持久化方式,由 Docker
管理,独立于容器生命周期。
Volume 基础操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| docker volume create mydata
docker volume create --label env=prod \ --label app=myapp \ prod-data
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune
|
Volume 高级用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| docker volume create \ --driver local \ --opt type=none \ --opt device=/host/path \ --opt o=bind \ myvolume
docker run -d --name app \ -v mydata:/var/lib/data:ro \ myapp:latest
docker run -d --name app \ -v data1:/app/data1 \ -v data2:/app/data2 \ -v data3:/app/data3 \ myapp:latest
|
Volume 备份与恢复:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| docker run --rm \ -v mydata:/data \ -v $(pwd):/backup \ alpine tar czf /backup/mydata-backup.tar.gz -C /data .
docker run --rm \ -v mydata:/data \ -v $(pwd):/backup \ alpine sh -c "cd /data && tar xzf /backup/mydata-backup.tar.gz"
docker run --rm \ -v source-volume:/source \ -v target-volume:/target \ alpine sh -c "cp -a /source/. /target/"
|
绑定挂载( Bind Mount)
绑定挂载将主机文件系统路径直接挂载到容器,适合开发环境和配置文件管理。
绑定挂载用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| docker run -d --name app \ -v /host/path:/container/path \ myapp:latest
docker run -d --name app \ -v /host/config:/app/config:ro \ myapp:latest
docker run -d --name app \ -v /host/config.json:/app/config.json:ro \ myapp:latest
docker run -d --name app \ -v $(pwd)/config:/app/config \ myapp:latest
|
绑定挂载注意事项:
- 路径必须存在,否则 Docker 会创建目录
- 文件挂载时,如果文件不存在, Docker 会创建空文件
- 权限问题:容器内进程的 UID/GID 需要匹配文件权限
- 性能:绑定挂载性能略低于 Volume
权限问题处理:
1 2 3 4 5 6 7 8 9 10 11
| ls -la /host/path
docker run -d --name app \ --user 1000:1000 \ -v /host/path:/container/path \ myapp:latest
|
临时文件系统( tmpfs)
tmpfs 将数据存储在内存中,适合临时数据和缓存。
tmpfs 用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| docker run -d --name app \ --tmpfs /tmp \ myapp:latest
docker run -d --name app \ --tmpfs /tmp:rw,noexec,nosuid,size=100m \ myapp:latest
docker run -d --name app \ --tmpfs /tmp:size=100m \ --tmpfs /cache:size=200m \ myapp:latest
|
tmpfs 适用场景:
- 临时文件存储
- 缓存数据(如编译缓存)
- 敏感数据(容器停止后自动清除)
- 高性能临时存储需求
存储最佳实践
1. 选择合适的存储方式:
1 2 3 4 5 6 7 8
| docker run -v db-data:/var/lib/mysql mysql:8.0
docker run -v $(pwd):/app myapp:dev
docker run --tmpfs /tmp myapp:latest
|
2. 数据卷命名规范:
1 2 3 4 5 6 7 8 9
| docker volume create app-db-data docker volume create app-cache-data
docker volume create \ --label project=myapp \ --label env=production \ prod-db-data
|
3. 存储清理策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| docker system df
docker system prune
docker system prune -a --volumes
docker container prune -f --filter "until=168h"
docker image prune -a -f --filter "until=168h"
docker volume prune -f
|
4. 存储监控:
1 2 3 4 5 6 7 8
| docker system df -v | grep -A 10 "VOLUME NAME"
du -sh /var/lib/docker/volumes/*
docker exec <container> find /data -type f -size +100M
|
Dockerfile
最佳实践与多阶段构建
Dockerfile 基础语法
Dockerfile 由一系列指令组成,每条指令创建一个新的镜像层。
常用指令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| FROM ubuntu:20.04
LABEL maintainer="your-email@example.com"
WORKDIR /app
COPY requirements.txt . COPY . .
ADD https://example.com/file.tar.gz /tmp/
RUN apt-get update && apt-get install -y python3
ENV PYTHONUNBUFFERED=1 ENV APP_VERSION=1.0
EXPOSE 8080
ENTRYPOINT ["python3", "app.py"]
CMD ["--help"]
|
Dockerfile 最佳实践
1. 使用多阶段构建减少镜像大小
Docker
多阶段构建:从 2GB 到 20MB 的镜像瘦身实战
多阶段构建( Multi-stage Build)是 Docker 17.05
引入的特性,可以在一个 Dockerfile 中使用多个 FROM 指令,每个 FROM
指令开始一个新的构建阶段。通过在最终阶段只复制需要的构建产物,可以将镜像大小从
GB 级别压缩到 MB
级别,同时确保生产镜像不包含编译工具和源代码,提升安全性。
问题背景:传统单阶段构建的问题: -
镜像臃肿:包含编译工具链( gcc 、 make 、
SDK)和源代码,导致镜像体积巨大。例如 Go 应用,包含 golang
镜像(~800MB)+ 源代码(~200MB)+ 依赖(~1GB)= 2GB+ -
安全风险:生产镜像包含编译工具和源代码,增加攻击面。攻击者可以利用编译工具在容器内编译恶意程序
- 构建缓慢:每次修改代码都需要重新下载依赖和编译,
CI/CD 流水线耗时长
解决思路: 1. 构建阶段(
builder):使用完整的 SDK 镜像(如
golang:1.19-alpine)编译应用,生成可执行文件 2. 运行阶段(
production):使用最小化的基础镜像(如 alpine 、
distroless),只复制可执行文件和运行时依赖 3.
依赖隔离:第一阶段安装所有依赖,第二阶段只复制必要文件
4. 缓存优化:合理组织 COPY 指令顺序,最大化利用 Docker
层缓存
设计考虑: - 基础镜像选择:
alpine( 5MB)最小但可能有兼容性问题, distroless(
20MB)更安全但调试困难, debian-slim( 100MB)兼容性最好但体积较大 -
构建时间 vs
镜像大小:多阶段构建增加构建时间(需要构建多个阶段),但大幅减少镜像大小和传输时间。对于频繁部署的应用,镜像大小优化更重要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
FROM golang:1.19-alpine AS builder
WORKDIR /build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates tzdata
WORKDIR /root/
COPY --from=builder /build/app .
EXPOSE 8080
CMD ["./app"]
|
深入解读:
关键点解释:
- 多阶段构建的优势:
- 镜像大小优化:从 2GB+(包含 golang 镜像)压缩到
20MB( alpine + 可执行文件),减少 95%+
- 安全性提升:生产镜像不包含编译工具( gcc 、
go)和源代码,攻击者无法在容器内编译恶意程序
- 传输加速:镜像大小从 2GB 减少到
20MB,拉取镜像从分钟级别降低到秒级
- 层次清晰:构建阶段和运行阶段分离,职责明确,便于维护
- CGO_ENABLED=0 的作用:
- CGO: Go 的 C 语言互操作功能,允许 Go 调用 C
代码
- CGO_ENABLED=0:禁用
CGO,生成静态链接的可执行文件
- 为什么禁用:启用 CGO
会生成动态链接的可执行文件,依赖 glibc 等 C 库。 alpine 使用 musl
libc(与 glibc 不兼容),会导致运行失败
- 静态链接的优势:可执行文件包含所有依赖,可以在任何
Linux 发行版运行(甚至 scratch 空镜像)
- -ldflags="-w -s" 的作用:
- -ldflags:传递给链接器的参数
- -w:去除 DWARF 调试信息(用于 gdb
调试),减小文件大小约 10-15%
- -s:去除符号表(函数名、变量名),减小文件大小约
10-15%
- 总体效果:可执行文件大小减少约 30%,但无法使用 gdb
调试
- 生产建议:生产环境使用-w
-s(不需要调试),开发环境不使用(保留调试信息)
- 为什么不使用 scratch 镜像:
- scratch: Docker 的空镜像( 0
字节),不包含任何文件
- 优势:镜像极小(只有可执行文件大小)
- 劣势:没有 shell(无法 exec 进入容器调试),没有
ca-certificates( HTTPS 失败),没有时区数据(时间错误)
- 选择:对于纯静态链接且不需要调试的应用,使用
scratch;其他情况使用 alpine
设计权衡:
| 基础镜像 |
大小 |
优势 |
劣势 |
适用场景 |
| scratch |
0 MB |
极小,最安全 |
无 shell,无调试工具,无证书 |
纯静态链接的 Go/Rust 应用 |
| alpine |
5-10 MB |
小,包含基础工具 |
musl libc 兼容性问题 |
大多数 Go/Rust 应用 |
| distroless |
20-30 MB |
更安全(无 shell), glibc 兼容 |
无调试工具,无包管理器 |
安全要求高的生产环境 |
| debian-slim |
100 MB |
兼容性最好,调试方便 |
体积较大 |
需要调试的应用 |
常见问题与解决方案:
| 问题 |
原因 |
解决方案 |
| 运行阶段找不到共享库 |
动态链接的可执行文件缺少依赖 |
使用 CGO_ENABLED=0 生成静态链接,或使用 debian-slim 镜像 |
| HTTPS 请求失败 |
alpine 缺少 ca-certificates |
添加RUN apk add ca-certificates |
| 时区不正确 |
alpine 缺少时区数据 |
添加RUN apk add tzdata,设置ENV TZ=Asia/Shanghai |
| 镜像构建缓存失效 |
COPY 顺序不当,每次都重新下载依赖 |
先 COPY 依赖文件( go.mod),后 COPY 代码 |
| 无法 exec 进入容器调试 |
scratch 或 distroless 没有 shell |
改用 alpine 或 debian-slim,或使用临时调试镜像 |
| 可执行文件无法运行 |
musl/glibc 不兼容 |
使用 CGO_ENABLED=0 静态链接,或改用 debian-slim |
生产实践建议:
依赖缓存优化:先复制依赖文件,再复制代码,最大化利用
Docker 层缓存: 1 2 3 4 5 6 7
| COPY go.mod go.sum ./ RUN go mod download
COPY . . RUN go build -o app .
|
使用.dockerignore 减少上下文大小:
1 2 3 4 5 6
| .git .env *.log .DS_Store node_modules dist
|
镜像大小监控:在 CI/CD
流程中监控镜像大小,防止镜像膨胀:
1 2 3 4
| docker images myapp:latest --format "{{ .Size }}"
|
多架构支持:使用 docker buildx 构建多架构镜像(
amd64 、 arm64): 1
| docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest .
|
安全扫描:使用 trivy 扫描镜像漏洞:
1
| trivy image myapp:latest
|
2. 合理利用缓存层
1 2 3 4 5 6
| COPY requirements.txt . RUN pip install -r requirements.txt
COPY . .
|
3. 使用 .dockerignore
创建 .dockerignore 文件:
1 2 3 4 5
| node_modules .git .env *.log dist
|
4. 使用非 root 用户运行
1 2 3 4 5 6
| FROM node:16-alpine RUN addgroup -g 1000 appuser && \ adduser -D -u 1000 -G appuser appuser USER appuser WORKDIR /home/appuser COPY --chown=appuser:appuser . .
|
5. 健康检查
1 2
| HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1
|
多阶段构建实战
示例:构建 Python Flask 应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| FROM python:3.9-slim AS builder WORKDIR /build COPY requirements.txt . RUN pip install --user --no-cache-dir -r requirements.txt
FROM python:3.9-slim WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
ENV PATH=/root/.local/bin:$PATH
EXPOSE 5000
CMD ["python", "app.py"]
|
示例:构建 Node.js 应用
1 2 3 4 5 6 7 8 9 10 11 12 13
| FROM node:16-alpine AS builder WORKDIR /build COPY package*.json ./ RUN npm ci --only=production
FROM node:16-alpine WORKDIR /app COPY --from=builder /build/node_modules ./node_modules COPY . . EXPOSE 3000 CMD ["node", "server.js"]
|
Docker Compose 编排
Docker Compose 用于定义和运行多容器 Docker 应用。通过 YAML
文件配置服务、网络和卷。
Compose 文件结构
基本示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| version: '3.8'
services: web: build: . ports:
- "5000:5000" environment:
- FLASK_ENV=production depends_on:
- db - redis
db: image: postgres:13 environment: POSTGRES_DB: myapp POSTGRES_USER: user POSTGRES_PASSWORD: password volumes:
- db_data:/var/lib/postgresql/data
redis: image: redis:6-alpine ports:
- "6379:6379"
volumes: db_data:
|
常用配置项
服务配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| services: app: build: context: . dockerfile: Dockerfile.prod args: VERSION: 1.0 image: myapp:v1.0 command: python app.py --debug environment:
- NODE_ENV=production - DATABASE_URL=postgres://user:pass@db:5432/mydb env_file:
- .env - .env.production ports:
- "8080:80" - "8443:443" volumes:
- ./data:/app/data - app_cache:/app/cache networks:
- frontend - backend depends_on:
- db - cache restart: unless-stopped deploy: resources: limits: cpus: '0.5' memory: 512M reservations: cpus: '0.25' memory: 256M healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s
|
网络配置:
1 2 3 4 5 6 7 8 9 10 11
| networks: frontend: driver: bridge ipam: config:
- subnet: 172.20.0.0/16 backend: driver: bridge internal: true
|
卷配置:
1 2 3 4 5 6 7
| volumes: db_data: driver: local driver_opts: type: none o: bind device: /path/to/data
|
Compose 命令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| docker-compose up -d
docker-compose ps
docker-compose logs -f web
docker-compose stop
docker-compose down
docker-compose down -v
docker-compose up -d --build
docker-compose up -d --scale web=3
docker-compose exec web python manage.py migrate
|
实战案例:微服务应用栈
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| version: '3.8'
services: nginx: image: nginx:alpine ports:
- "80:80" - "443:443" volumes:
- ./nginx.conf:/etc/nginx/nginx.conf - ./ssl:/etc/nginx/ssl depends_on:
- api - frontend networks:
- frontend
frontend: build: context: ./frontend dockerfile: Dockerfile environment:
- API_URL=http://api:3000 networks:
- frontend
api: build: context: ./api dockerfile: Dockerfile environment:
- DATABASE_URL=postgres://user:pass@db:5432/mydb - REDIS_URL=redis://redis:6379 depends_on:
- db - redis networks:
- frontend - backend
db: image: postgres:13 environment: POSTGRES_DB: mydb POSTGRES_USER: user POSTGRES_PASSWORD: password volumes:
- db_data:/var/lib/postgresql/data networks:
- backend
redis: image: redis:6-alpine command: redis-server --appendonly yes volumes:
- redis_data:/data networks:
- backend
volumes: db_data: redis_data:
networks: frontend: driver: bridge backend: driver: bridge
|
Kubernetes 核心概念
Kubernetes( K8s)是 Google
开源的容器编排平台,用于自动化部署、扩展和管理容器化应用。
集群架构
Kubernetes 集群由控制平面( Control Plane)和工作节点(
Node)组成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| ┌─────────────────────────────────────┐ │ Control Plane │ │ ┌──────────┐ ┌──────────┐ │ │ │ API │ │ etcd │ │ │ │ Server │ │ │ │ │ └──────────┘ └──────────┘ │ │ ┌──────────┐ ┌──────────┐ │ │ │ Scheduler │ │ Controller │ │ │ │ │ │ Manager │ │ │ └──────────┘ └──────────┘ │ └─────────────────────────────────────┘ │ │ ┌─────────┴─────────┐ │ │ ┌───▼────┐ ┌───▼────┐ │ Node 1 │ │ Node 2 │ │ ┌────┐ │ │ ┌────┐ │ │ │ Pod │ │ │ │ Pod │ │ │ └────┘ │ │ └────┘ │ │ ┌────┐ │ │ ┌────┐ │ │ │ Pod │ │ │ │ Pod │ │ │ └────┘ │ │ └────┘ │ └────────┘ └────────┘
|
控制平面组件:
- API Server:集群的前端接口,处理所有 REST 请求
- etcd:分布式键值存储,保存集群状态
- Scheduler:调度器,决定 Pod 运行在哪个节点
- Controller
Manager:运行各种控制器,维护集群状态
节点组件:
- kubelet:节点代理,与 API Server 通信
- kube-proxy:网络代理,实现服务发现和负载均衡
- 容器运行时: Docker 、 containerd 等
Pod
Pod 是 Kubernetes
的最小调度单元,包含一个或多个容器,共享网络和存储。
Pod 定义示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| apiVersion: v1 kind: Pod metadata: name: nginx-pod labels: app: nginx env: production spec: containers:
- name: nginx image: nginx:1.21 ports:
- containerPort: 80 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" volumeMounts:
- name: config mountPath: /etc/nginx/conf.d volumes:
- name: config configMap: name: nginx-config
|
Pod 生命周期:
- Pending: Pod 已被创建,但容器尚未启动
- Running: Pod 已绑定到节点,所有容器已创建
- Succeeded:所有容器成功终止
- Failed:至少一个容器终止失败
- Unknown:无法获取 Pod 状态
Service
Service 为 Pod 提供稳定的网络访问,实现服务发现和负载均衡。
Service 类型:
- ClusterIP:默认类型,在集群内部访问
- NodePort:通过节点端口暴露服务
- LoadBalancer:使用云提供商的负载均衡器
- ExternalName:将服务映射到外部 DNS 名称
Service 定义示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| apiVersion: v1 kind: Service metadata: name: nginx-service spec: type: ClusterIP selector: app: nginx ports:
- protocol: TCP port: 80 targetPort: 8080 sessionAffinity: ClientIP sessionAffinityConfig: clientIP: timeoutSeconds: 10800
|
NodePort Service:
1 2 3 4 5 6 7 8 9 10 11 12 13
| apiVersion: v1 kind: Service metadata: name: nginx-nodeport spec: type: NodePort selector: app: nginx ports:
- port: 80 targetPort: 8080 nodePort: 30080
|
Deployment
Deployment 管理 Pod 的副本集,提供声明式更新、回滚和扩缩容功能。
Deployment 生产级配置完全指南
Kubernetes
Deployment:高可用应用部署的最佳实践
Deployment 是 Kubernetes 中管理无状态应用的核心资源对象,它通过
ReplicaSet 控制 Pod
副本数量,提供声明式更新、滚动发布、自动回滚和弹性伸缩能力。理解
Deployment 的配置细节和最佳实践,是构建生产级 Kubernetes
应用的基础。
问题背景:手动管理 Pod 存在诸多问题: -
高可用性: Pod 故障后无法自动重建,导致服务中断 -
滚动更新:手动更新需要逐个停止/启动 Pod,过程复杂且易错
- 版本回滚:更新失败后无法快速回滚到上一个稳定版本 -
弹性伸缩:流量高峰时无法快速扩容,流量低谷时浪费资源
Deployment 正是为解决这些问题而设计的。
解决思路: 1. 副本管理(
replicas):声明期望的 Pod 副本数, Kubernetes
自动维护(故障自愈、自动重建) 2. 滚动更新(
RollingUpdate):逐步替换旧版本 Pod,确保服务零中断 3.
健康检查( Probes): livenessProbe 检测应用存活,
readinessProbe 检测应用就绪,自动剔除故障 Pod 4. 资源配额(
Resources): requests 保证最小资源, limits
限制最大资源,防止资源抢占 5. 更新策略(
Strategy):控制更新过程, maxSurge 允许超出副本数,
maxUnavailable 限制不可用副本数
设计考虑: -
副本数选择:生产环境建议至少 3
个副本(高可用),关键服务 5
个以上。副本数应为节点数的倍数,确保均匀分布 -
资源配额: requests 过低导致 Pod
被驱逐(节点资源不足), limits 过高导致资源浪费。建议: requests =
平均使用量, limits = 峰值使用量 × 1.5 - 健康检查:
initialDelaySeconds 过短导致应用未启动就被杀死, periodSeconds
过长导致故障检测延迟。建议: initialDelaySeconds = 应用启动时间 + 5s -
更新策略: maxUnavailable = 0 确保零停机,但更新较慢;
maxUnavailable = 1 加速更新,但短暂影响服务能力
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
|
apiVersion: apps/v1
kind: Deployment
metadata: name: nginx-deployment labels: app: nginx
spec: replicas: 3 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.21 ports: - containerPort: 80 name: http protocol: TCP resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" livenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 30 periodSeconds: 10 failureThreshold: 3 readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 periodSeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0
|
深入解读:
关键点解释:
- 副本数( replicas)与高可用性:
- 为什么至少 3 个副本: 2 个副本时,如果 1 个 Pod
故障,剩余 1 个 Pod 可能无法承载全部流量。 3 个副本时,即使 1 个 Pod
故障,剩余 2 个 Pod 仍可提供服务
- 副本数与节点数:如果集群有 4 个节点,副本数应该是 4
的倍数(如 4 、 8),确保 Pod 均匀分布
- PodAntiAffinity:使用 Pod
反亲和性,强制将副本调度到不同节点,避免单点故障
- 资源配额( Resources)的重要性:
- requests:调度器根据 requests 选择节点。如果
requests 过低, Pod 可能被调度到资源不足的节点,导致 OOM 或限流
- limits:限制容器最大资源使用。没有设置 limits 的
Pod 可能耗尽节点资源,影响其他 Pod
- QoS 等级: Kubernetes 根据 requests 和 limits 将
Pod 分为三个等级:
- Guaranteed( requests =
limits):最高优先级,不会被驱逐
- Burstable( requests <
limits):中等优先级,资源不足时可能被驱逐
- BestEffort(无
requests/limits):最低优先级,首先被驱逐
- 生产建议:关键服务使用 Guaranteed( requests =
limits),非关键服务使用 Burstable
- 健康检查( Probes)的最佳实践:
- livenessProbe vs readinessProbe:
- livenessProbe:检测应用是否存活(死锁、无响应),失败会重启容器
- readinessProbe:检测应用是否就绪(启动中、依赖服务故障),失败会移除
Pod from Service
- 探测端点设计:不要只检查 HTTP
200,应该检查应用核心功能(如数据库连接、缓存可用性)
- 避免频繁重启: livenessProbe 的 initialDelaySeconds
和 failureThreshold 应该足够宽松,避免偶发故障导致重启
- 滚动更新策略( RollingUpdate):
- maxSurge = 1, maxUnavailable =
0:零停机更新策略,更新过程中始终保持至少 replicas 个可用
Pod
- 更新流程:
- 创建 1 个新 Pod( maxSurge=1)
- 等待新 Pod 就绪( readinessProbe 成功)
- 删除 1 个旧 Pod
- 重复步骤 1-3,直到所有旧 Pod 被替换
- 更新速度:取决于 Pod 启动时间和 readinessProbe
配置。如果 Pod 启动慢,更新会很慢
设计权衡:
| 配置项 |
选项 |
优势 |
劣势 |
适用场景 |
| replicas |
1 |
资源占用最小 |
无高可用,故障会中断服务 |
开发/测试环境 |
|
3 |
高可用,容忍 1 个副本故障 |
资源占用中等 |
生产环境(推荐) |
|
5+ |
高可用,容忍多个副本故障 |
资源占用大 |
关键服务 |
| maxUnavailable |
0 |
零停机,始终有足够副本 |
更新较慢 |
关键服务(推荐) |
|
1 |
更新较快 |
短暂影响服务能力 |
非关键服务 |
| QoS 等级 |
Guaranteed |
最高优先级,不会被驱逐 |
资源利用率低 |
关键服务 |
|
Burstable |
资源利用率高 |
可能被驱逐 |
非关键服务 |
常见问题与解决方案:
| 问题 |
原因 |
解决方案 |
| Pod 频繁重启 |
livenessProbe 配置过严 |
增加 initialDelaySeconds 和 failureThreshold |
| Pod 无法就绪 |
readinessProbe 失败或应用启动慢 |
检查应用日志,调整 initialDelaySeconds |
| 更新卡住( Progressing) |
新 Pod 无法就绪或资源不足 |
检查 Pod 状态( kubectl describe pod),回滚更新 |
| OOMKilled |
内存 limits 过低 |
增加 memory limits,或优化应用内存使用 |
| CPU Throttle |
CPU limits 过低 |
增加 cpu limits,或优化应用 CPU 使用 |
| 单节点故障导致服务中断 |
Pod 都调度到同一节点 |
使用 PodAntiAffinity,强制 Pod 分布到不同节点 |
| 更新过程中服务不可用 |
maxUnavailable 过大 |
设置 maxUnavailable=0,确保零停机 |
生产实践建议:
使用 HPA( Horizontal Pod Autoscaler)自动伸缩:
1
| kubectl autoscale deployment nginx-deployment --cpu-percent=50 --min=3 --max=10
|
监控 Deployment 状态: 1 2 3 4 5 6 7 8
| kubectl get deployment nginx-deployment
kubectl get pods -l app=nginx
kubectl describe deployment nginx-deployment
|
金丝雀发布( Canary Deployment): 创建两个
Deployment( stable 和 canary), canary 先发布新版本,验证无误后更新
stable 。
使用 PodDisruptionBudget( PDB)保证可用性:
1 2 3 4 5 6 7 8 9
| apiVersion: policy/v1 kind: PodDisruptionBudget metadata: name: nginx-pdb spec: minAvailable: 2 selector: matchLabels: app: nginx
|
定期清理旧 ReplicaSet: 1 2
| kubectl delete replicaset --all --field-selector status.replicas=0
|
Deployment 操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| kubectl apply -f deployment.yaml
kubectl get deployments
kubectl scale deployment nginx-deployment --replicas=5
kubectl set image deployment/nginx-deployment nginx=nginx:1.22
kubectl rollout history deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment
kubectl rollout undo deployment/nginx-deployment --to-revision=2
kubectl rollout status deployment/nginx-deployment
|
StatefulSet
StatefulSet 用于管理有状态应用,提供稳定的网络标识和有序部署。
StatefulSet 特性:
- 稳定的网络标识: Pod 名称和 DNS 名称保持不变
- 有序部署和扩展:按顺序创建和删除 Pod
- 有序更新:按顺序更新 Pod
- 持久存储:每个 Pod 有独立的存储卷
StatefulSet 定义示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| apiVersion: apps/v1 kind: StatefulSet metadata: name: mysql-statefulset spec: serviceName: mysql replicas: 3 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers:
- name: mysql image: mysql:8.0 env:
- name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: password ports:
- containerPort: 3306 volumeMounts:
- name: data mountPath: /var/lib/mysql volumeClaimTemplates:
- metadata: name: data spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi
|
StatefulSet 操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| kubectl apply -f statefulset.yaml
kubectl get statefulset
kubectl get pods -l app=mysql
kubectl scale statefulset mysql-statefulset --replicas=5
kubectl delete statefulset mysql-statefulset
|
K8s 集群部署
kubeadm 部署(推荐)
kubeadm 是 Kubernetes
官方提供的集群部署工具,适合快速搭建测试和生产环境。
前置准备:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
|
swapoff -a sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF
sudo modprobe overlay sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF
sudo sysctl --system
cat <<EOF | sudo tee /etc/modules-load.d/containerd.conf overlay br_netfilter EOF
sudo modprobe overlay sudo modprobe br_netfilter
sudo mkdir -p /etc/containerd containerd config default | sudo tee /etc/containerd/config.toml sudo systemctl restart containerd sudo systemctl enable containerd
sudo apt-get update sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update sudo apt-get install -y kubelet kubeadm kubectl sudo apt-mark hold kubelet kubeadm kubectl
|
初始化控制平面节点:
1 2 3 4 5 6 7 8 9 10 11
| sudo kubeadm init \ --pod-network-cidr=10.244.0.0/16 \ --apiserver-advertise-address=192.168.1.100 \ --control-plane-endpoint=192.168.1.100:6443 \ --upload-certs
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
|
安装网络插件( Flannel):
1
| kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
加入工作节点:
1 2 3 4
| sudo kubeadm join 192.168.1.100:6443 \ --token <token> \ --discovery-token-ca-cert-hash sha256:<hash>
|
验证集群:
1 2 3 4 5 6 7 8
| kubectl get nodes
kubectl get pods --all-namespaces
kubectl cluster-info
|
二进制部署
二进制部署提供更多控制,适合需要自定义配置的场景。
下载二进制文件:
1 2 3 4 5 6 7
| wget https://dl.k8s.io/v1.28.0/kubernetes-server-linux-amd64.tar.gz tar -xzf kubernetes-server-linux-amd64.tar.gz
wget https://github.com/etcd-io/etcd/releases/download/v3.5.9/etcd-v3.5.9-linux-amd64.tar.gz tar -xzf etcd-v3.5.9-linux-amd64.tar.gz
|
配置 etcd:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| cat > /etc/etcd/etcd.conf <<EOF ETCD_NAME=etcd1 ETCD_DATA_DIR=/var/lib/etcd ETCD_LISTEN_CLIENT_URLS=http://0.0.0.0:2379 ETCD_ADVERTISE_CLIENT_URLS=http://192.168.1.100:2379 EOF
cat > /etc/systemd/system/etcd.service <<EOF [Unit] Description=etcd After=network.target
[Service] Type=notify ExecStart=/usr/local/bin/etcd --config-file=/etc/etcd/etcd.conf Restart=always
[Install] WantedBy=multi-user.target EOF
systemctl daemon-reload systemctl enable etcd systemctl start etcd
|
配置 API Server:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| cat > /etc/kubernetes/apiserver.conf <<EOF KUBE_API_ARGS="--etcd-servers=http://127.0.0.1:2379 \ --service-cluster-ip-range=10.96.0.0/12 \ --advertise-address=192.168.1.100 \ --allow-privileged=true \ --authorization-mode=Node,RBAC \ --enable-admission-plugins=NodeRestriction" EOF
cat > /etc/systemd/system/kube-apiserver.service <<EOF [Unit] Description=Kubernetes API Server After=etcd.service
[Service] ExecStart=/usr/local/bin/kube-apiserver \$KUBE_API_ARGS Restart=always
[Install] WantedBy=multi-user.target EOF
systemctl daemon-reload systemctl enable kube-apiserver systemctl start kube-apiserver
|
高可用部署
高可用集群需要多个控制平面节点,使用负载均衡器分发请求。
架构设计:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ┌─────────────┐ │ Load │ │ Balancer │ │ (HAProxy) │ └──────┬──────┘ │ ┌──────────────────┼──────────────────┐ │ │ │ ┌───────▼──────┐ ┌────────▼──────┐ ┌────────▼──────┐ │ Master Node 1 │ │ Master Node 2 │ │ Master Node 3 │ │ │ │ │ │ │ │ API Server │ │ API Server │ │ API Server │ │ etcd │ │ etcd │ │ etcd │ │ Scheduler │ │ Scheduler │ │ Scheduler │ │ Controller │ │ Controller │ │ Controller │ └──────────────┘ └───────────────┘ └───────────────┘
|
使用 kubeadm 部署高可用集群:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| cat > /etc/haproxy/haproxy.cfg <<EOF global log /dev/log local0 chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin stats timeout 30s user haproxy group haproxy daemon
defaults mode http log global option httplog option dontlognull timeout connect 5000ms timeout client 50000ms timeout server 50000ms
frontend kubernetes-frontend bind *:6443 mode tcp option tcplog default_backend kubernetes-backend
backend kubernetes-backend mode tcp balance roundrobin option tcp-check server master1 192.168.1.101:6443 check server master2 192.168.1.102:6443 check server master3 192.168.1.103:6443 check EOF
systemctl restart haproxy
sudo kubeadm init \ --control-plane-endpoint=192.168.1.100:6443 \ --upload-certs \ --pod-network-cidr=10.244.0.0/16
sudo kubeadm join 192.168.1.100:6443 \ --control-plane \ --token <token> \ --discovery-token-ca-cert-hash sha256:<hash> \ --certificate-key <certificate-key>
|
K8s 网络与存储
Kubernetes 网络模型
Kubernetes 网络遵循以下原则:
- 每个 Pod 都有独立的 IP 地址
- Pod 之间可以直接通信,无需 NAT
- 节点上的 Pod 可以与所有节点上的 Pod 通信
网络插件:
- Flannel:简单易用,使用 VXLAN 或 host-gw
- Calico:功能强大,支持网络策略和 BGP
- Weave Net:自动网络发现,支持加密
- Cilium:基于 eBPF,高性能
Flannel 配置示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| apiVersion: v1 kind: ConfigMap metadata: name: kube-flannel-cfg namespace: kube-system data: cni-conf.json: | { "name": "cbr0", "cniVersion": "0.3.1", "plugins": [ { "type": "flannel", "delegate": { "hairpinMode": true, "isDefaultGateway": true } }, { "type": "portmap", "capabilities": { "portMappings": true } } ] } net-conf.json: | { "Network": "10.244.0.0/16", "Backend": { "Type": "vxlan" } }
|
Service 网络
ClusterIP Service:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: v1 kind: Service metadata: name: my-service spec: type: ClusterIP selector: app: myapp ports:
- port: 80 targetPort: 8080
|
Headless Service(用于 StatefulSet):
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: v1 kind: Service metadata: name: mysql spec: clusterIP: None selector: app: mysql ports:
- port: 3306
|
Ingress 详解
Ingress 提供 HTTP/HTTPS 路由,支持基于域名和路径的路由,是 Kubernetes
中暴露服务到集群外部的主要方式。
Ingress 基础概念
Ingress 需要 Ingress Controller 才能工作,常见的 Controller
包括:
- Nginx Ingress Controller:功能丰富,使用最广泛
- Traefik:自动服务发现,配置简单
- HAProxy Ingress:高性能,适合大规模场景
- Istio Gateway:与服务网格集成
安装 Nginx Ingress Controller:
1 2 3 4 5 6 7 8 9 10
| kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx helm install ingress-nginx ingress-nginx/ingress-nginx
kubectl get pods -n ingress-nginx kubectl get svc -n ingress-nginx
|
Ingress 基本配置
简单 Ingress 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: my-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: / spec: ingressClassName: nginx rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
PathType 说明:
Exact:精确匹配路径
Prefix:前缀匹配(最常用)
ImplementationSpecific:由 Ingress Controller 决定
Ingress 高级配置
多路径路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: multi-path-ingress annotations: nginx.ingress.kubernetes.io/rewrite-target: /$2 spec: ingressClassName: nginx rules:
- host: example.com http: paths: - path: /api(/|$)(.*) pathType: ImplementationSpecific backend: service: name: api-service port: number: 8080 - path: /app(/|$)(.*) pathType: ImplementationSpecific backend: service: name: frontend-service port: number: 80 - path: / pathType: Prefix backend: service: name: default-service port: number: 80
|
TLS/HTTPS 配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: tls-ingress spec: ingressClassName: nginx tls:
- hosts: - api.example.com - app.example.com secretName: tls-secret rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
- host: app.example.com http: paths:
- path: / pathType: Prefix backend: service: name: app-service port: number: 80
|
创建 TLS Secret:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| kubectl create secret tls tls-secret \ --cert=path/to/cert.crt \ --key=path/to/cert.key
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml
apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: your-email@example.com privateKeySecretRef: name: letsencrypt-prod solvers:
- http01: ingress: class: nginx
|
使用 cert-manager 自动 TLS:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: auto-tls-ingress annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" spec: ingressClassName: nginx tls:
- hosts: - api.example.com secretName: api-tls-secret rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
Nginx Ingress 常用注解
限流配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rate-limit-ingress annotations: nginx.ingress.kubernetes.io/limit-rps: "100" nginx.ingress.kubernetes.io/limit-connections: "10" spec: ingressClassName: nginx rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
CORS 配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: cors-ingress annotations: nginx.ingress.kubernetes.io/enable-cors: "true" nginx.ingress.kubernetes.io/cors-allow-origin: "https://example.com" nginx.ingress.kubernetes.io/cors-allow-methods: "GET, POST, PUT, DELETE, OPTIONS" nginx.ingress.kubernetes.io/cors-allow-headers: "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization" spec: ingressClassName: nginx rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
SSL 重定向:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: ssl-redirect-ingress annotations: nginx.ingress.kubernetes.io/ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true" spec: ingressClassName: nginx tls:
- hosts: - api.example.com secretName: tls-secret rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
自定义 Nginx 配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: custom-config-ingress annotations: nginx.ingress.kubernetes.io/proxy-body-size: "10m" nginx.ingress.kubernetes.io/proxy-connect-timeout: "60" nginx.ingress.kubernetes.io/proxy-send-timeout: "60" nginx.ingress.kubernetes.io/proxy-read-timeout: "60" nginx.ingress.kubernetes.io/client-max-body-size: "10m" spec: ingressClassName: nginx rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
基于 Cookie 的会话保持:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: session-affinity-ingress annotations: nginx.ingress.kubernetes.io/affinity: "cookie" nginx.ingress.kubernetes.io/session-cookie-name: "route" nginx.ingress.kubernetes.io/session-cookie-expires: "172800" nginx.ingress.kubernetes.io/session-cookie-max-age: "172800" spec: ingressClassName: nginx rules:
- host: app.example.com http: paths:
- path: / pathType: Prefix backend: service: name: app-service port: number: 80
|
Ingress 故障排查
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| kubectl get ingress
kubectl describe ingress my-ingress
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
curl -H "Host: api.example.com" http://<ingress-ip>/
kubectl exec -n ingress-nginx deployment/ingress-nginx-controller -- cat /etc/nginx/nginx.conf
|
存储卷
PersistentVolume( PV)和 PersistentVolumeClaim(
PVC):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| apiVersion: v1 kind: PersistentVolume metadata: name: mysql-pv spec: capacity: storage: 20Gi accessModes:
- ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: local-storage hostPath: path: /data/mysql
---
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: mysql-pvc spec: accessModes:
- ReadWriteOnce resources: requests: storage: 20Gi storageClassName: local-storage
---
apiVersion: v1 kind: Pod metadata: name: mysql-pod spec: containers:
- name: mysql image: mysql:8.0 volumeMounts:
- name: mysql-storage mountPath: /var/lib/mysql volumes:
- name: mysql-storage persistentVolumeClaim: claimName: mysql-pvc
|
StorageClass(动态 provisioning):
1 2 3 4 5 6 7
| apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: fast-ssd provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer allowVolumeExpansion: true
|
ConfigMap 和 Secret 管理
ConfigMap 和 Secret 是 Kubernetes
中管理配置和敏感信息的重要资源。
ConfigMap 详解
ConfigMap
用于存储非敏感的配置数据,如配置文件、环境变量、命令行参数等。
创建 ConfigMap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| kubectl create configmap my-config \ --from-literal=key1=value1 \ --from-literal=key2=value2
kubectl create configmap my-config \ --from-file=config.properties
kubectl create configmap my-config \ --from-file=/path/to/config/dir
kubectl create configmap my-config \ --from-env-file=config.env
|
YAML 方式定义 ConfigMap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| apiVersion: v1 kind: ConfigMap metadata: name: app-config namespace: default data: database.host: "mysql-service" database.port: "3306" cache.host: "redis-service" cache.port: "6379" nginx.conf: | server { listen 80; server_name example.com; location / { proxy_pass http://backend; } } application.properties: | spring.datasource.url=jdbc:mysql://mysql-service:3306/mydb spring.redis.host=redis-service spring.redis.port=6379
|
在 Pod 中使用 ConfigMap:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| apiVersion: v1 kind: Pod metadata: name: app-pod spec: containers:
- name: app image: myapp:latest env:
- name: DB_HOST valueFrom: configMapKeyRef: name: app-config key: database.host
- name: DB_PORT valueFrom: configMapKeyRef: name: app-config key: database.port envFrom:
- configMapRef: name: app-config volumeMounts:
- name: config-volume mountPath: /etc/config
- name: nginx-config-volume mountPath: /etc/nginx/conf.d readOnly: true volumes: - name: config-volume configMap: name: app-config - name: nginx-config-volume configMap: name: app-config items:
- key: nginx.conf path: nginx.conf
|
ConfigMap 更新和热重载:
1 2 3 4 5 6 7 8 9 10 11 12 13
| kubectl edit configmap app-config
kubectl create configmap app-config \ --from-file=config.properties \ --dry-run=client -o yaml | kubectl apply -f -
kubectl get configmap app-config -o yaml
kubectl delete configmap app-config
|
ConfigMap 使用最佳实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| apiVersion: v1 kind: Pod metadata: name: app-pod spec: containers:
- name: app image: myapp:latest volumeMounts:
- name: config-volume mountPath: /etc/config/application.properties subPath: application.properties volumes:
- name: config-volume configMap: name: app-config
apiVersion: v1 kind: Pod metadata: name: app-pod spec: containers:
- name: app image: myapp:latest env:
- name: DB_HOST value: "localhost"
- name: DB_PORT valueFrom: configMapKeyRef: name: app-config key: database.port optional: true
|
Secret 详解
Secret 用于存储敏感信息,如密码、令牌、密钥等。 Secret 数据会被
Base64 编码(不是加密),需要额外的加密措施保护。
创建 Secret:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| kubectl create secret generic my-secret \ --from-literal=username=admin \ --from-literal=password=secret123
kubectl create secret generic my-secret \ --from-file=username.txt \ --from-file=password.txt
kubectl create secret docker-registry regcred \ --docker-server=registry.example.com \ --docker-username=admin \ --docker-password=secret123 \ --docker-email=admin@example.com
kubectl create secret tls tls-secret \ --cert=path/to/cert.crt \ --key=path/to/cert.key
|
YAML 方式定义 Secret:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| apiVersion: v1 kind: Secret metadata: name: my-secret type: Opaque data: username: YWRtaW4= password: c2VjcmV0MTIz
apiVersion: v1 kind: Secret metadata: name: my-secret type: Opaque stringData: username: admin password: secret123
|
Secret 类型:
Opaque:用户定义的任意数据(默认)
kubernetes.io/dockerconfigjson: Docker
镜像仓库认证
kubernetes.io/tls: TLS 证书和密钥
kubernetes.io/service-account-token: Service Account
令牌
在 Pod 中使用 Secret:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| apiVersion: v1 kind: Pod metadata: name: app-pod spec: containers:
- name: app image: myapp:latest env:
- name: DB_USERNAME valueFrom: secretKeyRef: name: my-secret key: username
- name: DB_PASSWORD valueFrom: secretKeyRef: name: my-secret key: password envFrom:
- secretRef: name: my-secret volumeMounts:
- name: secret-volume mountPath: /etc/secrets readOnly: true volumes:
- name: secret-volume secret: secretName: my-secret defaultMode: 0400 items:
- key: username path: db-username
- key: password path: db-password mode: 0400
|
镜像拉取 Secret:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: v1 kind: Pod metadata: name: private-reg-pod spec: imagePullSecrets:
- name: regcred containers:
- name: app image: registry.example.com/myapp:latest
|
Secret 安全最佳实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
kubectl get secret my-secret -o yaml
kubectl get secret my-secret -o jsonpath='{.data.password}' | base64 -d
kubectl create secret generic my-secret \ --from-literal=password=newpassword \ --dry-run=client -o yaml | kubectl apply -f -
kubectl delete secret my-secret
|
使用 Sealed Secrets 加密 Secret:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| brew install kubeseal
kubectl create secret generic my-secret \ --from-literal=password=secret123 \ --dry-run=client -o yaml | \ kubeseal -o yaml > sealed-secret.yaml
kubectl apply -f sealed-secret.yaml
|
Kubernetes 资源限制与 QoS
Kubernetes 通过资源请求( requests)和限制( limits)来管理 Pod
的资源使用,并根据这些设置分配 QoS 等级。
资源请求和限制
CPU 和内存资源:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| apiVersion: v1 kind: Pod metadata: name: resource-demo spec: containers:
- name: app image: myapp:latest resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"
|
CPU 单位说明:
1000m = 1 = 1 个 CPU 核心
500m = 0.5 = 0.5 个 CPU 核心
100m = 0.1 = 0.1 个 CPU 核心
内存单位说明:
Mi = Mebibyte (1024^2 bytes)
Gi = Gibibyte (1024^3 bytes)
M = Megabyte (1000^2 bytes)
G = Gigabyte (1000^3 bytes)
扩展资源(如 GPU):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| apiVersion: v1 kind: Pod metadata: name: gpu-pod spec: containers:
- name: gpu-app image: gpu-app:latest resources: requests: nvidia.com/gpu: 1 limits: nvidia.com/gpu: 1
|
QoS 等级
Kubernetes 根据资源请求和限制分配三种 QoS 等级:
1. Guaranteed(保证):
- 所有容器都设置了 requests 和 limits
- requests 和 limits 相等
- 优先级最高,不会被驱逐(除非节点资源不足)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| apiVersion: v1 kind: Pod metadata: name: guaranteed-pod spec: containers:
- name: app image: myapp:latest resources: requests: memory: "128Mi" cpu: "500m" limits: memory: "128Mi" cpu: "500m"
|
2. Burstable(可突发):
- 至少有一个容器设置了 requests,但不满足 Guaranteed 条件
- 可以使用超出 requests 的资源(在 limits 范围内)
- 中等优先级
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| apiVersion: v1 kind: Pod metadata: name: burstable-pod spec: containers:
- name: app image: myapp:latest resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "256Mi" cpu: "1000m"
|
3. BestEffort(尽力而为):
- 所有容器都没有设置 requests 和 limits
- 优先级最低,资源不足时首先被驱逐
- 可以使用节点的所有可用资源
1 2 3 4 5 6 7 8 9 10
| apiVersion: v1 kind: Pod metadata: name: besteffort-pod spec: containers:
- name: app image: myapp:latest
|
资源配额( ResourceQuota)
ResourceQuota 用于限制命名空间的资源使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| apiVersion: v1 kind: ResourceQuota metadata: name: compute-quota namespace: production spec: hard: requests.cpu: "4" requests.memory: 8Gi limits.cpu: "8" limits.memory: 16Gi pods: "10" persistentvolumeclaims: "4" requests.storage: 100Gi configmaps: "10" secrets: "10"
|
查看资源配额:
1 2 3 4 5
| kubectl get resourcequota -n production
kubectl describe resourcequota compute-quota -n production
|
限制范围( LimitRange)
LimitRange 用于设置命名空间中 Pod 和容器的默认资源限制。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: v1 kind: LimitRange metadata: name: mem-limit-range namespace: production spec: limits: - default: memory: "512Mi" cpu: "500m" defaultRequest: memory: "256Mi" cpu: "250m" type: Container - max: memory: "1Gi" cpu: "1000m" min: memory: "128Mi" cpu: "100m" type: Pod
|
资源限制最佳实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: template: spec: containers:
- name: app image: myapp:latest resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m"
apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: myapp-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 2 maxReplicas: 10 metrics:
- type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
- type: Resource resource: name: memory target: type: Utilization averageUtilization: 80
|
资源监控和调优:
1 2 3 4 5 6 7 8 9 10 11 12
| kubectl top pod <pod-name>
kubectl top node
kubectl describe pod <pod-name> | grep -A 5 "Limits\|Requests"
kubectl get pods --all-namespaces -o json | \ jq '.items[] | {name: .metadata.name, namespace: .metadata.namespace, requests: .spec.containers[].resources.requests, limits: .spec.containers[].resources.limits}'
|
Helm 包管理
Helm 是 Kubernetes 的包管理器,类似于 apt/yum,用于管理 Kubernetes
应用。
Helm 基础
安装 Helm:
1 2 3 4 5 6
| curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
brew install helm apt-get install helm
|
Helm 概念:
- Chart: Helm 包,包含应用的所有资源定义
- Repository: Chart 仓库,存储 Chart
- Release: Chart 的部署实例
- Values:配置参数,用于定制 Chart
基本命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update
helm search repo nginx
helm install my-nginx bitnami/nginx
helm list
helm status my-nginx
helm upgrade my-nginx bitnami/nginx --set service.type=NodePort
helm uninstall my-nginx
|
创建自定义 Chart
Chart 结构:
1 2 3 4 5 6 7 8
| mychart/ ├── Chart.yaml # Chart 元数据 ├── values.yaml # 默认配置值 ├── templates/ # 模板文件 │ ├── deployment.yaml │ ├── service.yaml │ └── _helpers.tpl # 辅助模板 └── charts/ # 依赖 Chart
|
Chart.yaml:
1 2 3 4 5 6
| apiVersion: v2 name: myapp description: A Helm chart for my application type: application version: 0.1.0 appVersion: "1.0.0"
|
values.yaml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| replicaCount: 3
image: repository: nginx pullPolicy: IfNotPresent tag: "1.21"
service: type: ClusterIP port: 80
ingress: enabled: false className: "nginx" annotations: {} hosts:
- host: chart-example.local paths:
- path: / pathType: Prefix tls: []
resources: limits: cpu: 500m memory: 512Mi requests: cpu: 250m memory: 256Mi
|
templates/deployment.yaml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "myapp.fullname" . }} labels: {{ - include "myapp.labels" . | nindent 4 }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: {{ - include "myapp.selectorLabels" . | nindent 6 }} template: metadata: labels: {{ - include "myapp.selectorLabels" . | nindent 8 }} spec: containers:
- name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} ports:
- containerPort: 80 resources: {{ - toYaml .Values.resources | nindent 10 }}
|
**templates/_helpers.tpl**:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| {{ - define "myapp.name" - }} {{ - default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{ - end }}
{{ - define "myapp.fullname" - }} {{ - if .Values.nameOverride }} {{ - .Values.nameOverride | trunc 63 | trimSuffix "-" }} {{ - else }} {{ - printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} {{ - end }} {{ - end }}
{{ - define "myapp.labels" - }} helm.sh/chart: {{ include "myapp.chart" . }} {{ include "myapp.selectorLabels" . }} {{ - if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} {{ - end }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{ - end }}
{{ - define "myapp.selectorLabels" - }} app.kubernetes.io/name: {{ include "myapp.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{ - end }}
|
打包和安装:
1 2 3 4 5 6 7 8 9 10 11
| helm package mychart
helm install myapp ./mychart
helm install myapp ./mychart -f my-values.yaml
helm install myapp ./mychart --set replicaCount=5
|
服务网格( Istio)深入
服务网格( Service
Mesh)是处理服务间通信的基础设施层,提供服务发现、负载均衡、故障恢复、指标收集、安全策略等功能,无需修改应用代码。
Istio 架构详解
Istio 由数据平面和控制平面组成:
数据平面:
- Envoy 代理:以 Sidecar 形式部署在每个 Pod
中,拦截所有服务间通信
- 处理流量路由、负载均衡、健康检查、故障注入等
控制平面:
- Istiod:统一管理和配置所有 Envoy 代理
- 包含 Pilot(流量管理)、 Citadel(安全)、 Galley(配置管理)
架构图:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| ┌─────────────────────────────────────┐ │ Control Plane (Istiod) │ │ ┌──────────┐ ┌──────────┐ │ │ │ Pilot │ │ Citadel │ │ │ │ (Traffic)│ │ (Security)│ │ │ └──────────┘ └──────────┘ │ │ ┌──────────┐ │ │ │ Galley │ │ │ │ (Config)│ │ │ └──────────┘ │ └─────────────────────────────────────┘ │ │ 配置下发 ▼ ┌─────────────────────────────────────┐ │ Data Plane (Envoy) │ │ ┌──────┐ ┌──────┐ ┌──────┐ │ │ │ Pod1 │ │ Pod2 │ │ Pod3 │ │ │ │ ┌──┐ │ │ ┌──┐ │ │ ┌──┐ │ │ │ │ │ App │ │ │ │ App │ │ │ │ App │ │ │ │ │ └┬─┘ │ │ └┬─┘ │ │ └┬─┘ │ │ │ │ ┌▼─┐ │ │ ┌▼─┐ │ │ ┌▼─┐ │ │ │ │ │ Env │ │ │ │ Env │ │ │ │ Env │ │ │ │ │ │ oy │ │ │ │ oy │ │ │ │ oy │ │ │ │ │ └──┘ │ │ └──┘ │ │ └──┘ │ │ │ └──────┘ └──────┘ └──────┘ │ └─────────────────────────────────────┘
|
安装 Istio:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| curl -L https://istio.io/downloadIstio | sh - cd istio-*
export PATH=$PWD/bin:$PATH
istioctl install --set profile=default
istioctl verify-install
kubectl label namespace default istio-injection=enabled
istioctl kube-inject -f deployment.yaml | kubectl apply -f -
|
Istio 安装配置选项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| istioctl install --set profile=default \ --set values.global.proxy.logLevel=debug \ --set values.telemetry.v2.prometheus.enabled=true \ --set values.pilot.traceSampling=100.0
istioctl profile dump default
istioctl upgrade
istioctl uninstall --purge
|
流量管理深入
VirtualService 详解
VirtualService 定义路由规则,控制流量如何路由到服务。
基础路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- route: - destination: host: reviews subset: v1 weight: 50
- destination: host: reviews subset: v2 weight: 50
|
基于 Header 的路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- match: - headers: end-user: exact: jason uri: prefix: "/api/v2" route:
- destination: host: reviews subset: v2
- match: - headers: x-api-version: regex: "^v[2-9]" route:
- destination: host: reviews subset: v2
- route: - destination: host: reviews subset: v1 weight: 75
- destination: host: reviews subset: v3 weight: 25
|
基于 URI 的路由:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: api spec: hosts:
- api.example.com http:
- match: - uri: exact: /api/v1/users route:
- destination: host: user-service port: number: 8080 - match: - uri: prefix: /api/v2 rewrite: uri: /api/v1 route:
- destination: host: api-service port: number: 8080 - match: - uri: regex: "^/api/.*" route:
- destination: host: api-service port: number: 8080
|
故障注入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- fault: delay: percentage: value: 10 fixedDelay: 5s abort: percentage: value: 5 httpStatus: 500 route:
- destination: host: reviews subset: v1
|
超时和重试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- route: - destination: host: reviews subset: v1 timeout: 3s retries: attempts: 3 perTryTimeout: 2s retryOn: 5xx,gateway-error,connect-failure
|
DestinationRule 详解
DestinationRule 定义服务的流量策略,如负载均衡、连接池、熔断等。
负载均衡策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: reviews spec: host: reviews trafficPolicy: loadBalancer: simple: LEAST_CONN connectionPool: tcp: maxConnections: 100 connectTimeout: 30s http: http1MaxPendingRequests: 10 http2MaxRequests: 100 maxRequestsPerConnection: 2 maxRetries: 3 idleTimeout: 90s outlierDetection: consecutiveErrors: 5 interval: 30s baseEjectionTime: 30s maxEjectionPercent: 50 minHealthPercent: 50 subsets:
- name: v1 labels: version: v1 trafficPolicy: loadBalancer: simple: ROUND_ROBIN
- name: v2 labels: version: v2 trafficPolicy: loadBalancer: simple: LEAST_CONN
|
TLS 策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: reviews spec: host: reviews trafficPolicy: tls: mode: ISTIO_MUTUAL sni: reviews.example.com subjectAltNames:
- reviews.example.com subsets:
- name: v1 labels: version: v1 trafficPolicy: tls: mode: SIMPLE
|
Gateway 详解
Gateway 用于管理入口流量,类似于 Kubernetes Ingress 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: my-gateway spec: selector: istio: ingressgateway servers:
- port: number: 80 name: http protocol: HTTP hosts:
- api.example.com - app.example.com tls: httpsRedirect: true - port: number: 443 name: https protocol: HTTPS hosts:
- api.example.com - app.example.com tls: mode: SIMPLE credentialName: tls-secret
|
Gateway 与 VirtualService 配合:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: api-gateway spec: selector: istio: ingressgateway servers:
- port: number: 80 name: http protocol: HTTP hosts:
- api.example.com
---
apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: api spec: hosts:
- api.example.com gateways:
- api-gateway http:
- route: - destination: host: api-service port: number: 8080
|
安全策略深入
mTLS 配置
PeerAuthentication(对等认证):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: production spec: mtls: mode: STRICT
---
apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default namespace: istio-system spec: mtls: mode: STRICT selector: matchLabels: app: myapp
|
mTLS 模式说明:
DISABLE:禁用 mTLS
PERMISSIVE:允许明文和 mTLS 流量(迁移阶段使用)
STRICT:只允许 mTLS 流量(生产环境推荐)
授权策略
AuthorizationPolicy 详解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: allow-all spec: action: ALLOW rules:
- {}
---
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: deny-all spec: action: DENY rules:
- {}
---
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: ip-based-policy spec: selector: matchLabels: app: api action: ALLOW rules:
- from: - source: ipBlocks: ["192.168.1.0/24"] to:
- operation: methods: ["GET", "POST"]
---
apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: jwt-based-policy spec: selector: matchLabels: app: api action: ALLOW rules:
- from: - source: requestPrincipals: ["*"] to:
- operation: methods: ["GET"]
- from: - source: requestPrincipals: ["cluster.local/ns/default/sa/admin"] to:
- operation: methods: ["GET", "POST", "PUT", "DELETE"]
|
可观测性
指标收集( Prometheus):
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: control-plane spec: values: telemetry: v2: prometheus: enabled: true
|
分布式追踪( Jaeger):
1 2 3 4 5 6 7 8 9 10
| apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: control-plane spec: meshConfig: defaultConfig: tracing: sampling: 100.0
|
访问追踪数据:
1 2 3 4
| kubectl port-forward -n istio-system svc/jaeger-query 16686:16686
|
服务网格最佳实践
1. 渐进式采用:
- 先在非关键服务上启用
- 使用 PERMISSIVE mTLS 模式进行迁移
- 逐步启用 STRICT mTLS
2. 性能优化:
- 合理设置连接池大小
- 使用适当的负载均衡算法
- 监控 Sidecar 资源使用
3. 安全配置:
- 启用 mTLS
- 使用 AuthorizationPolicy 限制访问
- 定期轮换证书
4. 监控和告警:
微服务架构设计模式
API 网关模式
API
网关作为所有客户端请求的单一入口点,提供路由、认证、限流等功能。
使用 Kong 作为 API 网关:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| apiVersion: v1 kind: Service metadata: name: kong-proxy spec: type: LoadBalancer ports:
- port: 80 targetPort: 8000 protocol: TCP name: proxy
- port: 443 targetPort: 8443 protocol: TCP name: proxy-ssl selector: app: kong
|
服务发现模式
使用 Kubernetes Service 进行服务发现:
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: v1 kind: Service metadata: name: user-service spec: selector: app: user-service ports:
- port: 80 targetPort: 8080
|
应用通过服务名称访问:http://user-service:80
配置中心模式
使用 ConfigMap 存储配置:
1 2 3 4 5 6 7 8 9
| apiVersion: v1 kind: ConfigMap metadata: name: app-config data: database.host: "mysql-service" database.port: "3306" cache.host: "redis-service" cache.port: "6379"
|
在 Pod 中使用:
1 2 3 4 5 6 7 8 9 10 11
| apiVersion: v1 kind: Pod spec: containers:
- name: app image: myapp:latest envFrom:
- configMapRef: name: app-config
|
熔断器模式( Circuit Breaker)
熔断器模式用于防止级联故障,当服务失败率达到阈值时,快速失败而不是等待超时。
使用 Istio 实现熔断:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: httpbin spec: host: httpbin trafficPolicy: connectionPool: tcp: maxConnections: 100 connectTimeout: 30s http: http1MaxPendingRequests: 10 http2MaxRequests: 100 maxRequestsPerConnection: 2 maxRetries: 3 outlierDetection: consecutiveErrors: 5 interval: 30s baseEjectionTime: 30s maxEjectionPercent: 50 minHealthPercent: 50
|
熔断器状态:
- Closed(关闭):正常状态,请求正常通过
- Open(打开):失败率超过阈值,直接拒绝请求
- Half-Open(半开):尝试恢复,允许少量请求通过
使用 Spring Cloud 实现熔断:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @HystrixCommand(fallbackMethod = "fallbackMethod") public String callRemoteService() { return restTemplate.getForObject("http://remote-service/api", String.class); }
public String fallbackMethod() { return "Service temporarily unavailable"; }
@CircuitBreaker(name = "remoteService", fallbackMethod = "fallbackMethod") public String callRemoteService() { return restTemplate.getForObject("http://remote-service/api", String.class); }
|
限流模式( Rate Limiting)
限流模式用于控制服务的请求速率,防止系统过载。
使用 Istio 实现限流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| apiVersion: networking.istio.io/v1beta1 kind: EnvoyFilter metadata: name: rate-limit spec: configPatches:
- applyTo: HTTP_FILTER match: context: SIDECAR_INBOUND listener: filterChain: filter: name: "envoy.filters.network.http_connection_manager" patch: operation: INSERT_BEFORE value: name: envoy.filters.http.local_ratelimit typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit stat_prefix: http_local_rate_limiter token_bucket: max_tokens: 100 tokens_per_fill: 100 fill_interval: 60s filter_enabled: runtime_key: local_rate_limit_enabled default_value: numerator: 100 denominator: HUNDRED filter_enforced: runtime_key: local_rate_limit_enforced default_value: numerator: 100 denominator: HUNDRED
|
使用 Nginx Ingress 限流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: rate-limit-ingress annotations: nginx.ingress.kubernetes.io/limit-rps: "100" nginx.ingress.kubernetes.io/limit-connections: "10" nginx.ingress.kubernetes.io/limit-rpm: "1000" spec: ingressClassName: nginx rules:
- host: api.example.com http: paths:
- path: / pathType: Prefix backend: service: name: api-service port: number: 80
|
使用 Redis 实现分布式限流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import redis import time
class RateLimiter: def __init__(self, redis_client, key, max_requests, window_seconds): self.redis = redis_client self.key = key self.max_requests = max_requests self.window_seconds = window_seconds def is_allowed(self): now = time.time() window_start = now - self.window_seconds pipe = self.redis.pipeline() pipe.zremrangebyscore(self.key, 0, window_start) pipe.zcard(self.key) pipe.zadd(self.key, {str(now): now}) pipe.expire(self.key, self.window_seconds) results = pipe.execute() current_requests = results[1] return current_requests < self.max_requests
|
降级模式( Degradation)
降级模式在系统负载过高或部分服务不可用时,提供简化版功能或返回缓存数据。
降级策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- match: - headers: x-degrade: exact: "true" route:
- destination: host: reviews subset: v1-cache weight: 100
- route: - destination: host: reviews subset: v1 weight: 80
- destination: host: reviews subset: v2 weight: 20 fault: delay: percentage: value: 10 fixedDelay: 5s
|
降级实现示例( Java):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| @Service public class ProductService { @Autowired private CacheService cacheService; @Autowired private RemoteService remoteService; @Degrade(fallbackMethod = "getProductFromCache") public Product getProduct(String id) { return remoteService.getProduct(id); } public Product getProductFromCache(String id) { Product product = cacheService.get(id); if (product == null) { return Product.defaultProduct(); } return product; } }
|
重试模式( Retry)
重试模式用于处理临时性故障,通过重试提高请求成功率。
使用 Istio 实现重试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- route: - destination: host: reviews subset: v1 retries: attempts: 3 perTryTimeout: 2s retryOn: 5xx,gateway-error,connect-failure,refused-stream retryRemoteLocalities: false
|
指数退避重试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import time import random
def exponential_backoff_retry(func, max_retries=3, base_delay=1): for attempt in range(max_retries): try: return func() except Exception as e: if attempt == max_retries - 1: raise delay = base_delay * (2 ** attempt) + random.uniform(0, 1) time.sleep(delay) return None
|
超时模式( Timeout)
超时模式用于防止请求无限等待,及时释放资源。
使用 Istio 配置超时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: reviews spec: hosts:
- reviews http:
- route: - destination: host: reviews subset: v1 timeout: 3s
|
超时配置最佳实践:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: api spec: hosts:
- api.example.com http:
- match: - uri: prefix: "/api/fast" route:
- destination: host: api-service timeout: 1s - match: - uri: prefix: "/api/slow" route:
- destination: host: api-service timeout: 30s
|
服务发现模式扩展
使用 Consul 进行服务发现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| apiVersion: v1 kind: ConfigMap metadata: name: consul-config data: consul.json: | { "service": { "name": "myapp", "tags": ["web", "v1"], "port": 8080, "check": { "http": "http://localhost:8080/health", "interval": "10s" } } }
|
使用 Eureka 进行服务发现:
1 2 3 4 5 6 7 8 9 10 11 12 13
| apiVersion: v1 kind: ConfigMap metadata: name: eureka-config data: application.yml: | eureka: client: service-url: defaultZone: http://eureka-server:8761/eureka/ instance: prefer-ip-address: true
|
分布式追踪模式
使用 Jaeger 进行分布式追踪:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: apps/v1 kind: Deployment metadata: name: app-with-tracing spec: template: spec: containers:
- name: app image: myapp:latest env:
- name: JAEGER_AGENT_HOST value: jaeger-agent
- name: JAEGER_AGENT_PORT value: "6831"
- name: JAEGER_SAMPLER_TYPE value: "const"
- name: JAEGER_SAMPLER_PARAM value: "1"
|
使用 OpenTelemetry:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| apiVersion: apps/v1 kind: Deployment metadata: name: app-with-otel spec: template: spec: containers:
- name: app image: myapp:latest env:
- name: OTEL_EXPORTER_OTLP_ENDPOINT value: "http://otel-collector:4317"
- name: OTEL_SERVICE_NAME value: "myapp"
- name: OTEL_RESOURCE_ATTRIBUTES value: "service.name=myapp,service.version=1.0"
|
CI/CD 流水线实战
Jenkins Pipeline
Jenkinsfile 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| pipeline { agent any environment { DOCKER_REGISTRY = 'registry.example.com' IMAGE_NAME = 'myapp' KUBERNETES_NAMESPACE = 'production' } stages { stage('Checkout') { steps { checkout scm } } stage('Build') { steps { sh 'docker build -t ${IMAGE_NAME}:${BUILD_NUMBER} .' sh 'docker tag ${IMAGE_NAME}:${BUILD_NUMBER} ${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}' } } stage('Test') { steps { sh 'docker run --rm ${IMAGE_NAME}:${BUILD_NUMBER} npm test' } } stage('Push') { steps { withCredentials([usernamePassword(credentialsId: 'docker-registry', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]) { sh 'echo $PASSWORD | docker login -u $USERNAME --password-stdin ${DOCKER_REGISTRY}' sh 'docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}' } } } stage('Deploy') { steps { sh ''' kubectl set image deployment/myapp myapp=${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER} -n ${KUBERNETES_NAMESPACE} kubectl rollout status deployment/myapp -n ${KUBERNETES_NAMESPACE} ''' } } } post { success { echo 'Pipeline succeeded!' } failure { echo 'Pipeline failed!' } } }
|
GitLab CI/CD
.gitlab-ci.yml 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| stages:
- build - test - deploy
variables: DOCKER_REGISTRY: registry.gitlab.com IMAGE_NAME: $CI_REGISTRY_IMAGE KUBERNETES_NAMESPACE: production
build: stage: build script:
- docker build -t $IMAGE_NAME:$CI_COMMIT_SHA . - docker tag $IMAGE_NAME:$CI_COMMIT_SHA $IMAGE_NAME:latest - docker push $IMAGE_NAME:$CI_COMMIT_SHA - docker push $IMAGE_NAME:latest only:
- main - develop
test: stage: test script:
- docker run --rm $IMAGE_NAME:$CI_COMMIT_SHA npm test only:
- main - develop
deploy: stage: deploy script:
- kubectl set image deployment/myapp myapp=$IMAGE_NAME:$CI_COMMIT_SHA -n $KUBERNETES_NAMESPACE - kubectl rollout status deployment/myapp -n $KUBERNETES_NAMESPACE only:
- main environment: name: production url: https://myapp.example.com
|
GitHub Actions
.github/workflows/ci-cd.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| name: CI/CD Pipeline
on: push: branches: [ main ] pull_request: branches: [ main ]
env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}
jobs: build-and-push: runs-on: ubuntu-latest permissions: contents: read packages: write steps:
- uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log in to Container Registry uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push uses: docker/build-push-action@v4 with: context: . push: true tags: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest - name: Deploy to Kubernetes uses: azure/k8s-deploy@v4 with: manifests: | k8s/deployment.yaml k8s/service.yaml images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} namespace: production
|
实战案例
案例一:部署 WordPress 应用栈
架构: WordPress + MySQL + Redis
docker-compose.yml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| version: '3.8'
services: wordpress: image: wordpress:php8.0-apache ports:
- "8080:80" environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_NAME: wordpress volumes:
- wp_data:/var/www/html depends_on:
- db - redis networks:
- app-network
db: image: mysql:8.0 environment: MYSQL_DATABASE: wordpress MYSQL_USER: wordpress MYSQL_PASSWORD: wordpress MYSQL_ROOT_PASSWORD: rootpassword volumes:
- db_data:/var/lib/mysql networks:
- app-network
redis: image: redis:6-alpine command: redis-server --appendonly yes volumes:
- redis_data:/data networks:
- app-network
volumes: wp_data: db_data: redis_data:
networks: app-network: driver: bridge
|
Kubernetes 部署:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| apiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers:
- name: mysql image: mysql:8.0 env:
- name: MYSQL_ROOT_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: root-password
- name: MYSQL_DATABASE value: wordpress
- name: MYSQL_USER value: wordpress
- name: MYSQL_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: password ports:
- containerPort: 3306 volumeMounts:
- name: mysql-storage mountPath: /var/lib/mysql volumes:
- name: mysql-storage persistentVolumeClaim: claimName: mysql-pvc
--- apiVersion: v1 kind: Service metadata: name: mysql spec: selector: app: mysql ports:
- port: 3306
---
apiVersion: apps/v1 kind: Deployment metadata: name: wordpress spec: replicas: 3 selector: matchLabels: app: wordpress template: metadata: labels: app: wordpress spec: containers:
- name: wordpress image: wordpress:php8.0-apache ports:
- containerPort: 80 env:
- name: WORDPRESS_DB_HOST value: mysql
- name: WORDPRESS_DB_USER value: wordpress
- name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: mysql-secret key: password
- name: WORDPRESS_DB_NAME value: wordpress volumeMounts:
- name: wp-storage mountPath: /var/www/html volumes:
- name: wp-storage persistentVolumeClaim: claimName: wp-pvc
--- apiVersion: v1 kind: Service metadata: name: wordpress spec: type: LoadBalancer selector: app: wordpress ports:
- port: 80 targetPort: 80
|
案例二:构建微服务电商系统
服务架构:
- API Gateway( Kong)
- 用户服务( User Service)
- 商品服务( Product Service)
- 订单服务( Order Service)
- 支付服务( Payment Service)
- 数据库( PostgreSQL)
- 消息队列( RabbitMQ)
Kong API Gateway 配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| apiVersion: v1 kind: ConfigMap metadata: name: kong-config data: kong.yml: | _format_version: "1.1" services:
- name: user-service url: http://user-service:8080 routes:
- name: user-route paths:
- /api/users - name: product-service url: http://product-service:8080 routes:
- name: product-route paths:
- /api/products - name: order-service url: http://order-service:8080 routes:
- name: order-route paths:
- /api/orders
|
用户服务 Deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| apiVersion: apps/v1 kind: Deployment metadata: name: user-service spec: replicas: 3 selector: matchLabels: app: user-service template: metadata: labels: app: user-service spec: containers:
- name: user-service image: myregistry/user-service:v1.0 ports:
- containerPort: 8080 env:
- name: DATABASE_URL valueFrom: secretKeyRef: name: db-secret key: url
- name: RABBITMQ_URL value: amqp://rabbitmq:5672 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5
|
案例三:高可用 Redis 集群
Redis Sentinel 配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-master spec: serviceName: redis replicas: 1 selector: matchLabels: app: redis role: master template: metadata: labels: app: redis role: master spec: containers:
- name: redis image: redis:6-alpine command:
- redis-server - /etc/redis/redis.conf ports:
- containerPort: 6379 volumeMounts:
- name: redis-data mountPath: /data
- name: redis-config mountPath: /etc/redis volumes:
- name: redis-config configMap: name: redis-config
---
apiVersion: apps/v1 kind: StatefulSet metadata: name: redis-sentinel spec: serviceName: redis-sentinel replicas: 3 selector: matchLabels: app: redis-sentinel template: metadata: labels: app: redis-sentinel spec: containers:
- name: sentinel image: redis:6-alpine command:
- redis-sentinel - /etc/sentinel/sentinel.conf ports:
- containerPort: 26379 volumeMounts:
- name: sentinel-config mountPath: /etc/sentinel volumes:
- name: sentinel-config configMap: name: sentinel-config
|
❓ Q&A: 云原生与容器常见问题
Q1: Docker
容器和虚拟机的区别是什么?
A: Docker 容器和虚拟机的主要区别在于:
- 资源占用:容器共享主机操作系统内核,比虚拟机更轻量,启动更快
- 隔离级别:虚拟机提供硬件级隔离,容器提供进程级隔离
- 性能:容器性能接近原生应用,虚拟机有虚拟化开销
- 可移植性:容器镜像更小,更容易在不同环境间迁移
容器适合微服务、 CI/CD
等场景,虚拟机适合需要完整操作系统隔离的场景。
Q2: 如何选择 Kubernetes
的网络插件?
A: 选择网络插件需要考虑以下因素:
- Flannel:简单易用,适合中小型集群,性能良好
- Calico:功能强大,支持网络策略,适合需要细粒度安全控制的场景
- Weave
Net:自动网络发现,支持加密,适合多租户环境
- Cilium:基于 eBPF,高性能,适合大规模集群
对于大多数场景, Flannel 或 Calico 是不错的选择。
Q3: Pod 和容器的关系是什么?
A: Pod 是 Kubernetes
的最小调度单元,可以包含一个或多个容器。 Pod 内的容器:
- 共享网络命名空间(同一 IP 地址)
- 共享存储卷
- 可以通过 localhost 通信
- 生命周期一致(一起创建、删除)
单容器 Pod 最常见,多容器 Pod 通常用于:
- Sidecar 模式(如日志收集、代理)
- 初始化容器(准备主容器运行环境)
Q4: 如何实现 Kubernetes
的滚动更新?
A: Deployment 默认使用 RollingUpdate 策略:
1 2 3 4 5
| strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 0
|
更新过程: 1. 创建新版本 Pod 2. 等待新 Pod 就绪 3. 删除旧版本 Pod 4.
重复直到所有 Pod 更新完成
可以通过 kubectl rollout 命令管理更新:
kubectl rollout status 查看状态
kubectl rollout pause 暂停更新
kubectl rollout undo 回滚
Q5: StatefulSet 和
Deployment 的区别?
A: 主要区别:
| 特性 |
Deployment |
StatefulSet |
| 网络标识 |
随机名称 |
稳定名称( pod-0, pod-1) |
| 存储 |
共享存储 |
每个 Pod 独立存储 |
| 部署顺序 |
并行 |
有序( 0, 1, 2...) |
| 删除顺序 |
并行 |
逆序( 2, 1, 0) |
| 适用场景 |
无状态应用 |
有状态应用(数据库、消息队列) |
StatefulSet 适合需要稳定网络标识和持久存储的应用。
Q6: 如何调试 Kubernetes Pod
问题?
A: 调试步骤和常用命令:
1. 查看 Pod 状态: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| kubectl get pods
kubectl get pods -n production
kubectl describe pod <pod-name>
kubectl get pod <pod-name> -o yaml
kubectl get pod <pod-name> -o json
kubectl get pods --show-labels
kubectl get pods -l app=myapp
|
2. 查看日志: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| kubectl logs <pod-name>
kubectl logs <pod-name> -c <container-name>
kubectl logs -f <pod-name>
kubectl logs <pod-name> --tail=100
kubectl logs <pod-name> --since=1h kubectl logs <pod-name> --since-time=2025-01-02T10:00:00Z
kubectl logs <pod-name> --previous
kubectl logs <pod-name> --all-containers=true
|
3. 进入容器调试: 1 2 3 4 5 6 7 8 9 10 11 12 13
| kubectl exec -it <pod-name> -- /bin/bash
kubectl exec -it <pod-name> -- /bin/sh
kubectl exec <pod-name> -- ps aux kubectl exec <pod-name> -- env kubectl exec <pod-name> -- netstat -tlnp
kubectl exec -it <pod-name> -c <container-name> -- /bin/bash
|
4. 查看事件和资源: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| kubectl get events --sort-by=.metadata.creationTimestamp
kubectl get events -n production
kubectl top pod <pod-name>
kubectl top node
kubectl get pod <pod-name> -o wide
kubectl get pod <pod-name> -o jsonpath='{.spec.nodeName}'
|
5. 常见问题排查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| kubectl describe pod <pod-name> | grep -A 5 "Events" kubectl get nodes kubectl describe node <node-name>
kubectl logs <pod-name> --previous kubectl describe pod <pod-name> | grep -A 10 "State"
kubectl get pod <pod-name> -o yaml | grep -A 20 "containerStatuses" kubectl describe pod <pod-name> | grep -A 10 "Warning\|Error"
kubectl describe pod <pod-name> | grep -i "image\|pull"
kubectl describe pod <pod-name> | grep -A 5 "Limits\|Requests"
kubectl describe pod <pod-name> | grep -A 10 "Volumes\|Mounts"
|
6. 网络问题排查:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| kubectl get svc <service-name> kubectl get endpoints <service-name>
kubectl run -it --rm debug --image=busybox --restart=Never -- sh
kubectl get networkpolicy kubectl describe networkpolicy <policy-name>
kubectl exec <pod-name> -- cat /etc/resolv.conf
kubectl run -it --rm dns-test --image=busybox --restart=Never -- nslookup <service-name>
|
7. 使用临时调试容器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| kubectl run -it --rm debug \ --image=busybox \ --restart=Never \ -- sh
kubectl run -it --rm netshoot \ --image=nicolaka/netshoot \ --restart=Never \ -- bash
kubectl run -it --rm curl-test \ --image=curlimages/curl \ --restart=Never \ -- curl http://<service-name>:<port>
|
Q7: Helm Chart
的依赖管理如何工作?
A: Helm 支持 Chart 依赖,通过
Chart.yaml 的 dependencies 字段定义:
1 2 3 4 5 6 7 8 9
| dependencies:
- name: mysql version: 8.8.0 repository: https://charts.bitnami.com/bitnami
- name: redis version: 17.0.0 repository: https://charts.bitnami.com/bitnami
|
管理依赖: 1 2 3 4 5 6 7 8
| helm dependency update
helm package .
helm install myapp .
|
依赖 Chart 会被下载到 charts/ 目录,可以通过
values.yaml 覆盖依赖的配置。
Q8: 如何实现 Kubernetes
的自动扩缩容?
A: Kubernetes 提供 HPA( Horizontal Pod
Autoscaler):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: myapp-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: myapp minReplicas: 2 maxReplicas: 10 metrics:
- type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70
- type: Resource resource: name: memory target: type: Utilization averageUtilization: 80
|
HPA 会根据 CPU/内存使用率自动调整 Pod 数量。需要安装
metrics-server:
1
| kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
|
Q9: Docker
镜像层缓存机制如何优化构建速度?
A: Docker 使用层缓存机制,优化策略:
合理排序 Dockerfile 指令:
1 2 3 4 5 6
| COPY requirements.txt . RUN pip install -r requirements.txt
COPY . .
|
合并 RUN 指令: 1 2 3 4 5 6
| RUN apt-get update && \ apt-get install -y python3 && \ rm -rf /var/lib/apt/lists/*
|
使用 .dockerignore:排除不需要的文件
多阶段构建:减少最终镜像大小
Q10: 如何保障 Kubernetes
集群的安全性?
A: 安全最佳实践:
RBAC 权限控制: 1 2 3 4 5 6 7 8 9
| apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader rules:
- apiGroups: [""] resources: ["pods"] verbs: ["get", "watch", "list"]
|
网络策略: 1 2 3 4 5 6 7 8 9 10
| apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: deny-all spec: podSelector: {} policyTypes:
- Ingress - Egress
|
Secret 管理:使用 Secret
存储敏感信息,避免硬编码
镜像安全:扫描镜像漏洞,使用可信镜像源
Pod 安全策略:限制 Pod
权限,禁止特权容器
TLS 加密:启用 API Server
TLS,使用加密存储
定期更新 Kubernetes 版本,及时修复安全漏洞。
Q11: Docker
镜像构建缓慢,如何优化?
A: 优化 Docker 镜像构建速度的方法:
1. 利用构建缓存: 1 2 3 4 5 6
| COPY requirements.txt . RUN pip install -r requirements.txt
COPY . .
|
2. 使用多阶段构建: 1 2 3 4 5 6 7 8 9 10
| FROM node:16-alpine AS builder WORKDIR /build COPY package*.json ./ RUN npm ci --only=production
FROM node:16-alpine COPY --from=builder /build/node_modules ./node_modules COPY . .
|
3. 使用 .dockerignore: 1 2 3 4 5 6
| node_modules .git .env *.log dist .DS_Store
|
4. 使用 BuildKit: 1 2 3 4 5
| export DOCKER_BUILDKIT=1
docker build --progress=plain -t myapp .
|
5. 并行构建多个阶段: 1 2 3 4 5
| FROM alpine AS deps RUN apk add --no-cache python3
FROM alpine AS runtime RUN apk add --no-cache python3
|
6. 使用缓存挂载: 1 2
| RUN --mount=type=cache,target=/root/.cache/pip \ pip install -r requirements.txt
|
Q12: Kubernetes
Pod 一直处于 Pending 状态怎么办?
A: Pod Pending 状态的常见原因和解决方法:
1. 检查节点资源: 1 2 3 4 5 6 7
| kubectl describe node <node-name>
kubectl describe pod <pod-name>
|
2. 检查节点选择器: 1 2 3 4
| spec: nodeSelector: disktype: ssd
|
3. 检查污点和容忍度: 1 2 3 4 5 6 7 8 9 10 11
| kubectl describe node <node-name> | grep Taints
spec: tolerations:
- key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule"
|
4. 检查持久卷声明: 1 2 3 4 5 6
| kubectl get pvc
kubectl get storageclass kubectl get pv
|
5. 检查资源配额: 1 2 3 4
| kubectl describe resourcequota -n <namespace>
|
6. 查看调度器日志: 1 2
| kubectl logs -n kube-system <scheduler-pod-name>
|
Q13: Docker
容器无法访问外部网络怎么办?
A: 容器网络问题的排查步骤:
1. 检查容器网络模式: 1 2 3 4 5
| docker inspect <container-name> | grep -A 20 "NetworkSettings"
docker exec <container-name> ping -c 3 8.8.8.8
|
2. 检查 DNS 配置: 1 2 3 4 5
| docker exec <container-name> cat /etc/resolv.conf
docker run --dns=8.8.8.8 --dns=8.8.4.4 myapp
|
3. 检查防火墙规则: 1 2 3 4 5
| sudo iptables -L -n
docker network inspect bridge
|
4. 检查代理设置: 1 2 3 4
| docker run -e HTTP_PROXY=http://proxy:8080 \ -e HTTPS_PROXY=http://proxy:8080 \ myapp
|
5. 重启 Docker 服务: 1 2 3 4 5
| sudo systemctl restart docker
sudo systemctl restart docker-network
|
Q14: Kubernetes Service
无法访问,如何排查?
A: Service 访问问题的排查方法:
1. 检查 Service 和 Endpoints: 1 2 3 4 5 6 7 8
| kubectl get svc <service-name> -o yaml
kubectl get endpoints <service-name>
kubectl get pods --show-labels
|
2. 检查 Pod 标签和 Selector: 1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: v1 kind: Service metadata: name: my-service spec: selector: app: myapp ports:
- port: 80 targetPort: 8080
|
3. 检查 Pod 端口: 1 2 3 4 5
| kubectl exec <pod-name> -- netstat -tlnp
kubectl exec <pod-name> -- curl localhost:8080
|
4. 检查网络策略: 1 2 3 4
| kubectl get networkpolicy
|
5. 从 Pod 内部测试 Service: 1 2 3 4 5 6 7 8
| kubectl exec -it <pod-name> -- /bin/sh
nslookup my-service
curl http://my-service:80
|
6. 检查 kube-proxy: 1 2 3 4 5
| kubectl logs -n kube-system <kube-proxy-pod>
sudo iptables -t nat -L | grep <service-name>
|
Q15: Docker 和
Kubernetes 的资源消耗对比?
A: 资源消耗对比表:
| 资源类型 |
Docker |
Kubernetes (单节点) |
Kubernetes (3 节点) |
| CPU |
低(仅容器运行时) |
中等(控制平面+节点组件) |
高( 3 个控制平面+节点) |
| 内存 |
低(~100MB) |
中等(~2-4GB) |
高(~6-12GB) |
| 磁盘 |
低(镜像和容器) |
中等(+etcd 数据) |
高(+多节点数据) |
| 网络 |
低(仅容器网络) |
中等(+Service 网络) |
高(+跨节点通信) |
详细说明:
Docker:
- CPU:容器运行时开销约 1-5%
- 内存: Docker daemon 约 50-200MB,每个容器约 10-50MB 开销
- 磁盘:镜像存储,可共享层节省空间
- 网络: bridge 网络开销很小
Kubernetes(单节点):
- CPU:控制平面组件( API Server 、 etcd 、 Scheduler 、 Controller
Manager)约 500m-2 CPU
- 内存:控制平面约 1-2GB,节点组件( kubelet 、 kube-proxy)约
200-500MB
- 磁盘: etcd 数据约 1-10GB(取决于集群规模)
- 网络: CNI 插件额外开销
Kubernetes(多节点):
- 控制平面资源乘以节点数(高可用部署)
- 跨节点网络通信开销
- 分布式存储开销
优化建议: 1. 小规模应用:使用 Docker Compose 2.
中等规模:单节点 Kubernetes 或轻量级发行版( k3s 、 k0s) 3.
大规模生产:完整 Kubernetes 集群
Q16: 如何实现 Kubernetes
的蓝绿部署?
A: 蓝绿部署实现方法:
方法 1:使用两个 Deployment:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| apiVersion: apps/v1 kind: Deployment metadata: name: app-blue spec: replicas: 3 selector: matchLabels: app: myapp version: blue template: metadata: labels: app: myapp version: blue spec: containers:
- name: app image: myapp:v1.0
---
apiVersion: apps/v1 kind: Deployment metadata: name: app-green spec: replicas: 3 selector: matchLabels: app: myapp version: green template: metadata: labels: app: myapp version: green spec: containers:
- name: app image: myapp:v2.0
---
apiVersion: v1 kind: Service metadata: name: app-service spec: selector: app: myapp version: blue ports:
- port: 80 targetPort: 8080
|
切换脚本:
1 2 3 4 5 6 7 8 9
| #!/bin/bash
kubectl patch service app-service -p '{"spec":{"selector":{"version":"green" }}}'
kubectl get endpoints app-service
kubectl patch service app-service -p '{"spec":{"selector":{"version":"blue" }}}'
|
方法 2:使用 Istio VirtualService:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: app spec: hosts:
- app.example.com http:
- route: - destination: host: app-service subset: blue weight: 100
- destination: host: app-service subset: green weight: 0
---
|
Q17: Docker
容器日志管理最佳实践?
A: 容器日志管理策略:
1. 配置日志驱动:
1 2 3 4 5 6 7 8 9 10
| { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3", "labels": "production", "env": "os,customer" } }
|
2. 容器级别日志配置:
1 2 3 4 5 6 7 8 9
| docker run --log-opt max-size=10m \ --log-opt max-file=3 \ myapp
docker run --log-driver=syslog \ --log-opt syslog-address=udp://localhost:514 \ myapp
|
3. 使用日志收集工具:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| version: '3.8' services: app: image: myapp logging: driver: "fluentd" options: fluentd-address: localhost:24224 tag: docker.{{ .Name }}
fluentd: image: fluent/fluentd volumes:
- ./fluentd.conf:/fluentd/etc/fluent.conf ports:
- "24224:24224"
|
4. Kubernetes 日志管理:
1 2 3 4 5 6 7 8 9 10
| apiVersion: v1 kind: Pod metadata: name: app spec: containers:
- name: app image: myapp
|
5. 日志清理脚本:
1 2 3 4 5 6 7
| #!/bin/bash
docker system prune -f
docker logs <container-name> > /dev/null 2>&1 truncate -s 0 $(docker inspect <container-name> | grep LogPath | cut -d '"' -f 4)
|
Q18: Kubernetes
中如何实现服务间认证?
A: 服务间认证的几种方式:
1. 使用 ServiceAccount 和 Token:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| apiVersion: v1 kind: ServiceAccount metadata: name: app-sa
---
apiVersion: v1 kind: Pod metadata: name: app spec: serviceAccountName: app-sa containers:
- name: app image: myapp env:
- name: KUBERNETES_SERVICE_HOST value: "kubernetes.default.svc"
|
2. 使用 Istio mTLS:
1 2 3 4 5 6 7 8
| apiVersion: security.istio.io/v1beta1 kind: PeerAuthentication metadata: name: default spec: mtls: mode: STRICT
|
3. 使用 OAuth2/OIDC:
1 2 3 4 5 6 7 8
| apiVersion: v1 kind: ConfigMap metadata: name: oidc-config data: oidc-issuer-url: "https://auth.example.com" oidc-client-id: "kubernetes"
|
4. 使用 cert-manager 管理证书:
1 2 3 4 5 6 7 8 9 10 11 12
| apiVersion: cert-manager.io/v1 kind: Certificate metadata: name: service-cert spec: secretName: service-tls issuerRef: name: ca-issuer kind: ClusterIssuer dnsNames:
- service.example.com
|
Q19: Docker
镜像安全扫描和漏洞管理?
A: 镜像安全最佳实践:
1. 使用 Docker Scout:
1 2 3 4 5 6 7 8
| docker scout cves myapp:latest
docker scout cves --format json myapp:latest
docker scout watch myapp:latest
|
2. 使用 Trivy:
1 2 3 4 5 6 7 8
| brew install trivy
trivy image myapp:latest
trivy image -f json -o report.json myapp:latest
|
3. 使用 Clair:
1 2
| clair-scanner --ip <clair-server-ip> myapp:latest
|
4. CI/CD 集成:
1 2 3 4 5 6 7
| - name: Scan image uses: aquasecurity/trivy-action@master with: image-ref: myapp:latest format: 'sarif' output: 'trivy-results.sarif'
|
5. 使用基础镜像安全扫描:
Q20: Kubernetes
集群备份和恢复策略?
A: 集群备份和恢复方法:
1. etcd 备份:
1 2 3 4 5 6 7 8 9 10 11
| ETCDCTL_API=3 etcdctl \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/kubernetes/pki/etcd/ca.crt \ --cert=/etc/kubernetes/pki/etcd/server.crt \ --key=/etc/kubernetes/pki/etcd/server.key \ snapshot save /backup/etcd-snapshot-$(date +%Y%m%d).db
ETCDCTL_API=3 etcdctl snapshot restore /backup/etcd-snapshot.db \ --data-dir=/var/lib/etcd-backup
|
2. 资源备份脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| #!/bin/bash
NAMESPACE=production BACKUP_DIR=/backup/k8s-$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
kubectl get all -n $NAMESPACE -o yaml > $BACKUP_DIR/all-resources.yaml
kubectl get configmap -n $NAMESPACE -o yaml > $BACKUP_DIR/configmaps.yaml kubectl get secret -n $NAMESPACE -o yaml > $BACKUP_DIR/secrets.yaml
kubectl get pvc -n $NAMESPACE -o yaml > $BACKUP_DIR/pvcs.yaml
|
3. 使用 Velero:
1 2 3 4 5 6 7 8 9 10 11 12
| velero install \ --provider aws \ --bucket my-backup-bucket \ --secret-file ./credentials-velero
velero backup create production-backup \ --include-namespaces production
velero restore create --from-backup production-backup
|
4. 定期备份策略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| apiVersion: batch/v1 kind: CronJob metadata: name: etcd-backup spec: schedule: "0 2 * * *" jobTemplate: spec: template: spec: containers:
- name: etcd-backup image: bitnami/etcd:latest command:
- /bin/sh - -c - | ETCDCTL_API=3 etcdctl snapshot save /backup/etcd.db # 上传到云存储 volumes:
- name: backup hostPath: path: /backup restartPolicy: OnFailure
|
云原生技术正在快速发展,掌握容器技术和 Kubernetes
编排能力,对于现代软件开发和运维至关重要。通过本文的介绍,希望你能建立起对云原生技术的全面理解,并在实际项目中灵活运用这些工具和模式。持续学习,不断实践,才能在这个快速变化的领域中保持竞争力。