feat: allow overriding kine container image via additionalContainers (#1254)

* feat: allow overriding kine container image via additionalContainers

Modify buildKine to preserve custom image if set, enabling per-tenant
kine image overrides using additionalContainers with name 'kine'.

* docs: add documentation for custom kine image override

* test: add kine container image override tests

* fix(docs): minor suggestion

---------

Co-authored-by: Dario Tranchitella <dario@tranchitella.eu>
This commit is contained in:
Ross Golder
2026-07-29 13:03:15 +02:00
committed by GitHub
co-authored by Dario Tranchitella
parent 44128d87b8
commit 08f2c55bbb
3 changed files with 94 additions and 2 deletions
@@ -12,6 +12,29 @@ The following `make` recipes help you to setup alternative `Datastore` resources
- **NATS**: `$ make -C deploy/kine/nats nats`
## Using a Custom Kine Image
The default kine image can be overridden per-tenant by specifying a custom container image in the `additionalContainers` field:
```yaml
apiVersion: kamaji.clastix.io/v1alpha1
kind: TenantControlPlane
metadata:
name: tenant-name
namespace: kamaji-system
spec:
controlPlane:
deployment:
additionalContainers:
- name: kine
image: custom-kine-image:tag
```
This is useful for:
- Different database backends (postgresql, mysql, sqlite)
- Custom kine builds with specific features
- More granular control on a `TenantControlPlane` basis
!!! warning "Not for production"
The default settings are not production grade: the following scripts are just used to test the Kamaji usage of different drivers.
+6 -2
View File
@@ -960,7 +960,9 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant
}
podSpec.InitContainers[index].Name = kineInitContainerName
podSpec.InitContainers[index].Image = d.KineContainerImage
if podSpec.InitContainers[index].Image == "" {
podSpec.InitContainers[index].Image = d.KineContainerImage
}
podSpec.InitContainers[index].Command = []string{"sh"}
podSpec.InitContainers[index].Args = []string{
@@ -1019,7 +1021,9 @@ func (d Deployment) buildKine(podSpec *corev1.PodSpec, tcp kamajiv1alpha1.Tenant
}
podSpec.Containers[index].Name = kineContainerName
podSpec.Containers[index].Image = d.KineContainerImage
if podSpec.Containers[index].Image == "" {
podSpec.Containers[index].Image = d.KineContainerImage
}
podSpec.Containers[index].Command = []string{"/bin/kine"}
podSpec.Containers[index].Args = utilities.ArgsFromMapToSlice(args)
podSpec.Containers[index].VolumeMounts = []corev1.VolumeMount{
@@ -12,6 +12,7 @@ import (
pointer "k8s.io/utils/ptr"
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/utilities"
)
func TestControlplaneDeployment(t *testing.T) {
@@ -324,4 +325,68 @@ var _ = Describe("Controlplane Deployment", func() {
Expect(*podSpec.AutomountServiceAccountToken).To(BeFalse())
})
})
Describe("Kine container image override", func() {
var tcp kamajiv1alpha1.TenantControlPlane
BeforeEach(func() {
d.KineContainerImage = "rancher/kine:v0.11.0"
d.DataStore = kamajiv1alpha1.DataStore{
Spec: kamajiv1alpha1.DataStoreSpec{
Driver: kamajiv1alpha1.KinePostgreSQLDriver,
},
}
tcp = kamajiv1alpha1.TenantControlPlane{}
tcp.Status.Storage = kamajiv1alpha1.StorageStatus{
Config: kamajiv1alpha1.DataStoreConfigStatus{
SecretName: "test-secret",
},
}
})
It("should use default kine image when not overridden", func() {
podSpec := &corev1.PodSpec{}
tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{}
d.setAdditionalContainers(podSpec, tcp)
d.buildKine(podSpec, tcp)
found, index := utilities.HasNamedContainer(podSpec.Containers, "kine")
Expect(found).To(BeTrue())
Expect(podSpec.Containers[index].Image).To(Equal("rancher/kine:v0.11.0"))
})
It("should use custom kine image when overridden via additionalContainers", func() {
podSpec := &corev1.PodSpec{}
tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{
{
Name: "kine",
Image: "my-custom-kine:v1.0.0",
},
}
d.setAdditionalContainers(podSpec, tcp)
d.buildKine(podSpec, tcp)
found, index := utilities.HasNamedContainer(podSpec.Containers, "kine")
Expect(found).To(BeTrue())
Expect(podSpec.Containers[index].Image).To(Equal("my-custom-kine:v1.0.0"))
})
It("should preserve custom kine container image when set via additionalContainers", func() {
podSpec := &corev1.PodSpec{}
tcp.Spec.ControlPlane.Deployment.AdditionalContainers = []corev1.Container{
{
Name: "kine",
Image: "custom-kine:latest",
},
}
d.setAdditionalContainers(podSpec, tcp)
d.buildKine(podSpec, tcp)
found, index := utilities.HasNamedContainer(podSpec.Containers, "kine")
Expect(found).To(BeTrue())
Expect(podSpec.Containers[index].Image).To(Equal("custom-kine:latest"))
})
})
})