mirror of https://github.com/openkruise/kruise.git
sidecarset support shareVolumeDevicePolicy (#2011)
Signed-off-by: liheng.zms <liheng.zms@alibaba-inc.com>
This commit is contained in:
parent
d8bf9c9b53
commit
d65527ea66
|
@ -132,9 +132,14 @@ type SidecarContainer struct {
|
|||
UpgradeStrategy SidecarContainerUpgradeStrategy `json:"upgradeStrategy,omitempty"`
|
||||
|
||||
// If ShareVolumePolicy is enabled, the sidecar container will share the other container's VolumeMounts
|
||||
// in the pod(don't contains the injected sidecar container).
|
||||
// in the pod(not including the injected sidecar container).
|
||||
ShareVolumePolicy ShareVolumePolicy `json:"shareVolumePolicy,omitempty"`
|
||||
|
||||
// If ShareVolumeDevicePolicy is enabled, the sidecar container will share the other container's VolumeDevices
|
||||
// in the pod(don't contain the injected sidecar container).
|
||||
// This is a pointer to ensure that the sidecarset-hash does not change if the user does not configure this field, mainly for compatibility with older versions.
|
||||
ShareVolumeDevicePolicy *ShareVolumePolicy `json:"shareVolumeDevicePolicy,omitempty"`
|
||||
|
||||
// TransferEnv will transfer env info from other container
|
||||
// SourceContainerName is pod.spec.container[x].name; EnvName is pod.spec.container[x].Env.name
|
||||
TransferEnv []TransferEnvVar `json:"transferEnv,omitempty"`
|
||||
|
|
|
@ -2711,6 +2711,11 @@ func (in *SidecarContainer) DeepCopyInto(out *SidecarContainer) {
|
|||
in.Container.DeepCopyInto(&out.Container)
|
||||
out.UpgradeStrategy = in.UpgradeStrategy
|
||||
out.ShareVolumePolicy = in.ShareVolumePolicy
|
||||
if in.ShareVolumeDevicePolicy != nil {
|
||||
in, out := &in.ShareVolumeDevicePolicy, &out.ShareVolumeDevicePolicy
|
||||
*out = new(ShareVolumePolicy)
|
||||
**out = **in
|
||||
}
|
||||
if in.TransferEnv != nil {
|
||||
in, out := &in.TransferEnv, &out.TransferEnv
|
||||
*out = make([]TransferEnvVar, len(*in))
|
||||
|
|
|
@ -73,10 +73,19 @@ spec:
|
|||
otherwise it will be injected into the back.
|
||||
default BeforeAppContainerType
|
||||
type: string
|
||||
shareVolumeDevicePolicy:
|
||||
description: |-
|
||||
If ShareVolumeDevicePolicy is enabled, the sidecar container will share the other container's VolumeDevices
|
||||
in the pod(don't contain the injected sidecar container).
|
||||
This is a pointer to ensure that the sidecarset-hash does not change if the user does not configure this field, mainly for compatibility with older versions.
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
shareVolumePolicy:
|
||||
description: |-
|
||||
If ShareVolumePolicy is enabled, the sidecar container will share the other container's VolumeMounts
|
||||
in the pod(don't contains the injected sidecar container).
|
||||
in the pod(not including the injected sidecar container).
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
|
@ -173,10 +182,19 @@ spec:
|
|||
otherwise it will be injected into the back.
|
||||
default BeforeAppContainerType
|
||||
type: string
|
||||
shareVolumeDevicePolicy:
|
||||
description: |-
|
||||
If ShareVolumeDevicePolicy is enabled, the sidecar container will share the other container's VolumeDevices
|
||||
in the pod(don't contain the injected sidecar container).
|
||||
This is a pointer to ensure that the sidecarset-hash does not change if the user does not configure this field, mainly for compatibility with older versions.
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
type: object
|
||||
shareVolumePolicy:
|
||||
description: |-
|
||||
If ShareVolumePolicy is enabled, the sidecar container will share the other container's VolumeMounts
|
||||
in the pod(don't contains the injected sidecar container).
|
||||
in the pod(not including the injected sidecar container).
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
|
|
|
@ -313,6 +313,11 @@ func IsSharePodVolumeMounts(container *appsv1alpha1.SidecarContainer) bool {
|
|||
return container.ShareVolumePolicy.Type == appsv1alpha1.ShareVolumePolicyEnabled
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// If you share volume, the volume path of the business container may conflict with the volume path of the sidecar container,
|
||||
// resulting in a failed pod creation.
|
||||
// For example, if the user's main container volumeDevice has devicePath /var/log and the sidecar container has volumeMounts path /var/log,
|
||||
// the path will conflict and the creation will fail.
|
||||
func GetInjectedVolumeMountsAndEnvs(control SidecarControl, sidecarContainer *appsv1alpha1.SidecarContainer, pod *corev1.Pod) ([]corev1.VolumeMount, []corev1.EnvVar) {
|
||||
if !IsSharePodVolumeMounts(sidecarContainer) {
|
||||
return nil, nil
|
||||
|
@ -350,9 +355,38 @@ func GetInjectedVolumeMountsAndEnvs(control SidecarControl, sidecarContainer *ap
|
|||
}
|
||||
}
|
||||
}
|
||||
// TODO: share pod.spec.initContainers[*].volumeMounts
|
||||
return injectedMounts, injectedEnvs
|
||||
}
|
||||
|
||||
func IsSharePodVolumeDevices(container *appsv1alpha1.SidecarContainer) bool {
|
||||
if container.ShareVolumeDevicePolicy == nil {
|
||||
return false
|
||||
}
|
||||
return container.ShareVolumeDevicePolicy.Type == appsv1alpha1.ShareVolumePolicyEnabled
|
||||
}
|
||||
|
||||
func GetInjectedVolumeDevices(sidecarContainer *appsv1alpha1.SidecarContainer, pod *corev1.Pod) []corev1.VolumeDevice {
|
||||
if !IsSharePodVolumeDevices(sidecarContainer) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// injected volumeDevices
|
||||
var volumeDevices []corev1.VolumeDevice
|
||||
for _, appContainer := range pod.Spec.Containers {
|
||||
// ignore the injected sidecar container
|
||||
if IsInjectedSidecarContainerInPod(&appContainer) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, volumeDevice := range appContainer.VolumeDevices {
|
||||
volumeDevices = append(volumeDevices, volumeDevice)
|
||||
}
|
||||
}
|
||||
// TODO: share pod.spec.initContainers[*].volumeDevices
|
||||
return volumeDevices
|
||||
}
|
||||
|
||||
func GetSidecarTransferEnvs(sidecarContainer *appsv1alpha1.SidecarContainer, pod *corev1.Pod) (injectedEnvs []corev1.EnvVar) {
|
||||
// pre-process envs in pod, format: container.name/env.name -> container.env
|
||||
// if SourceContainerName is set, use it as source container name
|
||||
|
|
|
@ -1265,3 +1265,130 @@ func TestPodMatchedSidecarSet(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInjectedVolumeDevices(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
getSidecarContainer func() *appsv1alpha1.SidecarContainer
|
||||
getPod func() *corev1.Pod
|
||||
expect []corev1.VolumeDevice
|
||||
}{
|
||||
{
|
||||
name: "ShareVolumeDevicePolicy, disable",
|
||||
getSidecarContainer: func() *appsv1alpha1.SidecarContainer {
|
||||
obj := &appsv1alpha1.SidecarContainer{}
|
||||
return obj
|
||||
},
|
||||
getPod: func() *corev1.Pod {
|
||||
obj := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-1",
|
||||
DevicePath: "/data/volume-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-2",
|
||||
DevicePath: "/data/volume-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-3",
|
||||
DevicePath: "/data/volume-3",
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: SidecarEnvKey,
|
||||
Value: "true",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return obj
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "ShareVolumeDevicePolicy, disable",
|
||||
getSidecarContainer: func() *appsv1alpha1.SidecarContainer {
|
||||
obj := &appsv1alpha1.SidecarContainer{
|
||||
ShareVolumeDevicePolicy: &appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyEnabled,
|
||||
},
|
||||
}
|
||||
return obj
|
||||
},
|
||||
getPod: func() *corev1.Pod {
|
||||
obj := &corev1.Pod{
|
||||
Spec: corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-1",
|
||||
DevicePath: "/data/volume-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-2",
|
||||
DevicePath: "/data/volume-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-3",
|
||||
DevicePath: "/data/volume-3",
|
||||
},
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: SidecarEnvKey,
|
||||
Value: "true",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return obj
|
||||
},
|
||||
expect: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "vd-1",
|
||||
DevicePath: "/data/volume-1",
|
||||
},
|
||||
{
|
||||
Name: "vd-2",
|
||||
DevicePath: "/data/volume-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, cs := range cases {
|
||||
t.Run(cs.name, func(t *testing.T) {
|
||||
vd := GetInjectedVolumeDevices(cs.getSidecarContainer(), cs.getPod())
|
||||
if !reflect.DeepEqual(vd, cs.expect) {
|
||||
t.Fatalf("expect(%v), but get(%v)", cs.expect, vd)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,7 +105,18 @@ func (p *Processor) UpdateSidecarSet(sidecarSet *appsv1alpha1.SidecarSet) (recon
|
|||
return reconcile.Result{RequeueAfter: time.Second}, nil
|
||||
}
|
||||
|
||||
// 3. If sidecar container hot upgrade complete, then set the other one(empty sidecar container) image to HotUpgradeEmptyImage
|
||||
// 3. SidecarSet upgrade strategy type is NotUpdate
|
||||
if isSidecarSetNotUpdate(sidecarSet) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// 4. Paused indicates that the SidecarSet is paused to update matched pods
|
||||
if sidecarSet.Spec.UpdateStrategy.Paused {
|
||||
klog.V(3).InfoS("SidecarSet was paused", "sidecarSet", klog.KObj(sidecarSet))
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// 5. If sidecar container hot upgrade complete, then set the other one(empty sidecar container) image to HotUpgradeEmptyImage
|
||||
if isSidecarSetHasHotUpgradeContainer(sidecarSet) {
|
||||
var podsInHotUpgrading []*corev1.Pod
|
||||
for _, pod := range pods {
|
||||
|
@ -132,23 +143,12 @@ func (p *Processor) UpdateSidecarSet(sidecarSet *appsv1alpha1.SidecarSet) (recon
|
|||
}
|
||||
}
|
||||
|
||||
// 4. SidecarSet upgrade strategy type is NotUpdate
|
||||
if isSidecarSetNotUpdate(sidecarSet) {
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// 5. sidecarset already updates all matched pods, then return
|
||||
// 6. sidecarset already updates all matched pods, then return
|
||||
if isSidecarSetUpdateFinish(status) {
|
||||
klog.V(3).InfoS("SidecarSet matched pods were latest, and don't need update", "sidecarSet", klog.KObj(sidecarSet), "matchedPodCount", len(pods))
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// 6. Paused indicates that the SidecarSet is paused to update matched pods
|
||||
if sidecarSet.Spec.UpdateStrategy.Paused {
|
||||
klog.V(3).InfoS("SidecarSet was paused", "sidecarSet", klog.KObj(sidecarSet))
|
||||
return reconcile.Result{}, nil
|
||||
}
|
||||
|
||||
// 7. upgrade pod sidecar
|
||||
if err := p.updatePods(control, pods); err != nil {
|
||||
return reconcile.Result{}, err
|
||||
|
@ -572,7 +572,7 @@ func updatePodSidecarContainer(control sidecarcontrol.SidecarControl, pod *corev
|
|||
// when volumeMounts SubPathExpr contains expansions, then need copy container EnvVars(injectEnvs)
|
||||
injectedMounts, injectedEnvs := sidecarcontrol.GetInjectedVolumeMountsAndEnvs(control, &sidecarContainer, pod)
|
||||
// merge VolumeMounts from sidecar.VolumeMounts and shared VolumeMounts
|
||||
sidecarContainer.VolumeMounts = util.MergeVolumeMounts(sidecarContainer.VolumeMounts, injectedMounts)
|
||||
sidecarContainer.VolumeMounts = util.MergeVolumeMounts(sidecarContainer.Container, injectedMounts)
|
||||
|
||||
// get injected env & mounts explicitly so that can be compared with old ones in pod
|
||||
transferEnvs := sidecarcontrol.GetSidecarTransferEnvs(&sidecarContainer, pod)
|
||||
|
@ -581,6 +581,10 @@ func updatePodSidecarContainer(control sidecarcontrol.SidecarControl, pod *corev
|
|||
// merged Env from sidecar.Env and transfer envs
|
||||
sidecarContainer.Env = util.MergeEnvVar(sidecarContainer.Env, transferEnvs)
|
||||
|
||||
// merge volumeDevice
|
||||
injectedDevices := sidecarcontrol.GetInjectedVolumeDevices(&sidecarContainer, pod)
|
||||
sidecarContainer.VolumeDevices = util.MergeVolumeDevices(sidecarContainer.Container, injectedDevices)
|
||||
|
||||
// upgrade sidecar container to latest
|
||||
newContainer := control.UpgradeSidecarContainer(&sidecarContainer, pod)
|
||||
// no change, then continue
|
||||
|
|
|
@ -76,18 +76,44 @@ func DiffPods(pods1, pods2 []*v1.Pod) (ret []*v1.Pod) {
|
|||
return
|
||||
}
|
||||
|
||||
func MergeVolumeMounts(original, additional []v1.VolumeMount) []v1.VolumeMount {
|
||||
mountpoints := sets.NewString()
|
||||
for _, mount := range original {
|
||||
mountpoints.Insert(mount.MountPath)
|
||||
func MergeVolumeMounts(container v1.Container, additional []v1.VolumeMount) []v1.VolumeMount {
|
||||
mountPoints := sets.NewString()
|
||||
var original []v1.VolumeMount
|
||||
for _, mount := range container.VolumeMounts {
|
||||
mountPoints.Insert(mount.MountPath)
|
||||
original = append(original, mount)
|
||||
}
|
||||
for _, mount := range container.VolumeDevices {
|
||||
mountPoints.Insert(mount.DevicePath)
|
||||
}
|
||||
|
||||
for _, mount := range additional {
|
||||
if mountpoints.Has(mount.MountPath) {
|
||||
if mountPoints.Has(mount.MountPath) {
|
||||
continue
|
||||
}
|
||||
original = append(original, mount)
|
||||
mountpoints.Insert(mount.MountPath)
|
||||
mountPoints.Insert(mount.MountPath)
|
||||
}
|
||||
return original
|
||||
}
|
||||
|
||||
func MergeVolumeDevices(container v1.Container, additional []v1.VolumeDevice) []v1.VolumeDevice {
|
||||
mountPoints := sets.NewString()
|
||||
var original []v1.VolumeDevice
|
||||
for _, mount := range container.VolumeDevices {
|
||||
mountPoints.Insert(mount.DevicePath)
|
||||
original = append(original, mount)
|
||||
}
|
||||
for _, mount := range container.VolumeMounts {
|
||||
mountPoints.Insert(mount.MountPath)
|
||||
}
|
||||
|
||||
for _, mount := range additional {
|
||||
if mountPoints.Has(mount.DevicePath) {
|
||||
continue
|
||||
}
|
||||
original = append(original, mount)
|
||||
mountPoints.Insert(mount.DevicePath)
|
||||
}
|
||||
return original
|
||||
}
|
||||
|
|
|
@ -21,36 +21,138 @@ import (
|
|||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
func TestMergeVolumeMounts(t *testing.T) {
|
||||
original := []v1.VolumeMount{
|
||||
tests := []struct {
|
||||
name string
|
||||
getContainer func() v1.Container
|
||||
getVolumeMounts func() []v1.VolumeMount
|
||||
expect []v1.VolumeMount
|
||||
}{
|
||||
{
|
||||
MountPath: "/origin-1",
|
||||
},
|
||||
{
|
||||
MountPath: "/share",
|
||||
name: "test1",
|
||||
getContainer: func() v1.Container {
|
||||
obj := v1.Container{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-share",
|
||||
MountPath: "/share",
|
||||
},
|
||||
},
|
||||
VolumeDevices: []v1.VolumeDevice{
|
||||
{
|
||||
DevicePath: "/device-1",
|
||||
},
|
||||
},
|
||||
}
|
||||
return obj
|
||||
},
|
||||
getVolumeMounts: func() []v1.VolumeMount {
|
||||
return []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "/addition-1",
|
||||
},
|
||||
{
|
||||
Name: "addition-share",
|
||||
MountPath: "/share",
|
||||
},
|
||||
{
|
||||
MountPath: "/device-1",
|
||||
},
|
||||
}
|
||||
},
|
||||
expect: []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-share",
|
||||
MountPath: "/share",
|
||||
},
|
||||
{
|
||||
MountPath: "/addition-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
additional := []v1.VolumeMount{
|
||||
for i, test := range tests {
|
||||
obj := MergeVolumeMounts(test.getContainer(), test.getVolumeMounts())
|
||||
if !reflect.DeepEqual(obj, test.expect) {
|
||||
t.Fatalf("case %d: expect(%v), but get(%v)", i, test.expect, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeVolumeDevices(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
getContainer func() v1.Container
|
||||
getVolumeDevices func() []v1.VolumeDevice
|
||||
expect []v1.VolumeDevice
|
||||
}{
|
||||
{
|
||||
MountPath: "/addition-1",
|
||||
},
|
||||
{
|
||||
MountPath: "/share",
|
||||
name: "inject test1",
|
||||
getContainer: func() v1.Container {
|
||||
obj := v1.Container{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
MountPath: "/log",
|
||||
},
|
||||
},
|
||||
VolumeDevices: []v1.VolumeDevice{
|
||||
{
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
},
|
||||
}
|
||||
return obj
|
||||
},
|
||||
getVolumeDevices: func() []v1.VolumeDevice {
|
||||
additional := []v1.VolumeDevice{
|
||||
{
|
||||
DevicePath: "/addition-1",
|
||||
},
|
||||
{
|
||||
Name: "target-pvc",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
{
|
||||
DevicePath: "/log",
|
||||
},
|
||||
}
|
||||
return additional
|
||||
},
|
||||
expect: []v1.VolumeDevice{
|
||||
{
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
{
|
||||
DevicePath: "/addition-1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
volumeMounts := MergeVolumeMounts(original, additional)
|
||||
excepts := []string{"/origin-1", "/share", "/addition-1"}
|
||||
for i, except := range excepts {
|
||||
if volumeMounts[i].MountPath != except {
|
||||
t.Fatalf("except VolumeMount(%s), but get %s", except, volumeMounts[i].MountPath)
|
||||
for i, test := range tests {
|
||||
obj := MergeVolumeDevices(test.getContainer(), test.getVolumeDevices())
|
||||
if !reflect.DeepEqual(obj, test.expect) {
|
||||
t.Fatalf("case %d: expect(%v), but get(%v)", i, test.expect, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -435,20 +435,26 @@ func buildSidecars(isUpdated bool, pod *corev1.Pod, oldPod *corev1.Pod, matchedS
|
|||
transferEnvs := sidecarcontrol.GetSidecarTransferEnvs(initContainer, pod)
|
||||
// append volumeMounts SubPathExpr environments
|
||||
transferEnvs = util.MergeEnvVar(transferEnvs, injectedEnvs)
|
||||
klog.InfoS("try to inject initContainer sidecar",
|
||||
"containerName", initContainer.Name, "namespace", pod.Namespace, "podName", pod.Name, "envs", transferEnvs, "volumeMounts", injectedMounts)
|
||||
// insert volumes that initContainers used
|
||||
for _, mount := range initContainer.VolumeMounts {
|
||||
volumesInSidecars = append(volumesInSidecars, *volumesMap[mount.Name])
|
||||
}
|
||||
for _, mount := range initContainer.VolumeDevices {
|
||||
volumesInSidecars = append(volumesInSidecars, *volumesMap[mount.Name])
|
||||
}
|
||||
// merge VolumeMounts from sidecar.VolumeMounts and shared VolumeMounts
|
||||
initContainer.VolumeMounts = util.MergeVolumeMounts(initContainer.VolumeMounts, injectedMounts)
|
||||
initContainer.VolumeMounts = util.MergeVolumeMounts(initContainer.Container, injectedMounts)
|
||||
// add "IS_INJECTED" env in initContainer's envs
|
||||
initContainer.Env = append(initContainer.Env, corev1.EnvVar{Name: sidecarcontrol.SidecarEnvKey, Value: "true"})
|
||||
// merged Env from sidecar.Env and transfer envs
|
||||
initContainer.Env = util.MergeEnvVar(initContainer.Env, transferEnvs)
|
||||
isInjecting = true
|
||||
|
||||
// merge volumeDevice
|
||||
injectedDevices := sidecarcontrol.GetInjectedVolumeDevices(initContainer, pod)
|
||||
initContainer.VolumeDevices = util.MergeVolumeDevices(initContainer.Container, injectedDevices)
|
||||
klog.InfoS("try to inject initContainer sidecar",
|
||||
"containerName", initContainer.Name, "namespace", pod.Namespace, "podName", pod.Name, "envs", transferEnvs, "volumeMounts", injectedMounts, "volumeDevices", injectedDevices)
|
||||
// when sidecar container UpgradeStrategy is HotUpgrade
|
||||
if sidecarcontrol.IsSidecarContainer(initContainer.Container) && sidecarcontrol.IsHotUpgradeContainer(initContainer) {
|
||||
hotContainers, annotations := injectHotUpgradeContainers(hotUpgradeWorkInfo, initContainer)
|
||||
|
@ -475,8 +481,6 @@ func buildSidecars(isUpdated bool, pod *corev1.Pod, oldPod *corev1.Pod, matchedS
|
|||
transferEnvs := sidecarcontrol.GetSidecarTransferEnvs(sidecarContainer, pod)
|
||||
// append volumeMounts SubPathExpr environments
|
||||
transferEnvs = util.MergeEnvVar(transferEnvs, injectedEnvs)
|
||||
klog.InfoS("try to inject Container sidecar",
|
||||
"containerName", sidecarContainer.Name, "namespace", pod.Namespace, "podName", pod.Name, "envs", transferEnvs, "volumeMounts", injectedMounts)
|
||||
//when update pod object
|
||||
if isUpdated {
|
||||
// judge whether inject sidecar container into pod
|
||||
|
@ -499,13 +503,21 @@ func buildSidecars(isUpdated bool, pod *corev1.Pod, oldPod *corev1.Pod, matchedS
|
|||
for _, mount := range sidecarContainer.VolumeMounts {
|
||||
volumesInSidecars = append(volumesInSidecars, *volumesMap[mount.Name])
|
||||
}
|
||||
for _, mount := range sidecarContainer.VolumeDevices {
|
||||
volumesInSidecars = append(volumesInSidecars, *volumesMap[mount.Name])
|
||||
}
|
||||
// merge VolumeMounts from sidecar.VolumeMounts and shared VolumeMounts
|
||||
sidecarContainer.VolumeMounts = util.MergeVolumeMounts(sidecarContainer.VolumeMounts, injectedMounts)
|
||||
sidecarContainer.VolumeMounts = util.MergeVolumeMounts(sidecarContainer.Container, injectedMounts)
|
||||
// add the "Injected" env to the sidecar container
|
||||
sidecarContainer.Env = append(sidecarContainer.Env, corev1.EnvVar{Name: sidecarcontrol.SidecarEnvKey, Value: "true"})
|
||||
// merged Env from sidecar.Env and transfer envs
|
||||
sidecarContainer.Env = util.MergeEnvVar(sidecarContainer.Env, transferEnvs)
|
||||
|
||||
// merge volumeDevice
|
||||
injectedDevices := sidecarcontrol.GetInjectedVolumeDevices(sidecarContainer, pod)
|
||||
sidecarContainer.VolumeDevices = util.MergeVolumeDevices(sidecarContainer.Container, injectedDevices)
|
||||
klog.InfoS("try to inject Container sidecar",
|
||||
"containerName", sidecarContainer.Name, "namespace", pod.Namespace, "podName", pod.Name, "envs", transferEnvs, "volumeMounts", injectedMounts, "volumeDevices", injectedDevices)
|
||||
// when sidecar container UpgradeStrategy is HotUpgrade
|
||||
if sidecarcontrol.IsHotUpgradeContainer(sidecarContainer) {
|
||||
hotContainers, annotations := injectHotUpgradeContainers(hotUpgradeWorkInfo, sidecarContainer)
|
||||
|
|
|
@ -1647,3 +1647,196 @@ func newAdmissionRequest(op admissionv1.Operation, object, oldObject runtime.Raw
|
|||
SubResource: subResource,
|
||||
}
|
||||
}
|
||||
|
||||
func TestPodVolumeDevicesAppend(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
getPod func() *corev1.Pod
|
||||
getSidecarSet func() *appsv1alpha1.SidecarSet
|
||||
exceptInitVolumeDevices []corev1.VolumeDevice
|
||||
exceptVolumeDevices []corev1.VolumeDevice
|
||||
exceptVolumes []corev1.Volume
|
||||
}{
|
||||
{
|
||||
name: "append normal volumeDevices, ShareVolumeDevicePolicy=disable",
|
||||
getPod: func() *corev1.Pod {
|
||||
// /a/b、/e/f
|
||||
podIn := podWithStaragent.DeepCopy()
|
||||
podIn.Spec.Containers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "origin-pvc-1",
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-share",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
}
|
||||
podIn.Spec.Volumes = append(podIn.Spec.Volumes, corev1.Volume{Name: "origin-pvc-1"})
|
||||
podIn.Spec.Volumes = append(podIn.Spec.Volumes, corev1.Volume{Name: "origin-pvc-share"})
|
||||
return podIn
|
||||
},
|
||||
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
||||
sidecarSetIn := sidecarSetWithStaragent.DeepCopy()
|
||||
sidecarSetIn.Spec.Containers = sidecarSetIn.Spec.Containers[:1]
|
||||
sidecarSetIn.Spec.InitContainers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme0",
|
||||
},
|
||||
}
|
||||
sidecarSetIn.Spec.InitContainers[0].VolumeMounts = nil
|
||||
sidecarSetIn.Spec.InitContainers[0].ShareVolumePolicy = appsv1alpha1.ShareVolumePolicy{}
|
||||
sidecarSetIn.Spec.Containers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
}
|
||||
sidecarSetIn.Spec.Containers[0].VolumeMounts = nil
|
||||
sidecarSetIn.Spec.Containers[0].ShareVolumePolicy = appsv1alpha1.ShareVolumePolicy{}
|
||||
sidecarSetIn.Spec.Volumes = []corev1.Volume{{Name: "disk0"}}
|
||||
|
||||
return sidecarSetIn
|
||||
},
|
||||
exceptInitVolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme0",
|
||||
},
|
||||
},
|
||||
exceptVolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
},
|
||||
exceptVolumes: []corev1.Volume{
|
||||
{Name: "volume-a"},
|
||||
{Name: "volume-b"},
|
||||
{Name: "volume-staragent"},
|
||||
{Name: "origin-pvc-1"},
|
||||
{Name: "origin-pvc-share"},
|
||||
{Name: "disk0"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "append normal volumeDevices, ShareVolumeDevicePolicy=enable",
|
||||
getPod: func() *corev1.Pod {
|
||||
// /a/b、/e/f
|
||||
podIn := podWithStaragent.DeepCopy()
|
||||
podIn.Spec.Containers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "origin-pvc-1",
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-share",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
}
|
||||
podIn.Spec.Volumes = append(podIn.Spec.Volumes, corev1.Volume{Name: "origin-pvc-1"})
|
||||
podIn.Spec.Volumes = append(podIn.Spec.Volumes, corev1.Volume{Name: "origin-pvc-share"})
|
||||
return podIn
|
||||
},
|
||||
getSidecarSet: func() *appsv1alpha1.SidecarSet {
|
||||
sidecarSetIn := sidecarSetWithStaragent.DeepCopy()
|
||||
sidecarSetIn.Spec.Containers = sidecarSetIn.Spec.Containers[:1]
|
||||
sidecarSetIn.Spec.InitContainers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme0",
|
||||
},
|
||||
}
|
||||
sidecarSetIn.Spec.InitContainers[0].ShareVolumePolicy = appsv1alpha1.ShareVolumePolicy{}
|
||||
sidecarSetIn.Spec.InitContainers[0].ShareVolumeDevicePolicy = &appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyEnabled,
|
||||
}
|
||||
sidecarSetIn.Spec.Containers[0].VolumeDevices = []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
}
|
||||
sidecarSetIn.Spec.Containers[0].VolumeMounts = nil
|
||||
sidecarSetIn.Spec.Containers[0].ShareVolumePolicy = appsv1alpha1.ShareVolumePolicy{}
|
||||
sidecarSetIn.Spec.Containers[0].ShareVolumeDevicePolicy = &appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyEnabled,
|
||||
}
|
||||
sidecarSetIn.Spec.Volumes = []corev1.Volume{
|
||||
{Name: "volume-3"},
|
||||
{Name: "volume-4"},
|
||||
{Name: "volume-staragent"},
|
||||
{Name: "disk0"},
|
||||
}
|
||||
|
||||
return sidecarSetIn
|
||||
},
|
||||
exceptInitVolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme0",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-1",
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-share",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
},
|
||||
exceptVolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-1",
|
||||
DevicePath: "/origin-1",
|
||||
},
|
||||
{
|
||||
Name: "origin-pvc-share",
|
||||
DevicePath: "/share",
|
||||
},
|
||||
},
|
||||
exceptVolumes: []corev1.Volume{
|
||||
{Name: "volume-a"},
|
||||
{Name: "volume-b"},
|
||||
{Name: "volume-staragent"},
|
||||
{Name: "origin-pvc-1"},
|
||||
{Name: "origin-pvc-share"},
|
||||
{Name: "volume-3"},
|
||||
{Name: "volume-4"},
|
||||
{Name: "disk0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, cs := range cases {
|
||||
t.Run(cs.name, func(t *testing.T) {
|
||||
podIn := cs.getPod()
|
||||
decoder := admission.NewDecoder(scheme.Scheme)
|
||||
c := fake.NewClientBuilder().WithObjects(cs.getSidecarSet()).WithIndex(
|
||||
&appsv1alpha1.SidecarSet{}, fieldindex.IndexNameForSidecarSetNamespace, fieldindex.IndexSidecarSet,
|
||||
).Build()
|
||||
podOut := podIn.DeepCopy()
|
||||
podHandler := &PodCreateHandler{Decoder: decoder, Client: c}
|
||||
req := newAdmission(admissionv1.Create, runtime.RawExtension{}, runtime.RawExtension{}, "")
|
||||
_, err := podHandler.sidecarsetMutatingPod(context.Background(), req, podOut)
|
||||
if err != nil {
|
||||
t.Fatalf("inject sidecar into pod failed, err: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(cs.exceptInitVolumeDevices, podOut.Spec.InitContainers[0].VolumeDevices) {
|
||||
t.Fatalf("expect(%v), but get(%v)", cs.exceptInitVolumeDevices, podOut.Spec.InitContainers[0].VolumeDevices)
|
||||
}
|
||||
if !reflect.DeepEqual(cs.exceptVolumeDevices, podOut.Spec.Containers[1].VolumeDevices) {
|
||||
t.Fatalf("expect(%v), but get(%v)", cs.exceptVolumeDevices, podOut.Spec.Containers[1].VolumeDevices)
|
||||
}
|
||||
if !reflect.DeepEqual(cs.exceptVolumes, podOut.Spec.Volumes) {
|
||||
t.Fatalf("expect(%v), but get(%v)", util.DumpJSON(cs.exceptVolumes), util.DumpJSON(podOut.Spec.Volumes))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,6 +379,152 @@ func TestValidateSidecarSet(t *testing.T) {
|
|||
},
|
||||
expectErrs: 1,
|
||||
},
|
||||
{
|
||||
caseName: "wrong-volumeDevice-volumes",
|
||||
sidecarSet: appsv1alpha1.SidecarSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-sidecarset"},
|
||||
Spec: appsv1alpha1.SidecarSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
UpdateStrategy: appsv1alpha1.SidecarSetUpdateStrategy{
|
||||
Type: appsv1alpha1.NotUpdateSidecarSetStrategyType,
|
||||
},
|
||||
Containers: []appsv1alpha1.SidecarContainer{
|
||||
{
|
||||
PodInjectPolicy: appsv1alpha1.BeforeAppContainerType,
|
||||
ShareVolumePolicy: appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyDisabled,
|
||||
},
|
||||
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
||||
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
||||
},
|
||||
Container: corev1.Container{
|
||||
Name: "test-sidecar",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErrs: 1,
|
||||
},
|
||||
{
|
||||
caseName: "right-volumeDevice-volumes",
|
||||
sidecarSet: appsv1alpha1.SidecarSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-sidecarset"},
|
||||
Spec: appsv1alpha1.SidecarSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
UpdateStrategy: appsv1alpha1.SidecarSetUpdateStrategy{
|
||||
Type: appsv1alpha1.NotUpdateSidecarSetStrategyType,
|
||||
},
|
||||
Containers: []appsv1alpha1.SidecarContainer{
|
||||
{
|
||||
PodInjectPolicy: appsv1alpha1.BeforeAppContainerType,
|
||||
ShareVolumePolicy: appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyDisabled,
|
||||
},
|
||||
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
||||
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
||||
},
|
||||
Container: corev1.Container{
|
||||
Name: "test-sidecar",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/dev/nvme1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "disk0",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "pvc-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErrs: 0,
|
||||
},
|
||||
{
|
||||
caseName: "volumeDevice-volumeMount-path-conflict",
|
||||
sidecarSet: appsv1alpha1.SidecarSet{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-sidecarset"},
|
||||
Spec: appsv1alpha1.SidecarSetSpec{
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"a": "b"},
|
||||
},
|
||||
UpdateStrategy: appsv1alpha1.SidecarSetUpdateStrategy{
|
||||
Type: appsv1alpha1.NotUpdateSidecarSetStrategyType,
|
||||
},
|
||||
Containers: []appsv1alpha1.SidecarContainer{
|
||||
{
|
||||
PodInjectPolicy: appsv1alpha1.BeforeAppContainerType,
|
||||
ShareVolumePolicy: appsv1alpha1.ShareVolumePolicy{
|
||||
Type: appsv1alpha1.ShareVolumePolicyDisabled,
|
||||
},
|
||||
UpgradeStrategy: appsv1alpha1.SidecarContainerUpgradeStrategy{
|
||||
UpgradeType: appsv1alpha1.SidecarContainerColdUpgrade,
|
||||
},
|
||||
Container: corev1.Container{
|
||||
Name: "test-sidecar",
|
||||
Image: "test-image",
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
|
||||
VolumeDevices: []corev1.VolumeDevice{
|
||||
{
|
||||
Name: "disk0",
|
||||
DevicePath: "/home/admin/log",
|
||||
},
|
||||
},
|
||||
VolumeMounts: []corev1.VolumeMount{
|
||||
{
|
||||
Name: "log",
|
||||
MountPath: "/home/admin/log",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []corev1.Volume{
|
||||
{
|
||||
Name: "disk0",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: "pvc-0",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "log",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
EmptyDir: &corev1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErrs: 2,
|
||||
},
|
||||
{
|
||||
caseName: "wrong-metadata",
|
||||
sidecarSet: appsv1alpha1.SidecarSet{
|
||||
|
|
Loading…
Reference in New Issue