2026-07-15 11:54:47

Docker、containerd 与 Kubernetes 入门及命令速查

适用环境:Linux + systemd、Docker Engine、containerd、Kubernetes。本文面向初学者建立整体认识,也可用于日常运维、常见排障和快速查找命令。

目录

基础认知

容器日常操作

Kubernetes 核心能力

排障与速查

安全与进阶

1. 阅读路线

新手路线

  1. 阅读“核心概念与三者关系”,先分清镜像、容器、Pod、运行时和编排器。
  2. 用 Docker 完成镜像拉取、容器启动、查看日志、进入容器和删除容器。
  3. 理解 Kubernetes 节点通常通过 CRI 使用 containerd,而不是直接调用 Docker。
  4. 学习 Pod、Deployment、Service、ConfigMap、Secret、PVC 等对象。
  5. 按“分层排障手册”练习从 Kubernetes 一直定位到操作系统服务。

熟练用户路线

示例约定

占位符 含义 示例
<container> Docker 容器名或 ID web
<image> 镜像名和可选标签 nginx:1.27
<namespace> Kubernetes 命名空间 default
<pod> Pod 名称 web-7d9f...
<resource> Kubernetes 资源 deployment/web
<node> Kubernetes 节点名 worker-01

命令前的 $ 表示普通用户 shell,# 表示 root shell;复制时不要包含提示符。本手册不在命令中添加提权前缀:访问运行时 socket、系统日志或网络命名空间等特权操作,默认已进入 root shell,或当前用户已具备相应权限。

2. 核心概念与三者关系

2.1 一句话理解

  • Docker:面向开发和单机使用的完整容器工具链,包含镜像构建、容器管理、网络和卷等能力。
  • containerd:负责镜像管理和容器生命周期的容器运行时(container runtime),常作为 Kubernetes 节点运行时。
  • Kubernetes(K8s):跨节点编排容器的系统,负责声明期望状态、调度、自愈、伸缩和服务发现。

2.2 调用关系

image.png
图:Docker 与 Kubernetes 的管理路径,以及共用的底层容器运行时。

现代 Kubernetes 通常不通过 Docker daemon 启动 Pod。kubelet 通过 CRI(Container Runtime Interface) 调用 containerd;containerd 再通过 OCI 运行时(常见为 runc)创建容器进程。

2.3 关键术语

Image(镜像)

只读文件系统层和运行配置的集合,是创建容器的模板。

Container(容器)

镜像的运行实例,本质上是受 namespace、cgroup 等机制隔离的进程。

Registry(镜像仓库)

存储和分发镜像,如 Docker Hub 或私有 Harbor。

OCI

Open Container Initiative,定义镜像和容器运行时规范。

CRI

Kubernetes 与容器运行时之间的 gRPC 接口。

Pod

Kubernetes 最小调度单元,可包含一个或多个共享网络和存储的容器。

Namespace

Docker/containerd 的 Linux 隔离机制,也指 containerd 或 Kubernetes 中的逻辑隔离域;三者不是同一概念。

cgroup

对进程进行 CPU、内存、IO 等资源统计和限制的 Linux 内核机制。

CNI

Container Network Interface,Kubernetes 网络插件接口。

CSI

Container Storage Interface,Kubernetes 存储插件接口。

2.4 常见误区

  1. 容器不是轻量虚拟机:容器共享宿主机内核,不自带独立内核。
  2. Pod 不等于容器:Pod 是容器的运行环境和调度单元。
  3. docker images 看不到 K8s 镜像很正常:Docker daemon 和 Kubernetes 的 containerd 可能使用不同 socket、内容存储和命名空间。
  4. ctr 不是日常 CRI 运维工具:它偏底层调试;排查 Kubernetes 容器优先使用 crictl
  5. 删除 Pod 不一定解决问题:Deployment 会重建 Pod,必须找到镜像、配置、资源或节点层面的根因。

3. Linux 与 systemd 基础

3.1 服务管理

systemctl status docker

  • 用途:查看 Docker 服务状态和最近日志。
  • 注意:不改变服务状态。

systemctl status containerd

  • 用途:查看 containerd 状态。
  • 注意:K8s 节点常用。

systemctl status kubelet

  • 用途:查看 kubelet 状态。
  • 注意:控制面不可用时仍可执行。

systemctl restart containerd

  • 用途:重启 containerd。
  • 注意:有风险,会影响本机容器管理,应先评估业务。

systemctl restart kubelet

  • 用途:重启 kubelet。
  • 注意:本机已运行容器通常不会立刻退出,但管理短暂中断。

systemctl is-active kubelet

  • 用途:输出 active 或非活动状态。
  • 注意:适合脚本判断。

systemctl is-enabled containerd

  • 用途:检查是否开机启动。
  • 注意:不代表当前正在运行。

3.2 日志与资源

# 持续查看 kubelet 日志 journalctl -u kubelet -f # 查看 containerd 最近 100 行日志 journalctl -u containerd -n 100 --no-pager # 查看指定时间后的 Docker 日志 journalctl -u docker --since "2026-07-15 09:00:00" # 查看磁盘、inode、内存和进程 df -h df -ih free -h ps aux --sort=-%mem | head

效果:journalctl -f 持续追踪新日志;df -h 检查容量,df -ih 检查 inode。出现“磁盘还有空间但无法创建文件”时尤其要检查 inode。

4. Docker

4.1 架构和对象

Docker CLI 通过 Unix socket(通常为 /var/run/docker.sock)调用 Docker daemon。常用对象包括镜像、容器、网络、卷;Docker Compose 用 YAML 描述多个容器及其关系。

4.2 环境和服务

docker version

  • 用途:显示客户端、服务端版本;仅显示客户端通常表示 daemon 不可达。
  • 注意:可先查 socket 权限和服务状态。

docker info

  • 用途:显示存储驱动、cgroup、镜像和容器数量等。
  • 注意:输出较长。

docker system df

  • 用途:统计镜像、容器、卷和构建缓存占用。
  • 注意:不会清理数据。

docker context ls

  • 用途:查看当前连接的 Docker 环境。
  • 注意:* 表示当前 context。

若普通用户出现 permission denied,可临时用 docker ...。加入 docker 组相当于授予接近 root 的权限,不应把不可信用户加入该组。

4.3 镜像

docker pull nginx:1.27

  • 用途:拉取指定标签镜像到本机。
  • 注意:生产环境避免仅用可变的 latest

docker image ls

  • 用途:列出本地镜像。
  • 注意:-a 包含中间镜像。

docker image inspect <image>

  • 用途:输出镜像配置、层、架构等 JSON。
  • 注意:可配合 --format 提取字段。

docker build -t demo:v1 .

  • 用途:用当前目录 Dockerfile 构建镜像。
  • 注意:构建器只能访问构建上下文,使用 .dockerignore

docker tag demo:v1 registry.example.com/team/demo:v1

  • 用途:添加仓库标签。
  • 注意:不复制镜像层。

docker push registry.example.com/team/demo:v1

  • 用途:推送镜像。
  • 注意:需要登录和仓库权限。

docker save -o demo-v1.tar demo:v1

  • 用途:导出镜像及元数据。
  • 注意:用 docker load 恢复。

docker load -i demo-v1.tar

  • 用途:导入 docker save 生成的包。
  • 注意:保留标签和镜像元数据。

docker rmi <image>

  • 用途:删除本地镜像引用。
  • 注意:被容器引用时通常拒绝删除。

docker export/import 操作容器文件系统快照,不保留镜像历史和大部分配置;镜像迁移通常使用 save/load

4.4 Dockerfile

Dockerfile 是按顺序描述镜像构建过程的文本文件。docker build 读取 Dockerfile 和构建上下文,执行指令并生成不可变镜像。

构建上下文、层和缓存

# 使用当前目录下的 Dockerfile 和当前目录作为构建上下文 docker build -t demo:v1 . # 使用其他文件名,构建上下文仍是当前目录 docker build -f Dockerfile.prod -t demo:v1 . # 显示完整构建日志,排查缓存和失败步骤 docker build --progress=plain -t demo:v1 .

最后的 . 是默认构建上下文。COPYADD 默认只能读取该上下文中的文件,不能越过上下文边界读取 ../secret;BuildKit 还可通过显式声明的 named context 引入其他来源。上下文越大,传输、校验和缓存计算越慢,应使用 .dockerignore 排除无关文件。

RUNCOPYADD 等通常会产生文件系统层;CMDENTRYPOINTENVEXPOSE 等主要写入镜像配置。当前指令及其依赖输入未变化时,构建器可以复用缓存;某一步缓存失效后,后续步骤通常需要重新执行。

常用指令

FROM <image>

  • 用途:指定基础镜像并开始一个构建阶段。
  • 注意:每个阶段以 FROM 开始;首个 FROM 前可声明供其使用的全局 ARG。生产建议固定版本,严格场景固定 digest。

WORKDIR /app

  • 用途:设置后续指令和容器启动时的工作目录。
  • 注意:目录不存在时自动创建,优于连续使用 RUN cd ...

COPY src dst

  • 用途:从构建上下文复制文件到镜像。
  • 注意:默认优先于功能更复杂的 ADD;可使用 --chown 设置所有者。

ADD src dst

  • 用途:复制文件,并支持本地 tar 自动解包和 URL。
  • 注意:行为较隐式;普通复制使用 COPY

RUN <command>

  • 用途:在构建阶段执行命令并提交结果。
  • 注意:合并相关包管理命令并清理缓存,避免无效层和过大镜像。

ARG NAME=value

  • 用途:定义仅在构建时使用的变量。
  • 注意:可能出现在镜像历史或构建记录中,不能存放密码和 token。

ENV NAME=value

  • 用途:设置后续构建步骤和运行容器的环境变量。
  • 注意:会保留在镜像配置中,不应保存秘密。

EXPOSE 8080

  • 用途:声明应用预期监听的端口。
  • 注意:仅是元数据,不会自动发布端口;运行时仍需 -p

USER app

  • 用途:设置后续指令及容器默认运行用户。
  • 注意:应确保文件权限和监听端口允许该用户访问。

ENTRYPOINT [...]

  • 用途:设置容器固定入口程序。
  • 注意:JSON exec 格式便于正确接收信号。

CMD [...]

  • 用途:设置默认命令或 ENTRYPOINT 的默认参数。
  • 注意:Dockerfile 中只有最后一条生效,可被 docker run 参数覆盖。

HEALTHCHECK ...

  • 用途:定义 Docker 对容器执行的健康检查。
  • 注意:Kubernetes 通常使用自身的 startup/readiness/liveness probe。

LABEL key=value

  • 用途:添加版本、来源、维护者等镜像元数据。
  • 注意:适合记录源码 revision 和构建信息。

指令有两种常见写法:

# shell 格式:通过 /bin/sh -c 执行,支持变量展开和管道 RUN echo "$APP_ENV" # exec 格式:直接执行程序,参数边界和信号处理更可靠 CMD ["python", "app.py"]

容器主进程建议使用 exec 格式。CMD ["python", "app.py"] 中不能依赖 shell 展开 $VAR;确需 shell 功能时,应显式使用 sh -c 并正确处理信号。

基础示例:Python Web 应用

假设构建上下文包含 app.pyrequirements.txt 和以下 Dockerfile:

FROM python:3.13.5-slim-bookworm ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 WORKDIR /app # 依赖清单变化频率通常低于源码,先复制可提高缓存命中率。 COPY requirements.txt ./ RUN pip install --no-cache-dir --requirement requirements.txt RUN useradd --create-home --uid 10001 appuser COPY --chown=appuser:appuser app.py ./ USER appuser EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ CMD ["python", "-c", \ "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2)"] CMD ["python", "app.py"]
# 构建镜像 docker build -t example/python-web:v1 . # 查看镜像层和默认配置 docker history example/python-web:v1 docker image inspect example/python-web:v1 # 以前台方式试运行,Ctrl+C 结束 docker run --rm -p 127.0.0.1:8000:8000 example/python-web:v1

这个顺序使源码变化时通常只重新执行 COPY app.py 之后的步骤。应用必须监听容器内的 0.0.0.0:8000,并实现 /health;若没有健康端点,应调整或移除示例中的 HEALTHCHECK

多阶段构建:Go 应用

多阶段构建把编译工具链留在构建阶段,最终镜像只包含运行所需文件:

FROM golang:1.24-alpine AS build WORKDIR /src COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o /out/server ./cmd/server FROM alpine:3.21 RUN apk add --no-cache ca-certificates COPY --from=build /out/server /usr/local/bin/server USER 65532:65532 EXPOSE 8080 ENTRYPOINT ["/usr/local/bin/server"]
docker build -t example/go-server:v1 . docker run --rm -p 127.0.0.1:8080:8080 example/go-server:v1

AS build 命名构建阶段,COPY --from=build 只把产物复制到最终阶段。最终镜像不包含 Go 编译器、模块缓存和源码。

示例显式设置 GOOS=linux,表明目标是 Linux 容器;在 Linux 构建环境中通常可省略。若程序依赖 CGO,则不能直接沿用 CGO_ENABLED=0,需要匹配目标平台的编译工具链和运行时动态库。时区数据或额外证书等依赖也应加入最终阶段。

.dockerignore

.dockerignore 位于构建上下文根目录,语法类似 .gitignore。常见内容:

.git .gitignore .env *.log tmp/ dist/ coverage/ node_modules/ Dockerfile* docker-compose*.yml

不要盲目复制该清单:若构建确实需要某个文件,应保留它。尤其不要把私钥、云凭据、生产配置或包含 token 的 .env 放入构建上下文;即使后续 RUN rm,秘密也可能仍存在于早期镜像层或构建记录中。

缓存、体积和安全最佳实践

  1. 先复制依赖清单,再复制高频变化源码:例如先 COPY go.mod go.sumpackage*.json,安装依赖后再 COPY . .
  2. 固定基础镜像:至少固定明确版本;要求完全可复现时使用 image:tag@sha256:<digest>,并建立定期升级流程。
  3. 减少构建上下文:维护 .dockerignore,避免把 .git、构建产物、日志和依赖目录发送给构建器。
  4. 使用多阶段构建:编译器和开发依赖不进入最终镜像,可减少体积和攻击面。
  5. 使用非 root 用户:通过 USER 降低容器进程权限,并在切换用户前设置文件所有权。
  6. 合并包安装与缓存清理:例如 Debian 系镜像在同一 RUN 中执行 apt-get update、安装和删除 /var/lib/apt/lists/*
  7. 不要把秘密写入 ARGENVCOPY:需要构建时凭据时使用 BuildKit secret mount,并确保构建日志不回显秘密。
  8. 让 PID 1 正确接收信号:应用入口优先使用 exec 格式,应用处理 SIGTERM 并在停止超时内优雅退出。
  9. 不为减少层数牺牲缓存和可读性:现代镜像层本身开销很小,重点是避免把无用数据写入任何层。

BuildKit secret 的最小用法如下,秘密只在该条 RUN 执行期间挂载:

# syntax=docker/dockerfile:1 RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
docker build --secret id=npmrc,src="$HOME/.npmrc" -t example/app:v1 .

容易混淆的指令

对比 区别
COPYADD 普通文件复制优先 COPY;仅在明确需要 tar 自动解包等 ADD 行为时使用 ADD
CMDENTRYPOINT ENTRYPOINT 定义固定程序,CMD 定义默认命令或默认参数;运行时参数通常替换 CMD
ARGENV ARG 主要存在于构建过程,ENV 保留到镜像和容器运行时;两者都不适合存放秘密
EXPOSE-p EXPOSE 只声明元数据,docker run -p 才创建宿主机端口映射
bind mount 与 COPY bind mount 在运行时引用宿主机文件;COPY 在构建时把文件写入镜像层

例如:

ENTRYPOINT ["/usr/local/bin/server"] CMD ["--listen", ":8080"]

直接运行使用默认参数;docker run <image> --listen :9090 会保留 ENTRYPOINT,但用新参数替换 CMD。如需覆盖入口程序,可显式使用 docker run --entrypoint <program> <image>

构建检查和常见问题

COPY failed 或文件不存在

  • 排查:检查命令最后的上下文目录和 .dockerignore
  • 常见原因:文件不在上下文、路径大小写错误或被排除。

每次都重新安装依赖

  • 排查:用 docker build --progress=plain ... 查看缓存。
  • 常见原因:在依赖安装前执行了 COPY . .,源码变化使缓存失效。

镜像异常大

  • 排查:用 docker history <image> 查看各层大小。
  • 常见原因:把构建产物、包缓存、源码或依赖目录写入最终镜像。

容器启动即退出

  • 排查:使用 docker inspectdocker logs,并核对 CMD/ENTRYPOINT
  • 常见原因:主进程结束、命令不存在、权限不足或架构不匹配。

容器内文件 permission denied

  • 排查:检查 USERCOPY --chown 和目录权限。
  • 常见原因:切换非 root 用户前未授权目录。

exec format error

  • 排查:用 docker image inspectuname -m 对比架构。
  • 常见原因:构建了错误 CPU 架构、脚本缺少 shebang 或使用 CRLF 行尾。

拉取或安装依赖失败

  • 排查:检查 DNS、代理、证书和软件源。
  • 常见原因:网络不可达、企业 CA 未配置、代理只配置在宿主机。

镜像中发现凭据

  • 排查:检查 Dockerfile、上下文、docker history --no-trunc
  • 常见原因:使用了 ARG/ENV、复制后删除,或日志回显秘密;应立即轮换凭据。
# 不使用缓存重建,用于确认缓存是否掩盖问题;会增加耗时和网络流量 docker build --no-cache --progress=plain -t demo:debug . # 查看每层创建命令和大小 docker history --no-trunc demo:debug # 读取最终镜像配置中的用户、入口和默认参数 docker image inspect \ --format 'user={{.Config.User}} entrypoint={{json .Config.Entrypoint}} cmd={{json .Config.Cmd}}' \ demo:debug

不要把 --no-cache 作为日常构建默认选项。应先理解缓存失效原因,并通过合理的指令顺序和上下文边界获得可预测构建。使用 BuildKit/Buildx 时,可用 --no-cache-filter <stage> 只使指定构建阶段失去缓存,也可用 --cache-from--cache-to 管理外部缓存。

4.5 容器生命周期

# 后台启动 Nginx,将宿主机 8080 映射到容器 80 docker run -d --name web -p 8080:80 nginx:1.27 # 查看运行中容器;-a 包含已退出容器 docker ps docker ps -a # 停止、再次启动和重启 docker stop web docker start web docker restart web # 删除已停止容器 docker rm web

docker run [OPTIONS] IMAGE [COMMAND] [ARG...] 会基于镜像创建并启动一个新容器。常用参数如下:

--rm

  • 用途:容器退出后自动删除容器及其关联的匿名卷。
  • 注意:命名卷不会被删除;排障时退出后无法再用 docker inspect 查看现场。

--name <name>

  • 用途:指定易读且唯一的容器名。
  • 注意:同名容器存在时创建失败;可用 docker rmdocker rename 处理。

--network <network>

  • 用途:启动时连接指定网络。
  • 注意:用户自定义 bridge 网络支持按容器名解析;网络必须已存在。

-v <source>:<target>[:ro]

  • 用途:挂载命名卷或宿主机目录。
  • 注意:bind 源路径不存在时会在 Docker daemon 所在主机创建目录;复杂挂载优先 --mount

-e <key>=<value>

  • 用途:设置一个环境变量,可重复使用。
  • 注意:命令历史和容器配置可能暴露值;密码、令牌等敏感信息不要直接写在命令行。

-i

  • 用途:保持标准输入(STDIN)打开。
  • 注意:即使未连接终端也保持输入流,常与 -t 组合。

-t

  • 用途:分配伪终端(TTY)。
  • 注意:适合交互式 shell;脚本或管道通常不需要。

-it

  • 用途:同时启用 -i-t,获得交互式终端。
  • 注意:常用于临时运行 shell;后台服务通常使用 -d 而不是 -it
# 一次性交互式 shell:退出后自动删除容器 docker run --rm -it alpine:3.21 sh # 带名称、网络、持久卷和环境变量启动后台服务 docker network create app-net docker volume create app-data docker run -d --name app --network app-net \ -v app-data:/var/lib/app \ -e APP_ENV=production \ example/app:v1

选项必须放在镜像名之前;镜像名之后的内容是容器内执行的命令及参数。

例如,docker run --rm alpine:3.21 echo hello 中,echo hello 会覆盖镜像的默认 CMD

同一选项通常同时提供长短形式:--volume 等价于 -v--env 等价于 -e--interactive 等价于 -i--tty 等价于 -t

命令 用途与效果 注意事项
docker run --rm <image> <command> 创建并运行临时容器,退出后自动删除 适合测试命令
docker inspect <container> 输出容器完整 JSON 配置和状态 查 IP、挂载、退出码时常用
docker stats 实时显示容器 CPU、内存、网络、IO --no-stream 只输出一次
docker top <container> 查看容器内进程 从宿主机视角展示 PID
docker cp <container>:/path ./path 从容器复制文件到本机 反向参数顺序可复制进容器
docker rename <old> <new> 修改容器名 不重建容器

4.6 日志、进入容器和退出码

# 查看最后 100 行并持续追踪 docker logs --tail 100 -f web # 在运行中容器执行交互式 shell docker exec -it web sh # 查看状态、退出码和 OOM 标记 docker inspect \ --format 'status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}}' \ web

常见退出码:0 正常;1 应用通用错误;126 命令存在但不可执行;127 命令不存在;137 常表示收到 SIGKILL,可能是 OOM 或强制终止;143 表示收到 SIGTERM 后退出。退出码只是线索,应结合日志和 OOMKilled 判断。

4.7 网络

docker network ls docker network inspect bridge docker network create app-net docker run -d --name db --network app-net postgres:16 docker run --rm --network app-net busybox nslookup db

同一用户自定义 bridge 网络中的容器可通过容器名解析。-p 127.0.0.1:8080:80 仅监听宿主机回环地址;-p 8080:80 默认可能暴露到所有接口,需结合防火墙评估。

4.8 卷和挂载

docker volume create app-data

  • 用途:创建 Docker 管理的命名卷。
  • 注意:适合持久数据。

docker volume ls

  • 用途:列出卷。
  • 注意:不显示卷中文件内容。

docker volume inspect app-data

  • 用途:查看卷驱动和宿主机挂载点。
  • 注意:不建议绕过 Docker 直接改内部文件。

-v app-data:/data

  • 用途:把命名卷挂载到容器。
  • 注意:卷生命周期独立于容器;-v 也支持直接挂载宿主机目录,如 -v /host/data:/data

--mount type=bind,src=/srv/app,dst=/app,ro

  • 用途:只读绑定宿主机路径。
  • 注意:默认要求 daemon 主机上的源路径已存在;可显式使用 bind-create-src 创建目录。权限和 SELinux 需单独处理。

docker volume rm app-data

  • 用途:删除未使用卷。
  • 注意:破坏性操作,卷内数据不可恢复。

4.9 Compose 基础

# 校验并展示合并后的配置 docker compose config # 后台创建或更新服务 docker compose up -d # 查看服务和日志 docker compose ps docker compose logs -f --tail 100 # 停止并删除容器和默认网络 docker compose down

docker compose down -v 还会删除声明的命名卷,属于数据破坏操作。生产执行前应确认备份和卷用途。

4.10 清理

# 先查看空间占用 docker system df -v # 仅删除悬空镜像 docker image prune # 删除未使用的容器、网络、悬空镜像和构建缓存 docker system prune

危险操作: docker system prune -a --volumes 会扩大清理范围,可能删除所有未被容器引用的镜像和卷。不要把它当作常规磁盘清理命令。

5. containerd、ctr 与 crictl

5.1 三个工具的定位

工具 面向对象 典型用途
containerd 容器运行时守护进程 提供镜像、快照、容器、任务等底层能力
ctr containerd 原生调试 CLI 检查 containerd 内容、命名空间、镜像和 task
crictl CRI 调试 CLI 按 Kubernetes/CRI 视角查看 Pod sandbox、容器、镜像和日志

ctr 的命令接口偏底层且不保证像面向用户的 CLI 一样稳定;Kubernetes 节点排障优先使用 crictl

5.2 socket 和配置

常见 containerd socket 为 /run/containerd/containerd.sockcrictl 可通过 /etc/crictl.yaml 固定 endpoint:

runtime-endpoint: unix:///run/containerd/containerd.sock image-endpoint: unix:///run/containerd/containerd.sock timeout: 10 debug: false
crictl info crictl version ctr version

效果:验证 CLI 能否连接运行时;连接失败时检查 socket 路径、权限、containerd 服务和 CRI 插件配置。

5.3 containerd namespace

containerd namespace 是运行时内部的逻辑隔离。Kubernetes 常使用 k8s.io

ctr namespaces list ctr -n k8s.io images list ctr -n k8s.io containers list ctr -n k8s.io tasks list
  • container 是持久元数据对象,保存镜像、快照和运行配置引用。
  • task 是正在运行的进程对象。容器元数据存在不代表 task 正在运行。
  • 忘记 -n k8s.io 是“明明有 Pod 却查不到容器”的常见原因。

5.4 ctr 常用命令

命令 用途与效果 注意事项
ctr plugins list 查看插件状态 CRI 插件应非错误状态
ctr -n k8s.io images list 查看 K8s 命名空间镜像 输出引用、digest、大小和平台
ctr -n k8s.io images pull <image> 直接拉取镜像 镜像名通常需完整 registry 地址
ctr -n k8s.io images import image.tar 导入 OCI/Docker 镜像包 应确认平台架构和 namespace
ctr -n k8s.io containers info <id> 查看容器元数据 <id> 常不是 Pod 名称
ctr -n k8s.io tasks metrics <id> 查看 task 的 cgroup 指标 task 必须存在
ctr -n k8s.io content ls 查看内容存储中的 blobs 偏底层诊断

不要用 ctr containers rm 随意删除 kubelet 管理的容器;kubelet 可能重建对象,也可能造成状态短暂不一致。

5.5 crictl 常用命令

# 查看 Pod sandbox,包括非 Ready 项 crictl pods # 查看全部 CRI 容器 crictl ps -a # 按 Pod 名或标签过滤 crictl pods --name <pod> crictl ps --label io.kubernetes.pod.name=<pod> # 查看容器状态、日志和资源 crictl inspect <container-id> crictl logs --tail=100 <container-id> crictl stats <container-id>

crictl pods --namecrictl ps --name 按正则表达式过滤名称;若要匹配完整名称,可使用 --name '^<pod>$'。标签过滤由 CRI 传给运行时,更适合按 Kubernetes 元数据定位对象。

命令 用途与效果 注意事项
crictl images 查看 CRI 镜像 docker image ls 是不同视角
crictl inspectp <pod-id> 查看 Pod sandbox 网络命名空间和状态排障常用
crictl exec -it <container-id> sh 通过 CRI 进入容器 更常见的首选仍是 kubectl exec
crictl stopp <pod-id> 停止 Pod sandbox 有风险:仅用于明确的节点级诊断
crictl rmi <image> 删除 CRI 镜像 有风险:运行中引用和后续拉取需评估

crictl 操作的是具体节点。执行前先确认当前 shell 所在节点与目标 Pod 所在节点一致。

6. Kubernetes

6.1 控制面和节点

组件 职责
kube-apiserver 集群 API 入口,负责认证、鉴权、准入、校验并协调资源持久化。
etcd 控制面默认使用的集群状态键值存储;通常仅由 API Server 直接访问。
scheduler 为未调度 Pod 选择节点。
controller-manager 持续把实际状态收敛到期望状态。
kubelet 节点 agent,通过 CRI 管理 Pod 和容器。
kube-proxy 实现 Service 转发规则;部分 CNI 方案可替代其数据面。
CNI 插件 提供 Pod 网络、地址分配和网络策略能力。

6.2 核心资源对象

对象 作用 常见关系
Pod 最小调度单元 通常不直接长期维护
Deployment 管理无状态 Pod 的副本和滚动更新 Deployment → ReplicaSet → Pod
StatefulSet 管理有稳定身份或存储的有状态 Pod 常与 Headless Service、PVC 配合
DaemonSet 确保指定节点各运行一个 Pod 日志、网络、监控 agent 常用
Job/CronJob 一次性任务/定时任务 任务完成后 Pod 通常保留供查看
Service 为一组 Pod 提供稳定访问入口 通过 label selector 选择 Pod
Ingress 声明 HTTP/HTTPS 入口规则 需部署 Ingress Controller
ConfigMap 保存非敏感配置 可作为环境变量或文件挂载
Secret 保存敏感数据对象 默认仅 base64 编码,不等于加密
PV/PVC 集群存储资源/用户存储申请 通常由 StorageClass 动态供应
Namespace 对 API 资源进行逻辑分组 Node、PV 等为集群级资源

6.3 kubectl 上下文和帮助

kubectl version --client kubectl config current-context kubectl config get-contexts kubectl cluster-info kubectl api-resources kubectl explain deployment.spec.strategy

执行修改或删除前,必须确认当前 context、cluster 和 namespace。可用 kubectl config view --minify 查看当前上下文详情。

6.4 查看资源

kubectl get pods -A

  • 用途:查看所有 namespace 的 Pod。
  • 注意:-A 等于 --all-namespaces

kubectl get pods -n <namespace> -o wide

  • 用途:增加 Pod IP、节点等字段。
  • 注意:排查调度和网络常用。

kubectl get <resource> -o yaml

  • 用途:查看服务端保存的完整对象。
  • 注意:可能包含敏感配置。

kubectl describe pod <pod> -n <namespace>

  • 用途:查看状态、条件和 Events。
  • 注意:排障首选之一。

kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp

  • 用途:按时间查看事件。
  • 注意:事件有保留期限,不是长期日志。

kubectl get pods -n <namespace> -w

  • 用途:持续观察变化。
  • 注意:Ctrl+C 退出,不修改资源。

kubectl get pods -l app=web

  • 用途:使用标签筛选。
  • 注意:标签选择器是 Service 等对象关联基础。

常用输出:-o yaml-o json-o name-o wide-o jsonpath='{...}'-o custom-columns='...'

# 列出 Pod 名、节点和 Pod IP kubectl get pods -n <namespace> \ -o custom-columns='NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP' # 输出某 Pod 所有容器名 kubectl get pod <pod> -n <namespace> \ -o jsonpath='{.spec.containers[*].name}{"\n"}'

6.5 声明式管理

# 向 API Server 发起不持久化的预演请求,会经过服务端校验和准入链 kubectl apply --dry-run=server -f app.yaml # 仅在客户端构造并打印将发送的对象,不调用 API Server 或准入 Webhook kubectl apply --dry-run=client -f app.yaml # 创建或更新声明中的资源 kubectl apply -f app.yaml # 查看即将应用的差异 kubectl diff -f app.yaml # 删除清单描述的资源 kubectl delete -f app.yaml

推荐把 YAML 纳入版本控制,以 apply 维护期望状态。kubectl edit 和临时命令适合应急,但变更应回写配置源,避免漂移。

一个最小 Deployment 与 Service:

apiVersion: apps/v1 kind: Deployment metadata: name: web spec: replicas: 2 selector: matchLabels: app: web template: metadata: labels: app: web spec: containers: - name: nginx image: nginx:1.27 ports: - containerPort: 80 resources: requests: cpu: 100m memory: 64Mi limits: memory: 128Mi --- apiVersion: v1 kind: Service metadata: name: web spec: selector: app: web ports: - port: 80 targetPort: 80

6.6 日志、进入容器和复制文件

# 单容器 Pod 日志 kubectl logs <pod> -n <namespace> --tail=100 -f # 多容器 Pod 指定容器 kubectl logs <pod> -c <container> -n <namespace> # 查看上一次已退出容器日志,排查 CrashLoopBackOff 很关键 kubectl logs <pod> -c <container> -n <namespace> --previous # 执行 shell kubectl exec -it <pod> -c <container> -n <namespace> -- sh # 复制文件 kubectl cp <namespace>/<pod>:/tmp/file ./file -c <container>

kubectl cp 依赖容器内存在 tar。极简镜像没有 shell 或调试工具时,可在获得授权后使用 kubectl debug 创建临时调试容器:

kubectl debug -it <pod> -n <namespace> --image=busybox:1.36 --target=<container>

6.7 伸缩、更新和回滚

kubectl scale deployment/web -n <namespace> --replicas=3 kubectl set image deployment/web nginx=nginx:1.27.5 -n <namespace> kubectl rollout status deployment/web -n <namespace> kubectl rollout history deployment/web -n <namespace> kubectl rollout undo deployment/web -n <namespace>

命令效果:

  • scale 修改副本数。
  • set image 触发模板变化和滚动发布。
  • rollout status 等待发布结果。
  • undo 默认恢复上一 revision 的 Pod 模板,并由控制器产生新的滚动变更;历史 revision 仍可查询。

若资源由 GitOps、Helm 或 Operator 管理,手工修改可能被控制器覆盖,应修改真实配置源。

kubectl rollout restart deployment/web 会通过修改 Pod 模板注解触发重建,不等于修复配置错误,且会产生业务滚动影响。

6.8 节点维护

# 标记节点不可调度,不驱逐已有 Pod kubectl cordon <node> # 驱逐可驱逐工作负载,为维护腾空节点 kubectl drain <node> --ignore-daemonsets --delete-emptydir-data # 恢复调度 kubectl uncordon <node>

高风险操作:drain

  • drain 优先通过 Eviction API 驱逐 Pod,因此可能受 PodDisruptionBudget 限制。
  • --delete-emptydir-data 会允许删除使用 emptyDir 的 Pod,并丢失其中数据。
  • 若节点上存在无控制器管理的裸 Pod,命令默认拒绝继续;只有确认可删除后才使用 --force
  • --force 不等于绕过 PDB。真正强制改用 DELETE 并绕过 PDB 的是风险更高的 --disable-eviction

执行前检查副本、PDB、StatefulSet 和本地存储。

6.9 端口转发和代理测试

# 本机 8080 转发到 Service 80,Ctrl+C 后结束 kubectl port-forward -n <namespace> service/web 8080:80 # 在集群内创建一次性测试 Pod kubectl run netcheck -n <namespace> --rm -it --restart=Never \ --image=curlimages/curl -- curl -sv http://web:80/

port-forward 适合临时诊断,不是生产流量入口。一次性 Pod 的镜像需来自可信仓库并符合准入策略。

7. 镜像、网络、存储与资源

7.1 镜像拉取

Kubernetes 镜像问题常见状态为 ErrImagePullImagePullBackOff

kubectl describe pod <pod> -n <namespace> kubectl get pod <pod> -n <namespace> -o jsonpath='{.spec.containers[*].image}{"\n"}' crictl pull <image> journalctl -u containerd -n 100 --no-pager

依次检查:镜像名和标签、节点 DNS/网络、registry 证书、认证 Secret、限流、目标架构,以及 containerd registry 配置。生产镜像建议固定不可变 tag 或 digest。

7.2 网络数据路径

客户端 → LoadBalancer/Ingress → Service → EndpointSlice → Pod IP:port │ └─ 由 selector 和 Pod Ready 状态决定
kubectl get service web -n <namespace> -o wide kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=web kubectl get pods -n <namespace> -l app=web -o wide kubectl describe networkpolicy -n <namespace>

Service 无可用后端时,优先对比 Service selector 与 Pod labels,并检查 EndpointSlice 中各 endpoint 的 readyservingterminating 条件。

通常 ready 可理解为“正在 serving 且未 terminating”。但设置 publishNotReadyAddresses: true 时,未就绪 Pod 也可能发布为可用 endpoint。

端口含义:

  • port:Service 端口。
  • targetPort:后端端口。
  • nodePort:节点暴露端口。

DNS 排查:

kubectl run dnscheck -n <namespace> --rm -it --restart=Never \ --image=busybox:1.36 -- nslookup web.<namespace>.svc.cluster.local kubectl get pods -n kube-system -l k8s-app=kube-dns

7.3 存储

kubectl get storageclass kubectl get pv kubectl get pvc -A kubectl describe pvc <pvc> -n <namespace> kubectl get volumeattachment

PVC 长期 Pending 时检查 StorageClass、默认类、容量、访问模式、拓扑和 CSI controller 日志。Pod 卡在 ContainerCreating 时,从 Events 查挂载失败,再检查 CSI node 插件和节点系统日志。

删除 PVC 的数据后果取决于 PV reclaim policy:Delete 可能连同后端卷删除,Retain 通常保留后端数据等待人工处理。删除前必须确认策略和备份。

7.4 requests、limits 和 QoS

  • requests 用于调度时的资源预留依据。
  • limits.cpu 通过 CPU 配额限制,达到上限可能被 throttling。
  • limits.memory 由 cgroup 反应式执行;超限或内存压力下内核可能终止容器内进程。若 PID 1 被终止,容器通常退出,并按重启策略处理,状态中常见 OOMKilled
  • CPU 单位 100m 表示 0.1 个 CPU;内存建议使用 MiGi 等二进制单位。
kubectl top nodes kubectl top pods -A --containers kubectl describe node <node> kubectl get resourcequota,limitrange -n <namespace>

kubectl top 依赖 Metrics API(常由 metrics-server 提供),适合查看近期指标,不替代完整监控系统。

7.5 健康检查

Probe 失败效果 用途
startupProbe 未成功前暂停 liveness/readiness;连续失败达到阈值后终止容器 保护慢启动应用
readinessProbe 标记容器未就绪,使匹配 Service 停止向其发送常规流量;容器继续运行 判断是否可以接流量
livenessProbe 连续失败达到阈值后终止容器,再由重启策略决定后续动作 判断进程是否需要恢复

探针参数过严会造成重启风暴。先确认应用正常启动耗时,再设置 initialDelaySecondsperiodSecondstimeoutSecondsfailureThreshold

8. 分层排障手册

8.1 通用流程

现象确认 ↓ Kubernetes 对象:get / describe / events / logs ↓ 节点与 CRI:Pod 所在节点 / crictl pods, ps, inspect, logs ↓ containerd:服务日志 / 插件 / namespace / 镜像与 task ↓ Linux:CPU / 内存 / 磁盘 / inode / 网络 / cgroup / 内核日志

先收集证据,再重启或删除。重启可能清除现场、改变容器 ID,并让偶发故障更难复现。

8.2 Pod 为 Pending

kubectl describe pod <pod> -n <namespace> kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp kubectl get nodes kubectl describe node <node>

重点看 Events 中的 FailedScheduling:资源不足、taint/toleration 不匹配、node affinity、未绑定 PVC、端口冲突或配额限制。

8.3 Pod 为 CrashLoopBackOff

kubectl describe pod <pod> -n <namespace> kubectl logs <pod> -c <container> -n <namespace> --previous kubectl get pod <pod> -n <namespace> \ -o jsonpath='{range .status.containerStatuses[*]}{.name}{" exit="}'\ '{.lastState.terminated.exitCode}{" reason="}{.lastState.terminated.reason}{"\n"}{end}'

重点检查启动命令、配置、依赖服务、权限、探针、退出码和 OOM。CrashLoopBackOff 是重启退避状态,不是根因。

8.4 Pod 为 ContainerCreating

kubectl describe pod <pod> -n <namespace> kubectl get pod <pod> -n <namespace> -o wide # 登录 Pod 所在节点后: crictl pods --name <pod> journalctl -u kubelet -n 100 --no-pager journalctl -u containerd -n 100 --no-pager

常见原因:镜像拉取、CNI 创建网络失败、CSI 挂载失败、Secret/ConfigMap 不存在、sandbox 创建失败或磁盘满。

8.5 Service 不通

kubectl get service <service> -n <namespace> -o yaml kubectl get endpointslice -n <namespace> -l kubernetes.io/service-name=<service> kubectl get pods -n <namespace> --show-labels kubectl describe pod <pod> -n <namespace>

依次检查:

  • selector 与 Pod labels。
  • EndpointSlice 条件和 Readiness。
  • port/targetPort
  • 应用监听地址,按需求监听 Pod IP 或 0.0.0.0
  • NetworkPolicy、CNI 和 DNS。

注意 publishNotReadyAddresses 与 terminating endpoint 可能改变常规就绪过滤行为。先在同 namespace 内测试 Service,再测试跨 namespace 和集群外入口。

8.6 节点 NotReady

kubectl describe node <node> kubectl get events -A --field-selector involvedObject.kind=Node # 登录目标节点后: systemctl status kubelet containerd journalctl -u kubelet -n 200 --no-pager crictl info df -h df -ih free -h dmesg -T | tail -n 100

检查 kubelet 与 apiserver 连通性、证书时间、containerd、CNI、磁盘/内存压力、PIDPressure、内核和文件系统错误。

8.7 containerd 或 CRI 异常

systemctl status containerd crictl info ctr plugins list ctr -n k8s.io tasks list journalctl -u containerd --since "30 min ago" --no-pager

若 CRI 插件报错,检查 containerd 配置格式、插件是否被禁用、sandbox image、cgroup driver 和 registry 配置。修改配置前先备份,并使用当前版本支持的配置命令或文档校验。

8.8 Docker 容器立即退出

docker ps -a --filter name=<container> docker logs --tail 200 <container> docker inspect --format '{{json .State}}' <container> docker inspect --format '{{json .Config.Cmd}}' <container>

容器生命周期跟随 PID 1;主进程结束,容器即退出。检查入口命令、配置文件、挂载、权限、端口、依赖服务和 OOM 状态。

8.9 磁盘空间不足

df -h df -ih du -xhd1 /var/lib | sort -h docker system df -v crictl images journalctl --disk-usage

先确认占用来源和保留策略,再通过对应系统清理。不要直接删除 /var/lib/docker/var/lib/containerd 或 kubelet 数据目录中的文件,这会破坏元数据一致性。

9. 高频命令速查

9.1 Docker

目标 命令
服务信息 docker versiondocker info
构建镜像 docker build -t <image> .
完整构建日志 docker build --progress=plain -t <image> .
镜像层历史 docker history <image>
检查镜像配置 docker image inspect <image>
镜像列表/拉取 docker image lsdocker pull <image>
容器列表 docker ps -a
启动容器 docker run -d --name <container> <image>
日志 docker logs --tail 100 -f <container>
进入容器 docker exec -it <container> sh
检查配置 docker inspect <container>
资源统计 docker stats
停止/删除 docker stop <container>docker rm <container>
空间统计 docker system df -v

9.2 containerd/ctr

目标 命令
服务状态 systemctl status containerd
版本/插件 ctr versionctr plugins list
namespace ctr namespaces list
K8s 镜像 ctr -n k8s.io images list
K8s 容器元数据 ctr -n k8s.io containers list
K8s 运行任务 ctr -n k8s.io tasks list
服务日志 journalctl -u containerd -f

9.3 crictl

目标 命令
运行时信息 crictl info
Pod sandbox crictl pods
全部容器 crictl ps -a
镜像 crictl images
容器详情 crictl inspect <container-id>
Pod 详情 crictl inspectp <pod-id>
容器日志 crictl logs --tail=100 <container-id>
资源统计 crictl stats

9.4 kubectl

目标 命令
当前集群 kubectl config current-context
全部 Pod kubectl get pods -A -o wide
查看详情 kubectl describe pod <pod> -n <namespace>
事件 kubectl get events -n <namespace> --sort-by=.metadata.creationTimestamp
日志 kubectl logs <pod> -c <container> -n <namespace> --tail=100 -f
上次日志 kubectl logs <pod> -c <container> -n <namespace> --previous
进入容器 kubectl exec -it <pod> -c <container> -n <namespace> -- sh
应用配置 kubectl apply -f <file>
查看差异 kubectl diff -f <file>
发布状态 kubectl rollout status deployment/<name> -n <namespace>
端口转发 kubectl port-forward -n <namespace> service/<name> 8080:80
节点资源 kubectl top nodes

9.5 常用过滤技巧

# 只查看非 Running/Completed 的 Pod(依赖 awk) kubectl get pods -A --no-headers | awk '$4 != "Running" && $4 != "Completed"' # 按节点查看 Pod kubectl get pods -A --field-selector spec.nodeName=<node> -o wide # 查找发生过重启的容器 kubectl get pods -A \ -o custom-columns='NS:.metadata.namespace,POD:.metadata.name,'\ 'RESTARTS:.status.containerStatuses[*].restartCount' # Docker 格式化输出 docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}\t{{.Ports}}'

10. 安全操作清单

执行删除、重启、驱逐、清理或变更前检查:

  1. 当前 kubectl context 和 namespace 是否正确。
  2. 当前登录的节点是否确实是目标 Pod 所在节点。
  3. 资源是否由 Helm、GitOps、Operator 或其他控制器管理。
  4. 是否存在有效备份,PVC/PV reclaim policy 和卷用途是否明确。
  5. 是否满足副本数、PodDisruptionBudget 和维护窗口要求。
  6. 是否先收集了 Events、日志、对象 YAML、容器状态和节点指标。
  7. 命令中的 selector、通配符、-A--force--all-a-v 等扩大范围参数是否符合预期。

以下操作默认视为高风险:

  • kubectl deletekubectl drainkubectl scale ... --replicas=0
  • kubectl delete pvc、删除 PV 或 StorageClass
  • docker system prune -a --volumesdocker volume rm
  • 直接通过 ctr/crictl 删除 kubelet 管理的对象
  • 重启 containerd、Docker、kubelet 或网络/存储插件
  • 直接修改或删除 /var/lib/docker/var/lib/containerd/var/lib/kubelet 下的数据

11. 延伸学习

建议按以下顺序继续深入:

  1. Linux 隔离、资源与 rootless 容器

学习起点:

再继续学习 capabilities 与 seccomp。

  1. OCI、containerd 与 runc

学习起点:

再继续学习 image/runtime spec、snapshotter 与 shim。

  1. Kubernetes 调度与资源治理

Kubernetes 中文文档调度、抢占和驱逐 开始,继续学习探针、requests/limits、QoS、PDB 和优雅终止。

  1. CNI 与集群网络

CNI 官方文档Kubernetes 服务、负载均衡和联网 开始,继续学习 NetworkPolicy、CoreDNS、Service 与 Ingress。

  1. CSI 与数据保护

Kubernetes 存储Kubernetes CSI 开发者文档 开始,继续学习 StorageClass、访问模式、快照与备份恢复。

  1. Kubernetes 安全

Kubernetes 安全 开始,继续学习 RBAC、ServiceAccount、Secret 加密、Pod Security Standards 和供应链安全。

  1. 可观测性与审计

学习起点:

再继续学习集中日志、分布式追踪和审计日志。

官方资料索引

以下链接均指向对应项目、规范组织或 Linux 内核项目维护的官方资料。标注“中文”的链接优先用于入门;英文规范适合核对实现细节。

Docker

Linux 隔离

Linux 资源与安全

  • 资料: cgroup v2Seccomp BPF
  • 适合查阅: CPU、内存、IO、PID 控制器和系统调用过滤。

OCI

containerd

runc

  • 资料: opencontainers/runc
  • 适合查阅: OCI runtime 实现、bundle、rootless、cgroup v2 和运行时生命周期。

Kubernetes 总览

Kubernetes 调度与资源

CNI 与集群网络

CSI 与存储

Kubernetes 安全

可观测性

审计

  • 资料: Kubernetes 审计
  • 适合查阅: 审计策略、事件阶段、日志与 Webhook 后端。

查阅行为细节时,应以当前安装版本的 --helpkubectl explain 及对应版本官方文档为准。不同发行版、CNI/CSI 插件和 Kubernetes 版本可能改变 socket、配置路径、功能门控和输出字段。

本文链接:https://blog.zxysilent.com/post/docker-containerd-k8s.html

-- EOF --

Comments