Skip to content

Commit 37efaf4

Browse files
committed
Add additional storage configuration fields to ContainerRuntimeConfig
This enhancement extends ContainerRuntimeConfig API with three features for improved container storage flexibility: - additionalLayerStores: Enable lazy image pulling via storage plugins (BYOS approach with stargz-snapshotter, nydus-storage-plugin) - additionalImageStores: Read-only container image caches on shared or high-performance storage (NFS, SSD) for faster startup and reduced network overhead - additionalArtifactStores: Configurable OCI artifact storage locations (SSD-backed storage, pre-populated caches, air-gapped deployments) All features target AI/ML workload performance improvements and will ship as Tech Preview in 4.22 behind TechPreviewNoUpgrade feature gate. Path-based configuration with graceful fallback to standard behavior on failure. Unified API design pattern across all three features. Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
1 parent c16ec2b commit 37efaf4

7 files changed

Lines changed: 761 additions & 6 deletions

File tree

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
apiVersion: apiextensions.k8s.io/v1 # Hack because controller-gen complains if we don't have this
2+
name: "ContainerRuntimeConfig"
3+
crdName: containerruntimeconfigs.machineconfiguration.openshift.io
4+
tests:
5+
onCreate:
6+
# AdditionalLayerStores - comprehensive validation tests
7+
- name: Should be able to create ContainerRuntimeConfig with multiple additionalLayerStores
8+
initial: |
9+
apiVersion: machineconfiguration.openshift.io/v1
10+
kind: ContainerRuntimeConfig
11+
spec:
12+
containerRuntimeConfig:
13+
additionalLayerStores:
14+
- path: /var/lib/stargz-store
15+
- path: /mnt/nydus-store
16+
- path: /opt/layer_store-v1
17+
expected: |
18+
apiVersion: machineconfiguration.openshift.io/v1
19+
kind: ContainerRuntimeConfig
20+
spec:
21+
containerRuntimeConfig:
22+
additionalLayerStores:
23+
- path: /var/lib/stargz-store
24+
- path: /mnt/nydus-store
25+
- path: /opt/layer_store-v1
26+
27+
- name: Should fail if additionalLayerStores path is empty
28+
initial: |
29+
apiVersion: machineconfiguration.openshift.io/v1
30+
kind: ContainerRuntimeConfig
31+
spec:
32+
containerRuntimeConfig:
33+
additionalLayerStores:
34+
- path: ""
35+
expectedError: "path in body should be at least 1 chars long"
36+
37+
- name: Should fail if additionalLayerStores path is not absolute
38+
initial: |
39+
apiVersion: machineconfiguration.openshift.io/v1
40+
kind: ContainerRuntimeConfig
41+
spec:
42+
containerRuntimeConfig:
43+
additionalLayerStores:
44+
- path: var/lib/stargz-store
45+
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
46+
47+
- name: Should fail if additionalLayerStores path contains spaces
48+
initial: |
49+
apiVersion: machineconfiguration.openshift.io/v1
50+
kind: ContainerRuntimeConfig
51+
spec:
52+
containerRuntimeConfig:
53+
additionalLayerStores:
54+
- path: /var/lib/stargz store
55+
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
56+
57+
- name: Should fail if additionalLayerStores path contains invalid characters
58+
initial: |
59+
apiVersion: machineconfiguration.openshift.io/v1
60+
kind: ContainerRuntimeConfig
61+
spec:
62+
containerRuntimeConfig:
63+
additionalLayerStores:
64+
- path: /var/lib/stargz@store
65+
expectedError: "path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
66+
67+
- name: Should fail if additionalLayerStores path is too long
68+
initial: |
69+
apiVersion: machineconfiguration.openshift.io/v1
70+
kind: ContainerRuntimeConfig
71+
spec:
72+
containerRuntimeConfig:
73+
additionalLayerStores:
74+
- path: /aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
75+
expectedError: "path in body should be at most 256 chars long"
76+
77+
- name: Should fail if additionalLayerStores exceeds maximum of 5 items
78+
initial: |
79+
apiVersion: machineconfiguration.openshift.io/v1
80+
kind: ContainerRuntimeConfig
81+
spec:
82+
containerRuntimeConfig:
83+
additionalLayerStores:
84+
- path: /var/lib/store1
85+
- path: /var/lib/store2
86+
- path: /var/lib/store3
87+
- path: /var/lib/store4
88+
- path: /var/lib/store5
89+
- path: /var/lib/store6
90+
expectedError: "additionalLayerStores in body should have at most 5 items"
91+
92+
- name: Should fail if additionalLayerStores item has no path field
93+
initial: |
94+
apiVersion: machineconfiguration.openshift.io/v1
95+
kind: ContainerRuntimeConfig
96+
spec:
97+
containerRuntimeConfig:
98+
additionalLayerStores:
99+
- {}
100+
expectedError: "spec.containerRuntimeConfig.additionalLayerStores[0] in body should have at least 1 properties"
101+
102+
# AdditionalImageStores - test max items validation (different from layer stores)
103+
- name: Should fail if additionalImageStores exceeds maximum of 10 items
104+
initial: |
105+
apiVersion: machineconfiguration.openshift.io/v1
106+
kind: ContainerRuntimeConfig
107+
spec:
108+
containerRuntimeConfig:
109+
additionalImageStores:
110+
- path: /var/lib/store1
111+
- path: /var/lib/store2
112+
- path: /var/lib/store3
113+
- path: /var/lib/store4
114+
- path: /var/lib/store5
115+
- path: /var/lib/store6
116+
- path: /var/lib/store7
117+
- path: /var/lib/store8
118+
- path: /var/lib/store9
119+
- path: /var/lib/store10
120+
- path: /var/lib/store11
121+
expectedError: "additionalImageStores in body should have at most 10 items"
122+
123+
# AdditionalArtifactStores - test max items validation (different from layer stores)
124+
- name: Should fail if additionalArtifactStores exceeds maximum of 10 items
125+
initial: |
126+
apiVersion: machineconfiguration.openshift.io/v1
127+
kind: ContainerRuntimeConfig
128+
spec:
129+
containerRuntimeConfig:
130+
additionalArtifactStores:
131+
- path: /var/lib/store1
132+
- path: /var/lib/store2
133+
- path: /var/lib/store3
134+
- path: /var/lib/store4
135+
- path: /var/lib/store5
136+
- path: /var/lib/store6
137+
- path: /var/lib/store7
138+
- path: /var/lib/store8
139+
- path: /var/lib/store9
140+
- path: /var/lib/store10
141+
- path: /var/lib/store11
142+
expectedError: "additionalArtifactStores in body should have at most 10 items"
143+
144+
# Combined test - all storage types together with other fields
145+
- name: Should be able to create ContainerRuntimeConfig with all storage types and existing fields
146+
initial: |
147+
apiVersion: machineconfiguration.openshift.io/v1
148+
kind: ContainerRuntimeConfig
149+
spec:
150+
containerRuntimeConfig:
151+
defaultRuntime: crun
152+
logLevel: info
153+
additionalLayerStores:
154+
- path: /var/lib/stargz-store
155+
additionalImageStores:
156+
- path: /mnt/nfs-images
157+
- path: /mnt/ssd-images
158+
additionalArtifactStores:
159+
- path: /mnt/ssd-artifacts
160+
expected: |
161+
apiVersion: machineconfiguration.openshift.io/v1
162+
kind: ContainerRuntimeConfig
163+
spec:
164+
containerRuntimeConfig:
165+
defaultRuntime: crun
166+
logLevel: info
167+
additionalLayerStores:
168+
- path: /var/lib/stargz-store
169+
additionalImageStores:
170+
- path: /mnt/nfs-images
171+
- path: /mnt/ssd-images
172+
additionalArtifactStores:
173+
- path: /mnt/ssd-artifacts

machineconfiguration/v1/types.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,51 @@ type ContainerRuntimeConfiguration struct {
892892
// +kubebuilder:validation:Enum=crun;runc
893893
// +optional
894894
DefaultRuntime ContainerRuntimeDefaultRuntime `json:"defaultRuntime,omitempty"`
895+
896+
// additionalLayerStores configures additional layer store locations.
897+
//
898+
// Stores are checked in order until a layer is found.
899+
// Maximum of 5 stores allowed.
900+
//
901+
// When omitted, no additional layer stores are configured.
902+
//
903+
// +optional
904+
// +listType=atomic
905+
// +kubebuilder:validation:MinItems=1
906+
// +kubebuilder:validation:MaxItems=5
907+
AdditionalLayerStores []AdditionalLayerStore `json:"additionalLayerStores,omitempty"`
908+
909+
// additionalImageStores configures additional read-only container image store
910+
// locations for complete Open Container Initiative (OCI) images.
911+
//
912+
// Images are checked in order: additional stores first, then default location.
913+
// Stores are read-only.
914+
//
915+
// Maximum of 10 stores allowed.
916+
//
917+
// When omitted, only the default image location is used.
918+
//
919+
// +optional
920+
// +listType=atomic
921+
// +kubebuilder:validation:MinItems=1
922+
// +kubebuilder:validation:MaxItems=10
923+
AdditionalImageStores []AdditionalImageStore `json:"additionalImageStores,omitempty"`
924+
925+
// additionalArtifactStores configures additional read-only artifact storage
926+
// locations for Open Container Initiative (OCI) volumes.
927+
//
928+
// Artifacts are checked in order: additional stores first, then default location.
929+
// Stores are read-only.
930+
//
931+
// Maximum of 10 stores allowed.
932+
//
933+
// When omitted, only the default artifact location (/var/lib/containers/storage/artifacts/) is used.
934+
//
935+
// +optional
936+
// +listType=atomic
937+
// +kubebuilder:validation:MinItems=1
938+
// +kubebuilder:validation:MaxItems=10
939+
AdditionalArtifactStores []AdditionalArtifactStore `json:"additionalArtifactStores,omitempty"`
895940
}
896941

897942
type ContainerRuntimeDefaultRuntime string
@@ -904,6 +949,72 @@ const (
904949
ContainerRuntimeDefaultRuntimeDefault = ContainerRuntimeDefaultRuntimeCrun
905950
)
906951

952+
// AdditionalLayerStore defines a storage location for container image layers.
953+
// At least one field must be specified.
954+
// +kubebuilder:validation:MinProperties=1
955+
type AdditionalLayerStore struct {
956+
// path is the absolute path to the additional layer store location.
957+
//
958+
// The path must exist on the node before configuration is applied.
959+
// When a container image is requested, layers found at this location will be used instead of
960+
// retrieving from the registry.
961+
//
962+
// This field is required and must:
963+
// - Have length between 1 and 256 characters
964+
// - Start with '/' (absolute path)
965+
// - Contain only: a-z, A-Z, 0-9, '/', '_', '-' (no spaces or special characters)
966+
//
967+
// +required
968+
// +kubebuilder:validation:MinLength=1
969+
// +kubebuilder:validation:MaxLength=256
970+
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/_-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
971+
Path string `json:"path,omitempty"`
972+
}
973+
974+
// AdditionalImageStore defines an additional read-only storage location for complete container images.
975+
// At least one field must be specified.
976+
// +kubebuilder:validation:MinProperties=1
977+
type AdditionalImageStore struct {
978+
// path is the absolute path to the additional image store location.
979+
//
980+
// The path must exist on the node before configuration is applied.
981+
// When a container image is requested, images found at this location will be used instead of
982+
// retrieving from the registry.
983+
//
984+
// This field is required and must:
985+
// - Have length between 1 and 256 characters
986+
// - Start with '/' (absolute path)
987+
// - Contain only: a-z, A-Z, 0-9, '/', '_', '-' (no spaces or special characters)
988+
//
989+
// +required
990+
// +kubebuilder:validation:MinLength=1
991+
// +kubebuilder:validation:MaxLength=256
992+
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/_-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
993+
Path string `json:"path,omitempty"`
994+
}
995+
996+
// AdditionalArtifactStore defines an additional storage location for Open Container Initiative (OCI) artifacts.
997+
// At least one field must be specified.
998+
// +kubebuilder:validation:MinProperties=1
999+
type AdditionalArtifactStore struct {
1000+
// path is the absolute path to the additional artifact store location.
1001+
//
1002+
// The path must exist on the node before configuration is applied.
1003+
// When an Open Container Initiative (OCI) artifact is requested, artifacts found at this location will be used instead of
1004+
// retrieving from the registry.
1005+
//
1006+
// This field is required and must:
1007+
// - Have length between 1 and 256 characters
1008+
// - Start with '/' (absolute path)
1009+
// - Contain only: a-z, A-Z, 0-9, '/', '_', '-' (no spaces or special characters)
1010+
//
1011+
// +required
1012+
// +kubebuilder:validation:MinLength=1
1013+
// +kubebuilder:validation:MaxLength=256
1014+
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/_-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '_', and '-'"
1015+
Path string `json:"path,omitempty"`
1016+
}
1017+
9071018
// ContainerRuntimeConfigStatus defines the observed state of a ContainerRuntimeConfig
9081019
type ContainerRuntimeConfigStatus struct {
9091020
// observedGeneration represents the generation observed by the controller.

0 commit comments

Comments
 (0)