AWS EC2 Ubuntu GPU 深度学习环境:安全且可复现的 2026 配置指南

Amazon EC2 上安全、可复现的 Ubuntu GPU 工作流

2017 年的清单把全局可写的 Git 部署钩子、过时的 Bazel 软件源、未指定版本的 TensorFlow 源码构建、未锁定的 Python 包和公开 Notebook 教程混在一起。这些做法都不适合作为当前默认方案。

2026 版先确定版本矩阵与成本边界,让 Jupyter 仅监听回环地址并通过带身份验证的隧道访问,同时保存足够证据,以便安全复现或下线机器。这是一套工作流,并不保证任意框架版本都能搭配任意 GPU、CPU 架构、驱动或 CUDA 栈。启动前和安装前都应核对所选版本的官方矩阵。

1. 有意识地选择一条平台路径

路径适合场景可复现边界
AWS Deep Learning AMI(DLAMI)最快开始受支持的交互式工作固定区域与 AMI ID,阅读该镜像的发行说明,激活文档指定的环境,不要随意替换预装 CUDA 或框架包
AWS Deep Learning Container团队工作流、CI 和可重复任务用不可变摘要固定镜像,记录宿主机驱动与 GPU 运行时,数据和密钥放在镜像之外
标准 Ubuntu AMI需要完全控制,或 AWS 镜像不满足要求固定 Ubuntu AMI,只按当前 NVIDIA 指南安装驱动/工具包;这条路径的兼容性和补丁维护工作最多

AWS DLAMI 已配置常用框架和 NVIDIA 组件。AWS Deep Learning Container 文档会指向当前维护的容器目录。标准 Ubuntu 镜像不会天然更可复现;只有记录 AMI、软件源密钥环、软件包版本、框架锁文件和验证输出之后才算可复现。

安装过程中不要混用路径。尤其不要把无关的 CUDA runfile、发行版软件包和 pip 提供的 CUDA 库叠加在同一环境中,除非所选框架的文档明确支持该组合。

2. 启动前建立兼容性清单

从真正需要的框架版本向外选择,而不是从看起来最新的 GPU 倒推。逐项记录下表:

层级必须记录的精确值权威来源/检查方式
AWS 位置区域、可用区、实例类型、购买模式当前 EC2 控制台/API 与加速计算实例规格
机器镜像AMI ID、镜像名、所有者、创建日期EC2 镜像详情;AMI ID 与区域相关
CPUx86_64arm64实例规格与 uname -m
GPU型号、数量、显存、NVIDIA 架构、计算能力EC2 规格、nvidia-smiNVIDIA CUDA GPU 表
驱动精确驱动版本nvidia-smiNVIDIA 驱动工具参考
CUDA驱动支持的 CUDA 上限;另行记录已安装工具包版本nvidia-smi 不能证明已安装 nvcc;适用时运行 nvcc --version
框架名称、精确版本/构建、支持的 Python/CUDA/cuDNN/计算能力所选框架版本的官方安装/构建矩阵
Python 环境Python、pip、所有直接与传递依赖、wheel 哈希针对该操作系统、CPU 架构和 Python 版本生成的锁文件

只要有一项未知、所需 AMI 并非预期发布者所有、CPU 架构缺少所需 wheel、GPU 显存或计算能力不足,或框架矩阵与驱动/CUDA 组合冲突,就应在启动前停止。

3. 先设置安全与成本控制

  • 启动 GPU 实例前创建 AWS Budget 和提醒。提醒只是通知,不会自动关机;若要自动处理,应另行配置并测试预算操作。按所选区域核对当前价格、Spot 中断、配额、EBS、快照、公网 IPv4、流量和闲置资源成本。
  • 优先使用无需入站规则的 Systems Manager Session Manager。必须用 SSH 时,只允许固定管理员 CIDR 访问 TCP 22。绝不向 0.0.0.0/0::/0 开放 8888。
  • 给实例附加最小权限角色,只允许必需的制品、数据、日志和 Systems Manager 资源。不要把长期 AWS 访问密钥复制到实例。
  • 强制 IMDSv2。仅宿主机工作流将响应 hop limit 保持为 1;容器网络可能需要经过明确审查的值。除非确有需要,不通过元数据暴露实例标签。
  • 加密 EBS 卷,尽可能把持久数据与一次性工作区分开,并检查每个卷的 DeleteOnTermination。实例存储中的数据应视为临时数据。
  • 使用专用 Unix 用户和限制性权限。不要使用 chmod -R 777、无密码部署钩子或多人可写的 checkout。

在获得授权的管理机上,对现有实例强制使用 IMDSv2:

INSTANCE_ID='replace-with-instance-id'

aws ec2 modify-instance-metadata-options 
  --instance-id "$INSTANCE_ID" 
  --http-tokens required 
  --http-endpoint enabled 
  --http-put-response-hop-limit 1 
  --instance-metadata-tags disabled

相关第一方资料包括 IMDS 配置EC2 IAM 角色安全组规则EBS 加密AWS Budgets

4. 修改前盘点运行中的宿主机

以普通实例用户运行。IMDSv2 令牌有效期很短,不会写入清单,并在读取两个非秘密元数据字段后清除。令牌头通过标准输入传给 curl,不出现在其参数列表中;但仍应将 shell 和宿主机视为可信环境。run-manifest/ 可能暴露敏感的基础设施细节,应保持私密。

set -euo pipefail
umask 077
mkdir -p run-manifest

cat /etc/os-release | tee run-manifest/os-release.txt
uname -m | tee run-manifest/cpu-architecture.txt
python3 --version 2>&1 | tee run-manifest/python-system.txt

metadata_base='http://169.254.169.254/latest'
metadata_token="$(curl --fail --silent --show-error 
  --request PUT 
  --header 'X-aws-ec2-metadata-token-ttl-seconds: 60' 
  "$metadata_base/api/token")"
for key in ami-id instance-type; do
  builtin printf 
    'header = "X-aws-ec2-metadata-token: %s"n' 
    "$metadata_token" 
    | curl --fail --silent --show-error 
      --config - 
      "$metadata_base/meta-data/$key" 
    | tee "run-manifest/$key.txt"
  printf 'n'
done
unset metadata_token

command -v nvidia-smi >/dev/null || {
  printf '%sn' 'nvidia-smi is missing; stop and repair the driver path.' >&2
  exit 1
}
nvidia-smi | tee run-manifest/nvidia-smi.txt
nvidia-smi 
  --query-gpu=name,pci.bus_id,driver_version,memory.total 
  --format=csv,noheader 
  | tee run-manifest/gpu-inventory.csv

if command -v nvcc >/dev/null; then
  nvcc --version | tee run-manifest/nvcc.txt
else
  printf '%sn' 'nvcc not installed; no local CUDA toolkit recorded.' 
    | tee run-manifest/nvcc.txt
fi

若选择标准 Ubuntu,应遵循当前 NVIDIA CUDA Linux 安装指南。使用其受支持的软件源/密钥环流程和安装前检查;不要恢复旧的 apt-key、未签名软件源或 HTTP 软件源命令。驱动变更后,如官方说明要求则重启,重新盘点,并在驱动/库不匹配时停止。

5. 创建隔离且锁定的 Python 环境

使用所选框架构建支持的 Python 版本。虚拟环境可以隔离 Python 包,但不能解决驱动或系统库兼容性。

在与生产环境相同的操作系统、CPU 架构、Python 次版本和软件包索引策略下生成 requirements.lock。锁定所有直接和传递依赖并加入验证过的哈希。使用前审查锁文件;不要在长期环境中直接输入没有版本的 pip install tensorflow numpy pandas jupyter

set -euo pipefail
umask 077

python3 -m venv .venv
.venv/bin/python -m pip install 
  --require-hashes 
  --only-binary=:all: 
  --requirement requirements.lock
.venv/bin/python -m pip check
.venv/bin/python -m pip freeze --all 
  | tee run-manifest/python-freeze.txt
sha256sum requirements.lock 
  | tee run-manifest/requirements-lock.sha256

在受支持的标准 Linux GPU 安装中,TensorFlow 当前官方 pip 路径使用 tensorflow[and-cuda] extra,但具体版本及所有解析依赖仍须锁定。DLAMI 则可能要求激活其文档指定的预构建环境。请查阅 TensorFlow pip 安装指南、Python 的 venv 文档和 pip 的可重复安装指南

6. 证明框架确实在 GPU 上执行

不要只运行 nvidia-smi,还要执行框架级运算。下面的 TensorFlow 冒烟测试会报告软件包构建、可见设备和设备详情,并要求一次矩阵乘法放置在 GPU 0:

import json
import platform

import tensorflow as tf

tf.random.set_seed(20260901)
gpus = tf.config.list_physical_devices("GPU")
report = {
    "python": platform.python_version(),
    "tensorflow": tf.__version__,
    "build": tf.sysconfig.get_build_info(),
    "gpus": [
        tf.config.experimental.get_device_details(device)
        for device in gpus
    ],
}
print(json.dumps(report, indent=2, default=str))

if not gpus:
    raise SystemExit("no GPU visible to TensorFlow")

with tf.device("/GPU:0"):
    left = tf.random.uniform((512, 512))
    right = tf.random.uniform((512, 512))
    product = tf.linalg.matmul(left, right)

print({"device": product.device, "shape": product.shape.as_list()})
if "GPU:0" not in product.device.upper():
    raise SystemExit(f"operation was not placed on GPU 0: {product.device}")

用锁定环境的解释器运行,并把输出与任务记录一同保存。GPU 可见并不能证明数值正确、模型收敛、多 GPU 通信、混合精度行为或显存足够;应再为真实负载增加一个小型代表性测试。

7. 让 Jupyter 保持本地且启用身份验证

Jupyter Server 可以执行代码,应把访问权限当作 shell 权限。它默认启用令牌身份验证。保持验证开启,不要把生成的令牌写入工单或日志,并且只监听回环地址:

set -euo pipefail
umask 077
mkdir -p notebooks
cd notebooks

../.venv/bin/jupyter lab 
  --no-browser 
  --ServerApp.ip=127.0.0.1 
  --ServerApp.port=8888 
  --ServerApp.port_retries=0 
  --ServerApp.open_browser=False

不要为 8888 添加安全组入站规则。从管理员机器使用下列任一种隧道。SSH 方式:

ssh -N 
  -L 127.0.0.1:8888:127.0.0.1:8888 
  ubuntu@replace-with-hostname

或者,完成 Session Manager 前置配置并在本机安装插件后:

INSTANCE_ID='replace-with-managed-instance-id'

aws ssm start-session 
  --target "$INSTANCE_ID" 
  --document-name AWS-StartPortForwardingSession 
  --parameters '{"portNumber":["8888"],"localPortNumber":["8888"]}'

在本机打开 http://127.0.0.1:8888/,输入只显示在实例终端中的令牌。如需长期密码认证,使用 Jupyter 的交互式密码命令,以便只保存哈希。绝不能同时禁用密码与令牌。参见 Jupyter Server 安全指南、其回环默认值与公网服务器警告,以及 AWS Session Manager 端口转发

8. 分离代码、密钥、数据和日志

  • 代码:使用普通用户拥有的 checkout。用 Git 记录精确 commit 和 submodule;不要通过未经审查的 post-receive 钩子部署。
  • 密钥:使用有限范围的实例角色和获批密钥存储。绝不提交密钥、把密钥放入 Notebook、烘焙进 AMI/容器或打印到盘点日志。
  • 输入数据:尽量只读挂载或下载。记录数据集版本和校验和,不记录私有对象 URL 或客户标识符。
  • 输出:按明确周期把 checkpoint 写入持久加密 EBS 卷或获批对象存储。停止使用实例存储的机器前,验证远端副本。
  • 日志:记录软件包、驱动、框架、命令、退出状态、时间戳和负载指标;集中保存前删除令牌、签名 URL、提示词、个人或受监管数据。

在不修改部署权限的情况下记录源码状态:

set -euo pipefail

git status --porcelain=v1
git rev-parse HEAD | tee run-manifest/source-commit.txt
git submodule status --recursive 
  | tee run-manifest/source-submodules.txt

提交查询命令见 Git `rev-parse`。工作区不干净是可复现性停止条件:昂贵任务启动前,应提交、丢弃或明确归档差异。

9. 把源码构建视为例外

除非源码补丁、不受支持的计算能力或编译器要求使源码构建不可避免,否则使用已发布 wheel、DLAMI 环境或不可变容器。构建 TensorFlow 前,根据其已测试构建配置和相应 Bazel 安装文档填完矩阵:

必须锁定记录值
TensorFlow 标签和完整 Git commit
Python 版本
Bazel 版本
编译器和标准库版本
NVIDIA 驱动、CUDA 工具包和 cuDNN
GPU 型号、架构和计算能力
基础 AMI 或容器摘要
构建参数、补丁、wheel 哈希和预期测试

不要假设当前 Bazel 可以构建旧 TensorFlow。任何兼容性单元格只有推测而没有文档依据时,都不要继续。

set -euo pipefail
SOURCE_REF='replace-with-reviewed-tag-or-commit'

git clone --filter=blob:none 
  https://github.com/tensorflow/tensorflow.git
git -C tensorflow fetch --tags --prune
git -C tensorflow checkout --detach "$SOURCE_REF"
git -C tensorflow status --porcelain=v1
git -C tensorflow rev-parse HEAD

在一次性卷或容器中构建,保存完整日志,在源码树之外的全新环境中验证 wheel,并保留其校验和。构建完成本身不能证明 GPU 路径或目标负载可用。

10. 维护私密的可复现清单

把机器可读清单与锁文件、测试输出和校验和保存在一起。不要公开账户 ID、实例 ID、内部主机名、存储桶名、对象路径、令牌或数据集标识符。

schema_version: 1
captured_at_utc: replace-with-iso-8601-time
aws:
  region: replace
  availability_zone: replace
  instance_type: replace
  purchase_model: replace
  ami_id: replace
  ami_name: replace
  cpu_architecture: replace
gpu:
  model: replace
  count: replace
  architecture: replace
  compute_capability: replace
  driver_version: replace
  driver_cuda_ceiling: replace
  toolkit_version: replace-or-not-installed
environment:
  python_version: replace
  framework_name: tensorflow
  framework_version: replace
  framework_build: replace
  requirements_lock_sha256: replace
source:
  commit: replace
  dirty: false
  container_digest: replace-or-not-used
verification:
  gpu_smoke_test: pass-or-fail
  workload_smoke_test: pass-or-fail
storage:
  root_delete_on_termination: replace
  durable_output_location: private-reference-only

清单包含系统事实,不包含凭据。敏感资源映射应在更严格的访问控制下单独保存。

11. 验证、停止、回滚与清理

开始付费工作前:

  • 确认预算、提醒收件人、实例价格模式,以及负责停止闲置容量的指定人员或自动化。
  • 确认安全组没有 Notebook 端口、已强制 IMDSv2、实例角色最小化、卷已加密,并按要求记录 SSH/SSM 访问。
  • 对照 EC2 型号/架构、uname -m、GPU 清单、计算能力、驱动、CUDA 工具包、锁定的 Python 包和框架构建元数据。
  • 运行 pip check、GPU 冒烟测试、小型负载测试、checkpoint 恢复和仅隧道 Jupyter 访问。
  • 确认日志与清单不含秘密或私有数据,且不依赖实例也能恢复持久输出。

工作结束时,刷新并验证 checkpoint,停止 Jupyter,复制清单和必要日志,然后从获得授权的管理机停止实例:

INSTANCE_ID='replace-with-instance-id'

aws ec2 stop-instances --instance-ids "$INSTANCE_ID"
aws ec2 wait instance-stopped --instance-ids "$INSTANCE_ID"

停止实例会结束实例计算费用,但不会消除所有费用:EBS、快照、公网 IPv4/Elastic IP 和其他服务仍可能计费。停止/启动会清除实例存储数据。终止时默认删除根 EBS 卷,其他 EBS 卷则取决于 DeleteOnTermination;执行前阅读 EC2 实例状态变化

只有在明确的人工关卡验证备份、恢复能力、卷标志、共享依赖和保留义务后才终止实例。回滚时保留不可变 AMI/容器引用、环境锁、源码 commit、清单、数据版本和已知良好测试输出;用它们重新构建,不要原地修补一台没有文档的机器。

12. 官方资料

13. 2017 年原文存档

以下是 source_export 的完整可见正文,用于保留来源。仅规范化行末空白;未增加、删除、修正或激活任何内容。过时的 HTTP 软件源、apt-key、全局可写钩子、未锁定安装列表和公网 Jupyter 链接只作为历史证据,不得执行。


1. Git server building.`

$ ssh-­keygen -­t rsa ­-C "user.email"`
 Modifying hooks:`

$ vim sample.git/hooks/post-receive`
 Sample code for hooks:`

#!/bin/sh

GIT_WORK_TREE=/home/ubuntu/Deployment/sample git checkout -f

chmod -R 777 /home/ubuntu/Deployment/sample`
2. Install bazel.
 1). Add Bazel distribution URI as a package source (one time setup)

echo "deb [arch=amd64] http://storage.googleapis.com/bazel-apt stable jdk1.8" | sudo tee /etc/apt/sources.list.d/bazel.list
curl https://bazel.build/bazel-release.pub.gpg | sudo apt-key add -


If you want to install the testing version of Bazel, replace stable with testing.2). Install and update Bazel

sudo apt-get update && sudo apt-get install bazel
 Once installed, you can upgrade to a newer version of Bazel with:

sudo apt-get upgrade bazel


3. Tensorflow compiling.
4. Python module installing.

  - tensorflow
  - numpy
  - pandas

5. Juypter.
 https://punchagan.muse-amuse.in/posts/create-a-public-jupyter-server-quickly.html

Leave a Reply