From 6665236e4488e05095086a9db617a1a93251f7a1 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 27 Aug 2024 11:04:51 +1200 Subject: [PATCH] Add a ramdisk-logs sidecar This implements the runlogwatch.sh approach of metal3[1] to write any deployment logs to the console, making them accessable to the end user via the same mechanism as other openstack service logs. Jira: OSPRH-1947 [1] https://github.com/metal3-io/ironic-image/blob/main/scripts/runlogwatch.sh --- pkg/ironicconductor/statefulset.go | 23 +++++++++++++++++++ templates/ironicconductor/bin/runlogwatch.sh | 18 +++++++++++++++ .../config/ramdisk-logs-config.json | 10 ++++++++ .../ironicconductor_controller_test.go | 4 ++-- 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100755 templates/ironicconductor/bin/runlogwatch.sh create mode 100644 templates/ironicconductor/config/ramdisk-logs-config.json diff --git a/pkg/ironicconductor/statefulset.go b/pkg/ironicconductor/statefulset.go index 0012d2b5..2bc09115 100644 --- a/pkg/ironicconductor/statefulset.go +++ b/pkg/ironicconductor/statefulset.go @@ -151,10 +151,16 @@ func StatefulSet( httpbootEnvVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") httpbootEnvVars["CONFIG_HASH"] = env.SetValue(configHash) + ramdiskLogsEnvVars := map[string]env.Setter{} + ramdiskLogsEnvVars["KOLLA_CONFIG_STRATEGY"] = env.SetValue("COPY_ALWAYS") + ramdiskLogsEnvVars["CONFIG_HASH"] = env.SetValue(configHash) + ramdiskLogsEnvVars["LOG_DIR"] = env.SetValue("/var/log/ironic/deploy") + volumes := GetVolumes(instance) conductorVolumeMounts := GetVolumeMounts("ironic-conductor") httpbootVolumeMounts := GetVolumeMounts("httpboot") dnsmasqVolumeMounts := GetVolumeMounts("dnsmasq") + ramdiskLogsVolumeMounts := GetVolumeMounts("ramdisk-logs") initVolumeMounts := GetInitVolumeMounts() // Add the CA bundle @@ -163,6 +169,7 @@ func StatefulSet( conductorVolumeMounts = append(conductorVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) httpbootVolumeMounts = append(httpbootVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) dnsmasqVolumeMounts = append(dnsmasqVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) + ramdiskLogsVolumeMounts = append(ramdiskLogsVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) initVolumeMounts = append(initVolumeMounts, instance.Spec.TLS.CreateVolumeMounts(nil)...) } @@ -201,10 +208,26 @@ func StatefulSet( LivenessProbe: httpbootLivenessProbe, // StartupProbe: startupProbe, } + ramdiskLogsContainer := corev1.Container{ + Name: "ramdisk-logs", + Command: []string{ + "/bin/bash", + }, + Image: instance.Spec.ContainerImage, + Env: env.MergeEnvs([]corev1.EnvVar{}, ramdiskLogsEnvVars), + VolumeMounts: ramdiskLogsVolumeMounts, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: &runAsUser, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + }, + } containers := []corev1.Container{ conductorContainer, httpbootContainer, + ramdiskLogsContainer, } if instance.Spec.ProvisionNetwork != "" { diff --git a/templates/ironicconductor/bin/runlogwatch.sh b/templates/ironicconductor/bin/runlogwatch.sh new file mode 100755 index 00000000..4a18b718 --- /dev/null +++ b/templates/ironicconductor/bin/runlogwatch.sh @@ -0,0 +1,18 @@ +#!/usr/bin/bash + +# Ramdisk logs path +LOG_DIR=${LOG_DIR:-/var/log/ironic/deploy} + +while :; do + if ! ls "${LOG_DIR}"/*.tar.gz 1> /dev/null 2>&1; then + continue + fi + + for fn in "${LOG_DIR}"/*.tar.gz; do + echo "************ Contents of $fn ramdisk log file bundle **************" + tar -xOzvvf "$fn" | sed -e "s/^/$(basename "$fn"): /" + rm -f "$fn" + done + + sleep 5 +done \ No newline at end of file diff --git a/templates/ironicconductor/config/ramdisk-logs-config.json b/templates/ironicconductor/config/ramdisk-logs-config.json new file mode 100644 index 00000000..f008f32d --- /dev/null +++ b/templates/ironicconductor/config/ramdisk-logs-config.json @@ -0,0 +1,10 @@ +{ + "command": "/usr/local/bin/container-scripts/runlogwatch.sh", + "permissions": [ + { + "path": "/var/log/ironic", + "owner": "ironic:ironic", + "recurse": true + } + ] +} diff --git a/tests/functional/ironicconductor_controller_test.go b/tests/functional/ironicconductor_controller_test.go index 798aeab6..21d1f566 100644 --- a/tests/functional/ironicconductor_controller_test.go +++ b/tests/functional/ironicconductor_controller_test.go @@ -276,7 +276,7 @@ var _ = Describe("IronicConductor controller", func() { // Check the resulting deployment fields Expect(int(*depl.Spec.Replicas)).To(Equal(1)) Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(6)) - Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(3)) // cert deployment volumes th.AssertVolumeExists(ironicNames.CaBundleSecretName.Name, depl.Spec.Template.Spec.Volumes) @@ -309,7 +309,7 @@ var _ = Describe("IronicConductor controller", func() { // Check the resulting deployment fields Expect(int(*depl.Spec.Replicas)).To(Equal(1)) Expect(depl.Spec.Template.Spec.Volumes).To(HaveLen(6)) - Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(2)) + Expect(depl.Spec.Template.Spec.Containers).To(HaveLen(3)) // Grab the current config hash originalHash := GetEnvVarValue(