diff --git a/deployments/systemd/10-container-engines.conf b/deployments/systemd/10-container-engines.conf new file mode 100644 index 000000000..8504802bb --- /dev/null +++ b/deployments/systemd/10-container-engines.conf @@ -0,0 +1,33 @@ +# Copyright (c) NVIDIA CORPORATION. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Order the container engines after this service so that the first container +# started at boot does not race device node creation and CDI specification +# generation. +# +# This is shipped as a drop-in rather than as part of the unit so that it can be +# removed without overriding the whole unit: an empty file of the same name in +# /etc/systemd/system/nvidia-cdi-refresh.service.d/ takes precedence over this +# one and cancels it. Assigning an empty Before= in a drop-in does not reset the +# list, so an in-unit ordering could not be undone that way. +[Unit] +Before=docker.service containerd.service crio.service + +[Service] +# The unit is Type=oneshot, for which systemd defaults to +# TimeoutStartSec=infinity. Now that the container engines are ordered after it, +# bound the start so that a hung nvidia-smi cannot delay them indefinitely; on +# expiry the engines start and the CDI specification is refreshed on the next +# trigger. The value matches systemd's DefaultTimeoutStartSec. +TimeoutStartSec=90s diff --git a/packaging/debian/nvidia-container-toolkit-base.install b/packaging/debian/nvidia-container-toolkit-base.install index d30c63be0..86d50526e 100644 --- a/packaging/debian/nvidia-container-toolkit-base.install +++ b/packaging/debian/nvidia-container-toolkit-base.install @@ -5,3 +5,4 @@ nvidia-cdi-refresh.service /lib/systemd/system/ nvidia-cdi-refresh.path /lib/systemd/system/ nvidia-cdi-refresh.env /etc/nvidia-container-toolkit/ 99-nvidia-cdi-refresh.rules /lib/udev/rules.d/ +10-container-engines.conf /lib/systemd/system/nvidia-cdi-refresh.service.d/ diff --git a/packaging/debian/rules b/packaging/debian/rules index 90b3afb39..d8796e0ba 100755 --- a/packaging/debian/rules +++ b/packaging/debian/rules @@ -17,3 +17,4 @@ override_dh_fixperms: chmod 644 debian/$(shell dh_listpackages)/lib/systemd/system/nvidia-cdi-refresh.service || true chmod 644 debian/$(shell dh_listpackages)/lib/systemd/system/nvidia-cdi-refresh.path || true chmod 644 debian/$(shell dh_listpackages)/lib/udev/rules.d/99-nvidia-cdi-refresh.rules || true + chmod 644 debian/$(shell dh_listpackages)/lib/systemd/system/nvidia-cdi-refresh.service.d/10-container-engines.conf || true diff --git a/packaging/rpm/SPECS/nvidia-container-toolkit.spec b/packaging/rpm/SPECS/nvidia-container-toolkit.spec index daeb13246..d7c8ec1bd 100644 --- a/packaging/rpm/SPECS/nvidia-container-toolkit.spec +++ b/packaging/rpm/SPECS/nvidia-container-toolkit.spec @@ -22,6 +22,7 @@ Source8: nvidia-cdi-refresh.path Source9: nvidia-cdi-refresh.env Source10: 90-nvidia-container-toolkit.preset Source11: 99-nvidia-cdi-refresh.rules +Source12: 10-container-engines.conf %if 0%{?rhel} == 7 || 0%{?amzn} == 2 BuildRequires: systemd @@ -43,13 +44,14 @@ Requires: nvidia-container-toolkit-base == %{version}-%{release} Provides tools and utilities to enable GPU support in containers. %prep -cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} %{SOURCE7} %{SOURCE8} %{SOURCE9} %{SOURCE10} %{SOURCE11} . +cp %{SOURCE0} %{SOURCE1} %{SOURCE2} %{SOURCE3} %{SOURCE4} %{SOURCE5} %{SOURCE6} %{SOURCE7} %{SOURCE8} %{SOURCE9} %{SOURCE10} %{SOURCE11} %{SOURCE12} . %install mkdir -p %{buildroot}%{_bindir} mkdir -p %{buildroot}%{_unitdir} mkdir -p %{buildroot}%{_presetdir} mkdir -p %{buildroot}%{_udevrulesdir} +mkdir -p %{buildroot}%{_unitdir}/nvidia-cdi-refresh.service.d mkdir -p %{buildroot}%{_sysconfdir}/nvidia-container-toolkit install -m 755 -t %{buildroot}%{_bindir} nvidia-container-runtime-hook @@ -62,6 +64,7 @@ install -m 644 -t %{buildroot}%{_unitdir} nvidia-cdi-refresh.service install -m 644 -t %{buildroot}%{_unitdir} nvidia-cdi-refresh.path install -m 644 -t %{buildroot}%{_presetdir} 90-nvidia-container-toolkit.preset install -m 644 -t %{buildroot}%{_udevrulesdir} 99-nvidia-cdi-refresh.rules +install -m 644 -t %{buildroot}%{_unitdir}/nvidia-cdi-refresh.service.d 10-container-engines.conf install -m 644 -t %{buildroot}%{_sysconfdir}/nvidia-container-toolkit nvidia-cdi-refresh.env %post @@ -162,6 +165,7 @@ fi %{_unitdir}/nvidia-cdi-refresh.path %{_presetdir}/90-nvidia-container-toolkit.preset %{_udevrulesdir}/99-nvidia-cdi-refresh.rules +%{_unitdir}/nvidia-cdi-refresh.service.d/10-container-engines.conf %config(noreplace) %{_sysconfdir}/nvidia-container-toolkit/nvidia-cdi-refresh.env # The OPERATOR EXTENSIONS package consists of components that are required to enable GPU support in Kubernetes. diff --git a/tests/e2e/nvidia-cdi-refresh_test.go b/tests/e2e/nvidia-cdi-refresh_test.go index 13e894b28..0bee922ca 100644 --- a/tests/e2e/nvidia-cdi-refresh_test.go +++ b/tests/e2e/nvidia-cdi-refresh_test.go @@ -100,6 +100,17 @@ EOF fi ` + nvidiaCdiRefreshOrderingDropInInstalledTemplate = ` + if [ ! -f /lib/systemd/system/nvidia-cdi-refresh.service.d/10-container-engines.conf ]; then + echo "10-container-engines.conf is not installed" + exit 1 + fi + if ! systemctl show nvidia-cdi-refresh.service -p Before | grep -q docker.service; then + echo "nvidia-cdi-refresh.service is not ordered before docker.service" + exit 1 + fi + ` + nvidiaCdiRefreshFileExistsTemplate = ` # is /var/run/cdi/nvidia.yaml exists? and exit with 0 if it does not exist if [ ! -f /var/run/cdi/nvidia.yaml ]; then @@ -221,6 +232,11 @@ var _ = Describe("nvidia-cdi-refresh", Ordered, ContinueOnFailure, Label("system Expect(err).ToNot(HaveOccurred()) }) + It("should install the container engine ordering drop-in", func(ctx context.Context) { + _, _, err := systemdRunner.Run(nvidiaCdiRefreshOrderingDropInInstalledTemplate) + Expect(err).ToNot(HaveOccurred()) + }) + It("should generate the nvidia.yaml file", func(ctx context.Context) { _, _, err := systemdRunner.Run(nvidiaCdiRefreshFileExistsTemplate) Expect(err).ToNot(HaveOccurred()) @@ -275,6 +291,11 @@ var _ = Describe("nvidia-cdi-refresh", Ordered, ContinueOnFailure, Label("system Expect(err).ToNot(HaveOccurred()) }) + It("should install the container engine ordering drop-in", func(ctx context.Context) { + _, _, err := systemdRunner.Run(nvidiaCdiRefreshOrderingDropInInstalledTemplate) + Expect(err).ToNot(HaveOccurred()) + }) + It("should generate the nvidia.yaml file", func(ctx context.Context) { _, _, err := systemdRunner.Run(nvidiaCdiRefreshFileExistsTemplate) Expect(err).ToNot(HaveOccurred())