Skip to content

Commit c821c01

Browse files
DeveshB-1givensuman
authored andcommitted
fix(kube): export container healthcheck as LivenessProbe in generate kube
Signed-off-by: Devesh B <98201065+DeveshB-1@users.noreply.github.com> Signed-off-by: givensuman <givensuman@duck.com>
1 parent ef2117a commit c821c01

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

libpod/kube.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/sirupsen/logrus"
2121
"go.podman.io/common/libnetwork/types"
2222
"go.podman.io/common/pkg/config"
23+
"go.podman.io/image/v5/manifest"
2324
"go.podman.io/podman/v6/libpod/define"
2425
"go.podman.io/podman/v6/pkg/domain/entities"
2526
"go.podman.io/podman/v6/pkg/env"
@@ -1073,9 +1074,39 @@ func containerToV1Container(ctx context.Context, c *Container, getService bool)
10731074
}
10741075
dns.Options = dnsOptions
10751076
}
1077+
1078+
if hc := c.config.HealthCheckConfig; hc != nil {
1079+
kubeContainer.LivenessProbe = healthConfigToProbe(hc)
1080+
}
1081+
10761082
return kubeContainer, kubeVolumes, &dns, annotations, nil
10771083
}
10781084

1085+
// healthConfigToProbe converts a container's Schema2HealthConfig into a
1086+
// Kubernetes Probe for use as a LivenessProbe in generated kube YAML.
1087+
func healthConfigToProbe(hc *manifest.Schema2HealthConfig) *v1.Probe {
1088+
// Test[0] is the type: NONE, CMD, or CMD-SHELL. NONE means disabled.
1089+
if hc == nil || len(hc.Test) == 0 || hc.Test[0] == define.HealthConfigTestNone {
1090+
return nil
1091+
}
1092+
1093+
probe := &v1.Probe{
1094+
Handler: v1.Handler{
1095+
Exec: &v1.ExecAction{Command: hc.Test[1:]},
1096+
},
1097+
InitialDelaySeconds: int32(hc.StartPeriod.Seconds()),
1098+
TimeoutSeconds: int32(hc.Timeout.Seconds()),
1099+
PeriodSeconds: int32(hc.Interval.Seconds()),
1100+
FailureThreshold: int32(hc.Retries),
1101+
}
1102+
1103+
if hc.Test[0] == define.HealthConfigTestCmdShell {
1104+
probe.Handler.Exec.Command = append([]string{"/bin/sh", "-c"}, hc.Test[1:]...)
1105+
}
1106+
1107+
return probe
1108+
}
1109+
10791110
// portMappingToContainerPort takes a portmapping and converts
10801111
// it to a v1.ContainerPort format for kube output
10811112
func portMappingToContainerPort(portMappings []types.PortMapping, getService bool) ([]v1.ContainerPort, error) {

test/e2e/generate_kube_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2001,4 +2001,66 @@ EXPOSE 2004-2005/tcp`, CITEST_IMAGE)
20012001
kube.WaitWithDefaultTimeout()
20022002
Expect(kube).Should(ExitWithError(125, "k8s DaemonSets can only have restartPolicy set to Always"))
20032003
})
2004+
2005+
It("on container with healthcheck exports LivenessProbe", func() {
2006+
ctrName := "test-hc-ctr"
2007+
session := podmanTest.Podman([]string{
2008+
"create", "--name", ctrName,
2009+
"--health-cmd", "CMD /bin/true",
2010+
"--health-interval", "10s",
2011+
"--health-timeout", "5s",
2012+
"--health-retries", "3",
2013+
"--health-start-period", "2s",
2014+
CITEST_IMAGE, "top",
2015+
})
2016+
session.WaitWithDefaultTimeout()
2017+
Expect(session).Should(ExitCleanly())
2018+
2019+
kube := podmanTest.Podman([]string{"kube", "generate", ctrName})
2020+
kube.WaitWithDefaultTimeout()
2021+
Expect(kube).Should(ExitCleanly())
2022+
2023+
pod := new(v1.Pod)
2024+
err := yaml.Unmarshal(kube.Out.Contents(), pod)
2025+
Expect(err).ToNot(HaveOccurred())
2026+
Expect(pod.Spec.Containers).To(HaveLen(1))
2027+
2028+
probe := pod.Spec.Containers[0].LivenessProbe
2029+
Expect(probe).ToNot(BeNil(), "LivenessProbe should be set when container has a healthcheck")
2030+
Expect(probe.Exec).ToNot(BeNil())
2031+
Expect(probe.Exec.Command).To(ContainElement("/bin/true"))
2032+
Expect(probe.PeriodSeconds).To(Equal(int32(10)))
2033+
Expect(probe.TimeoutSeconds).To(Equal(int32(5)))
2034+
Expect(probe.FailureThreshold).To(Equal(int32(3)))
2035+
Expect(probe.InitialDelaySeconds).To(Equal(int32(2)))
2036+
})
2037+
2038+
It("on container with CMD-SHELL healthcheck wraps LivenessProbe with /bin/sh -c", func() {
2039+
ctrName := "test-hc-shell-ctr"
2040+
session := podmanTest.Podman([]string{
2041+
"create", "--name", ctrName,
2042+
"--health-cmd", "CMD-SHELL /bin/true",
2043+
"--health-interval", "10s",
2044+
"--health-timeout", "5s",
2045+
"--health-retries", "3",
2046+
"--health-start-period", "2s",
2047+
CITEST_IMAGE, "top",
2048+
})
2049+
session.WaitWithDefaultTimeout()
2050+
Expect(session).Should(ExitCleanly())
2051+
2052+
kube := podmanTest.Podman([]string{"kube", "generate", ctrName})
2053+
kube.WaitWithDefaultTimeout()
2054+
Expect(kube).Should(ExitCleanly())
2055+
2056+
pod := new(v1.Pod)
2057+
err := yaml.Unmarshal(kube.Out.Contents(), pod)
2058+
Expect(err).ToNot(HaveOccurred())
2059+
Expect(pod.Spec.Containers).To(HaveLen(1))
2060+
2061+
probe := pod.Spec.Containers[0].LivenessProbe
2062+
Expect(probe).ToNot(BeNil(), "LivenessProbe should be set when container has a healthcheck")
2063+
Expect(probe.Exec).ToNot(BeNil())
2064+
Expect(probe.Exec.Command).To(Equal([]string{"/bin/sh", "-c", "/bin/true"}))
2065+
})
20042066
})

0 commit comments

Comments
 (0)