Skip to content

Repos du guerrier

Estimated time to read: 3 minutes

Vu qu'on a bien travaillé, on peut se reposer un peu et nos pods aussi, on va donc mettre en place kube-downscaler pour éteindre nos workloads lors des temps de pause.

Installation

kube-downscaler est un projet plus récent, il n'est pas encore très industrialisé donc il est nécessaire de faire quelques adaptations pour le déployer:

  • changer le namespace default en kube-downscaler dans deploy/rbac.yml
  • désactiver le mode dry-run dans deploy/deployment.yml
  • (pour la démo) réduire la grace period de prise en compte des composants à 0min (plutôt que 15 par défaut) dans deploy/deployment.yml
  • (pour la démo) appliquer uniquement les policies sur le namespace demos dans deploy/deployment.yml
    - --grace-period=0
    - --namespace=demos
Pour les curieux, les fichiers rbac.yml et deployment.yml

rbac.yml:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-downscaler
  namespace: kube-downscaler
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kube-downscaler
  namespace: kube-downscaler
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - watch
  - list
- apiGroups:
  - apps
  resources:
  - deployments
  - statefulsets
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - argoproj.io
  resources:
  - rollouts
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - autoscaling
  resources:
  - horizontalpodautoscalers
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - batch
  resources:
  - cronjobs
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - keda.sh
  resources:
  - scaledobjects
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - zalando.org
  resources:
  - stacks
  verbs:
  - get
  - watch
  - list
  - update
  - patch
- apiGroups:
  - ""
  resources:
  - events
  verbs:
  - get
  - create
  - watch
  - list
  - update
  - patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-downscaler
  namespace: kube-downscaler
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: kube-downscaler
subjects:
- kind: ServiceAccount
  name: kube-downscaler
  namespace: kube-downscaler

deployment.yml:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    application: kube-downscaler
    version: v23.2.0
  name: kube-downscaler
  namespace: kube-downscaler
spec:
  replicas: 1
  selector:
    matchLabels:
      application: kube-downscaler
  template:
    metadata:
      labels:
        application: kube-downscaler
        version: v23.2.0
    spec:
      serviceAccountName: kube-downscaler
      containers:
      - name: downscaler
        image: hjacobs/kube-downscaler:23.2.0
        args:
          # dry run by default, remove to perform downscaling
          #- --dry-run
          - --interval=2
          - --grace-period=0
          - --namespace=demos
        envFrom:
          - configMapRef:
              name: kube-downscaler
              optional: true
        resources:
          limits:
            memory: 100Mi
          requests:
            cpu: 5m
            memory: 100Mi
        securityContext:
          readOnlyRootFilesystem: true
          runAsNonRoot: true
          runAsUser: 1000

Les fichiers sont dans le répertoire kube-downscaler/deploy, on utilise kustomize pour déployer (contrairement à Helm les autres fois).

kubectl apply -k kube-downscaler/deploy/ # (1)
  1. On utilise -k au lieu du -f habituel

Tout est créé

namespace/kube-downscaler created
serviceaccount/kube-downscaler created
clusterrole.rbac.authorization.k8s.io/kube-downscaler created
clusterrolebinding.rbac.authorization.k8s.io/kube-downscaler created
configmap/kube-downscaler created
deployment.apps/kube-downscaler created    

On vérifie que tout est ok

kubectl get all -n kube-downscaler

Tout est opérationnel

NAME                                  READY   STATUS    RESTARTS   AGE
pod/kube-downscaler-f5cbb6cfc-f2j9w   1/1     Running   0          39s

NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kube-downscaler   1/1     1            1           39s

NAME                                        DESIRED   CURRENT   READY   AGE
replicaset.apps/kube-downscaler-f5cbb6cfc   1         1         1       39s    

Test

Vu qu'on aime pas trop bosser, on va configurer kube-downscaler pour que nos pods ne soient démarrés que le lundi de 7h30 à 18h 🫢

  annotations:
    downscaler/uptime: Mon-Mon 07:30-18:00 CET
    downscaler/force-downtime: "true"

Pour cela, on annote notre namespace demos pour qu'il ne soit up que sur cette période.

NB: kube-dowscaler peut être configuré à différents niveaux, on aurait pu annoter les deployments directement plutôt que le namespace.

kubectl annotate ns demos 'downscaler/uptime=Mon-Mon 07:30-18:00 CET'

Le namespace est annoté pour s'éteindre

kubectl describe ns demos
Name:         demos
Labels:       kubernetes.io/metadata.name=demos
Annotations:  downscaler/uptime: Mon-Fri 21:30-23:30 CET
Status:       Active

No resource quota.

No LimitRange resource.    

On peut voir immédiatement que nos pods sont éteints et que nos déploiements sont à 0

Tout est éteint

kubectl get po -n demos
No resources found in demos namespace

et les déploiements

kubectl get deploy -n demos
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
asciinematic-hardened   0/0     0            0           156m
new-deployment          0/0     0            0           28h
simple-deployment       0/0     0            0           28h    

On peut voir dans les logs de kube-downscaler qu'il a traité notre configuration

kubectl logs -f $(kubectl get po -n kube-downscaler | grep kube-downscaler | cut -d' ' -f1) -n kube-downscaler

Info

2023-12-20 18:28:55,501 INFO: Downscaler v23.2.0 started with debug=False, default_downtime=never, default_uptime=Mon-Fri 07:30-20:30 CET, deployment_time_annotation=None, downscale_period=never, downtime_replicas=0, dry_run=False, enable_events=False, exclude_deployments=kube-downscaler,downscaler, exclude_namespaces=kube-system, grace_period=0, include_resources=deployments, interval=2, namespace=demos, once=False, upscale_period=never
2023-12-20 18:47:29,649 INFO: Scaling down Deployment demos/asciinematic-hardened from 1 to 0 replicas (uptime: Mon-Fri 21:30-23:30 CET, downtime: never)
2023-12-20 18:47:29,675 INFO: Scaling down Deployment demos/new-deployment from 1 to 0 replicas (uptime: Mon-Fri 21:30-23:30 CET, downtime: never)
2023-12-20 18:47:29,700 INFO: Scaling down Deployment demos/simple-deployment from 1 to 0 replicas (uptime: Mon-Fri 21:30-23:30 CET, downtime: never)

Voilà, on a une recette bien complète, faisons un petit récapitulatif ➡️