加密与安全加固

商业版/私有化交付前给系统做加固(去外网仓库、清源码、删kubeconfig),或需要对镜像做存储加密时读这篇

04-运维管理 / 安全加固
加密安全加固商业化交付镜像加密containerdimgcryptocicryptctr-enc镜像存储加密encrypted imageimage encryptionkubeconfighistory私有化部署security hardening

加密与安全加固

本篇汇总两类加固工作:

  • 商业化/私有化交付加固清单:交付前对系统、镜像、凭据、源码做的一次性收尾操作。
  • containerd 镜像存储加密:基于 containerd imgcrypt/ocicrypt 的镜像层加密,保护镜像在仓库与磁盘上的存储安全。

来源:install/kubernetes/rancher/加密/系统加密.mdinstall/kubernetes/rancher/加密/镜像存储加密.md


一、交付加固清单

商业版交付(私有化、内网环境)前,按以下清单逐项收尾,目的是不泄露源码、不残留可被反向利用的凭据与外网仓库通道。

  1. 编译加密版本代码,构建加密代码版本的镜像。 即使用加密后的代码产出业务镜像,避免容器内可直接读到明文源码。镜像构建流程见 06-二次开发 / 镜像构建总览

  2. 对关键镜像做加密。 需要加密的镜像包括:镜像名后缀含 encryption 的镜像,以及 labelstudiojupytervscode 等镜像。加密方式见下文「containerd 镜像存储加密」。

  3. 关闭外网仓库通道、收紧权限。

    • 不使用外网仓库镜像,不在平台中配置仓库账号密码;
    • 仅下发有限权限的 token
    • 去除 cluster 版本的 dashboard(避免暴露集群级管理面)。
  4. 清理本地拉取的源码,并登出镜像仓库。

    docker logout ccr.ccs.tencentyun.com
    

    ccr.ccs.tencentyun.com/cube-studio/ 是 CubeStudio 的官方镜像仓库前缀(见 myapp/config.py:978 REPOSITORY_ORG)。交付环境登出后即无法再从该仓库拉取。

  5. 清空 shell 历史记录。

    history -c && history -w
    
  6. 删除 kubeconfig,断开对集群的本地管理入口。

    rm -rf ~/.kube/config
    

    kubekey 部署的 config 文件在 /etc/kubernetes/admin.conf,如需彻底收紧也要一并处理(注意:删除后本机将无法再用 kubectl 管理集群,请确认已无后续运维需求)。

  7. 删除所有下载到本机的代码。


二、containerd 镜像存储加密

⚠️ 重要前提:containerd 镜像加密只能加密存储(仓库里、磁盘上的镜像层是密文)。但镜像一旦在 k8s 中运行起来,仍然可以 kubectl exec 进入容器查看其中内容。因此它防的是“镜像被下载/落盘后被窃取源码或资产”,不防“运行态容器内查看”。

加密方案基于 containerd 官方的 imgcryptocicrypt 体系),命令行工具为 ctr-enc

2.1 为 containerd 安装 imgcrypt 插件

先安装指定版本 Go(按 CPU 架构二选一):

# amd64
apt update
wget https://mirrors.aliyun.com/golang/go1.23.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.23.0.linux-amd64.tar.gz
export PATH=/usr/local/go/bin:$PATH
go version

# arm64
apt update
wget https://mirrors.aliyun.com/golang/go1.23.0.linux-arm64.tar.gz
sudo tar -C /usr/local -xzf go1.23.0.linux-arm64.tar.gz
export PATH=/usr/local/go/bin:$PATH
go version

从源码构建 imgcrypt(使用官方 containerd.io 包时通常需要这样自行构建):

git clone -b v2.0.0 https://github.com/containerd/imgcrypt.git
cd imgcrypt
go env -w GOPROXY=https://goproxy.cn,direct
make
sudo make install

2.2 配置 containerd 解密策略

编辑 /etc/containerd/config.toml

vi /etc/containerd/config.toml

配置解密策略(如果类型是 pod,则需要在 k8s pod 上添加注释并挂载秘钥):

[plugins."io.containerd.grpc.v1.cri".image_decryption]
  key_model = "node"

配置解密步骤(stream processors):

[stream_processors]
  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
    returns = "application/vnd.oci.image.layer.v1.tar+gzip"
    path = "ctd-decoder"
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
  [stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
    accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
    returns = "application/vnd.oci.image.layer.v1.tar"
    path = "ctd-decoder"
    args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
    env= ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]

重载并重启 containerd:

systemctl daemon-reload
systemctl restart containerd

2.3 生成密钥对

openssl genrsa -out mykey.pem
openssl rsa -in mykey.pem -pubout -out mypubkey.pem
  • mypubkey.pem:公钥,用于加密镜像(推送方持有即可)。
  • mykey.pem:私钥,用于解密镜像(运行节点持有,须保密)。

2.4 加密镜像并推送到仓库

# 拉取原始镜像
ctr-enc --namespace k8s.io images pull ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01

# 用公钥加密镜像,输出一个 -encrypted 标签的镜像
ctr-enc --namespace k8s.io images encrypt \
  --recipient=jwe:mypubkey.pem \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01 \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted

# 推送加密镜像
nerdctl --namespace k8s.io push ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted

上面的镜像名/标签(ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01)只是示例,按实际镜像替换。

2.5 验证加解密

# 用私钥解密回明文镜像
ctr-enc --namespace k8s.io images decrypt --key=mykey.pem \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01

# 不提供秘钥直接运行加密镜像 —— 会报错
ctr-enc --namespace k8s.io run --rm \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted test ls

# 提供秘钥运行加密镜像 —— 正常
ctr-enc --namespace k8s.io run --rm --key mykey.pem \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted test echo 'Hello World!'

2.6 k8s 节点侧解密配置

在需要运行加密镜像的节点上,把秘钥放到 containerd 约定目录并重启:

mkdir -p /etc/containerd/ocicrypt/keys /run/containerd/ocicrypt/keys/
cp mykey.pem /etc/containerd/ocicrypt/keys/
cp mypubkey.pem /etc/containerd/ocicrypt/keys/
cp -r /etc/containerd/ocicrypt/keys/* /run/containerd/ocicrypt/keys/
systemctl restart containerd

# 节点拉取加密镜像(带私钥)
ctr-enc --namespace k8s.io images pull --key mykey.pem \
  ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted

2.7 k8s Deployment 示例

节点完成解密配置后,直接像普通镜像一样在 Deployment 中引用加密镜像即可:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: main
        image: ccr.ccs.tencentyun.com/cube-studio/kubeflow-dashboard:2026.07.01-encrypted
        imagePullPolicy: IfNotPresent
        command: ["sleep","1000000"]
最后更新 2026-07-04完整文档以官方仓库为准:GitHub Wiki