mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-08 12:41:58 +00:00
Adding ResourceRequirementSpec to v1beta1, v1beta2, and v1beta3 APIs. The old resource
quantities 'CPU' and 'Memory' will be preserved until support for v1beta1 and v1beta2 APIs are dropped. Improved resource validation in the process.
This commit is contained in:
@@ -103,8 +103,8 @@ func PodLimitFunc(limitRange *api.LimitRange, kind string, obj runtime.Object) e
|
||||
|
||||
for i := range pod.Spec.Containers {
|
||||
container := pod.Spec.Containers[i]
|
||||
containerCPU := container.CPU.MilliValue()
|
||||
containerMem := container.Memory.Value()
|
||||
containerCPU := container.Resources.Limits.Cpu().MilliValue()
|
||||
containerMem := container.Resources.Limits.Memory().Value()
|
||||
|
||||
if i == 0 {
|
||||
minContainerCPU = containerCPU
|
||||
@@ -113,8 +113,8 @@ func PodLimitFunc(limitRange *api.LimitRange, kind string, obj runtime.Object) e
|
||||
maxContainerMem = containerMem
|
||||
}
|
||||
|
||||
podCPU = podCPU + container.CPU.MilliValue()
|
||||
podMem = podMem + container.Memory.Value()
|
||||
podCPU = podCPU + container.Resources.Limits.Cpu().MilliValue()
|
||||
podMem = podMem + container.Resources.Limits.Memory().Value()
|
||||
|
||||
minContainerCPU = Min(containerCPU, minContainerCPU)
|
||||
minContainerMem = Min(containerMem, minContainerMem)
|
||||
|
@@ -23,6 +23,19 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/resource"
|
||||
)
|
||||
|
||||
func getResourceRequirements(cpu, memory string) api.ResourceRequirementSpec {
|
||||
res := api.ResourceRequirementSpec{}
|
||||
res.Limits = api.ResourceList{}
|
||||
if cpu != "" {
|
||||
res.Limits[api.ResourceCPU] = resource.MustParse(cpu)
|
||||
}
|
||||
if memory != "" {
|
||||
res.Limits[api.ResourceMemory] = resource.MustParse(memory)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func TestPodLimitFunc(t *testing.T) {
|
||||
limitRange := &api.LimitRange{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
@@ -32,25 +45,13 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Limits: []api.LimitRangeItem{
|
||||
{
|
||||
Type: api.LimitTypePod,
|
||||
Max: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("200m"),
|
||||
api.ResourceMemory: resource.MustParse("4Gi"),
|
||||
},
|
||||
Min: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("50m"),
|
||||
api.ResourceMemory: resource.MustParse("2Mi"),
|
||||
},
|
||||
Max: getResourceRequirements("200m", "4Gi").Limits,
|
||||
Min: getResourceRequirements("50m", "2Mi").Limits,
|
||||
},
|
||||
{
|
||||
Type: api.LimitTypeContainer,
|
||||
Max: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("100m"),
|
||||
api.ResourceMemory: resource.MustParse("2Gi"),
|
||||
},
|
||||
Min: api.ResourceList{
|
||||
api.ResourceCPU: resource.MustParse("25m"),
|
||||
api.ResourceMemory: resource.MustParse("1Mi"),
|
||||
},
|
||||
Max: getResourceRequirements("100m", "2Gi").Limits,
|
||||
Min: getResourceRequirements("25m", "1Mi").Limits,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -62,14 +63,12 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "foo:V1",
|
||||
CPU: resource.MustParse("100m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "foo:V1",
|
||||
Resources: getResourceRequirements("100m", "2Gi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("100m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("100m", "2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -79,9 +78,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("100m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("100m", "2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -94,9 +92,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("25m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("25m", "2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -106,9 +103,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("110m"),
|
||||
Memory: resource.MustParse("1Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("110m", "1Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -118,9 +114,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("30m"),
|
||||
Memory: resource.MustParse("0"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("30m", "0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -130,9 +125,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("30m"),
|
||||
Memory: resource.MustParse("3Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("30m", "3Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -142,9 +136,8 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("40m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("40m", "2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -154,24 +147,20 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("1Mi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("60m", "1Mi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V2",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("1Mi"),
|
||||
Image: "boo:V2",
|
||||
Resources: getResourceRequirements("60m", "1Mi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V3",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("1Mi"),
|
||||
Image: "boo:V3",
|
||||
Resources: getResourceRequirements("60m", "1Mi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V4",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("1Mi"),
|
||||
Image: "boo:V4",
|
||||
Resources: getResourceRequirements("60m", "1Mi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -181,19 +170,16 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("60m", "2Gi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V2",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V2",
|
||||
Resources: getResourceRequirements("60m", "2Gi"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V3",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("2Gi"),
|
||||
Image: "boo:V3",
|
||||
Resources: getResourceRequirements("60m", "2Gi"),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -203,19 +189,16 @@ func TestPodLimitFunc(t *testing.T) {
|
||||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Image: "boo:V1",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("0"),
|
||||
Image: "boo:V1",
|
||||
Resources: getResourceRequirements("60m", "0"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V2",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("0"),
|
||||
Image: "boo:V2",
|
||||
Resources: getResourceRequirements("60m", "0"),
|
||||
},
|
||||
{
|
||||
Image: "boo:V3",
|
||||
CPU: resource.MustParse("60m"),
|
||||
Memory: resource.MustParse("0"),
|
||||
Image: "boo:V3",
|
||||
Resources: getResourceRequirements("60m", "0"),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@@ -55,11 +55,12 @@ func (resourceDefaults) Admit(a admission.Attributes) (err error) {
|
||||
obj := a.GetObject()
|
||||
pod := obj.(*api.Pod)
|
||||
for index := range pod.Spec.Containers {
|
||||
if pod.Spec.Containers[index].Memory.Value() == 0 {
|
||||
pod.Spec.Containers[index].Memory = resource.MustParse(defaultMemory)
|
||||
pod.Spec.Containers[index].Resources.Limits = api.ResourceList{}
|
||||
if pod.Spec.Containers[index].Resources.Limits.Memory().Value() == 0 {
|
||||
pod.Spec.Containers[index].Resources.Limits[api.ResourceMemory] = resource.MustParse(defaultMemory)
|
||||
}
|
||||
if pod.Spec.Containers[index].CPU.Value() == 0 {
|
||||
pod.Spec.Containers[index].CPU = resource.MustParse(defaultCPU)
|
||||
if pod.Spec.Containers[index].Resources.Limits.Cpu().Value() == 0 {
|
||||
pod.Spec.Containers[index].Resources.Limits[api.ResourceCPU] = resource.MustParse(defaultCPU)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
@@ -41,11 +41,13 @@ func TestAdmission(t *testing.T) {
|
||||
}
|
||||
|
||||
for i := range pod.Spec.Containers {
|
||||
if pod.Spec.Containers[i].Memory.String() != "512Mi" {
|
||||
t.Errorf("Unexpected memory value %s", pod.Spec.Containers[i].Memory.String())
|
||||
memory := pod.Spec.Containers[i].Resources.Limits.Memory().String()
|
||||
cpu := pod.Spec.Containers[i].Resources.Limits.Cpu().String()
|
||||
if memory != "512Mi" {
|
||||
t.Errorf("Unexpected memory value %s", memory)
|
||||
}
|
||||
if pod.Spec.Containers[i].CPU.String() != "1" {
|
||||
t.Errorf("Unexpected cpu value %s", pod.Spec.Containers[i].CPU.String())
|
||||
if cpu != "1" {
|
||||
t.Errorf("Unexpected cpu value %s", cpu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,19 @@ import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
)
|
||||
|
||||
func getResourceRequirements(cpu, memory string) api.ResourceRequirementSpec {
|
||||
res := api.ResourceRequirementSpec{}
|
||||
res.Limits = api.ResourceList{}
|
||||
if cpu != "" {
|
||||
res.Limits[api.ResourceCPU] = resource.MustParse(cpu)
|
||||
}
|
||||
if memory != "" {
|
||||
res.Limits[api.ResourceMemory] = resource.MustParse(memory)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func TestAdmissionIgnoresDelete(t *testing.T) {
|
||||
namespace := "default"
|
||||
handler := NewResourceQuota(&client.Fake{})
|
||||
@@ -43,7 +56,7 @@ func TestIncrementUsagePods(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -78,7 +91,7 @@ func TestIncrementUsageMemory(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -96,7 +109,7 @@ func TestIncrementUsageMemory(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
}}
|
||||
dirty, err := IncrementUsage(admission.NewAttributesRecord(newPod, namespace, "pods", "CREATE"), status, client)
|
||||
if err != nil {
|
||||
@@ -121,7 +134,7 @@ func TestExceedUsageMemory(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -139,7 +152,7 @@ func TestExceedUsageMemory(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("3Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "3Gi")}},
|
||||
}}
|
||||
_, err := IncrementUsage(admission.NewAttributesRecord(newPod, namespace, "pods", "CREATE"), status, client)
|
||||
if err == nil {
|
||||
@@ -156,7 +169,7 @@ func TestIncrementUsageCPU(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -174,7 +187,7 @@ func TestIncrementUsageCPU(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
}}
|
||||
dirty, err := IncrementUsage(admission.NewAttributesRecord(newPod, namespace, "pods", "CREATE"), status, client)
|
||||
if err != nil {
|
||||
@@ -199,7 +212,7 @@ func TestExceedUsageCPU(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -217,7 +230,7 @@ func TestExceedUsageCPU(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("500m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("500m", "1Gi")}},
|
||||
}}
|
||||
_, err := IncrementUsage(admission.NewAttributesRecord(newPod, namespace, "pods", "CREATE"), status, client)
|
||||
if err == nil {
|
||||
@@ -234,7 +247,7 @@ func TestExceedUsagePods(t *testing.T) {
|
||||
ObjectMeta: api.ObjectMeta{Name: "123", Namespace: namespace},
|
||||
Spec: api.PodSpec{
|
||||
Volumes: []api.Volume{{Name: "vol"}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Memory: resource.MustParse("1Gi"), CPU: resource.MustParse("100m")}},
|
||||
Containers: []api.Container{{Name: "ctr", Image: "image", Resources: getResourceRequirements("100m", "1Gi")}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
Reference in New Issue
Block a user