2026 最强容器技术指南:Kubernetes 和 Docker 关系深度解析,一文讲透核心原理与企业落地(建议收藏)

0 阅读24分钟

2026 最强容器技术指南:Kubernetes 和 Docker 关系深度解析,一文讲透核心原理与企业落地(建议收藏)

15c278c1-4631-4627-a42b-3ce97a1021fb_408.5KB.png

前言

话说回来,2026 年的今天,如果你还分不清 Docker 和 Kubernetes 的区别,那面试官看你的眼神,大概就像你看三年前自己写的代码一样——充满了复杂的情感。

别担心,今天这篇文章,就是来帮你彻底理清这对"世纪冤家"的关系。我会从痛点场景出发,用大白话解释原理,配上 Python 实战代码,最后再来点面试题压压惊。

准备好了吗?发车!

一、痛点场景:你中招了几个?

在正式开始之前,让我们先来聊聊那些年,我们一起踩过的容器坑。

场景一:开发环境正常,上线就翻车

"在我的机器上能跑啊!"

这句话大概是程序员说过的最著名谎言之一。你在本地 Windows 上开发得好好的 Python 服务,丢到服务器上就报错:"ModuleNotFoundError: No module named 'xxx'"。同事跑过来一看:"哦,你用的是 macOS 啊,那个包在 Linux 上编译不过的。"

然后你们开始了漫长的"依赖对齐"大战:改环境变量、装编译工具链、处理版本冲突……一通操作猛如虎,上线时间已经过了两天。

这就是"环境一致性"问题,而 Docker 正是来解决这个问题的。

场景二:手动扩缩容之痛

"双十一马上到了,老板说流量要扩容到 10 倍!"

你看着手里的 50 台服务器,陷入了沉思。手动登录每一台机器,执行 docker run 命令,然后手动配置负载均衡……

等你扩完容,双十一都结束了。

更可怕的是,峰值过后你要再缩回去。如果手动操作,你可能会在凌晨三点一边缩容一边怀疑人生:"我为什么要学计算机?"

这就是"弹性扩缩容"问题,而 Kubernetes 正是来解决这个问题的。

场景三:集群规模膨胀之痛

随着业务发展,你的 Docker 容器从 10 个变成了 100 个,又从 100 个变成了 1000 个。

然后你发现:

  • 某个容器挂了,没人知道
  • 某个服务响应慢,不知道是谁的问题
  • 要更新某个服务,得一个个手动操作
  • 资源分配不均,有的机器打满了,有的还空着

你开始怀念当初只有 10 个容器的日子,那时候一切都很简单,简单到你可以记住每一个容器的名字和用途。

这就是"容器编排"问题,而 Kubernetes 就是来解决这个问题的。

场景四:面试翻车之痛

面试官:"Docker 和 Kubernetes 有什么区别?"

你(信心满满):"Docker 是容器,Kubernetes 是编排平台!"

面试官(微笑):"那 Kubernetes 为什么在 1.24 版本移除了对 Docker 的直接支持?"

你:"???"

面试官:"你知道 CRI 是什么吗?"

你:"?????"

这就是"知识深度不够"的问题,今天这篇文章就是来帮你避免这种社死场面的。

二、痛点解决方案:为什么是 Docker+Kubernetes?

2.1 黄金组合:各司其职

其实啊,Docker 和 Kubernetes 从来就不是竞争关系,而是最佳拍档

  • Docker:负责"打包"——把你的应用和依赖打包成一个标准化的容器镜像
  • Kubernetes:负责"调度"——管理这些容器的运行、扩缩容、故障恢复等

这就好比:

  • Docker = 快递公司(打包、封装货物)
  • Kubernetes = 物流调度中心(分配路线、处理异常、批量管理)

2.2 数据说话

根据 CNCF(云原生计算基金会)2025 年的调查数据:

  • 82% 的组织已经在生产环境中使用 Kubernetes
  • 77% 的组织使用 Docker 作为容器运行时
  • 65% 的组织同时使用两者

换句话说,不懂 Docker 和 Kubernetes,你可能连跟同行聊天都费劲。

2.3 核心公式

容器化应用 = Dockerfile(构建) -> Docker Image(打包) -> Docker Registry(分发)
容器编排系统 = Kubernetes(调度) -> Pod(调度单元) -> Deployment(管理)

记住这个公式,你就理解了容器技术的半壁江山。

三、是什么:极简概念与原理

3.1 Docker 核心定义

官方定义:Docker 是一个开源的容器化平台,让开发者能够打包应用及其依赖到一个可移植的容器中。

大白话版:Docker 就是一个"应用打包工厂"。你把代码和运行环境一股脑丢给 Docker,它给你吐出一个"集装箱"——这个集装箱里包含了代码、运行时、系统工具、系统库,你把这个集装箱往哪一放,它就能在哪跑起来。

核心组件

  • Dockerfile:定义镜像构建规则的"配方"
  • Docker Image:只读的容器模板,可以理解为"模具"
  • Docker Container:基于镜像运行的实例,可以理解为"用模具造出来的产品"
  • Docker Daemon (dockerd):后台服务,负责管理容器
  • Docker CLI:命令行工具,你和 Docker 交互的"翻译官"

3.2 Kubernetes 核心定义

官方定义:Kubernetes(简称 K8s)是一个开源的容器编排平台,用于自动化容器化应用的部署、扩缩容和管理。

大白话版:Kubernetes 就是一个"机房管理员",只不过这个管理员从不休息、从不犯错、记忆力还特别好。它能自动监控你所有的容器,发现哪个挂了立刻重启,发现流量大了自动扩容,发现资源不够自动调度。

核心组件

  • Master Node:集群的"大脑",负责整体调度决策
    • kube-apiserver:API 入口,所有操作的"前台接待"
    • kube-scheduler:负责分配 Pod 到哪个节点
    • kube-controller-manager:各种控制器,管理各种资源状态
    • etcd:分布式存储,保存集群的所有状态
  • Worker Node:干活的"工人",实际运行容器
    • kubelet:节点上的"监工",汇报节点状态
    • kube-proxy:网络代理,负责服务间通信
    • container-runtime:实际运行容器的引擎
  • Pod:K8s 的最小调度单位,一个 Pod 里可以有一个或多个容器
  • Deployment:管理 Pod 副本数的控制器
  • Service:为 Pod 提供稳定的访问入口
  • Ingress:管理外部访问的"大门"

3.3 二者关系的形象比喻

让我用一个更接地气的比喻来解释 Docker 和 Kubernetes 的关系:

把 Docker 想象成"货车"

  • 你有一批货物(应用代码)
  • 货车负责把货物装进集装箱(构建镜像)
  • 货车负责把集装箱运到目的地(分发镜像)

把 Kubernetes 想象成"物流调度中心"

  • 调度中心决定用多少辆车、每辆车装什么货
  • 调度中心监控每辆车的状态,发现抛锚立刻换车
  • 调度中心根据订单量动态调整运力

关键点:货车本身不重要,重要的是能运货。同样,Docker 只是容器运行时的一种选择,Kubernetes 还支持 containerd、CRI-O 等其他运行时。

3.4 Kubernetes 为什么不用 Docker 了?

等等,既然 Docker 和 Kubernetes 是"最佳拍档",为什么 Kubernetes 在 1.24 版本移除了对 Docker 的直接支持?

答案:为了简化架构、提高性能。

让我们来看看架构演变:

旧架构(K8s 1.24 之前)

kubelet -> dockershim -> dockerd -> containerd -> runc

新架构(K8s 1.24 之后)

kubelet -> CRI -> containerd -> runc

变化在哪里?

  1. 移除了 dockershim:dockershim 是 K8s 为了兼容 Docker 临时写的一段"适配器代码",维护起来很麻烦
  2. 直接对接 containerd:containerd 才是 Docker 的核心,K8s 直接对接它就够了
  3. 更少层级,更高性能:少了一层转发,资源消耗更少

但是!你之前的 Dockerfile 没有白写。

因为 Docker 镜像遵循 OCI 标准(Open Container Initiative),这个标准包括:

  • Image-spec:镜像格式规范
  • Distribution-spec:镜像分发规范
  • Runtime-spec:运行时规范

所以 containerd 和 CRI-O 都能 100% 兼容你的 Docker 镜像。你的 docker build 命令白打了吗?当然没有!

3.5 Dockerfile 没有白写

即使你用的是 containerd 而不是 Docker 作为运行时,你的 Dockerfile 依然有效,因为:

  1. 工具链通用docker build 生成的镜像,ctrnerdctl 都能使用
  2. 镜像格式兼容:OCI 格式是行业标准,所有符合 OCI 的运行时都能运行
  3. 构建工具替代:可以用 buildahkanikobuildkit 等工具替代 docker build

所以,Dockerfile 是你编写过最值钱的配置之一,它让你的应用可以被任何 OCI 兼容的容器运行时使用。

四、为什么用:核心优势与对比

4.1 Docker vs 虚拟机

维度Docker 容器虚拟机
启动速度秒级(通常 1-2 秒)分钟级(通常 1-5 分钟)
资源占用轻量(MB 级别)重量(GB 级别,需要独立 OS)
密度高(单机能跑上百个容器)低(单机能跑几个 VM)
隔离性进程级隔离硬件级隔离(更强)
性能损耗几乎无损耗有虚拟化开销(约 5-10%)
镜像大小小(通常几十到几百 MB)大(通常几 GB)

比喻版

  • 虚拟机 = 独立房子,每个房子有自己的水电系统,安全但贵
  • Docker 容器 = 酒店房间,共享基础设施,便宜但依赖酒店服务

选谁?

  • 需要强隔离、安全性优先 -> 虚拟机
  • 需要快速部署、高密度、资源效率 -> Docker 容器

4.2 Kubernetes vs 手动 docker run

手动管理 100 个容器

# 你需要做的事情
docker run -d --name app1 -p 8001:80 myapp:v1
docker run -d --name app2 -p 8002:80 myapp:v1
docker run -d --name app3 -p 8003:80 myapp:v1
# ... 重复97次

# 监控:手动登录每台机器
docker ps
docker logs app1
docker stats

# 扩缩容:逐个操作
docker scale app1=10  # 不支持!

# 更新:逐个替换
docker stop app1
docker rm app1
docker run -d --name app1 -p 8001:80 myapp:v2

Kubernetes 管理 100 个容器

# 一个Deployment搞定一切
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 100
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:v1
        ports:
        - containerPort: 80

一条命令:kubectl apply -f deployment.yaml,然后:

  • 自动创建 100 个 Pod
  • 自动分配到合适的节点
  • 自动监控健康状态
  • 自动故障恢复
  • 自动扩缩容

结论:容器少的时候 Docker 够用,容器多了必须上 K8s。

4.3 Kubernetes vs Docker Compose vs Docker Swarm

特性Docker ComposeDocker SwarmKubernetes
定位单机容器编排集群容器编排企业级容器编排
复杂度
功能启动多个关联容器基本的集群管理全面的编排能力
扩缩容手动半自动自动
服务发现基础内置内置
负载均衡基础内置需配合 Service
滚动更新支持支持支持
回滚支持支持支持
适用场景开发测试小规模生产大规模生产

选择建议

  • 本地开发:Docker Compose(简单、快速)
  • 小规模生产(<100 容器):Docker Swarm(简单、功能够用)
  • 大规模生产:Kubernetes(功能全面、生态成熟)

4.4 2026 年运行时选型建议

截至 2026 年 4 月,主要的容器运行时选择:

运行时版本适用场景特点
containerd2.1.x (LTS)大规模生产集群性能最优,K8s 默认
CRI-O最新稳定版边缘计算、安全敏感场景更轻量,与 K8s 原生集成
Docker27.x/29.x开发环境、CI/CD生态最完善

2026 年新变化:Kubernetes 1.35 要求使用 cgroups v2,如果你还在用 cgroups v1,需要升级内核。

选型建议

  • 生产环境首选 containerd
  • 安全要求极高选 CRI-O
  • 开发环境用 Docker 即可

五、怎么用:保姆级基础教学

5.1 环境搭建

Docker 安装(Ubuntu 为例)

# 安装Docker
curl -fsSL https://get.docker.com | sh
​
# 验证安装
docker --version
# Docker version 27.x.x# 配置当前用户
sudo usermod -aG docker $USER

Kubernetes 安装(MiniKube 单节点)

# 安装kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
​
# 安装MiniKube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
​
# 启动MiniKube
minikube start --driver=docker

阿里云 ACK(托管 K8s)

# 安装阿里云CLI和ACK插件
curl -sSL https://aliyuncli.alibabacloud.com/install.sh | sh
​
# 配置凭证
aliyun configure
​
# 创建ACK集群(需要阿里云账号)
aliyun cs POST /clusters --body "$(cat cluster-config.json)"

5.2 Python + Docker SDK 实战

安装 Docker SDK for Python

pip install docker

实战 1:构建镜像并运行容器

import docker

# 创建Docker客户端
client = docker.from_env()

# 构建自定义镜像
print("开始构建镜像...")
image, build_logs = client.images.build(
    path='.',
    tag='my-python-app:latest',
    rm=True  # 构建成功后删除中间容器
)

# 打印构建日志
for log in build_logs:
    if 'stream' in log:
        print(log['stream'], end='')

print(f"镜像构建成功: {image.tags}")

# 运行容器
print("启动容器...")
container = client.containers.run(
    "my-python-app:latest",
    ports={"5000/tcp": 5000},
    detach=True,  # 后台运行
    environment={
        "FLASK_ENV": "production",
        "LOG_LEVEL": "info"
    },
    name="my-flask-app",
    remove=False  # 停止后保留容器
)

print(f"容器已启动: {container.short_id}")
print(f"容器状态: {container.status}")

实战 2:管理容器生命周期

import docker
import time

client = docker.from_env()

# 获取容器
container = client.containers.get("my-flask-app")

# 查看容器状态
print(f"容器ID: {container.id}")
print(f"容器名: {container.name}")
print(f"容器状态: {container.status}")
print(f"容器镜像: {container.image.tags}")

# 查看日志
print("\n--- 容器日志 ---")
for log_line in container.logs(stream=True, follow=True):
    print(log_line.decode().strip())

# 停止容器
# container.stop()

# 重启容器
# container.restart()

# 查看资源使用
stats = container.stats(stream=False)
print(f"\nCPU使用: {stats['cpu_stats']['cpu_usage']['total_usage']}")
print(f"内存使用: {stats['memory_stats']['usage']}")

实战 3:列出和清理资源

import docker

client = docker.from_env()

# 列出所有容器
print("=== 所有容器 ===")
all_containers = client.containers.list(all=True)
for c in all_containers:
    print(f"  {c.name}: {c.status}")

# 列出所有镜像
print("\n=== 所有镜像 ===")
all_images = client.images.list()
for img in all_images:
    tags = img.tags if img.tags else ['<none>']
    print(f"  {', '.join(tags)}: {img.attrs['Size']} bytes")

# 清理未使用的资源
print("\n清理未使用的资源...")
client.containers.prune()
client.images.prune()
print("清理完成")

5.3 Python + Kubernetes API 实战

安装 Kubernetes SDK

pip install kubernetes

实战 1:创建 Deployment

from kubernetes import client, config
from kubernetes.client.rest import ApiException
import yaml

# 加载kubeconfig(本地开发用)
# 生产环境可用 config.load_incluster_config()
config.load_kube_config()

# 创建API实例
api_instance = client.AppsV1Api()

# 定义Deployment
deployment = client.V1Deployment(
    api_version="apps/v1",
    kind="Deployment",
    metadata=client.V1ObjectMeta(
        name="nginx-deployment",
        labels={"app": "nginx", "environment": "production"}
    ),
    spec=client.V1DeploymentSpec(
        replicas=3,
        selector=client.V1LabelSelector(
            match_labels={"app": "nginx"}
        ),
        template=client.V1PodTemplateSpec(
            metadata=client.V1ObjectMeta(
                labels={"app": "nginx"}
            ),
            spec=client.V1PodSpec(
                containers=[
                    client.V1Container(
                        name="nginx",
                        image="nginx:latest",
                        ports=[client.V1ContainerPort(
                            container_port=80,
                            protocol="TCP"
                        )],
                        resources=client.V1ResourceRequirements(
                            requests={"cpu": "100m", "memory": "128Mi"},
                            limits={"cpu": "500m", "memory": "512Mi"}
                        ),
                        liveness_probe=client.V1Probe(
                            http_get=client.V1HTTPGetAction(
                                path="/",
                                port=80
                            ),
                            initial_delay_seconds=3,
                            period_seconds=10
                        )
                    )
                ]
            )
        )
    )
)

# 创建Deployment
try:
    api_instance.create_namespaced_deployment(
        namespace="default",
        body=deployment
    )
    print("Deployment创建成功!")
except ApiException as e:
    if e.status == 409:
        print("Deployment已存在,更新中...")
        api_instance.replace_namespaced_deployment(
            name="nginx-deployment",
            namespace="default",
            body=deployment
        )
        print("Deployment更新成功!")
    else:
        print(f"创建失败: {e}")

实战 2:扩缩容与滚动更新

from kubernetes import client, config

config.load_kube_config()
api_instance = client.AppsV1Api()

# 扩缩容
def scale_deployment(name, replicas, namespace="default"):
    """扩缩容Deployment"""
    body = {"spec": {"replicas": replicas}}
    api_instance.patch_namespaced_deployment_scale(
        name=name,
        namespace=namespace,
        body=body
    )
    print(f"已将 {name} 扩缩容到 {replicas} 副本")

# 滚动更新镜像
def update_image(name, new_image, namespace="default"):
    """更新容器镜像"""
    body = {
        "spec": {
            "template": {
                "spec": {
                    "containers": [{
                        "name": name,
                        "image": new_image
                    }]
                }
            }
        }
    }
    api_instance.patch_namespaced_deployment(
        name=name,
        namespace=namespace,
        body=body
    )
    print(f"已将 {name} 更新到镜像 {new_image}")

# 示例调用
scale_deployment("nginx-deployment", replicas=10)
update_image("nginx-deployment", "nginx:1.25-alpine")

实战 3:监控 Pod 状态

from kubernetes import client, config
import time

config.load_kube_config()
v1 = client.CoreV1Api()

def watch_pods(namespace="default"):
    """实时监控Pod状态"""
    print(f"监控 {namespace} 命名空间下的Pod...\n")
    
    count = 0
    for event in v1.watch.namespaced_pod(namespace).watch():
        pod = event['object']
        pod_name = pod.metadata.name
        phase = pod.status.phase
        reason = pod.status.reason or ""
        
        event_type = event['type']
        timestamp = pod.metadata.creation_timestamp.strftime("%H:%M:%S")
        
        print(f"[{timestamp}] {event_type:10} | {pod_name:30} | {phase:10} | {reason}")
        
        count += 1
        if count > 20:  # 监控20条事件后退出
            break

def get_pod_stats(namespace="default"):
    """获取Pod统计信息"""
    pods = v1.list_namespaced_pod(namespace)
    
    stats = {"Running": 0, "Pending": 0, "Failed": 0, "Succeeded": 0}
    for pod in pods.items:
        stats[pod.status.phase] = stats.get(pod.status.phase, 0) + 1
    
    print(f"\n=== {namespace} Pod统计 ===")
    for state, count in stats.items():
        if count > 0:
            print(f"  {state}: {count}")
    
    return stats

# 获取统计
get_pod_stats()

5.4 Python 自动化部署脚本

一个完整的自动化部署脚本

#!/usr/bin/env python3
"""
企业级自动化部署脚本
功能:构建镜像 -> 推送仓库 -> 部署到K8s -> 验证
"""

import docker
from kubernetes import client, config
from kubernetes.client.rest import ApiException
import time
import sys

class K8sDeployer:
    def __init__(self, image_name, namespace="default"):
        self.docker_client = docker.from_env()
        self.image_name = image_name
        self.namespace = namespace
        
        # 加载K8s配置
        try:
            config.load_kube_config()
            self.k8s_available = True
        except Exception:
            self.k8s_available = False
            print("警告: 无法连接Kubernetes集群,仅执行Docker操作")
        
        if self.k8s_available:
            self.apps_v1 = client.AppsV1Api()
            self.core_v1 = client.CoreV1Api()
    
    def build_image(self, dockerfile_path=".", tag=None):
        """构建Docker镜像"""
        if tag is None:
            tag = self.image_name
        
        print(f"[1/4] 构建镜像: {tag}")
        try:
            image, logs = self.docker_client.images.build(
                path=dockerfile_path,
                tag=tag,
                rm=True
            )
            for log in logs:
                if 'stream' in log:
                    print(f"  {log['stream'].strip()}")
            print(f"  镜像构建成功: {image.short_id}")
            return tag
        except Exception as e:
            print(f"  镜像构建失败: {e}")
            return None
    
    def push_to_registry(self, image_tag):
        """推送到镜像仓库(需要先登录)"""
        print(f"[2/4] 推送镜像到仓库: {image_tag}")
        try:
            for line in self.docker_client.images.push(
                image_tag.split(':')[0],
                tag=image_tag.split(':')[1] if ':' in image_tag else 'latest',
                stream=True,
                decode=True
            ):
                if 'status' in line:
                    print(f"  {line['status']}", end='\r')
            print("\n  镜像推送成功!")
            return True
        except Exception as e:
            print(f"\n  镜像推送失败: {e}")
            return False
    
    def deploy_to_k8s(self, image_tag, replicas=3):
        """部署到Kubernetes"""
        if not self.k8s_available:
            print("[3/4] 跳过K8s部署(集群不可用)")
            return False
        
        print(f"[3/4] 部署到Kubernetes: {image_tag}")
        deployment_name = self.image_name.split('/')[-1].replace(':', '-')
        
        deployment = client.V1Deployment(
            api_version="apps/v1",
            kind="Deployment",
            metadata=client.V1ObjectMeta(
                name=deployment_name,
                namespace=self.namespace
            ),
            spec=client.V1DeploymentSpec(
                replicas=replicas,
                selector=client.V1LabelSelector(
                    match_labels={"app": deployment_name}
                ),
                template=client.V1PodTemplateSpec(
                    metadata=client.V1ObjectMeta(
                        labels={"app": deployment_name}
                    ),
                    spec=client.V1PodSpec(
                        containers=[client.V1Container(
                            name="app",
                            image=image_tag,
                            ports=[client.V1ContainerPort(container_port=8080)]
                        )]
                    )
                )
            )
        )
        
        try:
            self.apps_v1.create_namespaced_deployment(
                namespace=self.namespace,
                body=deployment
            )
            print(f"  Deployment创建成功")
        except ApiException as e:
            if e.status == 409:
                self.apps_v1.replace_namespaced_deployment(
                    name=deployment_name,
                    namespace=self.namespace,
                    body=deployment
                )
                print(f"  Deployment更新成功")
            else:
                print(f"  Deployment操作失败: {e}")
                return False
        
        # 等待Pod就绪
        print("  等待Pod就绪...", end='')
        for _ in range(30):
            time.sleep(2)
            pods = self.core_v1.list_namespaced_pod(
                self.namespace,
                label_selector=f"app={deployment_name}"
            )
            ready = sum(1 for p in pods.items if p.status.phase == "Running")
            print(f"\r  等待Pod就绪... ({ready}/{replicas})", end='')
            if ready >= replicas:
                print("\n  所有Pod已就绪!")
                return True
        print("\n  等待超时,部分Pod可能未就绪")
        return True
    
    def verify_deployment(self):
        """验证部署"""
        if not self.k8s_available:
            print("[4/4] 跳过验证(集群不可用)")
            return
        
        print("[4/4] 验证部署状态")
        deployment_name = self.image_name.split('/')[-1].replace(':', '-')
        
        deployment = self.apps_v1.read_namespaced_deployment(
            name=deployment_name,
            namespace=self.namespace
        )
        
        replicas = deployment.status.ready_replicas or 0
        desired = deployment.spec.replicas
        
        print(f"  期望副本: {desired}")
        print(f"  就绪副本: {replicas}")
        print(f"  状态: {'成功' if replicas == desired else '部分就绪'}")


def main():
    if len(sys.argv) < 2:
        print("用法: python deploy.py <image_name> [--namespace NS] [--replicas N]")
        sys.exit(1)
    
    image_name = sys.argv[1]
    namespace = "default"
    replicas = 3
    
    # 简单参数解析
    if "--namespace" in sys.argv:
        idx = sys.argv.index("--namespace")
        namespace = sys.argv[idx + 1]
    if "--replicas" in sys.argv:
        idx = sys.argv.index("--replicas")
        replicas = int(sys.argv[idx + 1])
    
    # 执行部署
    deployer = K8sDeployer(image_name, namespace)
    image_tag = deployer.build_image()
    
    if image_tag:
        deployer.push_to_registry(image_tag)
        deployer.deploy_to_k8s(image_tag, replicas)
        deployer.verify_deployment()
    
    print("\n部署流程完成!")


if __name__ == "__main__":
    main()

5.5 调试与常见避坑指南

坑 1:Docker 构建慢

# 优化:使用构建缓存
# 正确:把不变的内容放前面,变化的放后面
FROM python:3.11-slim
COPY requirements.txt .
RUN pip install -r requirements.txt  # 变化少,放前面
COPY . .  # 变化多,放后面

# 优化:使用.dockerignore
echo "node_modules\n.git\n__pycache__" > .dockerignore

坑 2:K8s Pod 一直 Pending

# 查看原因
kubectl describe pod <pod-name>
# 常见原因:资源不足、调度失败、镜像拉取失败

# 检查节点资源
kubectl describe nodes

坑 3:Docker 镜像拉取失败

# 配置私有仓库认证
import docker

client = docker.from_env()
client.login(
    registry="registry.example.com",
    username="user",
    password="password"
)

坑 4:K8s 访问被拒绝

# 检查kubeconfig
kubectl config view
kubectl config current-context

# 切换上下文
kubectl config use-context <context-name>

六、常用场景列举

6.1 Python 微服务容器化与部署

项目结构

my-microservice/
├── Dockerfile
├── docker-compose.yml
├── requirements.txt
├── app/
│   ├── __init__.py
│   ├── main.py
│   ├── config.py
│   └── models/
└── k8s/
    ├── deployment.yaml
    ├── service.yaml
    └── ingress.yaml

Dockerfile

FROM python:3.11-slim

WORKDIR /app

# 先复制依赖文件,利用构建缓存
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 再复制代码
COPY . .

# 非root用户运行
RUN useradd -m appuser && chown -R appuser:appuser /app
USER appuser

EXPOSE 8080

CMD ["python", "app/main.py"]

Kubernetes Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-microservice
  labels:
    app: my-microservice
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-microservice
  template:
    metadata:
      labels:
        app: my-microservice
    spec:
      containers:
      - name: my-microservice
        image: my-registry.com/my-microservice:v1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: my-secrets
              key: database-url
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"

6.2 CI/CD 自动化流水线

GitLab CI 示例

stages:
  - build
  - test
  - deploy

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

build:
  stage: build
  image: docker:latest
  services:
    - docker:dind
  script:
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

test:
  stage: test
  image: $IMAGE_TAG
  script:
    - pytest tests/

deploy:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/my-app app=$IMAGE_TAG
    - kubectl rollout status deployment/my-app
  only:
    - main

6.3 微服务架构多服务编排

docker-compose.yml

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - api
      - redis
    environment:
      - API_URL=http://api:8001
      - REDIS_URL=redis://redis:6379

  api:
    build: ./api
    ports:
      - "8001:8001"
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/mydb

  worker:
    build: ./worker
    depends_on:
      - db
      - redis

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  db:
    image: postgres:15-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=mydb

volumes:
  postgres_data:

6.4 企业级多环境管理

开发环境

apiVersion: v1
kind: Namespace
metadata:
  name: dev
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: dev
spec:
  replicas: 1
  # 开发者需要快速迭代,单副本即可

生产环境

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: prod
spec:
  replicas: 10
  # 生产环境高可用,多副本
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%

使用 Kustomize 管理差异

# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - deployment.yaml
  - service.yaml

# overlays/dev/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: dev
bases:
  - ../../base
patches:
  - patch.yaml

6.5 容器化监控与可观测性

部署 Prometheus + Grafana

apiVersion: v1
kind: ConfigMap
metadata:
  name: prometheus-config
data:
  prometheus.yml: |
    global:
      scrape_interval: 15s
    scrape_configs:
      - job_name: 'kubernetes-pods'
        kubernetes_sd_configs:
          - role: pod

查看资源使用

# kubectl top查看资源使用
kubectl top nodes
kubectl top pods

# 查看Pod日志
kubectl logs -f deployment/myapp --previous

6.6 蓝绿部署与金丝雀发布

蓝绿部署

# 新版本Service
apiVersion: v1
kind: Service
metadata:
  name: myapp-bluegreen
spec:
  selector:
    version: v2  # 切换这个标签即可切换流量
---
# v1 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v1
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: myapp
        version: v1
---
# v2 Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-v2
spec:
  replicas: 3
  template:
    metadata:
      labels:
        app: myapp
        version: v2

金丝雀发布(Istio)

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: myapp
spec:
  hosts:
    - myapp
  http:
    - route:
        - destination:
            host: myapp
            subset: v1
          weight: 90
        - destination:
            host: myapp
            subset: v2
          weight: 10  # 只有10%流量到新版本

七、专业解释 + 大白话 + 生活案例

7.1 Docker 分层镜像与联合文件系统

专业解释

Docker 镜像采用分层(Layer)结构,每一层代表 Dockerfile 中的一条指令。当容器启动时,所有层通过联合文件系统(如 OverlayFS)叠加挂载,形成统一的文件系统视图。

关键特性

  • 写时复制(Copy-on-Write):容器修改某文件时,只在该容器层复制一份,其他容器不受影响
  • 层共享:多个镜像可以共享相同的底层层,节省存储空间
  • 增量更新:只需传输变更的层

大白话版

想象你是一个美食博主,你的"红烧肉菜谱"被拆成了多个层级:

  • 第 1 层:基础调料(盐、酱油)
  • 第 2 层:辅料(葱姜蒜)
  • 第 3 层:主料(猪肉)
  • 第 4 层:烹饪方法

现在有两个人要学做红烧肉:

  • A 学了 1-3 层,直接上手
  • B 学了全部 4 层,做得更精细

Docker 的做法是:你们各自只需要保存"自己独有的那层",公共层大家共享。就像 A 只需要保存"红烧肉"三个字,而 B 需要保存完整的菜谱。

生活案例

  • 你的手机系统更新:更新只下载变化的部分,不是整个系统重装
  • 程序员写代码:每个人只修改自己负责的模块,然后合并到主分支

性能影响

# 优化:把变化频繁的放在最后
FROM python:3.11-slim

# 变化少,放前面(利用缓存)
COPY requirements.txt .
RUN pip install -r requirements.txt

# 变化多,放后面
COPY app/ .

# 变化最频繁的放最后
CMD ["python", "app/main.py"]

7.2 CRI 与容器运行时架构演变

专业解释

CRI(Container Runtime Interface)是 Kubernetes 定义的容器运行时接口标准,让 Kubelet 能够支持多种容器运行时。CRI 通过 gRPC 与运行时通信,主要包括 RuntimeService 和 ImageService。

架构演变

阶段架构K8s 版本
早期kubelet -> dockershim -> dockerd -> containerd -> runc1.24 之前
过渡kubelet -> dockershim -> containerd -> runc1.24-1.26
现在kubelet -> CRI -> containerd -> runc1.27+

为什么弃用 dockershim?

dockershim 是一段"临时补丁"代码,因为 Docker 比 K8s 早出现,K8s 不得不写代码去适配 Docker。后来 containerd 原生支持 CRI 后,这段"适配代码"就成了技术债务,维护成本高、额外开销大,所以被移除了。

大白话版

想象你要给手机充电:

  • 旧方案:苹果充电线 -> 安卓转换头 -> 手机(多了一层转换,效率低)
  • 新方案:Type-C 充电线 -> 手机(直接对接,效率高)

dockershim 就是那个"安卓转换头",虽然能用,但没必要。

生活案例

  • 早期 USB 接口混乱:各种转接头满天飞
  • 现在 USB-C 一统天下:统一接口,直接插就能用

7.3 Kubernetes 控制循环与声明式状态管理

专业解释

Kubernetes 采用"控制循环"(Control Loop)模式实现声明式状态管理。每个控制器持续监控当前状态(Status)与期望状态(Spec)的差异,并通过调谐(Reconcile)使当前状态趋近期望状态。

期望状态 (Spec) -> 控制器 -> 当前状态 (Status) -> 比较 -> 调谐 -> 期望状态 (Spec)

核心控制器

  • Deployment Controller:管理 Pod 副本数,确保期望的 Pod 数量运行
  • ReplicaSet Controller:确保 Pod 副本数与期望一致
  • Node Controller:监控节点状态,标记不可用节点
  • Service Controller:管理 Service 的 Endpoints

大白话版

想象你是外卖店长,你告诉店员:

"我要保持店里始终有 3 个厨师在岗。"

这就是"声明式"——你只说期望,不说具体怎么做。

店员(Controller)会:

  1. 实时检查当前有几个厨师在岗
  2. 发现少了一个,立刻招聘新人
  3. 发现多了一个,考虑是否裁员

你不需要亲自盯着每一个厨师,店员会帮你维护"3 个厨师"的期望状态。

生活案例

  • 空调自动控温:你设定 26 度,空调自动开关,这就是控制循环
  • 电饭煲保温:低于温度就加热,高于就停止,典型的控制循环

Python 模拟 K8s 控制循环

import time
from dataclasses import dataclass

@dataclass
class DeploymentSpec:
    replicas: int

@dataclass
class DeploymentStatus:
    current_replicas: int = 0

class DeploymentController:
    """模拟K8s的Deployment控制器"""
    
    def __init__(self, spec: DeploymentSpec):
        self.spec = spec
        self.status = DeploymentStatus()
    
    def reconcile(self):
        """调谐:使当前状态匹配期望状态"""
        diff = self.spec.replicas - self.status.current_replicas
        
        if diff > 0:
            print(f"需要创建 {diff} 个Pod")
            self.status.current_replicas += diff
        elif diff < 0:
            print(f"需要删除 {-diff} 个Pod")
            self.status.current_replicas += diff
        else:
            print("Pod数量已达标,无需调整")
    
    def get_status(self):
        return f"期望: {self.spec.replicas}, 当前: {self.status.current_replicas}"

# 模拟使用
controller = DeploymentController(spec=DeploymentSpec(replicas=5))

while True:
    print(controller.get_status())
    controller.reconcile()
    time.sleep(2)
    
    # 模拟外部修改(如人工扩容)
    if controller.status.current_replicas > 0 and input("模拟Pod崩溃? (y/n): ").lower() == 'y':
        controller.status.current_replicas -= 1
        print("一个Pod崩溃了!")

八、面试官高频面试题

面试题 1:Docker 和虚拟机的核心区别是什么?

参考答案

维度Docker 容器虚拟机
架构共享宿主机内核,进程级隔离独立操作系统,硬件级隔离
启动速度秒级分钟级
资源占用MB 级别GB 级别
性能几乎无损耗有虚拟化开销(5-10%)
密度单机可运行上百个通常几个到十几个

加分回答:容器不是"更轻量的虚拟机",它们解决的是不同问题。容器提供应用级封装,虚拟机提供系统级隔离。在安全要求高的场景(如多租户),虚拟机仍是首选。

面试题 2:Kubernetes 和 Docker 是什么关系?

参考答案

Docker 和 Kubernetes 不是竞争关系,而是协作关系:

  • Docker:负责"打包"——将应用和依赖封装成容器镜像
  • Kubernetes:负责"编排"——管理这些容器的部署、扩缩容、故障恢复等

Docker 是容器运行时之一,Kubernetes 通过 CRI 接口来调用容器运行时。

常见误区:很多人认为"Kubernetes 要取代 Docker",实际上 K8s 取代的是"用 Docker 命令手动管理容器"的方式,而不是 Docker 镜像格式本身。

面试题 3:Kubernetes 弃用 Docker 是哪个版本?具体表现是什么?

参考答案

  • Kubernetes 1.20(2020 年 12 月):开始弃用 dockershim 警告
  • Kubernetes 1.24(2022 年 5 月):正式移除 dockershim

具体表现:kubelet 不再直接调用 dockershim,而是通过 CRI 接口直接调用 containerd。

架构变化

  • 旧:kubelet -> dockershim -> dockerd -> containerd -> runc
  • 新:kubelet -> CRI -> containerd -> runc

面试题 4:为什么要弃用 Docker?

参考答案

  1. 架构简化:移除 dockershim 这一层,减少维护负担和性能开销
  2. 统一接口:通过 CRI 标准化容器运行时接口,支持更多选择(containerd、CRI-O)
  3. 更少依赖:减少对 Docker 特定 API 的依赖,降低耦合度
  4. 性能提升:直接调用 containerd,减少一层转发

注意:Docker 镜像仍然可用,因为它们遵循 OCI 标准。

面试题 5:Docker Compose 和 Kubernetes 的区别是什么?

参考答案

维度Docker ComposeKubernetes
范围单机集群
复杂度简单复杂
功能定义多容器应用全面的容器编排平台
扩缩容手动自动
适用场景开发、测试生产环境

进阶回答:Docker Compose 适合本地开发和测试,Kubernetes 适合大规模生产环境。两者解决的问题维度不同,不是替代关系。

面试题 6:Pod 和 Container 是什么关系?

参考答案

核心概念

  • Container(容器):镜像的运行实例,是操作系统级虚拟化的基本单位
  • Pod(容器组):K8s 的最小调度单位,一个 Pod 包含一个或多个共享网络的容器

关系解释

  • 一个 Pod 里的容器共享同一个 Linux 命名空间(网络、进程间通信、文件系统)
  • Pod 像是一个"逻辑主机",Container 是里面的"进程"
  • 通常一个 Pod 只包含一个容器(单容器 Pod),但也支持多容器 Pod(Sidecar 模式)

大白话:Pod 是"盒子",Container 是盒子里的"物品"。一个盒子可以装多个物品,这些物品共享盒子的空间。

面试题 7:Deployment 和 StatefulSet 的区别是什么?

参考答案

维度DeploymentStatefulSet
用途无状态应用有状态应用
Pod 标识随机后缀固定序号
存储共享存储独立持久存储
扩缩容随意按序号顺序
场景Web 服务、API数据库、消息队列

典型使用

  • Deployment:Nginx、Python Flask API、前端应用
  • StatefulSet:MySQL、MongoDB、Kafka、Zookeeper

核心区别:Deployment 创建的 Pod 可以互换(谁挂了换谁),StatefulSet 创建的 Pod 有固定身份(有持久存储和网络标识)。

面试题 8:如何用 Python 代码管理 Kubernetes?

参考答案

使用官方的 Kubernetes Python 客户端:

from kubernetes import client, config

# 加载配置
config.load_kube_config()  # 本地开发
# config.load_incluster_config()  # Pod内运行

# 创建API实例
api = client.CoreV1Api()
apps_api = client.AppsV1Api()

# 列出Pod
pods = api.list_namespaced_pod(namespace="default")
for pod in pods.items:
    print(f"{pod.metadata.name}: {pod.status.phase}")

# 创建Deployment
deployment = client.V1Deployment(...)
apps_api.create_namespaced_deployment(namespace="default", body=deployment)

# 扩缩容
apps_api.patch_namespaced_deployment_scale(
    name="myapp",
    namespace="default",
    body={"spec": {"replicas": 10}}
)

加分回答:生产环境中,通常配合 Kubernetes 的 Watch 机制实现事件驱动,或使用 Operator 模式封装复杂逻辑。

九、企业级实战指导

9.1 技术选型决策树

应用场景评估
    |
    v
是否有强烈的隔离需求?
    |
    是 -> 选择虚拟机(安全优先场景)
    |
    否 -> 是否需要大规模编排?
            |
            是 -> 容器数量 > 100?
                    |
                    是 -> 选择Kubernetes
                    |
                    否 -> 选择Docker Swarm / Docker Compose
            |
            否 -> 是否需要快速部署?
                    |
                    是 -> 选择Docker
                    |
                    否 -> 选择传统部署

2026 年选型建议

场景推荐方案原因
本地开发Docker Compose简单、快速
小团队(<10 人)Docker Swarm + Portainer简单、可视化
中型团队Kubernetes(托管版)省运维、自动扩缩容
大型企业Kubernetes(自建/多集群)完全可控、安全合规
边缘计算K3s / CRI-O轻量、低资源占用
安全敏感Kata Containers + K8s硬件级隔离

9.2 Kubernetes 部署架构最佳实践

高可用集群架构

┌─────────────────┐
                    │   负载均衡器    │
                    └────────┬────────┘
                             │
        ┌────────────────────┼────────────────────┐
        │                    │                    │
   ┌────▼────┐          ┌────▼────┐          ┌────▼────┐
   │ Master  │          │ Master  │          │ Master  │
   │ Node 1  │◄────────►│ Node 2  │◄────────►│ Node 3  │
   └────┬────┘          └────┬────┘          └────┬────┘
        │                    │                    │
        └────────────────────┼────────────────────┘
                             │ etcd集群
        ┌────────────────────┼────────────────────┐
        │                    │                    │
   ┌────▼────┐          ┌────▼────┐          ┌────▼────┐
   │ Worker  │          │ Worker  │          │ Worker  │
   │ Node 1  │          │ Node 2  │          │ Node 3  │
   └─────────┘          └─────────┘          └─────────┘

命名空间隔离策略

apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    env: production
---
apiVersion: v1
kind: ResourceQuota
metadata:
  name: prod-quota
  namespace: prod
spec:
  hard:
    requests.cpu: "20"
    requests.memory: 40Gi
    pods: "100"
    services: "20"
---
apiVersion: v1
kind: LimitRange
metadata:
  name: prod-limits
  namespace: prod
spec:
  limits:
  - max:
      cpu: "4"
      memory: 8Gi
    min:
      cpu: "50m"
      memory: 64Mi
    default:
      cpu: "500m"
      memory: 512Mi
    defaultRequest:
      cpu: "100m"
      memory: 128Mi
    type: Container

9.3 企业级容器化四步落地法

第一步:评估与规划(1-2 周)

1. 应用分类
   - 无状态应用:优先迁移(Web服务、API)
   - 有状态应用:评估复杂度(数据库、缓存)
   - 遗留系统:考虑重构或虚拟化

2. 依赖梳理
   - 列出所有依赖(系统包、环境变量、配置文件)
   - 识别外部服务(数据库、消息队列、第三方API)
   - 评估网络需求(服务间通信、端口暴露)

3. 团队能力评估
   - Docker基础
   - K8s基础
   - CI/CD经验

第二步:试点迁移(2-4 周)

# 试点项目:选择一个低风险应用
FROM python:3.11-slim

# 最小化依赖
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 非root运行
RUN useradd -m appuser
COPY --chown=appuser:appuser . .
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

EXPOSE 8000
CMD ["python", "main.py"]

第三步:生产就绪(2-4 周)

# 生产配置清单
apiVersion: apps/v1
kind: Deployment
metadata:
  name: production-app
spec:
  replicas: 5  # 高可用
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 0  # 零停机更新
  template:
    spec:
      affinity:  # 反亲和,避免单点
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - production-app
                topologyKey: kubernetes.io/hostname
      containers:
      - name: app
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        readinessProbe:
          httpGet:
            path: /ready
            port: 8000
          initialDelaySeconds: 5
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /health
            port: 8000
          initialDelaySeconds: 15
          periodSeconds: 20

第四步:规模化运营(持续)

# 监控指标
kubectl get --raw /apis/metrics.k8s.io/v1beta1/nodes | jq '.items[].usage'

# 成本优化
kubectl top pods --sort-by=memory

# 资源审计
kubectl describe resourcequota

9.4 生产环境避坑指南

坑 1:镜像拉取超时

# 错误配置
image: myregistry.com/myapp:latest  # 网络不稳定时会卡死

# 正确配置
imagePullSecrets + 超时配置
imagePullPolicy: IfNotPresent  # 本地已有就不拉取

坑 2:内存泄漏未限制

# 危险:无资源限制
containers:
  - name: app
    image: app:v1

# 安全:设置资源限制
containers:
  - name: app
    image: app:v1
    resources:
      limits:
        memory: "512Mi"  # 防止内存泄漏拖垮节点
      requests:
        memory: "128Mi"  # 调度依据

坑 3:健康检查缺失

# 没有健康检查:Pod挂了不知道
containers:
  - name: app
    image: app:v1

# 有健康检查:自动发现、自动重启
containers:
  - name: app
    image: app:v1
    livenessProbe:
      httpGet:
        path: /health
        port: 8080
      failureThreshold: 3
      periodSeconds: 10
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 5

坑 4:滚动更新配置不当

# 危险配置
strategy:
  type: Recreate  # 会导致服务中断

# 安全配置
strategy:
  type: RollingUpdate
  rollingUpdate:
    maxSurge: 1  # 最多超出1个Pod
    maxUnavailable: 0  # 确保服务始终可用

9.5 2026 年前沿趋势与未来展望

趋势 1:Serverless 容器

  • Knative:在 K8s 上运行 Serverless 工作负载
  • AWS Fargate:无需管理服务器
  • 阿里云 ASK:Serverless Kubernetes

趋势 2:智能扩缩容

  • KEDA:基于事件的自动扩缩容
  • Horizontal Pod Autoscaler V2:支持自定义指标
  • Vertical Pod Autoscaler:自动调整资源请求

趋势 3:安全加固

  • Sigstore:软件签名和透明日志
  • Kyverno:K8s 原生策略引擎
  • Falco:运行时安全检测

趋势 4:多集群管理

  • Fleet:大规模 K8s 管理
  • Cluster API:声明式集群管理
  • GitOps:以 Git 为中心的运维模式(ArgoCD、Flux)

趋势 5:AI/ML 工作负载支持

  • Kubeflow:ML 工作流平台
  • GPU 调度:NVIDIA GPU Operator
  • 分布式训练:PyTorch Elastic

总结

好啦,今天这篇文章就到这里。我们来回顾一下核心知识点:

  1. Docker:负责打包,是"集装箱工厂"
  2. Kubernetes:负责编排,是"物流调度中心"
  3. 关系:Docker 打包,K8s 调度,是最佳拍档
  4. 弃用真相:K8s 移除了 dockershim,但 Docker 镜像仍可用(OCI 标准)
  5. 选择建议:小规模用 Docker/Swarm,大规模用 K8s

记住,学习容器技术不是为了应付面试,而是为了真正理解现代云原生应用是如何构建和运行的。希望这篇文章能帮你在容器化的道路上走得更稳、更远

参考链接

转载声明

本文系原创文章,遵循 CC BY-SA 4.0 协议,转载需注明出处。

欢迎各位开发者朋友转发分享,如需在其他平台转载,请私信联系作者获取授权。