Horizontal Pod Autoscaling for Docker Compose
Horizontal Pod Autoscaling requires metrics-server installed in the cluster.
HPA feature is supported for Application
, Service
and Database
component kinds.
HPA is allowed only for resulting K8s Deployment and StatefulSet. It's not supported for DaemonSets or Pods, this is a Kube restriction.
HPA is allowed only if you didn't set dockerCompose.deploy.replicas
on the component. Theoretically Kube allows this, but the behaviour will be hard to guess, when the HPA will be allowed to work, when the static replicas number will be enforced, so Bunnyshell forces you to choose one.
The HPA config needs to specify the min and max replicas to scale between, optionally the metrics used to trigger the scaling, and optionally the scaleUp and scaleDown behaviours, basically the scaling rate, how many Pods per unit of time, to spawn or to destroy.
components:
- kind: Service
name: nginx
dockerCompose:
image: nginx
deploy:
resources:
reservations:
cpus: 100m
memory: 100MiB
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- cpu: 70%
- memory: 80%
scaleUp:
policies:
- value: 100%
periodSeconds: 30
- value: 25%
periodSeconds: 300
scaleDown:
stabilizationWindowSeconds: 300
selectPolicy: Min
policies:
- value: 25%
periodSeconds: 30
- value: 1
periodSeconds: 60
Metrics
Kubernetes supports 5 metric types:
- Resource
- ContainerResource
- Pods
- Object
- External
Resource
and ContainerResource
are implemented by default in the metrics-server. For the custom metrics Pods
and Object
you may need extra tools and configs in cluster, also for the External
one.
type Resource
This metric refers to Pod resources, CPU or Memory. It is the default type in Bunnyshell, and it has an oversimplified syntax for it. Just specify the cpu or the memory property with either a percent value or an absolute one.
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- cpu: 60%
- cpu: 200m
- memory: 80%
- memory: 300Mi
You can have more cpu (or memory) metrics, although it may not make sense, but Kube will evaluate the current consumption and compare it with each declared metric and decide if it needs to trigger the scaling.
The way how HPA works in kubernetes, it requires the Pod to have set the resources.requests, because the HPA algorithm computes the used percentage relative to these requests values.
type ContainerResource
This is very similar with the Resource, just that it refers to a container resources and not the whole Pod. It's useful when you have a larger Pod, with a main container and many sidecars, and you want to control the scaling based on specific containers only.
This also has a very simple syntax in Bunnyshell, just add the type property. Optionally you can set also the container, if not set by default it means the main container.
Same as for the Resource one, at least the required container should have set the resources.requests.
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- type: ContainerResource
cpu: 60%
- type: ContainerResource
cpu: 200m
container: nginx
- type: ContainerResource
memory: 80%
container: nginx
- type: ContainerResource
memory: 300Mi
You can combine Resource type metrics with ContainerResource type, as said above, Kube will compute all the required metrics, compare them with specified values, and trigger the scaling or not.
type Pods
This is a custom metric, you may need extra tools and configuration in the cluster.
The Bunnyshell syntax is similar with the K8s one. matchLabels are optional.
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- type: Pods
metricName: pod_metric_name
matchLabels:
optional: value
averageValue: '100'
- type: Pods
metricName: phpfpm_active_processes_utilization
averageValue: 700m
type Object
This is a custom metric, you may need extra tools and configuration in the cluster.
The Bunnyshell syntax is similar with the K8s one. matchLabels are optional and it can use either value or averageValue.
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- type: Object
describedObject:
apiVersion: /v1
kind: Service
name: my-srv
metricName: obj_metric_name
matchLabels:
optional: value
value: '100'
- type: Object
describedObject:
apiVersion: /v1
kind: Service
name: rabbitmq
metricName: rabbitmq_queue_messages_ready
matchLabels:
queue: rabbit_queue_name
averageValue: "3"
type External
You may need extra tools and configuration in the cluster for this, but it allows to autoscale based on metrics that don't have an obvious relationship to any object in the Kubernetes cluster, such as metrics describing a hosted service with no direct correlation to Kubernetes namespaces.
The Bunnyshell syntax is similar with the K8s one. matchLabels are optional and it can use either value or averageValue.
hpa:
minReplicas: 1
maxReplicas: 3
metrics:
- type: External
metricName: ext_metric_name
matchLabels:
optional: value
value: '100'
- type: External
metricName: ext2_metric_name
averageValue: "3"
Updated about 1 month ago