Skip to content

Commit 119a2df

Browse files
committed
Extract deb and rpm packages to single image
This change swithces to using a single image for the NVIDIA Container Toolkit contianer. Here the contents of the architecture-specific deb and rpm packages are extracted to a known root. These contents can then be installed using the updated installation mechanism which has been updated to detect the source root based on the packaging type. Signed-off-by: Evan Lezar <[email protected]>
1 parent de3d736 commit 119a2df

File tree

11 files changed

+223
-259
lines changed

11 files changed

+223
-259
lines changed

.github/workflows/image.yaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ jobs:
4949
- ispr: true
5050
target: centos8-ppc64le
5151
fail-fast: false
52-
52+
5353
steps:
5454
- uses: actions/checkout@v4
5555
name: Check out code
@@ -80,14 +80,8 @@ jobs:
8080
strategy:
8181
matrix:
8282
dist:
83-
- ubuntu20.04
8483
- ubi8
8584
- packaging
86-
ispr:
87-
- ${{ github.ref_name != 'main' && !startsWith( github.ref_name, 'release-' ) }}
88-
exclude:
89-
- ispr: true
90-
dist: ubi8
9185
needs: packages
9286
steps:
9387
- uses: actions/checkout@v4

cmd/nvidia-ctk-installer/main.go

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/NVIDIA/nvidia-container-toolkit/cmd/nvidia-ctk-installer/toolkit"
1515
"github.com/NVIDIA/nvidia-container-toolkit/internal/info"
1616
"github.com/NVIDIA/nvidia-container-toolkit/internal/logger"
17+
"github.com/NVIDIA/nvidia-container-toolkit/internal/lookup"
1718
)
1819

1920
const (
@@ -36,10 +37,11 @@ var signalReceived = make(chan bool, 1)
3637
type options struct {
3738
toolkitInstallDir string
3839

39-
noDaemon bool
40-
runtime string
41-
pidFile string
42-
sourceRoot string
40+
noDaemon bool
41+
runtime string
42+
pidFile string
43+
sourceRoot string
44+
packageType string
4345

4446
toolkitOptions toolkit.Options
4547
runtimeOptions runtime.Options
@@ -123,11 +125,17 @@ func (a app) build() *cli.App {
123125
EnvVars: []string{"TOOLKIT_INSTALL_DIR", "ROOT"},
124126
},
125127
&cli.StringFlag{
126-
Name: "source-root",
127-
Value: "/",
128-
Usage: "The folder where the required toolkit artifacts can be found",
128+
Name: "toolkit-source-root",
129+
Usage: "The folder where the required toolkit artifacts can be found. If this is not specified, the path /artifacts/{{ .ToolkitPackageType }} is used where ToolkitPackageType is the resolved package type",
129130
Destination: &options.sourceRoot,
130-
EnvVars: []string{"SOURCE_ROOT"},
131+
EnvVars: []string{"TOOLKIT_SOURCE_ROOT"},
132+
},
133+
&cli.StringFlag{
134+
Name: "toolkit-package-type",
135+
Usage: "specify the package type to use for the toolkit. One of ['deb', 'rpm', 'auto', '']. If 'auto' or '' are used, the type is inferred automatically.",
136+
Value: "auto",
137+
Destination: &options.packageType,
138+
EnvVars: []string{"TOOLKIT_PACKAGE_TYPE"},
131139
},
132140
&cli.StringFlag{
133141
Name: "pid-file",
@@ -145,6 +153,15 @@ func (a app) build() *cli.App {
145153
}
146154

147155
func (a *app) Before(c *cli.Context, o *options) error {
156+
if o.sourceRoot == "" {
157+
sourceRoot, err := a.resolveSourceRoot(o.runtimeOptions.HostRootMount, o.packageType)
158+
if err != nil {
159+
return fmt.Errorf("failed to resolve source root: %v", err)
160+
}
161+
a.logger.Infof("Resolved source root to %v", sourceRoot)
162+
o.sourceRoot = sourceRoot
163+
}
164+
148165
a.toolkit = toolkit.NewInstaller(
149166
toolkit.WithLogger(a.logger),
150167
toolkit.WithSourceRoot(o.sourceRoot),
@@ -277,3 +294,35 @@ func (a *app) shutdown(pidFile string) {
277294
a.logger.Warningf("Unable to remove pidfile: %v", err)
278295
}
279296
}
297+
298+
func (a *app) resolveSourceRoot(hostRoot string, packageType string) (string, error) {
299+
resolvedPackageType, err := a.resolvePackageType(hostRoot, packageType)
300+
if err != nil {
301+
return "", err
302+
}
303+
switch resolvedPackageType {
304+
case "deb":
305+
return "/artifacts/deb", nil
306+
case "rpm":
307+
return "/artifacts/rpm", nil
308+
default:
309+
return "", fmt.Errorf("invalid package type: %v", resolvedPackageType)
310+
}
311+
}
312+
313+
func (a *app) resolvePackageType(hostRoot string, packageType string) (rPackageTypes string, rerr error) {
314+
if packageType != "" && packageType != "auto" {
315+
return packageType, nil
316+
}
317+
318+
locator := lookup.NewExecutableLocator(a.logger, hostRoot)
319+
if candidates, err := locator.Locate("/usr/bin/rpm"); err == nil && len(candidates) > 0 {
320+
return "rpm", nil
321+
}
322+
323+
if candidates, err := locator.Locate("/usr/bin/dpkg"); err == nil && len(candidates) > 0 {
324+
return "deb", nil
325+
}
326+
327+
return "deb", nil
328+
}

cmd/nvidia-ctk-installer/main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ swarm-resource = ""
418418
"--driver-root-ctr-path=" + hostRoot,
419419
"--pid-file=" + filepath.Join(testRoot, "toolkit.pid"),
420420
"--restart-mode=none",
421-
"--source-root=" + filepath.Join(artifactRoot, "deb"),
421+
"--toolkit-source-root=" + filepath.Join(artifactRoot, "deb"),
422422
}
423423

424424
err := app.Run(append(testArgs, tc.args...))

cmd/nvidia-ctk-installer/toolkit/installer/installer.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,16 @@ var _ Installer = (*toolkitInstaller)(nil)
4747

4848
// New creates a toolkit installer with the specified options.
4949
func New(opts ...Option) (Installer, error) {
50-
t := &toolkitInstaller{}
50+
t := &toolkitInstaller{
51+
sourceRoot: "/",
52+
}
5153
for _, opt := range opts {
5254
opt(t)
5355
}
5456

5557
if t.logger == nil {
5658
t.logger = logger.New()
5759
}
58-
if t.sourceRoot == "" {
59-
t.sourceRoot = "/"
60-
}
6160
if t.artifactRoot == nil {
6261
artifactRoot, err := newArtifactRoot(t.logger, t.sourceRoot)
6362
if err != nil {

cmd/nvidia-ctk-installer/toolkit/toolkit.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ func Flags(opts *Options) []cli.Flag {
215215

216216
// An Installer is used to install the NVIDIA Container Toolkit from the toolkit container.
217217
type Installer struct {
218-
logger logger.Interface
218+
logger logger.Interface
219+
219220
sourceRoot string
220221
// toolkitRoot specifies the destination path at which the toolkit is installed.
221222
toolkitRoot string

deployments/container/Dockerfile

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
ARG GOLANG_VERSION=x.x.x
16+
ARG VERSION="N/A"
17+
18+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubi8 AS build
19+
20+
RUN yum install -y \
21+
wget make git gcc \
22+
&& \
23+
rm -rf /var/cache/yum/*
24+
25+
ARG GOLANG_VERSION=x.x.x
26+
RUN set -eux; \
27+
\
28+
arch="$(uname -m)"; \
29+
case "${arch##*-}" in \
30+
x86_64 | amd64) ARCH='amd64' ;; \
31+
ppc64el | ppc64le) ARCH='ppc64le' ;; \
32+
aarch64 | arm64) ARCH='arm64' ;; \
33+
*) echo "unsupported architecture" ; exit 1 ;; \
34+
esac; \
35+
wget -nv -O - https://storage.googleapis.com/golang/go${GOLANG_VERSION}.linux-${ARCH}.tar.gz \
36+
| tar -C /usr/local -xz
37+
38+
39+
ENV GOPATH=/go
40+
ENV PATH=$GOPATH/bin:/usr/local/go/bin:$PATH
41+
42+
WORKDIR /build
43+
COPY . .
44+
45+
RUN mkdir /artifacts
46+
ARG VERSION="N/A"
47+
ARG GIT_COMMIT="unknown"
48+
RUN make PREFIX=/artifacts cmd-nvidia-ctk-installer
49+
50+
# The packaging stage collects the deb and rpm packages built for supported
51+
# architectures.
52+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubi8 AS packaging
53+
54+
ARG ARTIFACTS_ROOT
55+
COPY ${ARTIFACTS_ROOT} /artifacts/packages/
56+
57+
WORKDIR /artifacts/packages
58+
59+
# build-args are added to the manifest.txt file below.
60+
ARG PACKAGE_VERSION
61+
ARG GIT_BRANCH
62+
ARG GIT_COMMIT
63+
ARG GIT_COMMIT_SHORT
64+
ARG SOURCE_DATE_EPOCH
65+
ARG VERSION
66+
67+
# Create a manifest.txt file with the absolute paths of all deb and rpm packages in the container
68+
RUN echo "#IMAGE_EPOCH=$(date '+%s')" > /artifacts/manifest.txt && \
69+
env | sed 's/^/#/g' >> /artifacts/manifest.txt && \
70+
find /artifacts/packages -iname '*.deb' -o -iname '*.rpm' >> /artifacts/manifest.txt
71+
72+
RUN mkdir /licenses && mv /NGC-DL-CONTAINER-LICENSE /licenses/NGC-DL-CONTAINER-LICENSE
73+
74+
# The debpackages stage is used to extract the contents of deb packages.
75+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubuntu20.04 AS debpackages
76+
77+
ARG TARGETARCH
78+
ARG PACKAGE_DIST_DEB=ubuntu18.04
79+
80+
COPY --from=packaging /artifacts/packages/${PACKAGE_DIST_DEB} /deb-packages
81+
82+
RUN mkdir -p /artifacts/deb
83+
RUN set -eux; \
84+
\
85+
case "${TARGETARCH}" in \
86+
x86_64 | amd64) ARCH='amd64' ;; \
87+
ppc64el | ppc64le) ARCH='ppc64le' ;; \
88+
aarch64 | arm64) ARCH='arm64' ;; \
89+
*) echo "unsupported architecture" ; exit 1 ;; \
90+
esac; \
91+
for p in $(ls /deb-packages/${ARCH}/*.deb); do dpkg-deb -xv $p /artifacts/deb/; done
92+
93+
# The rpmpackages stage is used to extract the contents of the rpm packages.
94+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubi8 AS rpmpackages
95+
RUN dnf install -y cpio
96+
97+
ARG TARGETARCH
98+
ARG PACKAGE_DIST_RPM=centos7
99+
100+
COPY --from=packaging /artifacts/packages/${PACKAGE_DIST_RPM} /rpm-packages
101+
102+
RUN mkdir -p /artifacts/rpm
103+
RUN set -eux; \
104+
\
105+
case "${TARGETARCH}" in \
106+
x86_64 | amd64) ARCH='x86_64' ;; \
107+
ppc64el | ppc64le) ARCH='ppc64le' ;; \
108+
aarch64 | arm64) ARCH='aarch64' ;; \
109+
*) echo "unsupported architecture" ; exit 1 ;; \
110+
esac; \
111+
for p in $(ls /rpm-packages/${ARCH}/*.rpm); do rpm2cpio $p | cpio -idmv -D /artifacts/rpm; done
112+
113+
# The artifacts image serves as an intermediate stage to collect the artifacts
114+
# From the previous stages:
115+
# - The extracted deb packages
116+
# - The extracted rpm packages
117+
# - The nvidia-ctk-installer binary
118+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubi8 AS artifacts
119+
120+
COPY --from=rpmpackages /artifacts/rpm /artifacts/rpm
121+
COPY --from=debpackages /artifacts/deb /artifacts/deb
122+
COPY --from=build /artifacts/bin /artifacts/build
123+
124+
FROM nvcr.io/nvidia/cuda:12.8.1-base-ubi8
125+
126+
ENV NVIDIA_DISABLE_REQUIRE="true"
127+
ENV NVIDIA_VISIBLE_DEVICES=void
128+
ENV NVIDIA_DRIVER_CAPABILITIES=utility
129+
130+
COPY --from=artifacts /artifacts/rpm /artifacts/rpm
131+
COPY --from=artifacts /artifacts/deb /artifacts/deb
132+
COPY --from=artifacts /artifacts/build /work
133+
134+
WORKDIR /work
135+
ENV PATH=/work:$PATH
136+
137+
ARG VERSION
138+
LABEL io.k8s.display-name="NVIDIA Container Runtime Config"
139+
LABEL name="NVIDIA Container Runtime Config"
140+
LABEL vendor="NVIDIA"
141+
LABEL version="${VERSION}"
142+
LABEL release="N/A"
143+
LABEL summary="Automatically Configure your Container Runtime for GPU support."
144+
LABEL description="See summary"
145+
146+
RUN mkdir /licenses && mv /NGC-DL-CONTAINER-LICENSE /licenses/NGC-DL-CONTAINER-LICENSE
147+
148+
ENTRYPOINT ["/work/nvidia-ctk-installer"]

deployments/container/Dockerfile.packaging

Lines changed: 0 additions & 38 deletions
This file was deleted.

0 commit comments

Comments
 (0)