/zero-pod-autoscaler

tcp proxy that scales Deployment resource to zero

Primary LanguageGoApache License 2.0Apache-2.0

Zero Pod Autoscaler

Zero Pod Autoscaler (ZPA) manages a Deployment resource. It can scale the Deployment all the way down to zero replicas when it is not in use. It can work alongside an HPA: when scaled to zero, the HPA ignores the Deployment; once scaled back to one, the HPA may scale up further.

To do this, ZPA is a TCP proxy in front of the Service load balancing a Deployment. This allows the ZPA to track the number of connections and scale the Deployment to zero when the connection count has been zero for some time period.

If scaled to zero, an incoming connection triggers a scale-to-one action. Once Service's Endpoints include a "ready" address, the connection can complete, hopefully before the client times out.

Status

Alpha-quality. Currently deployed successfully for some internal use-cases. Currently recommended for use only if willing to read and/or customize the code.

Usage

Usage is awkward, certainly more difficult than using an HPA.

The ZPA points to an existing Deployment resource with a corresponding Service resource and needs three main configuration parameters:

  • name of the Deployment
  • name of the Endpoints associated with the Service
  • target address:port to which requests should be proxied (typically the Service name and port)

The ZPA then consists of another Deployment of the ZPA and another Service selecting the ZPA pods. Instead of connecting to the original Service, clients must connect to the ZPA Service resource.

Finally, the ZPA needs a service account with sufficient permissions to watch Endpoints and scale Deployments.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myzpa
  labels:
    app.kubernetes.io/name: myzpa
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: myzpa
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myzpa
    spec:
      serviceAccountName: zpa
      containers:
      - name: zpa
        image: greenkeytech/zero-pod-autoscaler:0.4.0
        imagePullPolicy: IfNotPresent
        args:
        - --namespace=$(NAMESPACE)
        - --address=0.0.0.0:80
        - --deployment=myapp
        - --endpoints=myapp
        - --target=myapp:80
        ports:
        - name: proxy
          protocol: TCP
          containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
  name: myzpa
spec:
  type: ClusterIP
  ports:
  - name: http
    port: 80
    targetPort: proxy
    protocol: TCP
  selector:
    app.kubernetes.io/name: myzpa
    
---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: zpa

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-deployments
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch"]

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: scale-deployments
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "deployments/scale"]
  verbs: ["patch", "update"]

---

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-endpoints
rules:
- apiGroups: [""]
  resources: ["endpoints"]
  verbs: ["get", "list", "watch"]

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: zpa-read-endpoints
subjects:
- kind: ServiceAccount
  name: zpa
roleRef:
  kind: Role
  name: read-endpoints
  apiGroup: rbac.authorization.k8s.io

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: zpa-read-deployments
subjects:
- kind: ServiceAccount
  name: zpa
roleRef:
  kind: Role
  name: read-deployments
  apiGroup: rbac.authorization.k8s.io

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: zpa-scale-deployments
subjects:
- kind: ServiceAccount
  name: zpa
roleRef:
  kind: Role
  name: scale-deployments
  apiGroup: rbac.authorization.k8s.io