从零搭建Docker与Kubernetes实战环境:手把手教程与排错指南
最近在帮团队搭建新的微服务环境,发现很多刚接触容器化和云原生的同学,对 Docker 和 Kubernetes (K8S) 的理解还停留在“听说过”的阶段。从安装配置到实际部署应用,中间踩的坑一个接一个,网上资料要么太旧,要么太散,不成体系。
如果你也正面临类似困境——想系统学习容器技术却不知从何下手,或者项目急需落地但被复杂的配置和网络问题卡住——那么这篇文章就是为你准备的。本文将带你从零开始,手把手搭建一套完整的 Docker + K8S 学习与实践环境。内容涵盖从 Linux 基础操作、Docker 核心概念与实战,到 K8S 集群搭建、应用部署与管理,最后还会探讨其在云计算运维中的核心价值。文末提供了完整的实战项目配置文件和常见问题排查清单,无论是学生练手还是企业开发,都能直接复用。
1. 背景与核心概念:为什么是 Docker 和 K8S?
在深入动手之前,我们需要先理解这两个技术解决了什么问题,以及它们之间的关系。
Docker 的核心是 容器化 。你可以把它想象成一个超级轻量级的“虚拟机”。但与虚拟机需要模拟完整的操作系统(Guest OS)不同,容器直接共享宿主机的操作系统内核,只打包应用及其运行所需的库和依赖。这使得容器具有启动快、资源消耗小、部署一致性好等巨大优势。Docker 提供了构建、分发和运行容器的完整工具链。
Kubernetes (K8S) 的核心是 容器编排 。当你的应用从单体服务拆分成数十甚至上百个微服务,每个服务都用容器封装后,如何管理这些容器的生命周期?如何实现自动扩缩容、负载均衡、服务发现、滚动更新和故障自愈?手动操作 Docker 命令会变得极其困难。K8S 就是一个生产级的容器编排平台,它负责自动化管理成百上千的容器,让开发者可以专注于应用本身。
它们的关系 :Docker 是“集装箱”,负责把货物(应用)标准化打包;Kubernetes 是“超级货轮和港口调度系统”,负责管理成千上万个集装箱的运输、存放和调度。通常,我们使用 Docker 来创建容器镜像,然后在 K8S 集群中运行这些镜像。
应用场景 :
- 开发环境一致性 :用 Docker 镜像固化环境,“一次构建,处处运行”,彻底解决“在我机器上是好的”问题。
- CI/CD 流水线 :容器作为构建和测试的标准单元,实现快速、可靠的持续集成与部署。
- 微服务架构 :K8S 是微服务架构的理想运行平台,提供服务治理、弹性伸缩等能力。
- 混合云与多云部署 :K8S 提供了抽象层,让应用可以无缝运行在不同的云平台或数据中心。
2. 环境准备与版本说明
本文将在一个纯净的 Linux 环境下进行所有操作。为了保证教程的通用性和可复现性,我们选择 Ubuntu 22.04 LTS 作为演示系统。其他 Linux 发行版(如 CentOS、Debian)的命令会有细微差别,文中会适当说明。
核心软件版本 :
- 操作系统 :Ubuntu 22.04.4 LTS (Jammy Jellyfish)
- Docker Engine :24.0.7
- Kubernetes (kubeadm, kubelet, kubectl) :1.28.2
- 容器运行时 :containerd 1.7.6 (由 Docker 安装时默认集成,K8S 也使用它)
硬件与网络要求 :
- 至少 2核 CPU , 4GB 内存 (运行 K8S 单节点集群的最低要求,生产环境需更高)。
- 稳定的网络连接,用于下载软件包和容器镜像。
-
禁用交换分区(Swap),K8S 默认要求。
sudo swapoff -a并编辑/etc/fstab注释掉 swap 行。
重要提示 :容器和云原生生态迭代迅速,版本兼容性至关重要。本文提供的安装命令和配置基于上述版本验证。如果你的环境是其他版本(尤其是较新的版本),部分命令或参数可能需要调整。建议先通读全文理解原理,再根据官方文档进行微调。
3. Linux 基础与 Docker 核心实战
在搭建 K8S 之前,我们必须先掌握 Docker,而 Docker 又运行在 Linux 之上。因此,我们从必要的 Linux 操作开始。
3.1 必备 Linux 命令速查
即使你是 Windows 或 macOS 用户,在服务器领域,Linux 是绝对的主流。以下是容器运维中最常用的命令:
# 1. 系统与权限
sudo -i # 切换到 root 用户(谨慎使用)
whoami # 查看当前用户
cat /etc/os-release # 查看系统版本
df -h # 查看磁盘使用情况
free -h # 查看内存使用情况
# 2. 文件操作
ls -la /path/ # 详细列出目录内容
cp -r source dest # 递归复制
mv old new # 移动或重命名
rm -rf dir # 强制递归删除(危险!)
chmod +x script.sh # 给脚本添加执行权限
chown user:group file # 修改文件属主和属组
# 3. 网络与进程
ip addr show # 查看 IP 地址(替代老旧的 ifconfig)
netstat -tulnp # 查看端口监听情况(需安装 net-tools)
ss -tulnp # 查看端口监听情况(更现代的 ss 命令)
ps aux | grep nginx # 查找 nginx 进程
systemctl status docker # 查看 Docker 服务状态
journalctl -u docker -f # 实时查看 Docker 服务日志
# 4. 包管理 (Ubuntu/Debian)
sudo apt update # 更新软件包列表
sudo apt upgrade -y # 升级所有已安装的包
sudo apt install -y vim curl wget git # 安装常用工具
3.2 Docker 安装与配置
在 Ubuntu 上安装 Docker 官方版本是最佳实践。
# 1. 卸载旧版本(如果是全新系统可跳过)
sudo apt remove docker docker-engine docker.io containerd runc
# 2. 安装依赖工具
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. 设置稳定版仓库
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 Engine
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 6. 启动 Docker 并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker
# 7. 验证安装
sudo docker run hello-world
如果看到 “Hello from Docker!” 的输出,说明安装成功。
配置镜像加速器 :从 Docker Hub 拉取镜像在国内可能很慢。我们需要配置国内镜像源。
# 编辑 Docker 守护进程配置文件
sudo vim /etc/docker/daemon.json
将以下内容写入(如果文件不存在则创建),这里使用阿里云和网易的镜像加速器。
{
"registry-mirrors": [
"https://<你的ID>.mirror.aliyuncs.com",
"https://hub-mirror.c.163.com"
],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
保存后,重启 Docker 使配置生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
3.3 Docker 核心概念与实战
理解三个核心概念: 镜像(Image) 、 容器(Container) 、 仓库(Registry) 。
1. 镜像操作 镜像是容器的模板,是一个只读的文件层集合。
# 搜索镜像
docker search nginx
# 拉取镜像(从 Docker Hub)
docker pull nginx:alpine # 拉取轻量版 nginx 镜像
docker pull mysql:8.0
# 查看本地镜像
docker images
# 或使用更强大的格式
docker image ls --format "table {{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"
# 删除镜像
docker rmi <镜像ID或名称>
docker image prune -a # 删除所有未被容器使用的镜像(悬空镜像)
2. 容器操作 容器是镜像的运行实例。
# 运行一个容器
# -d: 后台运行
# -p 80:80: 将宿主机的80端口映射到容器的80端口
# --name mynginx: 给容器命名
docker run -d -p 80:80 --name mynginx nginx:alpine
# 查看运行中的容器
docker ps
# 查看所有容器(包括已停止的)
docker ps -a
# 进入容器内部(就像 SSH 到一台服务器)
docker exec -it mynginx /bin/sh # alpine 镜像用 /bin/sh
# 对于 Ubuntu/CentOS 镜像,通常用 /bin/bash
# docker exec -it myubuntu /bin/bash
# 查看容器日志
docker logs mynginx
docker logs -f mynginx # 实时跟踪日志
# 停止、启动、重启容器
docker stop mynginx
docker start mynginx
docker restart mynginx
# 删除容器(必须先停止)
docker rm mynginx
docker rm -f mynginx # 强制删除运行中的容器(危险!)
# 拷贝文件
docker cp /host/path/file.txt mynginx:/container/path/ # 宿主机 -> 容器
docker cp mynginx:/container/path/log.txt /host/path/ # 容器 -> 宿主机
3. 使用 Dockerfile 构建自定义镜像 这是 Docker 的核心技能。假设我们有一个简单的 Python Web 应用。
# 创建项目目录
mkdir mypythonapp && cd mypythonapp
# 创建应用文件 app.py
cat > app.py << 'EOF'
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Docker & K8S from Python Flask!\n"
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
EOF
# 创建依赖文件 requirements.txt
cat > requirements.txt << 'EOF'
Flask==2.3.3
EOF
# 创建 Dockerfile
cat > Dockerfile << 'EOF'
# 使用官方 Python 轻量级镜像作为基础
FROM python:3.11-alpine
# 设置工作目录
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY . .
# 声明容器运行时暴露的端口
EXPOSE 5000
# 定义容器启动命令
CMD ["python", "app.py"]
EOF
# 构建镜像
docker build -t my-python-app:1.0 .
# 运行自定义镜像的容器
docker run -d -p 5000:5000 --name myapp my-python-app:1.0
# 访问应用
curl http://localhost:5000
# 应输出:Hello, Docker & K8S from Python Flask!
4. 使用 docker-compose 编排多容器应用 对于需要多个容器协作的应用(如 Web + 数据库),使用 docker-compose 更方便。
# docker-compose.yml
version: '3.8'
services:
web:
build: . # 使用当前目录的 Dockerfile 构建
ports:
- "5000:5000"
depends_on:
- db
environment:
- DATABASE_URL=postgresql://user:password@db:5432/mydb
networks:
- app-network
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres-data:/var/lib/postgresql/data
networks:
- app-network
volumes:
postgres-data:
networks:
app-network:
driver: bridge
运行:
docker-compose up -d
;停止:
docker-compose down
。
4. Kubernetes (K8S) 单节点集群搭建与核心概念
掌握了 Docker,我们就可以进军 K8S 了。生产环境通常是多节点集群,但对于学习和开发测试,一个单节点集群(All-in-One)完全足够。我们将使用
kubeadm
这个官方工具来搭建。
4.1 安装前系统配置
这些步骤至关重要,很多安装失败都源于此。
# 1. 关闭交换分区(K8S 1.8+ 要求)
sudo swapoff -a
# 永久关闭:编辑 /etc/fstab,注释掉所有包含 swap 的行,然后重启。
# 2. 设置主机名(可选,但有助于识别)
sudo hostnamectl set-hostname k8s-master
# 修改 /etc/hosts,确保主机名能解析到本机IP
# 例如:192.168.1.100 k8s-master
# 3. 允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system
4.2 安装容器运行时和 K8S 组件
K8S 本身不直接运行容器,它通过 CRI (Container Runtime Interface) 调用容器运行时。我们将使用 Docker 安装时已经集成的
containerd
。
# 1. 安装 containerd 的配置工具(如果尚未安装)
sudo apt install -y containerd
# 2. 生成 containerd 的默认配置文件
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# 3. 修改配置文件,使用 systemd 作为 cgroup 驱动(与 K8S 保持一致)
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 4. 重启 containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
# 5. 安装 kubeadm, kubelet, kubectl
# 添加 Kubernetes 阿里云镜像源
sudo apt install -y apt-transport-https ca-certificates curl
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 安装指定版本(避免使用最新版可能带来的兼容性问题)
sudo apt update
sudo apt install -y kubelet=1.28.2-00 kubeadm=1.28.2-00 kubectl=1.28.2-00
sudo apt-mark hold kubelet kubeadm kubectl # 阻止自动更新
# 6. 初始化 Master 节点(单节点集群)
# 注意:将 <MASTER_IP> 替换为你本机的实际 IP 地址
sudo kubeadm init \
--apiserver-advertise-address=<MASTER_IP> \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.28.2 \
--service-cidr=10.96.0.0/12 \
--pod-network-cidr=10.244.0.0/16
# 初始化成功后会输出类似以下信息,请务必保存好最后的 kubeadm join 命令(虽然单节点用不上):
# kubeadm join 192.168.1.100:6443 --token xxxxxx.xxxxxxxxxxxxxx \
# --discovery-token-ca-cert-hash sha256:xxxxxxxx...
# 7. 配置 kubectl(普通用户)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 8. 安装 Pod 网络插件(CNI)
# 这是 K8S 集群的“神经系统”,负责 Pod 间的通信。这里安装最常用的 Flannel。
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
# 等待所有 Pod 变为 Running 状态
kubectl get pods --all-namespaces -w
# 看到 kube-flannel-* 和 coredns-* 都 Running 即可。
4.3 K8S 核心概念与对象
在 K8S 中,一切皆对象。通过 YAML 文件定义对象的期望状态,K8S 会努力让实际状态与之匹配。
- Pod :K8S 的最小调度单元。一个 Pod 可以包含一个或多个紧密关联的容器(如主容器和 Sidecar 容器),它们共享网络和存储空间。
- Deployment :用于部署无状态应用。它管理一组相同的 Pod(称为 ReplicaSet),并提供滚动更新、回滚等功能。
- Service :定义一组 Pod 的访问策略。为 Pod 提供一个稳定的 IP 地址和 DNS 名称,并实现负载均衡。
- Namespace :虚拟集群,用于在物理集群中划分多个虚拟环境,实现资源隔离(如 dev, test, prod)。
- ConfigMap & Secret :用于将配置信息和敏感数据(如密码)与容器镜像解耦。
4.4 第一个 K8S 应用:部署 Nginx
让我们用 kubectl 命令和 YAML 文件两种方式部署一个 Nginx。
方式一:使用
kubectl run
命令(快速测试)
# 创建一个名为 my-nginx 的 Deployment,使用 nginx 镜像
kubectl create deployment my-nginx --image=nginx:alpine
# 将 Deployment 暴露为一个 Service(NodePort 类型,便于从集群外访问)
kubectl expose deployment my-nginx --type=NodePort --port=80
# 查看资源状态
kubectl get deployments
kubectl get pods
kubectl get services
# 获取 NodePort 端口号
kubectl get svc my-nginx -o jsonpath='{.spec.ports[0].nodePort}'
# 假设输出是 31876,则在浏览器访问 http://<你的服务器IP>:31876
方式二:使用 YAML 文件(推荐,可版本控制)
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2 # 运行 2 个 Pod 副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
---
# nginx-service.yaml (也可以和上面写在一个文件里,用 --- 分隔)
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx # 选择标签为 app: nginx 的 Pod
ports:
- protocol: TCP
port: 80 # Service 对内的端口
targetPort: 80 # Pod 容器的端口
nodePort: 30080 # 集群外访问的端口 (范围 30000-32767)
type: NodePort
应用配置:
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
# 或合并执行:kubectl apply -f .
5. 深入实战:在 K8S 中部署有状态应用(MySQL)
无状态应用(如 Nginx)的 Pod 可以随意创建和销毁。有状态应用(如数据库)则需要持久化存储和稳定的网络标识。我们使用 StatefulSet 和 PersistentVolume (PV) / PersistentVolumeClaim (PVC) 来部署 MySQL。
5.1 创建持久化存储
首先,我们创建一个本地目录作为存储(生产环境请使用网络存储如 NFS、Ceph、云盘等)。
# 在宿主机上创建存储目录
sudo mkdir -p /data/mysql
sudo chmod 777 /data/mysql # 简化权限,生产环境需严格设置
然后,创建 PV 和 PVC 的 YAML 文件。
# mysql-pv-pvc.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce # 单节点读写
hostPath:
path: /data/mysql
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
应用:
kubectl apply -f mysql-pv-pvc.yaml
5.2 创建 ConfigMap 存储配置
将 MySQL 的配置文件从镜像中分离。
# mysql-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql-config
data:
my.cnf: |
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-authentication-plugin=mysql_native_password
max_connections=1000
5.3 创建 Secret 存储密码
敏感信息必须用 Secret。
# 使用 kubectl 命令创建 Secret(密码会经过 base64 编码)
kubectl create secret generic mysql-secret \
--from-literal=root-password=MyStrongPassword123!
5.4 创建 MySQL StatefulSet 和 Service
# mysql-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: mysql-service # 必须有,用于提供稳定的 DNS
replicas: 1 # 单实例 MySQL,生产环境可考虑主从
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
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: mysql-data
mountPath: /var/lib/mysql
- name: mysql-config
mountPath: /etc/mysql/conf.d
volumes:
- name: mysql-config
configMap:
name: mysql-config
volumeClaimTemplates: # StatefulSet 特有的,为每个 Pod 动态创建 PVC
- metadata:
name: mysql-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
clusterIP: None # Headless Service,用于 StatefulSet 的 DNS 解析
应用所有配置:
kubectl apply -f mysql-configmap.yaml
kubectl apply -f mysql-statefulset.yaml
5.5 验证与连接
# 查看 Pod 状态
kubectl get pods -l app=mysql -w
# 等待状态变为 Running
# 查看 PVC 绑定状态
kubectl get pvc
# 进入 MySQL Pod 执行命令
kubectl exec -it mysql-0 -- mysql -uroot -pMyStrongPassword123!
# 或者在集群内其他 Pod 中,通过 Service 名连接
# mysql -h mysql-service -uroot -p
6. 常见问题与排查思路
在学习和使用 Docker 与 K8S 的过程中,你一定会遇到各种问题。以下是高频问题排查指南。
| 问题现象 | 可能原因 | 排查思路与解决方案 |
|---|---|---|
Docker 命令报错
Got permission denied
|
当前用户不在
docker
用户组。
|
1.
sudo usermod -aG docker $USER
2. 注销并重新登录 (或执行
newgrp docker
)。
|
docker pull
速度极慢或超时
| 默认 Docker Hub 镜像源在国内访问慢。 |
配置国内镜像加速器(见 3.2 节
/etc/docker/daemon.json
)。
|
kubeadm init
卡在
pull image
或失败
|
无法拉取
k8s.gcr.io
镜像。
|
1. 使用
--image-repository
参数指定阿里云等国内镜像源。
2. 或提前用
docker pull
拉取镜像并打标签。
|
kubectl get pods
显示
Pending
| Pod 无法被调度到节点。 |
1.
kubectl describe pod <pod-name>
查看事件。
2. 常见原因:资源不足、节点有污点(Taint)、未安装网络插件。 |
kubectl get pods
显示
ImagePullBackOff
| 无法拉取容器镜像。 |
1.
kubectl describe pod
查看具体错误。
2. 检查镜像名称拼写、镜像仓库权限、网络。 |
kubectl get pods
显示
CrashLoopBackOff
| 容器启动后立即退出。 |
1.
kubectl logs <pod-name>
查看容器日志。
2. 检查应用配置、依赖、启动命令、端口冲突。 |
| Pod 间网络不通 | Pod 网络插件(CNI)未正常工作。 |
1.
kubectl get pods -n kube-system
检查
kube-flannel-*
等 CNI Pod 状态。
2. 查看 CNI Pod 日志:
kubectl logs -n kube-system <cni-pod-name>
。
|
| Service 无法通过 NodePort 访问 | 防火墙未放行端口、节点 IP 错误。 |
1. 检查服务器防火墙(如
ufw
)是否允许 NodePort 范围(30000-32767)。
2.
curl http://<节点内网IP>:<NodePort>
测试。
|
kubectl
命令报错
The connection to the server was refused
| Kubernetes API Server 未运行或配置错误。 |
1.
sudo systemctl status kubelet
检查 kubelet 状态。
2. 检查
$HOME/.kube/config
文件是否存在且内容正确。
3. 确认
kubeadm init
已成功完成。
|
| 磁盘空间不足 | 容器镜像、日志、未清理的停止容器占用空间。 |
1.
docker system df
查看 Docker 磁盘使用。
2.
docker system prune -a
清理(谨慎,会删除未使用的镜像)。
3. 清理 K8S 日志:
journalctl --vacuum-time=7d
。
|
通用排查命令 :
-
kubectl describe <资源类型> <资源名>:查看资源的详细状态和事件,是排错第一选择。 -
kubectl logs <pod-name> [-c <container-name>]:查看 Pod 或指定容器的日志。 -
kubectl exec -it <pod-name> -- /bin/sh:进入 Pod 内部调试。 -
kubectl get events --sort-by=.metadata.creationTimestamp:查看集群级别的事件。
7. 最佳实践与工程建议
将技术用于生产环境,必须考虑稳定性、安全性和可维护性。
7.1 Docker 最佳实践
-
使用多阶段构建
:对于编译型语言(如 Go, Java),在第一个阶段编译,在第二个仅包含运行环境的阶段拷贝二进制文件,极大减小镜像体积。
# 以 Go 应用为例 FROM golang:1.20 AS builder WORKDIR /app COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -o myapp . FROM alpine:latest WORKDIR /root/ COPY --from=builder /app/myapp . CMD ["./myapp"] -
使用
.dockerignore文件 :避免将node_modules,.git, 日志等不必要的文件拷贝进镜像,加速构建并减小体积。 -
以非 root 用户运行容器
:在 Dockerfile 中创建并使用非 root 用户,增强安全性。
RUN addgroup -g 1000 appuser && adduser -u 1000 -G appuser -s /bin/sh -D appuser USER appuser -
明确指定镜像标签
:避免使用
latest标签,应指定具体版本号(如nginx:1.25-alpine),保证环境一致性。 -
限制容器资源
:使用
-m,--cpus等参数限制容器内存和 CPU 使用,防止单个容器耗尽主机资源。
7.2 Kubernetes 最佳实践
-
使用 Namespace 隔离环境
:为开发、测试、生产环境创建不同的命名空间。
kubectl create namespace dev kubectl create namespace prod kubectl config set-context --current --namespace=dev # 切换当前上下文命名空间 -
为 Pod 设置资源请求和限制
:这是 K8S 进行合理调度和防止资源争抢的基础。
resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m" -
使用 Readiness 和 Liveness 探针
:确保流量只被发送到已准备好的 Pod,并能自动重启不健康的 Pod。
livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 10 readinessProbe: httpGet: path: /ready port: 8080 initialDelaySeconds: 5 periodSeconds: 5 - 将配置与镜像分离 :永远不要将配置文件、密码等硬编码在镜像中。使用 ConfigMap 和 Secret,并通过环境变量或卷挂载注入容器。
-
制定更新策略
:在 Deployment 中配置
strategy,实现零停机的滚动更新。strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 # 更新过程中可以超出期望 Pod 数的最大值 maxUnavailable: 0 # 更新过程中不可用 Pod 的最大数量 - 做好日志与监控 :集群层面部署 EFK (Elasticsearch, Fluentd, Kibana) 或 Loki 日志系统,以及 Prometheus + Grafana 监控系统。
7.3 云计算运维视角
从运维角度看,Docker 和 K8S 带来了基础设施即代码 (IaC) 和 GitOps 的实践。
- 版本化一切 :将 Dockerfile、K8S YAML、Helm Charts 纳入 Git 仓库管理。
- CI/CD 流水线 :将镜像构建、安全扫描、推送仓库、部署到 K8S 的过程自动化。
- 不可变基础设施 :一旦部署,不再直接登录容器修改配置。任何变更都应通过更新镜像或 ConfigMap,然后重新部署来实现。
- 关注安全 :定期扫描镜像漏洞、使用 Pod 安全策略、管理好 RBAC 权限、保护 etcd 数据。
8. 总结与学习路线
通过本文,你应该已经完成了一个从零到一的 Docker 与 Kubernetes 实战旅程:从 Linux 基础、Docker 安装与镜像构建,到 K8S 单节点集群搭建、核心对象操作,再到部署有状态的 MySQL 应用。我们不仅涵盖了操作步骤,更深入探讨了排错方法和生产级的最佳实践。
下一步学习建议 :
- 深入 K8S 核心概念 :学习 Ingress (七层负载均衡)、 ConfigMap/Secret 高级用法、 RBAC (权限控制)、 Helm (包管理)。
-
搭建多节点集群
:尝试使用
kubeadm添加 Worker 节点,理解集群高可用架构。 - 体验云厂商托管服务 :在阿里云 ACK、腾讯云 TKE、华为云 CCE 上创建托管集群,体会云原生的便捷。
- 学习服务网格 :了解 Istio 或 Linkerd ,这是处理微服务间通信、安全、可观测性的下一代技术。
- 参与实际项目 :将你的个人项目或公司的一个非核心服务容器化并部署到 K8S,这是最好的学习方式。
技术的道路很长,但每一步都算数。容器化和云原生不是银弹,但它们确实是构建现代可扩展、高可用应用架构的基石。希望这份教程能成为你探索这个广阔领域的坚实起点。如果在实践中遇到新的问题,欢迎随时回顾文中的排查思路,或查阅官方文档。动手去做,遇到问题解决问题,才是掌握技术的唯一捷径。
更多推荐
所有评论(0)