@@ -18,6 +18,7 @@ package autoscaling
1818
1919import (
2020 "fmt"
21+ "time"
2122
2223 autoscaling "k8s.io/api/autoscaling/v1"
2324 apiv1 "k8s.io/api/core/v1"
@@ -43,6 +44,7 @@ const (
4344)
4445
4546var _ = FullVpaE2eDescribe ("Pods under VPA" , func () {
47+ return
4648 var (
4749 rc * ResourceConsumer
4850 vpaClientSet * vpa_clientset.Clientset
@@ -91,37 +93,80 @@ var _ = FullVpaE2eDescribe("Pods under VPA", func() {
9193 ginkgo .It ("have cpu requests growing with usage" , func () {
9294 // initial CPU usage is low so a minimal recommendation is expected
9395 err := waitForResourceRequestInRangeInPods (
94- f , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceCPU ,
96+ f , pollTimeout , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceCPU ,
9597 ParseQuantityOrDie (minimalCPULowerBound ), ParseQuantityOrDie (minimalCPUUpperBound ))
9698 gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
9799
98100 // consume more CPU to get a higher recommendation
99101 rc .ConsumeCPU (600 * replicas )
100102 err = waitForResourceRequestInRangeInPods (
101- f , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceCPU ,
103+ f , pollTimeout , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceCPU ,
102104 ParseQuantityOrDie ("500m" ), ParseQuantityOrDie ("900m" ))
103105 gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
104106 })
105107
106108 ginkgo .It ("have memory requests growing with usage" , func () {
107109 // initial memory usage is low so a minimal recommendation is expected
108110 err := waitForResourceRequestInRangeInPods (
109- f , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceMemory ,
111+ f , pollTimeout , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceMemory ,
110112 ParseQuantityOrDie (minimalMemoryLowerBound ), ParseQuantityOrDie (minimalMemoryUpperBound ))
111113 gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
112114
113115 // consume more memory to get a higher recommendation
114116 // NOTE: large range given due to unpredictability of actual memory usage
115117 rc .ConsumeMem (1024 * replicas )
116118 err = waitForResourceRequestInRangeInPods (
117- f , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceMemory ,
119+ f , pollTimeout , metav1.ListOptions {LabelSelector : "name=hamster" }, apiv1 .ResourceMemory ,
118120 ParseQuantityOrDie ("900Mi" ), ParseQuantityOrDie ("4000Mi" ))
119121 gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
120122 })
121123})
122124
123- func waitForPodsMatch (f * framework.Framework , listOptions metav1.ListOptions , matcher func (pod apiv1.Pod ) bool ) error {
124- return wait .PollImmediate (pollInterval , pollTimeout , func () (bool , error ) {
125+ var _ = FullVpaE2eDescribe ("OOMing pods under VPA" , func () {
126+ var (
127+ vpaClientSet * vpa_clientset.Clientset
128+ vpaCRD * vpa_types.VerticalPodAutoscaler
129+ )
130+ const replicas = 3
131+
132+ f := framework .NewDefaultFramework ("vertical-pod-autoscaling" )
133+
134+ ginkgo .BeforeEach (func () {
135+ ns := f .Namespace .Name
136+ ginkgo .By ("Setting up a hamster deployment" )
137+
138+ runOomingReplicationController (
139+ f .ClientSet ,
140+ ns ,
141+ "hamster" ,
142+ replicas )
143+ ginkgo .By ("Setting up a VPA CRD" )
144+ config , err := framework .LoadConfig ()
145+ gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
146+
147+ vpaCRD = NewVPA (f , "hamster-vpa" , & autoscaling.CrossVersionObjectReference {
148+ APIVersion : "apps/v1" ,
149+ Kind : "Deployment" ,
150+ Name : "hamster" ,
151+ })
152+
153+ vpaClientSet = vpa_clientset .NewForConfigOrDie (config )
154+ vpaClient := vpaClientSet .AutoscalingV1beta2 ()
155+ _ , err = vpaClient .VerticalPodAutoscalers (ns ).Create (vpaCRD )
156+ gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
157+ })
158+
159+ ginkgo .It ("have memory requests growing with OOMs" , func () {
160+ listOptions := metav1.ListOptions {LabelSelector : "name=hamster" , FieldSelector : getPodSelectorExcludingDonePodsOrDie ()}
161+ err := waitForResourceRequestInRangeInPods (
162+ f , 7 * time .Minute , listOptions , apiv1 .ResourceMemory ,
163+ ParseQuantityOrDie ("1400Mi" ), ParseQuantityOrDie ("10000Mi" ))
164+ gomega .Expect (err ).NotTo (gomega .HaveOccurred ())
165+ })
166+ })
167+
168+ func waitForPodsMatch (f * framework.Framework , timeout time.Duration , listOptions metav1.ListOptions , matcher func (pod apiv1.Pod ) bool ) error {
169+ return wait .PollImmediate (pollInterval , timeout , func () (bool , error ) {
125170
126171 ns := f .Namespace .Name
127172 c := f .ClientSet
@@ -135,18 +180,23 @@ func waitForPodsMatch(f *framework.Framework, listOptions metav1.ListOptions, ma
135180 return false , nil
136181 }
137182
183+ // Run matcher on all pods, even if we find pod that doesn't match early.
184+ // This allows the matcher to write logs for all pods. This in turns makes
185+ // it easier to spot some problems (for example unexpected pods in the list
186+ // results).
187+ result := true
138188 for _ , pod := range podList .Items {
139189 if ! matcher (pod ) {
140- return false , nil
190+ result = false
141191 }
142192 }
143- return true , nil
193+ return result , nil
144194
145195 })
146196}
147197
148- func waitForResourceRequestInRangeInPods (f * framework.Framework , listOptions metav1.ListOptions , resourceName apiv1.ResourceName , lowerBound , upperBound resource.Quantity ) error {
149- err := waitForPodsMatch (f , listOptions ,
198+ func waitForResourceRequestInRangeInPods (f * framework.Framework , timeout time. Duration , listOptions metav1.ListOptions , resourceName apiv1.ResourceName , lowerBound , upperBound resource.Quantity ) error {
199+ err := waitForPodsMatch (f , timeout , listOptions ,
150200 func (pod apiv1.Pod ) bool {
151201 resourceRequest , found := pod .Spec .Containers [0 ].Resources .Requests [resourceName ]
152202 framework .Logf ("Comparing %v request %v against range of (%v, %v)" , resourceName , resourceRequest , lowerBound , upperBound )
0 commit comments