From 332e39d487061953ee31f8039f6d8c227fc4d290 Mon Sep 17 00:00:00 2001 From: Yatin Karel Date: Tue, 13 Aug 2024 04:47:10 -0400 Subject: [PATCH] Move db initialization to an init container There is a potential race condition where ovs-vswitchd containers can run ovs db commands and fails while ovsdb-server stops and restarts after db initialization. This makes ovs-vswitchd container to fail and restart and it eventually recovers and it's better to avoid this. This patch moves the db initialization part to init container to avoid this race. Resolves: OSPRH-637 --- pkg/ovncontroller/daemonset.go | 19 ++++++++++++ .../ovncontroller/bin/init-ovsdb-server.sh | 22 ++++++++++++++ .../ovncontroller/bin/start-ovsdb-server.sh | 5 ---- .../ovncontroller_controller_test.go | 30 +++++++++++++++++++ 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100755 templates/ovncontroller/bin/init-ovsdb-server.sh diff --git a/pkg/ovncontroller/daemonset.go b/pkg/ovncontroller/daemonset.go index 215bd621..09ce8e33 100644 --- a/pkg/ovncontroller/daemonset.go +++ b/pkg/ovncontroller/daemonset.go @@ -169,6 +169,24 @@ func CreateOVSDaemonSet( envVars := map[string]env.Setter{} envVars["CONFIG_HASH"] = env.SetValue(configHash) + initContainers := []corev1.Container{ + { + Name: "ovsdb-server-init", + Command: []string{"/usr/local/bin/container-scripts/init-ovsdb-server.sh"}, + Image: instance.Spec.OvsContainerImage, + SecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{"NET_ADMIN", "SYS_ADMIN", "SYS_NICE"}, + Drop: []corev1.Capability{}, + }, + RunAsUser: &runAsUser, + Privileged: &privileged, + }, + Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), + VolumeMounts: GetOVSDbVolumeMounts(), + }, + } + containers := []corev1.Container{ { Name: "ovsdb-server", @@ -240,6 +258,7 @@ func CreateOVSDaemonSet( }, Spec: corev1.PodSpec{ ServiceAccountName: instance.RbacResourceName(), + InitContainers: initContainers, Containers: containers, Volumes: GetOVSVolumes(instance.Name, instance.Namespace), }, diff --git a/templates/ovncontroller/bin/init-ovsdb-server.sh b/templates/ovncontroller/bin/init-ovsdb-server.sh new file mode 100755 index 00000000..c9f311c9 --- /dev/null +++ b/templates/ovncontroller/bin/init-ovsdb-server.sh @@ -0,0 +1,22 @@ +#!/bin/sh +# +# Copyright 2023 Red Hat Inc. +# +# 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. + +set -ex + +# Initialize or upgrade database if needed +CTL_ARGS="--system-id=random --no-ovs-vswitchd" +/usr/share/openvswitch/scripts/ovs-ctl start $CTL_ARGS +/usr/share/openvswitch/scripts/ovs-ctl stop $CTL_ARGS diff --git a/templates/ovncontroller/bin/start-ovsdb-server.sh b/templates/ovncontroller/bin/start-ovsdb-server.sh index 42bf8f63..b27fb00f 100755 --- a/templates/ovncontroller/bin/start-ovsdb-server.sh +++ b/templates/ovncontroller/bin/start-ovsdb-server.sh @@ -20,11 +20,6 @@ source $(dirname $0)/functions # Remove the obsolete semaphore file in case it still exists. cleanup_ovsdb_server_semaphore -# Initialize or upgrade database if needed -CTL_ARGS="--system-id=random --no-ovs-vswitchd" -/usr/share/openvswitch/scripts/ovs-ctl start $CTL_ARGS -/usr/share/openvswitch/scripts/ovs-ctl stop $CTL_ARGS - # Start the service ovsdb-server /etc/openvswitch/conf.db \ --pidfile \ diff --git a/tests/functional/ovncontroller_controller_test.go b/tests/functional/ovncontroller_controller_test.go index ba321325..8792c2b4 100644 --- a/tests/functional/ovncontroller_controller_test.go +++ b/tests/functional/ovncontroller_controller_test.go @@ -890,6 +890,36 @@ var _ = Describe("OVNController controller", func() { ) }) + It("OVS Daemonset is created with 3 containers including an init container", func() { + DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(types.NamespacedName{ + Name: CABundleSecretName, + Namespace: namespace, + })) + DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(types.NamespacedName{ + Name: OvnDbCertSecretName, + Namespace: namespace, + })) + + daemonSetName := types.NamespacedName{ + Namespace: namespace, + Name: "ovn-controller", + } + + SimulateDaemonsetNumberReady(daemonSetName) + + daemonSetNameOVS := types.NamespacedName{ + Namespace: namespace, + Name: "ovn-controller-ovs", + } + + SimulateDaemonsetNumberReady(daemonSetNameOVS) + + ds := GetDaemonSet(daemonSetNameOVS) + + Expect(ds.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(ds.Spec.Template.Spec.Containers).To(HaveLen(2)) + }) + It("creates a Daemonset with TLS certs attached", func() { DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(types.NamespacedName{ Name: CABundleSecretName,