Skip to content

Commit cd3fe4f

Browse files
deckhouse-BOaTswainyaroslavborbatdiafour
authored
Backport: feat(core): add dvcr config for containerd v2 (#1409)
feat(core): add dvcr config for containerd v2 (#1395) - Support containerd v2 config layout: change NGC with dvcr registry. - Support erofs tar unpacking: erofs strictly requires end-of-file tar marker. - Fix creation time and add common fields in generated DVCR images manifests. --------- Signed-off-by: Yaroslav Borbat <[email protected]> Signed-off-by: Ivan Mikheykin <[email protected]> Co-authored-by: Yaroslav Borbat <[email protected]> Co-authored-by: Ivan Mikheykin <[email protected]>
1 parent 1b71aa0 commit cd3fe4f

File tree

3 files changed

+135
-10
lines changed

3 files changed

+135
-10
lines changed

images/dvcr-artifact/pkg/registry/registry.go

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ import (
3131
"os/exec"
3232
"path"
3333
"strings"
34+
"time"
3435

3536
"github.com/google/go-containerregistry/pkg/authn"
3637
"github.com/google/go-containerregistry/pkg/name"
38+
"github.com/google/go-containerregistry/pkg/v1"
3739
"github.com/google/go-containerregistry/pkg/v1/empty"
3840
"github.com/google/go-containerregistry/pkg/v1/mutate"
3941
"github.com/google/go-containerregistry/pkg/v1/remote"
@@ -54,6 +56,11 @@ const (
5456
imageLabelSourceImageSize = "source-image-size"
5557
imageLabelSourceImageVirtualSize = "source-image-virtual-size"
5658
imageLabelSourceImageFormat = "source-image-format"
59+
imageLabelEROFSCompatible = "erofs-compatible-layers"
60+
imageArchitecture = "amd64"
61+
imageOS = "linux"
62+
imageAuthor = "DVCR client"
63+
imageWorkingDir = "/"
5764
)
5865

5966
type ImportRes struct {
@@ -171,16 +178,36 @@ func (p DataProcessor) inspectAndStreamSourceImage(
171178
) error {
172179
var tarWriter *tar.Writer
173180
{
181+
now := time.Now()
182+
174183
tarWriter = tar.NewWriter(pipeWriter)
184+
dirHeader := &tar.Header{
185+
Name: "disk",
186+
Mode: 0o755,
187+
Uid: 107,
188+
Gid: 107,
189+
AccessTime: now,
190+
ChangeTime: now,
191+
Typeflag: tar.TypeDir,
192+
}
193+
if err := tarWriter.WriteHeader(dirHeader); err != nil {
194+
return fmt.Errorf("error writing tar header [disk]: %w", err)
195+
}
196+
197+
imagePath := path.Join("disk", sourceImageFilename)
175198
header := &tar.Header{
176-
Name: path.Join("disk", sourceImageFilename),
177-
Size: int64(sourceImageSize),
178-
Mode: 0o644,
179-
Typeflag: tar.TypeReg,
199+
Name: imagePath,
200+
Size: int64(sourceImageSize),
201+
Mode: 0o644,
202+
Uid: 107,
203+
Gid: 107,
204+
AccessTime: now,
205+
ChangeTime: now,
206+
Typeflag: tar.TypeReg,
180207
}
181208

182209
if err := tarWriter.WriteHeader(header); err != nil {
183-
return fmt.Errorf("error writing tar header: %w", err)
210+
return fmt.Errorf("error writing tar header [%s]: %w", imagePath, err)
184211
}
185212
}
186213

@@ -247,6 +274,12 @@ func (p DataProcessor) inspectAndStreamSourceImage(
247274
}
248275
}
249276

277+
// Append end-of-file marker for tar archive.
278+
err = writeTarEOFMarker(pipeWriter)
279+
if err != nil {
280+
return fmt.Errorf("adding tar EOF marker: %w", err)
281+
}
282+
250283
klog.Infoln("Source streaming completed")
251284

252285
return nil
@@ -305,7 +338,8 @@ func (p DataProcessor) uploadLayersAndImage(
305338

306339
klog.Infof("Got image info: virtual size: %d, format: %s", informer.GetVirtualSize(), informer.GetFormat())
307340

308-
cnf.Config.Labels = map[string]string{}
341+
populateCommonConfigFields(cnf)
342+
309343
cnf.Config.Labels[imageLabelSourceImageVirtualSize] = fmt.Sprintf("%d", informer.GetVirtualSize())
310344
cnf.Config.Labels[imageLabelSourceImageSize] = fmt.Sprintf("%d", sourceImageSize)
311345
cnf.Config.Labels[imageLabelSourceImageFormat] = informer.GetFormat()
@@ -328,6 +362,29 @@ func (p DataProcessor) uploadLayersAndImage(
328362
return nil
329363
}
330364

365+
// populateCommonConfigFields adds some required fields according to the document:
366+
// https://github.com/opencontainers/image-spec/blob/main/config.md
367+
func populateCommonConfigFields(cnf *v1.ConfigFile) {
368+
now := time.Now().UTC()
369+
cnf.Created = v1.Time{Time: now}
370+
cnf.Architecture = imageArchitecture
371+
cnf.OS = imageOS
372+
cnf.Author = imageAuthor
373+
374+
// Initialize labels, add label to distinguish from previous images with non-complete tar archives.
375+
cnf.Config.Labels = make(map[string]string)
376+
cnf.Config.Labels[imageLabelEROFSCompatible] = "true"
377+
378+
cnf.Config.WorkingDir = imageWorkingDir
379+
380+
cnf.History = append(cnf.History, v1.History{
381+
Author: imageAuthor,
382+
Created: v1.Time{Time: now},
383+
Comment: "streamed from the datasource",
384+
EmptyLayer: false,
385+
})
386+
}
387+
331388
func getImageInfo(ctx context.Context, sourceReader io.ReadCloser) (ImageInfo, error) {
332389
formatSourceReaders, err := importer.NewFormatReaders(sourceReader, 0)
333390
if err != nil {
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2025 Flant JSC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package registry
18+
19+
import (
20+
"fmt"
21+
"io"
22+
)
23+
24+
const (
25+
tarRecordSize = 512
26+
tarEOFMarkerCount = 2
27+
)
28+
29+
var zero = []byte{0x00}
30+
31+
// writeTarEOFMarker writes EOF marker into Writer.
32+
// The EOF marker for tar is simply two 512-byte blocks of zeros.
33+
func writeTarEOFMarker(w io.Writer) error {
34+
for i := 0; i < tarRecordSize*tarEOFMarkerCount; i++ {
35+
n, err := w.Write(zero)
36+
if n != 1 {
37+
return fmt.Errorf("error writing zero byte to writer")
38+
}
39+
if err != nil {
40+
return err
41+
}
42+
}
43+
return nil
44+
}

templates/dvcr/ nodegroupconfiguration.yaml

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,46 @@ spec:
1616
bundles: ["*"]
1717
content: |
1818
# Copyright 2023 Flant JSC
19-
# Licensed under the Apache License, Version 2.0 (the "License");
19+
# Licensed under the Apache License, Version 2.0 (the "License");
2020
# you may not use this file except in compliance with the License.
2121
# You may obtain a copy of the License at
22-
# http://www.apache.org/licenses/LICENSE-2.0
23-
# Unless required by applicable law or agreed to in writing, software
22+
# http://www.apache.org/licenses/LICENSE-2.0
23+
# Unless required by applicable law or agreed to in writing, software
2424
# distributed under the License is distributed on an "AS IS" BASIS,
2525
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2626
# See the License for the specific language governing permissions and
2727
# limitations under the License.
2828
29-
mkdir -p /etc/containerd/conf.d
3029
bb-event-on 'registry-ca-changed' '_restart_containerd'
3130
bb-event-on 'containerd-config-changed' '_restart_containerd'
3231
_restart_containerd() {
3332
bb-flag-set containerd-need-restart
3433
}
34+
35+
{{ "{{- if eq .cri \"ContainerdV2\" }}" }}
36+
37+
mkdir -p "/etc/containerd/registry.d/{{ $registry }}"
38+
mkdir -p "/etc/containerd/certs.d/{{ $registry }}"
39+
bb-sync-file "/etc/containerd/certs.d/{{ $registry }}/ca.crt" - registry-ca-changed << "EOF"
40+
{{- $ca | nindent 4 }}
41+
EOF
42+
43+
bb-sync-file "/etc/containerd/registry.d/{{ $registry }}/hosts.toml" - containerd-config-changed << "EOF"
44+
server = "https://{{ $registry }}"
45+
[host."https://{{ $endpoint }}"]
46+
capabilities = ["pull", "resolve"]
47+
ca = "/etc/containerd/certs.d/{{ $registry }}/ca.crt"
48+
[host."https://{{ $endpoint }}".auth]
49+
auth = {{ $password | quote }}
50+
EOF
51+
52+
{{ "{{- else }}" }}
53+
54+
mkdir -p /etc/containerd/conf.d
3555
bb-sync-file /etc/containerd/conf.d/dvcr-ca.crt - registry-ca-changed << "EOF"
3656
{{- $ca | nindent 4 }}
3757
EOF
58+
3859
bb-sync-file /etc/containerd/conf.d/dvcr.toml - containerd-config-changed << "EOF"
3960
[plugins]
4061
[plugins."io.containerd.grpc.v1.cri"]
@@ -50,4 +71,7 @@ spec:
5071
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."{{ $registry }}"]
5172
endpoint = ["https://{{ $endpoint }}"]
5273
EOF
74+
75+
{{ "{{- end }}" }}
76+
5377
{{- end }}

0 commit comments

Comments
 (0)