play kube: set defaults to container resources
this fixes https://github.com/containers/podman/issues/13115 the change tries to immitate k8s behavior. when limits are not set the container's limits are all CPU and all RAM when requests are missing then they are equal to limits Signed-off-by: Yaron Dayagi <ydayagi@redhat.com>
This commit is contained in:
parent
8b2432422f
commit
5cba5cbfdb
|
|
@ -7,6 +7,7 @@ import (
|
|||
"math"
|
||||
"net"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -22,6 +23,7 @@ import (
|
|||
"github.com/containers/podman/v4/pkg/specgen"
|
||||
"github.com/containers/podman/v4/pkg/specgen/generate"
|
||||
"github.com/containers/podman/v4/pkg/util"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/docker/go-units"
|
||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
|
|
@ -700,8 +702,12 @@ func envVarValueResourceFieldRef(env v1.EnvVar, opts *CtrSpecGenOptions) (*strin
|
|||
divisor.Set(1)
|
||||
}
|
||||
|
||||
resources, err := getContainerResources(opts.Container)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var value *resource.Quantity
|
||||
resources := opts.Container.Resources
|
||||
resourceName := env.ValueFrom.ResourceFieldRef.Resource
|
||||
var isValidDivisor bool
|
||||
|
||||
|
|
@ -757,6 +763,46 @@ func isCPUDivisor(divisor resource.Quantity) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func getContainerResources(container v1.Container) (v1.ResourceRequirements, error) {
|
||||
result := v1.ResourceRequirements{
|
||||
Limits: v1.ResourceList{},
|
||||
Requests: v1.ResourceList{},
|
||||
}
|
||||
|
||||
limits := container.Resources.Limits
|
||||
requests := container.Resources.Requests
|
||||
|
||||
if limits == nil || limits.Memory().IsZero() {
|
||||
mi, err := system.ReadMemInfo()
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result.Limits[v1.ResourceMemory] = *resource.NewQuantity(mi.MemTotal, resource.DecimalSI)
|
||||
} else {
|
||||
result.Limits[v1.ResourceMemory] = limits[v1.ResourceMemory]
|
||||
}
|
||||
|
||||
if limits == nil || limits.Cpu().IsZero() {
|
||||
result.Limits[v1.ResourceCPU] = *resource.NewQuantity(int64(runtime.NumCPU()), resource.DecimalSI)
|
||||
} else {
|
||||
result.Limits[v1.ResourceCPU] = limits[v1.ResourceCPU]
|
||||
}
|
||||
|
||||
if requests == nil || requests.Memory().IsZero() {
|
||||
result.Requests[v1.ResourceMemory] = result.Limits[v1.ResourceMemory]
|
||||
} else {
|
||||
result.Requests[v1.ResourceMemory] = requests[v1.ResourceMemory]
|
||||
}
|
||||
|
||||
if requests == nil || requests.Cpu().IsZero() {
|
||||
result.Requests[v1.ResourceCPU] = result.Limits[v1.ResourceCPU]
|
||||
} else {
|
||||
result.Requests[v1.ResourceCPU] = requests[v1.ResourceCPU]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getPodPorts converts a slice of kube container descriptions to an
|
||||
// array of portmapping
|
||||
func getPodPorts(containers []v1.Container) []types.PortMapping {
|
||||
|
|
|
|||
|
|
@ -6,10 +6,12 @@ import (
|
|||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/containers/common/pkg/secrets"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"github.com/stretchr/testify/assert"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
|
@ -193,6 +195,11 @@ func TestEnvVarValue(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(d)
|
||||
secretsManager := createSecrets(t, d)
|
||||
stringNumCPUs := strconv.Itoa(runtime.NumCPU())
|
||||
|
||||
mi, err := system.ReadMemInfo()
|
||||
assert.Nil(t, err)
|
||||
stringMemTotal := strconv.FormatInt(mi.MemTotal, 10)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
|
@ -694,6 +701,78 @@ func TestEnvVarValue(t *testing.T) {
|
|||
true,
|
||||
strconv.Itoa(int(float64(cpuInt) / 0.001)),
|
||||
},
|
||||
{
|
||||
"ResourceFieldRefNoLimitMemory",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
ResourceFieldRef: &v1.ResourceFieldSelector{
|
||||
Resource: "limits.memory",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Container: v1.Container{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
true,
|
||||
stringMemTotal,
|
||||
},
|
||||
{
|
||||
"ResourceFieldRefNoRequestMemory",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
ResourceFieldRef: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.memory",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Container: v1.Container{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
true,
|
||||
stringMemTotal,
|
||||
},
|
||||
{
|
||||
"ResourceFieldRefNoLimitCPU",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
ResourceFieldRef: &v1.ResourceFieldSelector{
|
||||
Resource: "limits.cpu",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Container: v1.Container{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
true,
|
||||
stringNumCPUs,
|
||||
},
|
||||
{
|
||||
"ResourceFieldRefNoRequestCPU",
|
||||
v1.EnvVar{
|
||||
Name: "FOO",
|
||||
ValueFrom: &v1.EnvVarSource{
|
||||
ResourceFieldRef: &v1.ResourceFieldSelector{
|
||||
Resource: "requests.cpu",
|
||||
},
|
||||
},
|
||||
},
|
||||
CtrSpecGenOptions{
|
||||
Container: v1.Container{
|
||||
Name: "test",
|
||||
},
|
||||
},
|
||||
true,
|
||||
stringNumCPUs,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
|||
Loading…
Reference in New Issue