news 2026/9/18 10:22:57

使用 ZenML 在 AWS 上搭建生产级 Pipeline 栈:S3、SageMaker Pipelines 与 ECR 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 ZenML 在 AWS 上搭建生产级 Pipeline 栈:S3、SageMaker Pipelines 与 ECR 实战指南

使用 ZenML 在 AWS 上搭建生产级 Pipeline 栈:S3、SageMaker Pipelines 与 ECR 实战指南

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

导读:本文基于 ZenML 官方指南,完整讲解如何在 AWS 上搭建一套最小化生产级 ZenML 栈——用 Amazon S3 作为 Artifact Store(制品存储)、Amazon SageMaker Pipelines 作为 Orchestrator(编排器)、Amazon ECR 作为 Container Registry(容器镜像仓库),并通过最小权限 IAM 角色与 ZenML Service Connector 完成安全认证。读完本文,你将掌握从 IAM 权限设计、Service Connector 注册、三个栈组件注册到最终 Stack 组装与验证的完整流程,并了解 Warm Pools、成本控制与资源清理等生产实践。

为什么要在 AWS 上运行 ZenML

ZenML 是一个从 Pipeline 到 Agent 的一体化 AI 平台,其核心设计理念是"基础设施无关":你用 Python 定义 Pipeline 与 Step,剩下的计算、存储与容器管理交给背后的 Stack 组件完成。当本地开发无法满足生产需求时(共享制品、弹性计算、规模化运行),把 ZenML 栈迁移到 AWS 是最自然的选择。

通过本文搭建的 AWS 栈,你将获得三个关键能力:

  • S3 Artifact Store:集中存储并版本化 Pipeline 运行产生的数据制品,支持跨机器、跨团队共享运行结果;
  • SageMaker Pipelines Orchestrator:以声明式方式在 AWS 云端执行 Pipeline,充分利用 SageMaker 生态的调度、重试与监控能力;
  • ECR Container Registry:统一存放 Pipeline 步骤运行所需的 Docker 镜像。

在 ZenML 源码中,AWS 相关能力由 aws 集成模块 提供,它声明了sagemaker>=2.237.3,<3.0.0等依赖,并注册了aws容器镜像仓库、aws镜像构建器、aws部署器以及sagemaker编排器/Step 操作器等 5 个 Stack 组件 flavor(见 AWSIntegration.flavors)。

如果不想手动操作,ZenML 还提供浏览器内 Stack 部署向导、Stack 注册向导以及 AWS Terraform 模块等快捷方式,可在 infrastructure-deployment 文档 相关章节查阅。

前置条件

开始之前,请确认满足以下要求:

  • 一个具备 S3、SageMaker、ECR、ECS 相关权限的 AWS 账号;
  • 已安装 ZenML(参考 安装指南);
  • 已安装并配置好 AWS CLI,本地具备 AWS 凭证(参考 AWS CLI 官方安装文档)。

第 1 步:准备凭证与本地环境

1.1 选择 AWS 区域

在 AWS 控制台右上角选择一个部署区域,记下区域名(如us-east-1eu-west-2),后续所有命令与配置都需要使用它。

1.2 创建 IAM 角色

首先获取你的 AWS 账号 ID:

aws sts get-caller-identity --query Account --output text

这里获取的是登录 AWS 控制台所用的根账号 ID;如果你使用了更复杂的账号/IAM 角色体系,此命令可能不适用,需要自行确认根账号 ID。

然后创建名为assume-role-policy.json的信任策略文件,允许 ZenML 以该角色访问 AWS 资源:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<YOUR_ACCOUNT_ID>:root", "Service": "sagemaker.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

<YOUR_ACCOUNT_ID>替换为实际账号 ID,然后创建角色(示例角色名为zenml-role,可自行修改):

aws iam create-role --role-name zenml-role --assume-role-policy-document file://assume-role-policy.json

务必记录命令输出,尤其是Role ARN,后续注册 Orchestrator 时需要用execution_role参数引用它。

1.3 创建并挂载最小权限策略

与直接使用宽泛的 AWS 托管策略不同,这里遵循最小权限原则(least privilege),为 S3、ECR、SageMaker 分别创建自定义策略。

S3 策略(s3-policy.json——仅允许访问你的专属 Bucket:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:ListBucket", "s3:GetObject", "s3:PutObject", "s3:DeleteObject", "s3:GetBucketVersioning", "s3:ListBucketVersions", "s3:DeleteObjectVersion" ], "Resource": [ "arn:aws:s3:::your-bucket-name", "arn:aws:s3:::your-bucket-name/*" ] }, { "Effect": "Allow", "Action": "s3:ListAllMyBuckets", "Resource": "*" } ] }

ECR 策略(ecr-policy.json——仅覆盖容器镜像推送/拉取等操作:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ecr:BatchGetImage", "ecr:BatchCheckLayerAvailability", "ecr:GetDownloadUrlForLayer", "ecr:GetAuthorizationToken", "ecr:InitiateLayerUpload", "ecr:UploadLayerPart", "ecr:CompleteLayerUpload", "ecr:PutImage", "ecr:DescribeRepositories", "ecr:ListRepositories", "ecr:DescribeImages" ], "Resource": "*" } ] }

SageMaker 策略(sagemaker-policy.json——仅覆盖 Pipeline 与训练/处理作业相关操作,并附带受限的iam:PassRole条件:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "sagemaker:CreatePipeline", "sagemaker:StartPipelineExecution", "sagemaker:StopPipelineExecution", "sagemaker:DescribePipeline", "sagemaker:DescribePipelineExecution", "sagemaker:ListPipelineExecutions", "sagemaker:ListPipelineExecutionSteps", "sagemaker:UpdatePipeline", "sagemaker:DeletePipeline", "sagemaker:CreateProcessingJob", "sagemaker:DescribeProcessingJob", "sagemaker:StopProcessingJob", "sagemaker:CreateTrainingJob", "sagemaker:DescribeTrainingJob", "sagemaker:StopTrainingJob" ], "Resource": "*" }, { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/zenml-role", "Condition": { "StringEquals": { "iam:PassedToService": "sagemaker.amazonaws.com" } } } ] }

替换<YOUR_ACCOUNT_ID>your-bucket-name后,创建并挂载策略:

# 创建自定义策略 aws iam create-policy --policy-name ZenML-S3-Policy --policy-document file://s3-policy.json aws iam create-policy --policy-name ZenML-ECR-Policy --policy-document file://ecr-policy.json aws iam create-policy --policy-name ZenML-SageMaker-Policy --policy-document file://sagemaker-policy.json # 将策略挂载到角色 aws iam attach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-S3-Policy aws iam attach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-ECR-Policy aws iam attach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-SageMaker-Policy

1.4 安装 ZenML AWS 与 S3 集成

zenml integration install aws s3 -y

从源码角度看,aws 集成模块 的依赖包括sagemakerkubernetesaws-profile-managerpytz;其中kubernetes在卸载集成时会被保留(REQUIREMENTS_IGNORED_ON_UNINSTALL = ["kubernetes"]),因为 EKS 相关能力可能被其他组件共用。

第 2 步:在 ZenML 中创建 Service Connector

Service Connector 是 ZenML 统一管理云凭证的机制,它让 ZenML 与各个 Stack 组件可以用同一个 IAM 角色安全地认证 AWS。AWS 集成激活时会自动注册对应的 Service Connector 类型(见 AWSIntegration.activate)。

使用 CLI 注册 AWS Service Connector:

zenml service-connector register aws_connector \ --type aws \ --auth-method iam-role \ --role_arn=<ROLE_ARN> \ --region=<YOUR_REGION> \ --aws_access_key_id=<YOUR_ACCESS_KEY_ID> \ --aws_secret_access_key=<YOUR_SECRET_ACCESS_KEY>

<ROLE_ARN>替换为前面创建的 IAM 角色 ARN,<YOUR_REGION>替换为所选区域,并填入你的 AWS Access Key ID 与 Secret Access Key。

从源码可以确认,AWS Service Connector 支持多种认证方法(见 AWSAuthenticationMethods):

认证方法说明
implicit利用环境变量、AWS CLI 本地配置或 AWS 资源上附加的 IAM 角色隐式认证,最快捷但可复现性差
secret-key显式长生命周期 Access Key / Secret Key
sts-token显式 STS 临时凭证(Access Key + Secret Key + Session Token)
iam-role动态 AssumeRole 生成临时 STS 令牌(本文采用)
session-tokenSTS Session Token
federation-tokenFederation Token

其中iam-role方式通过调用 STSAssumeRoleAPI 生成默认有效期 1 小时的临时令牌(最短 15 分钟,最长可配置到 12 小时),并将令牌权限收敛到目标资源所需的最小集合,是安全性与便利性均衡的推荐选择。

第 3 步:创建 Stack 组件

3.1 Artifact Store(S3)

Artifact Store 用于存储和版本化 Pipeline 中流转的数据。如果还没有 S3 Bucket,先创建(Bucket 名称需全局唯一):

aws s3api create-bucket --bucket your-bucket-name

然后注册 S3 Artifact Store 并关联到刚才的 Service Connector:

zenml artifact-store register cloud_artifact_store -f s3 --path=s3://bucket-name --connector aws_connector

关于 S3 Artifact Store 的深入说明可参考 S3 组件指南。该文档补充了几个值得注意的细节:

  • --path是唯一必填参数,格式必须为s3://bucket-name
  • 推荐通过 Service Connector 认证(而不是隐式认证),否则部署在远端的 ZenML Server、Orchestrator、Step Operator 等组件将无法访问本地 AWS CLI 凭证,导致认证失败;
  • 高级参数client_kwargsconfig_kwargss3_additional_kwargs会以 JSON 字符串形式透传给底层s3fs/ botocore,可用于对接 MinIO、Ceph RGW 等 S3 兼容存储,例如:
zenml artifact-store register minio_store -f s3 \ --path='s3://minio_bucket' \ --client_kwargs='{"endpoint_url": "http://minio.cluster.local:9000", "region_name": "us-east-1"}'

从源码看,S3ArtifactStoreConfig 继承自BaseArtifactStoreConfigAuthenticationConfigMixin,除path外的所有属性都会传递给s3fs.S3FileSystem初始化。

3.2 Orchestrator(SageMaker Pipelines)

Orchestrator 是 Pipeline 的计算后端。SageMaker orchestrator 依赖SageMaker Domain——它是区域内所有 SageMaker 用户与资源的中央管理单元,提供 SSO 登录、隔离的用户工作区(含 JupyterLab、计算资源与持久化存储)。SageMaker Pipelines 是 Domain 生态的一部分,允许以声明式方式定义、执行和管理端到端 ML 工作流,因此 ZenML 的 SageMaker orchestrator 需要先创建 Domain 才能运行 Pipeline。

按 AWS 官方文档创建 SageMaker Domain(如已有可跳过),然后注册 orchestrator,这里需要用到之前记录的 IAM 角色 ARN 作为执行角色:

zenml orchestrator register sagemaker-orchestrator --flavor=sagemaker --region=<YOUR_REGION> --execution_role=<ROLE_ARN>

注意:SageMaker orchestrator 运行时不通过 Service Connector 直接认证,而是依赖 AWS CLI 配置或环境变量中的 AWS 凭证。

从源码可以更深入地理解这个组件的配置面。在 SagemakerOrchestratorConfig 中,除了必填的execution_role,还支持以下常用配置:

  • scheduler_role:供 EventBridge 服务扮演以启动 SageMaker Pipeline 的 IAM 角色 ARN,调度 Pipeline 时必填
  • aws_access_key_id/aws_secret_access_key:显式凭证(敏感字段),未提供时使用默认 AWS 配置;
  • aws_profile:指定 AWS 配置文件中 profile 名称;
  • aws_auth_role_arn:认证时先假设的中间 IAM 角色 ARN;
  • region:处理作业运行的区域,缺省时取 AWS 默认配置;
  • bucket:存放作业产物的 S3 Bucket 名称,缺省时自动创建sagemaker-{region}-{aws-account-id}格式的默认 Bucket。

此外,SagemakerOrchestratorSettings 提供了丰富的逐 Step 运行时设置:

设置项默认值说明
synchronousTrue是否阻塞客户端等待全部 Step 完成;False时异步返回,适合长时间生产 Pipeline
instance_typeml.m5.xlarge(训练)/ml.t3.medium(处理)Step 运行的 EC2 实例类型
volume_size_in_gb30Step 执行存储的 EBS 卷大小(1–16384 GB)
max_runtime_in_seconds86400(24 小时)作业最长运行时间,防止失控并控制成本(上限 432000 秒/5 天)
tags/pipeline_tags{}应用到 Processor/Estimator 或 Pipeline 上的标签
keep_alive_period_in_seconds300(5 分钟)Warm Pools 保活时间,仅对 TrainingStep 生效
use_training_stepNone(自动判断)是否使用 TrainingStep 类型;当output_data_s3_uri为 dict 或output_data_s3_mode != 'EndOfJob'时不允许使用
processor_args/estimator_args{}逐 Step 覆盖默认 Processor / Estimator 参数
environment{}传给容器的环境变量
input_data_s3_modeFile数据进入容器的方式(File/Pipe
input_data_s3_uri/output_data_s3_uri输入/输出数据的 S3 URI,支持字符串或字典
output_data_s3_modeEndOfJob数据上传 S3 的方式(EndOfJob/Continuous

值得一提的是,use_training_stepoutput_data_s3_urioutput_data_s3_mode之间存在校验约束:当启用 TrainingStep 时不允许使用 dict 形式的输出 URI,也不允许输出模式不是EndOfJob(见 SagemakerOrchestratorSettings.validate_model)。

3.3 Container Registry(ECR)

Container Registry 用于存放 Pipeline 的 Docker 镜像。先创建 ECR 仓库(如已有可跳过):

aws ecr create-repository --repository-name zenml --region <YOUR_REGION>

然后注册 ECR Container Registry 栈组件:

zenml container-registry register ecr-registry --flavor=aws --uri=<ACCOUNT_ID>.dkr.ecr.<YOUR_REGION>.amazonaws.com --connector aws-connector

注意 URI 格式为<ACCOUNT_ID>.dkr.ecr.<YOUR_REGION>.amazonaws.com。从源码看,AWSContainerRegistryConfig 有一个关键校验:URI不能包含/,一个合法示例是715803424592.dkr.ecr.us-east-1.amazonaws.com;同时该 flavor 要求关联类型为aws的 Service Connector(见其service_connector_requirements)。该集成还在aws集成包内提供了awsimage builder flavor(aws_image_builder_flavor.py),便于在云端构建镜像。

第 4 步:组装并激活 Stack

现在把三个组件组合成 Stack 并设为当前激活栈。CLI 方式:

export STACK_NAME=aws_stack zenml stack register ${STACK_NAME} -o ${ORCHESTRATOR_NAME} \ -a ${ARTIFACT_STORE_NAME} -c ${CONTAINER_REGISTRY_NAME} --set

${ORCHESTRATOR_NAME}${ARTIFACT_STORE_NAME}${CONTAINER_REGISTRY_NAME}替换为前面注册的组件名(如sagemaker-orchestratorcloud_artifact_storeecr-registry)。--set会把该 Stack 设为当前激活栈。如需加入其他栈组件(如 Step Operator、Model Deployer),也可以按需追加参数。

Dashboard 方式:在 ZenML Dashboard 的 Stack 创建表单中,将三个组件组合起来,同样可以自由添加其他组件。

第 5 步:验证——在 AWS 栈上运行第一个 Pipeline

定义一个最简单的 ZenML Pipeline:

from zenml import pipeline, step @step def hello_world() -> str: return "Hello from SageMaker!" @pipeline def aws_sagemaker_pipeline(): hello_world() if __name__ == "__main__": aws_sagemaker_pipeline()

将代码保存为run.py并执行:

python run.py

运行时,Pipeline 将使用 S3 存储制品、SageMaker Pipelines 执行编排、ECR 存放镜像。运行成功后,你可以在 ZenML Dashboard 中查看 Pipeline 运行记录与制品,也可以在 AWS 控制台检查 SageMaker Pipeline 执行情况、S3 Bucket 中的制品对象与 ECR 中的镜像。

生产实践与最佳实践

坚持 IAM 最小权限原则

本文提供的三份自定义策略就是最小权限的范例:S3 仅限定你的专属 Bucket、SageMaker 仅限 Pipeline 与训练/处理作业操作、ECR 仅限容器操作,并带上了正确的iam:PassRole条件。建议定期用 AWS CloudTrail 审计实际使用到的权限,及时移除多余授权。

使用 AWS 资源标签

为所有 Pipeline 相关资源打上统一标签,便于成本分摊与清理。例如给 S3 Bucket 打标签:

aws s3api put-bucket-tagging --bucket your-bucket-name --tagging 'TagSet=[{Key=Project,Value=ZenML},{Key=Environment,Value=Production}]'

标签同样可以直接配置到 SageMaker 组件上:SagemakerOrchestratorSettingstagspipeline_tags字段会把标签应用到对应的 Processor/Estimator 与 Pipeline 上,与 AWS 原生标签体系打通。

落实成本管理

使用 AWS Cost Explorer 与 AWS Budgets 监控支出。先创建预算配置文件budget-config.json

{ "BudgetLimit": { "Amount": "100", "Unit": "USD" }, "BudgetName": "ZenML Monthly Budget", "BudgetType": "COST", "CostFilters": { "TagKeyValue": [ "user:Project$ZenML" ] }, "CostTypes": { "IncludeTax": true, "IncludeSubscription": true, "UseBlended": false }, "TimeUnit": "MONTHLY" }

再创建预算,并按需创建成本分类标签:

aws budgets create-budget --account-id your-account-id --budget file://budget-config.json aws ce create-cost-category-definition --name ZenML-Projects --rules-version 1 --rules file://rules.json

为 SageMaker Pipelines 启用 Warm Pools

Warm Pools 能让计算实例在作业结束后保持"温热"状态,显著缩短 Step 启动时间,特别适合迭代式开发或高频运行的 Pipeline。使用SagemakerOrchestratorSettings开启:

from zenml.integrations.aws.orchestrators.sagemaker import SagemakerOrchestratorSettings sagemaker_orchestrator_settings = SagemakerOrchestratorSettings( keep_alive_period_in_seconds = 300, # 5 分钟,默认值 )

如上源码表所示,keep_alive_period_in_seconds默认即 300 秒:每次作业完成后实例保持 5 分钟,期间发起的后续作业可直接复用,从而跳过冷启动。

建立可靠的备份策略

为关键数据与配置定期备份。S3 上可开启版本控制(Bucket 版本控制),并考虑启用跨区域复制(CRR)以实现灾难恢复。注意,S3 Artifact Store 的最小权限策略中已包含s3:GetBucketVersionings3:ListBucketVersionss3:DeleteObjectVersion等版本相关权限,为版本化备份做好了权限准备。

清理资源

警告:以下命令具有破坏性,请确认不再需要相关资源后再执行,避免产生不必要的费用。

按顺序清理(务必在创建资源的同一区域执行):

# 删除 S3 Bucket aws s3 rm s3://your-bucket-name --recursive aws s3api delete-bucket --bucket your-bucket-name # 删除 SageMaker Domain aws sagemaker delete-domain --domain-id <DOMAIN_ID> # 删除 ECR 仓库 aws ecr delete-repository --repository-name zenml-repository --force # 从 IAM 角色分离自定义策略 aws iam detach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-S3-Policy aws iam detach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-ECR-Policy aws iam detach-role-policy --role-name zenml-role --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-SageMaker-Policy # 删除自定义策略 aws iam delete-policy --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-S3-Policy aws iam delete-policy --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-ECR-Policy aws iam delete-policy --policy-arn arn:aws:iam::<YOUR_ACCOUNT_ID>:policy/ZenML-SageMaker-Policy # 删除 IAM 角色 aws iam delete-role --role-name zenml-role

总结

本文完整走通了"最小权限 IAM 角色 → ZenML Service Connector → 三个栈组件 → Stack 组装 → 运行验证"的 AWS 生产栈搭建闭环。这个栈带来的核心收益包括:

  • 可扩展性:借助 AWS 的弹性能力承载大规模 ML 负载;
  • 可复现性:版本化制品与容器化环境确保 Pipeline 结果可复现;
  • 协作性:集中式 Stack 与共享资源让团队成员高效协作;
  • 灵活性:可按需定制与扩展栈组件。

进一步探索的方向:阅读 生产指南 学习生产级 Pipeline 的部署与管理最佳实践;查阅 组件指南 了解 ZenML 与 MLOps 生态中其他工具的集成方式;通过 AWS 集成模块 与 SageMaker orchestrator 实现 深入理解底层实现,进一步定制自己的 AWS 栈。

【免费下载链接】zenmlZenML 🙏: One AI Platform from Pipelines to Agents. https://zenml.io.项目地址: https://gitcode.com/GitHub_Trending/ze/zenml

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 10:21:20

申通快递3亿诉讼案背后的桐庐帮商业江湖

1. 事件背景与核心人物关系梳理2023年8月&#xff0c;国内快递行业爆出重大商业纠纷——申通快递实际控制人陈小英被其前夫奚春阳提起诉讼&#xff0c;索赔金额高达近3亿元人民币。这起案件之所以引发业界广泛关注&#xff0c;不仅因为涉案金额巨大&#xff0c;更因其背后牵扯出…

作者头像 李华
网站建设 2026/9/18 10:21:12

Gumroad 新手怎么上架第一件商品

Gumroad 新手怎么上架第一件商品 【免费下载链接】gumroad See what sticks 项目地址: https://gitcode.com/GitHub_Trending/gumr/gumroad 你手上有一套录好的课程想卖&#xff0c;但卡在三件事上&#xff1a;文件放在哪、钱打给谁、货怎么交。Gumroad 就是干这个的&am…

作者头像 李华
网站建设 2026/9/18 10:20:51

FPGA以太网UDP协议栈实战:verilog-ethernet仿真到上板

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 10:18:32

Colibri:面向MoE模型的C语言级轻量推理引擎

1. 项目概述&#xff1a;Colibri 是什么&#xff0c;它解决的不是“跑模型”而是“让模型在真实设备上稳住”Colibri 这个名字乍一听像某种蜂鸟——轻盈、敏捷、高频振翅。这恰恰是它最核心的设计隐喻。它不是另一个大语言模型&#xff08;LLM&#xff09;本体&#xff0c;也不…

作者头像 李华
网站建设 2026/9/18 10:18:26

Jetson Xavier NX 刷 JetPack 5.1.7 到 NVMe

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 10:16:56

用Draw.io快速画出专业微服务架构图:分层布局与图层复用全攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华