在云计算和运维领域,容器化与编排技术已成为现代应用部署的基石。无论是个人开发者快速搭建环境,还是企业构建微服务架构,Docker与Kubernetes(K8S)都是绕不开的核心技能。然而,面对海量零散的教程,很多朋友反馈从入门到实战的路径漫长且充满“坑点”,环境配置、概念理解、集群搭建每一步都可能卡住。

本文旨在整合一套从零开始的系统性实战教程,以 Docker 和 K8S 为核心,串联 Linux 基础与 云计算运维 的关键操作。我们将从最基础的环境安装讲起,逐步深入到镜像构建、容器管理、集群部署和服务发布,并提供完整的可复现代码与配置。无论你是刚接触运维的初学者,还是希望系统梳理容器技术的开发者,都能通过本文构建清晰的知识脉络和实操能力。

1. 背景与核心概念:为什么是 Docker 和 K8S?

在深入动手之前,理解技术解决的问题至关重要。这能帮助你在后续遇到复杂配置时,明白其设计初衷,而非机械记忆命令。

1.1 容器化技术:Docker 解决了什么?

传统软件部署面临“环境一致性”的经典难题:开发环境运行正常,测试环境报错,生产环境直接崩溃。根源在于操作系统、库依赖、配置文件的不一致。

Docker 的出现,提供了一种轻量级的标准化打包方案。它将应用及其所有依赖(库、环境变量、配置文件)打包成一个独立的“镜像”。这个镜像可以在任何安装了 Docker 引擎的机器上运行,并生成一个隔离的“容器”进程。简单理解:

  • 镜像 (Image) :类似于软件安装包(如 .exe 或 .dmg ),是一个只读的模板。
  • 容器 (Container) :类似于运行起来的软件进程,是基于镜像创建的可读写实例。

Docker 的核心价值 :一次构建,处处运行。它实现了开发、测试、生产环境的绝对一致,极大地简化了持续集成和交付(CI/CD)的流程。

1.2 容器编排:为什么需要 Kubernetes (K8S)?

当你的应用从单体架构演进为数十上百个微服务时,每个服务都可能由多个容器实例组成。这时,手动管理容器的生命周期(创建、销毁、扩缩容)、网络连接、存储挂载和负载均衡将变得极其复杂且容易出错。

Kubernetes (K8S) 就是一个生产级的容器编排系统。它像一个集群的“大脑”,自动化的管理着成百上千的容器。主要能力包括:

  • 服务发现与负载均衡 :自动为容器组分配 IP 和 DNS 名称,并实现流量分发。
  • 存储编排 :自动挂载你选择的存储系统(本地、云存储等)。
  • 自动部署和回滚 :可以声明应用的期望状态(如运行3个实例),K8S 会自动调整当前状态至目标状态。如果更新出错,可以一键回滚。
  • 自动扩缩容 :根据 CPU 使用率或自定义指标,自动增加或减少容器实例数量。
  • 自我修复 :重启失败的容器、替换不可用节点、杀死不健康的容器。

简单比喻 :Docker 是“集装箱”,标准化了货物的打包方式;Kubernetes 是“超级货轮和自动化港口系统”,管理着成千上万个集装箱的运输、调度和存放。

1.3 Linux、云计算与运维的关系

  • Linux :是 Docker 和 K8S 最主要的宿主操作系统。绝大多数容器化应用都运行在 Linux 内核之上。掌握 Linux 基础命令(文件操作、权限管理、进程查看、网络配置)是运维容器的基础。
  • 云计算 :提供了弹性的基础设施(虚拟机、网络、存储)。公有云(如阿里云、腾讯云、AWS)是快速搭建 K8S 集群的常见平台。云原生(Cloud Native)理念与容器、微服务、DevOps 紧密结合。
  • 运维 :在上述技术栈中,运维工程师的职责从传统的“保稳定”向“促交付”演进,需要掌握容器化部署、监控、日志收集、自动化脚本等技能,即 云计算运维 或 云原生运维 。

2. 环境准备与版本说明

我们将在一个 Linux 环境中完成所有实践。如果你使用 Windows 或 macOS,强烈建议通过虚拟机(如 VirtualBox + Ubuntu)或云服务器进行操作,以获得最接近生产环境的体验。

本文环境说明:

  • 操作系统 :Ubuntu 22.04 LTS (Jammy Jellyfish)。其他发行版(如 CentOS)命令略有不同,会附带说明。
  • Docker 版本 :24.0.5 (社区版)。安装方法适用于较新版本。
  • Kubernetes 版本 :1.28.0。使用 kubeadm 工具搭建单控制平面集群。
  • 硬件要求 :
    • 至少 2 CPU 核心。
    • 至少 2 GB 内存(推荐 4 GB+)。
    • 至少 20 GB 磁盘空间。

重要提示 :生产环境请务必参考官方文档,并使用经过充分测试的稳定版本。本文示例旨在演示核心流程和原理。

3. Linux 基础与 Docker 安装实战

在安装 Docker 之前,我们需要确保系统环境就绪,并熟悉一些必要的 Linux 操作。

3.1 基础 Linux 命令速查

打开终端,尝试以下命令:

# 1. 查看系统信息
cat /etc/os-release
uname -r # 查看内核版本,Docker要求内核3.10+

# 2. 更新软件包索引(Ubuntu/Debian)
sudo apt update && sudo apt upgrade -y

# 3. 安装常用工具
sudo apt install -y curl wget vim net-tools

# 4. 管理服务
sudo systemctl start <service-name>   # 启动服务
sudo systemctl stop <service-name>    # 停止服务
sudo systemctl restart <service-name> # 重启服务
sudo systemctl status <service-name>  # 查看服务状态
sudo systemctl enable <service-name>  # 设置开机自启

3.2 安装 Docker 引擎

我们将使用 Docker 官方提供的便捷脚本进行安装,这也是最推荐的方式。

# 1. 卸载旧版本(如果存在)
sudo apt remove docker docker-engine docker.io containerd runc

# 2. 安装依赖,允许 apt 通过 HTTPS 使用仓库
sudo apt update
sudo apt install -y ca-certificates curl gnupg lsb-release

# 3. 添加 Docker 官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. 设置 Docker 稳定版仓库
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. 安装 Docker 引擎
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 6. 验证安装
sudo docker run hello-world

如果看到 “Hello from Docker!” 等信息,说明安装成功。这个命令会从 Docker Hub 拉取一个测试镜像并运行。

3.3 配置 Docker(非 root 用户运行 & 镜像加速)

默认情况下,运行 docker 命令需要 sudo 权限。为了方便,我们将当前用户加入 docker 组。

# 1. 将当前用户加入 docker 组
sudo usermod -aG docker $USER

# 2. 退出当前终端并重新登录,使组权限生效
# 或者执行:newgrp docker

# 3. 验证无需 sudo 运行 docker
docker ps

国内访问 Docker Hub 可能较慢,需要配置镜像加速器(以阿里云为例):

# 创建或修改 Docker 守护进程配置文件
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  “registry-mirrors”: [“https://<你的ID>.mirror.aliyuncs.com“]
}
EOF

# 重启 Docker 服务使配置生效
sudo systemctl daemon-reload
sudo systemctl restart docker

# 检查配置是否生效
docker info | grep -A 1 “Registry Mirrors”

请将 <你的ID>.mirror.aliyuncs.com 替换为你从阿里云容器镜像服务获取的专属加速地址。

4. Docker 核心操作实战

现在,我们通过一个完整的 Web 应用示例来学习 Docker 的核心工作流:构建镜像、运行容器、管理数据、配置网络。

4.1 构建第一个 Docker 镜像

我们创建一个简单的 Python Flask 应用。

1. 创建项目目录和文件:

mkdir my-flask-app && cd my-flask-app

2. 编写应用代码 app.py :

# app.py
from flask import Flask
app = Flask(__name__)

@app.route(‘/’)
def hello():
    return ‘<h1>Hello, Docker and CSDN!</h1><p>This is my first containerized app.</p>’

if __name__ == ‘__main__’:
    app.run(host=‘0.0.0.0’, port=5000)

3. 编写依赖文件 requirements.txt :

Flask==2.3.2

4. 编写 Dockerfile(构建镜像的蓝图):

# 使用官方 Python 轻量级镜像作为基础
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 将依赖文件复制到容器内
COPY requirements.txt .

# 安装 Python 依赖
RUN pip install --no-cache-dir -r requirements.txt

# 将当前目录所有文件复制到容器的 /app 目录
COPY . .

# 声明容器运行时暴露的端口
EXPOSE 5000

# 定义容器启动时执行的命令
CMD [“python”, “app.py”]

5. 构建镜像:

# -t 参数为镜像打标签,格式通常为 名称:版本
docker build -t my-flask-app:1.0 .

构建成功后,使用 docker images 查看本地镜像列表。

4.2 运行与管理容器

1. 运行容器:

# -d 后台运行,-p 将主机端口 8080 映射到容器端口 5000
docker run -d -p 8080:5000 --name my-flask-container my-flask-app:1.0

2. 访问应用: 打开浏览器,访问 http://<你的服务器IP>:8080 ,即可看到 Flask 应用页面。

3. 常用容器管理命令:

# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a

# 查看容器日志
docker logs my-flask-container
# 实时查看日志
docker logs -f my-flask-container

# 进入容器内部(调试用)
docker exec -it my-flask-container /bin/bash

# 停止容器
docker stop my-flask-container
# 启动已停止的容器
docker start my-flask-container
# 删除容器(必须先停止)
docker rm my-flask-container

# 删除镜像(必须先删除依赖它的容器)
docker rmi my-flask-app:1.0

4.3 数据持久化:使用 Volume

容器内的文件是临时的,容器删除后数据会丢失。Volume(数据卷)是 Docker 推荐的持久化数据方式。

# 1. 创建一个命名卷
docker volume create my-data

# 2. 运行容器并挂载卷
# -v my-data:/app/data 将卷挂载到容器的 /app/data 目录
docker run -d -p 8081:5000 \
  --name flask-with-volume \
  -v my-data:/app/data \
  my-flask-app:1.0

# 3. 进入容器,在 /app/data 下创建文件
docker exec -it flask-with-volume /bin/bash
echo “Persistent Data” > /app/data/test.txt
exit

# 4. 删除容器
docker rm -f flask-with-volume

# 5. 重新运行一个新容器,挂载同一个卷
docker run -d -p 8082:5000 \
  --name new-flask-container \
  -v my-data:/app/data \
  my-flask-app:1.0

# 6. 进入新容器,查看文件是否还在
docker exec -it new-flask-container cat /app/data/test.txt

你会发现 test.txt 文件依然存在,数据实现了持久化。

5. Kubernetes (K8S) 单机集群搭建与核心概念

在生产中,K8S 运行在多台机器组成的集群上。为了学习和测试,我们使用 kubeadm 在单台机器上搭建一个“单节点集群”(All-in-One)。

5.1 安装前置依赖与 K8S 组件

1. 关闭 Swap 分区(K8S 要求):

sudo swapoff -a
# 永久关闭,编辑 /etc/fstab,注释掉 swap 相关行
sudo sed -i ‘/ swap / s/^\(.*\)$/#\1/g’ /etc/fstab

2. 安装容器运行时(containerd): Docker 本身包含 containerd,但 K8S 推荐直接使用 containerd。

# 安装 containerd
sudo apt update
sudo apt install -y containerd

# 生成默认配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 修改配置,使用 systemd 作为 cgroup 驱动(关键步骤!)
sudo sed -i ‘s/SystemdCgroup = false/SystemdCgroup = true/’ /etc/containerd/config.toml

# 重启并启用 containerd
sudo systemctl restart containerd
sudo systemctl enable containerd

3. 安装 kubeadm, kubelet, kubectl:

# 添加 Kubernetes 仓库密钥
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg

# 添加 Kubernetes 仓库
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 update
sudo apt install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
sudo apt-mark hold kubelet kubeadm kubectl # 阻止自动更新

5.2 使用 kubeadm 初始化集群

1. 初始化控制平面节点:

# 注意:将 <your-ip> 替换为你的服务器内网IP
sudo kubeadm init \
  --apiserver-advertise-address=<your-ip> \
  --image-repository registry.aliyuncs.com/google_containers \
  --kubernetes-version v1.28.0 \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16

初始化成功后会输出类似下面的信息, 请务必保存好最后的 kubeadm join 命令 ,用于添加工作节点(单机环境可忽略)。

2. 配置 kubectl(普通用户):

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

3. 安装 Pod 网络插件(CNI): Pod 之间需要网络才能通信。我们安装 Flannel。

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

4. 检查集群状态:

kubectl get nodes
# 稍等片刻,节点状态应为 Ready
kubectl get pods --all-namespaces
# 查看所有命名空间的 Pod,确保 CoreDNS 和 Flannel 的 Pod 都是 Running

5.3 K8S 核心对象实战:Deployment 与 Service

K8S 通过 YAML 文件来声明资源对象的期望状态。我们来部署一个 Nginx 服务。

1. 创建 Deployment ( nginx-deployment.yaml ): Deployment 管理 Pod 的副本集,确保指定数量的 Pod 副本始终运行。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3 # 期望运行3个副本
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine # 使用轻量级镜像
        ports:
        - containerPort: 80

2. 创建 Service ( nginx-service.yaml ): Service 为一组 Pod 提供稳定的网络访问入口,实现负载均衡。

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx # 选择标签为 app: nginx 的 Pod
  ports:
    - protocol: TCP
      port: 80 # Service 对外的端口
      targetPort: 80 # Pod 内容器的端口
  type: NodePort # 类型为 NodePort,会在每个节点上开放一个端口(30000-32767)映射到该 Service

3. 应用配置并验证:

# 应用 Deployment
kubectl apply -f nginx-deployment.yaml
# 应用 Service
kubectl apply -f nginx-service.yaml

# 查看资源状态
kubectl get deployments
kubectl get pods -l app=nginx
kubectl get svc nginx-service

kubectl get svc 会显示 nginx-service 的 CLUSTER-IP 和一个 PORT(S) ,例如 80:30678/TCP 。其中 30678 就是 NodePort。

4. 访问应用: 在浏览器访问 http://<你的服务器IP>:30678 ,即可看到 Nginx 欢迎页面。Service 会将你的请求负载均衡到后端的 3 个 Nginx Pod 之一。

6. 常见问题与排查思路

在学习和实践过程中,你一定会遇到各种问题。以下是高频问题的排查指南。

问题现象 可能原因 排查思路与解决方案
Docker 命令报错:权限被拒绝 当前用户不在 docker 组。 执行 sudo usermod -aG docker $USER , 注销并重新登录 。或临时使用 sudo 。
docker pull 镜像速度极慢 默认从 Docker Hub 拉取,网络不佳。 配置国内镜像加速器(如阿里云、中科大)。修改 /etc/docker/daemon.json 。
容器启动后立即退出 容器内主进程执行完毕。 检查 Dockerfile 中的 CMD 或 ENTRYPOINT 。前台进程需持续运行(如 nginx -g ‘daemon off;‘ )。使用 docker logs <容器ID> 查看日志。
kubeadm init 失败 1. Swap 未关闭。
2. 防火墙/安全组阻止端口。
3. 镜像拉取失败。
1. 确认 swapoff -a 并永久禁用。
2. 开放 6443, 2379-2380, 10250-10252 等端口。
3. 使用 --image-repository 指定国内镜像源。查看 journalctl -xeu kubelet 日志。
kubectl get nodes 显示 NotReady 1. 网络插件未安装。
2. kubelet 服务异常。
1. 安装 Flannel/Calico 等 CNI 插件。
2. 执行 systemctl status kubelet 查看状态, journalctl -xeu kubelet 查看详细错误。
Pod 状态一直为 Pending 资源不足(CPU/内存)或没有合适节点。 kubectl describe pod <pod-name> 查看事件详情。检查节点资源 kubectl describe node 。
Pod 状态为 CrashLoopBackOff 容器内应用启动失败。 kubectl logs <pod-name> 查看应用日志。 kubectl describe pod <pod-name> 查看事件。检查镜像、命令、端口配置。
Service 无法通过 NodePort 访问 1. 节点防火墙。
2. 云服务商安全组。
3. Pod 就绪检查失败。
1. 放行 NodePort 范围(30000-32767)。
2. 在云控制台配置安全组规则。
3. kubectl get endpoints <service-name> 检查 Endpoints 是否为空。
kubectl exec 进入 Pod 失败 Pod 内没有 /bin/bash 或 /bin/sh 。 尝试 /bin/sh 。或使用 kubectl debug 临时添加调试容器。

7. 最佳实践与工程建议

掌握基础操作后,遵循最佳实践能让你在生产环境中走得更稳。

7.1 Docker 最佳实践

  1. 使用多阶段构建 :对于编译型语言(如 Go, Java),在第一个阶段编译,在第二个仅包含运行环境的阶段复制二进制文件,可以极大减小最终镜像体积。
    FROM golang:1.19 AS builder
    WORKDIR /app
    COPY . .
    RUN go build -o myapp .
    
    FROM alpine:latest
    WORKDIR /root/
    COPY --from=builder /app/myapp .
    CMD [“./myapp”]
    
  2. 优化镜像层 :合并相关的 RUN 命令,清理缓存,减少镜像层数。
    # 不佳
    RUN apt update
    RUN apt install -y package
    RUN rm -rf /var/lib/apt/lists/*
    
    # 更佳
    RUN apt update && apt install -y package && rm -rf /var/lib/apt/lists/*
    
  3. 使用 .dockerignore 文件 :避免将本地不必要的文件(如 .git , node_modules , 日志)复制到镜像构建上下文,加速构建。
  4. 指定非 root 用户运行容器 :增强安全性。
    RUN groupadd -r appuser && useradd -r -g appuser appuser
    USER appuser
    
  5. 为镜像打上明确的标签 :避免使用 latest ,而是使用版本号或 Git 提交哈希,如 myapp:v1.2.3 。

7.2 Kubernetes 最佳实践

  1. 资源请求与限制 :为 Pod 设置 resources.requests 和 resources.limits ,防止单个 Pod 耗尽节点资源,也便于调度器决策。
    resources:
      requests:
        memory: “64Mi”
        cpu: “250m”
      limits:
        memory: “128Mi”
        cpu: “500m”
    
  2. 使用 ConfigMap 和 Secret 管理配置 :将配置与镜像分离。敏感信息(密码、密钥)用 Secret,普通配置用 ConfigMap。
  3. 就绪探针与存活探针 :配置 livenessProbe 和 readinessProbe ,让 K8S 能自动检查应用健康状态,实现自我修复和流量管理。
  4. 命名空间隔离 :使用 Namespace 对不同环境(dev, staging, prod)或不同团队的项目进行逻辑隔离。
  5. 声明式管理 :始终使用 kubectl apply -f <file.yaml> 来应用配置变更,而不是 kubectl edit 或 kubectl replace 。将 YAML 文件纳入版本控制(如 Git)。

7.3 学习路线与下一步

通过本文,你应该已经完成了从 Linux 基础到 Docker 容器化,再到 Kubernetes 集群部署和应用的完整闭环。要真正掌握云原生运维,建议按以下路径深化:

  1. 巩固基础 :反复练习 Dockerfile 编写、 kubectl 常用命令、YAML 语法。
  2. 深入核心概念 :学习 Pod 生命周期、Service 类型(ClusterIP, NodePort, LoadBalancer, Ingress)、ConfigMap/Secret、Volume 存储(PV/PVC)。
  3. 学习高级控制器 :掌握 StatefulSet(有状态应用)、DaemonSet(节点守护进程)、Job/CronJob(批处理任务)。
  4. 探索生态工具 :
    • Helm :K8S 的包管理工具,简化复杂应用的部署。
    • Ingress Controller (如 Nginx Ingress):管理集群外部 HTTP/HTTPS 访问。
    • 监控告警 :Prometheus + Grafana。
    • 日志收集 :EFK Stack(Elasticsearch, Fluentd, Kibana)或 Loki。
  5. 动手项目 :尝试在云服务器上搭建多节点 K8S 集群,并部署一个包含前端、后端、数据库的完整微服务应用。

技术的核心在于实践。遇到报错时,善用 docker logs 、 kubectl describe 、 kubectl logs 和 journalctl 查看日志,大部分问题都能找到线索。将本文的示例代码和命令亲手敲一遍,理解其背后的原理,你便已经迈入了容器化与云原生运维的大门。

更多推荐