Skip to content

Commit

Permalink
fix(ai): 多平台镜像上传到远程镜像仓库问题 (#1254)
Browse files Browse the repository at this point in the history
### 背景

在 #1181 中,通过 `nerdctl -n k8s.io push --all-platforms
`可以解决远程单一平台大镜像推送成功的问题,但是由此引入了新的问题

通过对当前系统中containerd容器运行时拉取和推送的命令进行进一步验证:
```
nerdctl -n k8s.io pull externalImage
nerdctl -n k8s.io tag externalImage taggedImage
nerdctl -n k8s.io push --all-platforms taggedImage
```
对于一个多平台镜像如图1中的jupyter/pyspark-notebook:ubuntu-22.04
,如果在拉取时无法获取每一个平台的镜像如图2(不符合当前平台的SIZE为0)

![image](https://github.com/PKUHPC/SCOW/assets/43978285/c7cc7dbd-a10f-499f-a85e-804fe10e7a71)

![image](https://github.com/PKUHPC/SCOW/assets/43978285/99871146-7ef2-4a70-8d1b-a6cede6fe29a)
那么推送时指定 --all-platforms会报错失败,但是不指定 --all-platforms
,会只进行推送当前使用当前节点平台的镜像,没有问题

- 如果像图2混入了他平台sha256层数据的情况,即使拉取时指定平台pull --platform
linux.amd64也一定会在nerdclt images中查看到多条平台的镜像,这个时候--all-platforms不会报错

-
单平台镜像无论在push中是否添加全平台或指定平台都没有这种问题,提交作业时即使使用了多平台镜像,在容器中commit时会按当前节点平台架构commit为单平台镜像,也不会有问题

**解决方法**
1.**在pull中加入--all-platforms可以保证拉取时获取每一个平台的镜像,使无论单平台还是多平台通过push
--all-platforms成功,但是这与目前时实际大多数单平台架构的模式不符,容易造成冗余**

2.**将之前添加的nerdctl -n k8s.io push --all-platforms taggedImage修改为nerdctl
-n k8s.io push taggedImage 尽量保证单平台/多平台镜像 在nerdctl
images下都只有当前系统平台,单一平台的数据**

1虽然满足了 #1181 问题的解决,但是经过进一步检查在nerdctl
images下也没有混入其他平台数据的情况,#1181问题已无法复现,通过推测可能由于平台数据不纯净混入了多平台的层数据或者由于nerdctl清楚缓存等机制造成了
镜像的当前平台层数据缺失


### 修改 

**此PR按上述解决方法2进行修改,删除上一次添加的 push 中的--all-platforms**
同时在push失败时尽量删除上一次拉取和tag的镜像,后台logger提示管理员检查镜像列表,尽量保证镜像列表环境纯净
但是对于# 1181问题如果再次出现需补充测试进一步验证

修改后确认如果Push失败会删除拉取到本地的镜像和tag后的镜像

![image](https://github.com/PKUHPC/SCOW/assets/43978285/0fa33a9d-d7e8-4f91-b4f8-1e3d7606d63d)
  • Loading branch information
piccaSun authored May 16, 2024
1 parent daf3885 commit 0957f1a
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-geese-rest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@scow/ai": patch
---

修改多平台镜像由于只在 nerdclt push 命令下指定 --all-platforms 导致其他平台层数据缺失无法推送的问题
2 changes: 1 addition & 1 deletion apps/ai/src/server/trpc/route/image/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export const createImage = procedure
throw new Error(`Image ${name}:${tag} create failed: image is not a tar file`);
}

// 本地镜像时docker加载镜像
// 本地镜像时加载镜像
localImageUrl = await getLoadedImage({
ssh,
clusterId: processClusterId,
Expand Down
18 changes: 14 additions & 4 deletions apps/ai/src/server/utils/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,20 @@ export async function pushImageToHarbor({
await loggedExec(ssh, logger, true, command, ["tag", localImageUrl, harborImageUrl]);

// push 镜像至harbor
// 运行时为 containerd 时,需添加 --all-platforms 确保多平台镜像可以正确推送
await loggedExec(ssh, logger, true, command,
runtime === k8sRuntime.containerd ?
["push", "--all-platforms", harborImageUrl] : ["push", harborImageUrl]);
await loggedExec(ssh, logger, true, command, ["push", harborImageUrl])
.catch(async (e) => {

logger.error(e, "Can not push image to the external repository. "
+ "Please verify if the image list includes unnecessary multi-platform image data.");
// 为了避免可能由于错误镜像缓存引起的问题,清除localImage,taggedImage
logger.info("Deleting the locally pulled image and the tagged image ...");
await loggedExec(ssh, logger, true, command, ["rmi", localImageUrl]);
await loggedExec(ssh, logger, true, command, ["rmi", harborImageUrl]);
throw new TRPCError({
code: "CONFLICT",
message: `Can not push image to the external repository. : ${e}`,
});
}); ;

// 清除本地镜像
await loggedExec(ssh, logger, true, command, ["rmi", harborImageUrl]);
Expand Down

0 comments on commit 0957f1a

Please sign in to comment.