feat: Add health check for HPA (#4915)

HorizontalPodAutoscaler uses annotations to store conditions. This commit adds a custom heath check that parses the conditions from annotation and creates health status.

Fixes: #4413

Signed-off-by: Chetan Banavikalmutt <chetanrns1997@gmail.com>
This commit is contained in:
Chetan Banavikalmutt
2020-12-01 23:14:10 +05:30
committed by GitHub
parent c108e2f061
commit f6a32a9ebc
6 changed files with 123 additions and 0 deletions

View File

@@ -0,0 +1,47 @@
local json = require("json")
health_status = {
status = "Progressing",
message = "Waiting to Autoscale"
}
function is_degraded( condition )
degraded_states = {
{"AbleToScale", "FailedGetScale"},
{"AbleToScale", "FailedUpdateScale"},
{"ScalingActive", "FailedGetResourceMetric"},
{"ScalingActive", "InvalidSelector"}
}
for i, state in ipairs(degraded_states) do
if condition.type == state[1] and condition.reason == state[2] then
return true
end
end
return false
end
condition_string = obj.metadata.annotations["autoscaling.alpha.kubernetes.io/conditions"]
if condition_string ~= nil then
conditions = json.decode(condition_string)
end
if conditions then
for i, condition in ipairs(conditions) do
if is_degraded(condition) then
health_status.status = "Degraded"
health_status.message = condition.message
return health_status
end
if condition.type == "AbleToScale" and condition.reason == "SucceededRescale" then
health_status.status = "Healthy"
health_status.message = condition.message
return health_status
end
if condition.type == "ScalingLimited" and condition.reason == "DesiredWithinRange" then
health_status.status = "Healthy"
health_status.message = condition.message
return health_status
end
end
end
return health_status

View File

@@ -0,0 +1,13 @@
tests:
- healthStatus:
status: Progressing
message: Waiting to Autoscale
inputPath: testdata/progressing_hpa.yaml
- healthStatus:
status: Healthy
message: the HPA controller was able to update the target scale to 1
inputPath: testdata/healthy_hpa.yaml
- healthStatus:
status: Degraded
message: the HPA controller was unable to get the target's current scale
inputPath: testdata/degraded_hpa.yaml

View File

@@ -0,0 +1,21 @@
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
annotations:
autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2020-11-23T19:38:38Z","reason":"FailedGetScale","message":"the HPA controller was unable to get the target''s current scale"},{"type":"ScalingActive","status":"False","lastTransitionTime":"2020-11-23T19:38:38Z","reason":"FailedGetResourceMetric","message":"the
HPA was unable to compute the replica count: unable to get metrics for resource
cpu: unable to fetch metrics from resource metrics API: the server is currently
unable to handle the request (get pods.metrics.k8s.io)"}]'
name: sample
namespace: argocd
spec:
maxReplicas: 1
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample
targetCPUUtilizationPercentage: 2
status:
currentReplicas: 1
desiredReplicas: 0

View File

@@ -0,0 +1,21 @@
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
annotations:
autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2020-11-23T19:38:38Z","reason":"SucceededRescale","message":"the HPA controller was able to update the target scale to 1"},{"type":"ScalingActive","status":"False","lastTransitionTime":"2020-11-23T19:38:38Z","reason":"FailedGetResourceMetric","message":"the
HPA was unable to compute the replica count: unable to get metrics for resource
cpu: unable to fetch metrics from resource metrics API: the server is currently
unable to handle the request (get pods.metrics.k8s.io)"}]'
name: sample
namespace: argocd
spec:
maxReplicas: 2
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample
targetCPUUtilizationPercentage: 2
status:
currentReplicas: 1
desiredReplicas: 1

View File

@@ -0,0 +1,18 @@
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
annotations:
autoscaling.alpha.kubernetes.io/conditions: '[{"type":"AbleToScale","status":"True","lastTransitionTime":"2020-11-23T19:38:38Z","reason":"SucceededGetScale","message":"the HPA controller was able to get the target''s current scale"}]'
name: sample
namespace: argocd
spec:
maxReplicas: 1
minReplicas: 1
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: sample
targetCPUUtilizationPercentage: 2
status:
currentReplicas: 1
desiredReplicas: 0

View File

@@ -88,6 +88,9 @@ func (vm VM) runLua(obj *unstructured.Unstructured, script string) (*lua.LState,
// preload our 'safe' version of the os library. Allows the 'local os = require("os")' to work
l.PreloadModule(lua.OsLibName, SafeOsLoader)
// preload json library to parse json in lua
luajson.Preload(l)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l.SetContext(ctx)