Skip to content

Commit

Permalink
Add support for using port names in Kubernetes health probes
Browse files Browse the repository at this point in the history
Closes #18645

Signed-off-by: Hedayat Vatankhah <hedayat.fwd@gmail.com>
  • Loading branch information
hedayat authored and ashley-cui committed Jul 20, 2023
1 parent 5445bd6 commit 6817e0a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 6 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ require (
github.com/vbauerster/mpb/v8 v8.4.0
github.com/vishvananda/netlink v1.2.1-beta.2
go.etcd.io/bbolt v1.3.7
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/net v0.11.0
golang.org/x/sync v0.3.0
golang.org/x/sys v0.9.0
Expand Down Expand Up @@ -166,7 +167,6 @@ require (
go.opentelemetry.io/otel v1.15.0 // indirect
go.opentelemetry.io/otel/trace v1.15.0 // indirect
golang.org/x/crypto v0.10.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/oauth2 v0.9.0 // indirect
golang.org/x/tools v0.9.3 // indirect
Expand Down
34 changes: 29 additions & 5 deletions pkg/specgen/generate/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/containers/podman/v4/pkg/domain/entities"
v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/api/resource"
"github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/util/intstr"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/containers/podman/v4/pkg/specgen/generate"
systemdDefine "github.com/containers/podman/v4/pkg/systemd/define"
Expand All @@ -35,6 +36,7 @@ import (
"github.com/docker/go-units"
spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"golang.org/x/exp/slices"
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -563,7 +565,7 @@ func parseMountPath(mountPath string, readOnly bool, propagationMode *v1.MountPr
return dest, opts, nil
}

func probeToHealthConfig(probe *v1.Probe) (*manifest.Schema2HealthConfig, error) {
func probeToHealthConfig(probe *v1.Probe, containerPorts []v1.ContainerPort) (*manifest.Schema2HealthConfig, error) {
var commandString string
failureCmd := "exit 1"
probeHandler := probe.Handler
Expand Down Expand Up @@ -591,21 +593,43 @@ func probeToHealthConfig(probe *v1.Probe) (*manifest.Schema2HealthConfig, error)
if probeHandler.HTTPGet.Path != "" {
path = probeHandler.HTTPGet.Path
}
commandString = fmt.Sprintf("curl -f %s://%s:%d%s || %s", uriScheme, host, probeHandler.HTTPGet.Port.IntValue(), path, failureCmd)
portNum, err := getPortNumber(probeHandler.HTTPGet.Port, containerPorts)
if err != nil {
return nil, err
}
commandString = fmt.Sprintf("curl -f %s://%s:%d%s || %s", uriScheme, host, portNum, path, failureCmd)
case probeHandler.TCPSocket != nil:
commandString = fmt.Sprintf("nc -z -v %s %d || %s", probeHandler.TCPSocket.Host, probeHandler.TCPSocket.Port.IntValue(), failureCmd)
portNum, err := getPortNumber(probeHandler.TCPSocket.Port, containerPorts)
if err != nil {
return nil, err
}
commandString = fmt.Sprintf("nc -z -v %s %d || %s", probeHandler.TCPSocket.Host, portNum, failureCmd)
}
return makeHealthCheck(commandString, probe.PeriodSeconds, probe.FailureThreshold, probe.TimeoutSeconds, probe.InitialDelaySeconds)
}

func getPortNumber(port intstr.IntOrString, containerPorts []v1.ContainerPort) (int, error) {
var portNum int
if port.Type == intstr.String && port.IntValue() == 0 {
idx := slices.IndexFunc(containerPorts, func(cp v1.ContainerPort) bool { return cp.Name == port.String() })
if idx == -1 {
return 0, fmt.Errorf("unknown port: %s", port.String())
}
portNum = int(containerPorts[idx].ContainerPort)
} else {
portNum = port.IntValue()
}
return portNum, nil
}

func setupLivenessProbe(s *specgen.SpecGenerator, containerYAML v1.Container, restartPolicy string) error {
var err error
if containerYAML.LivenessProbe == nil {
return nil
}
emptyHandler := v1.Handler{}
if containerYAML.LivenessProbe.Handler != emptyHandler {
s.HealthConfig, err = probeToHealthConfig(containerYAML.LivenessProbe)
s.HealthConfig, err = probeToHealthConfig(containerYAML.LivenessProbe, containerYAML.Ports)
if err != nil {
return err
}
Expand All @@ -624,7 +648,7 @@ func setupStartupProbe(s *specgen.SpecGenerator, containerYAML v1.Container, res
}
emptyHandler := v1.Handler{}
if containerYAML.StartupProbe.Handler != emptyHandler {
healthConfig, err := probeToHealthConfig(containerYAML.StartupProbe)
healthConfig, err := probeToHealthConfig(containerYAML.StartupProbe, containerYAML.Ports)
if err != nil {
return err
}
Expand Down
24 changes: 24 additions & 0 deletions pkg/specgen/generate/kube/kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"testing"

v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/containers/podman/v4/pkg/k8s.io/apimachinery/pkg/util/intstr"
"github.com/stretchr/testify/assert"
)

Expand Down Expand Up @@ -39,3 +40,26 @@ func TestParseMountPathRO(t *testing.T) {
assert.NoError(t, err)
assert.NotContains(t, options, "ro")
}

func TestGetPortNumber(t *testing.T) {
portSpec := intstr.IntOrString{Type: intstr.Int, IntVal: 3000, StrVal: "myport"}
cp1 := v1.ContainerPort{Name: "myport", ContainerPort: 4000}
cp2 := v1.ContainerPort{Name: "myport2", ContainerPort: 5000}
i, e := getPortNumber(portSpec, []v1.ContainerPort{cp1, cp2})
assert.NoError(t, e)
assert.Equal(t, i, int(portSpec.IntVal))

portSpec.Type = intstr.String
i, e = getPortNumber(portSpec, []v1.ContainerPort{cp1, cp2})
assert.NoError(t, e)
assert.Equal(t, i, 4000)

portSpec.StrVal = "not_valid"
_, e = getPortNumber(portSpec, []v1.ContainerPort{cp1, cp2})
assert.Error(t, e)

portSpec.StrVal = "6000"
i, e = getPortNumber(portSpec, []v1.ContainerPort{cp1, cp2})
assert.NoError(t, e)
assert.Equal(t, i, 6000)
}

0 comments on commit 6817e0a

Please sign in to comment.