Ce document a été traduit à l'aide d'une technologie de traduction automatique. Bien que nous nous efforcions de fournir des traductions exactes, nous ne fournissons aucune garantie quant à l'exhaustivité, l'exactitude ou la fiabilité du contenu traduit. En cas de divergence, la version originale anglaise prévaut et fait foi.

Cluster Autoscaler avec les groupes de mise à l’échelle automatique AWS EC2

Ce guide vous montrera comment installer et utiliser Kubernetes cluster-autoscaler sur des clusters personnalisés Rancher utilisant les groupes de mise à l’échelle automatique AWS EC2.

Nous allons installer un cluster personnalisé Rancher RKE2 avec un nombre fixe de nœuds ayant les rôles etcd et plan de contrôle, et un nombre variable de nœuds avec le rôle de travailleur, géré par cluster-autoscaler.

Conditions préalables

Ces éléments sont nécessaires pour suivre ce guide :

  • Le serveur Rancher est opérationnel

  • Vous avez un utilisateur AWS EC2 avec les permissions appropriées pour créer des machines virtuelles, des groupes de mise à l’échelle automatique et des profils et rôles IAM

1. Créer un cluster personnalisé

Sur le serveur Rancher, nous devrions créer un cluster k8s personnalisé. Référez-vous ici pour vérifier la compatibilité des versions.

Assurez-vous que le nom du fournisseur cloud est défini sur amazonec2. Une fois le cluster créé, nous devons obtenir :

  • clusterID : c-xxxxx sera utilisé sur le tag d’instance EC2 kubernetes.io/cluster/<clusterID>

  • clusterName : sera utilisé sur le tag d’instance EC2 k8s.io/cluster-autoscaler/<clusterName>

  • nodeCommand : sera ajouté aux données utilisateur de l’instance EC2 pour inclure de nouveaux nœuds dans le cluster

      sudo docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run rancher/rancher-agent:<RANCHER_VERSION> --server https://<RANCHER_URL> --token <RANCHER_TOKEN> --ca-checksum <RANCHER_CHECKSUM> <roles>

2. Configurer le fournisseur cloud

Sur AWS EC2, nous devrions créer quelques objets pour configurer notre système. Nous avons défini trois groupes distincts et des profils IAM à configurer sur AWS.

  1. Groupe d’auto-scaling : Nœuds qui feront partie du groupe d’autoscaling EC2 (ASG). L’ASG sera utilisé par cluster-autoscaler pour monter et descendre en charge.

    • Profil IAM : Requis par les nœuds k8s où le cluster-autoscaler sera en cours d’exécution. Il est recommandé pour les nœuds maîtres Kubernetes. Ce profil s’appelle K8sAutoscalerProfile.

       {
           "Version": "2012-10-17",
           "Statement": [
               {
                   "Effect": "Allow",
                   "Action": [
                       "autoscaling:DescribeAutoScalingGroups",
                       "autoscaling:DescribeAutoScalingInstances",
                       "autoscaling:DescribeLaunchConfigurations",
                       "autoscaling:SetDesiredCapacity",
                       "autoscaling:TerminateInstanceInAutoScalingGroup",
                       "autoscaling:DescribeTags",
                       "autoscaling:DescribeLaunchConfigurations",
                       "ec2:DescribeLaunchTemplateVersions"
                   ],
                   "Resource": [
                       "*"
                   ]
               }
           ]
       }
  2. Groupe maître : Nœuds qui feront partie de l’etcd Kubernetes et/ou des plans de contrôle. Cela sera en dehors de l’ASG.

    • Profil IAM : Requis par l’intégration cloud_provider de Kubernetes. Optionnellement, AWS_ACCESS_KEY et AWS_SECRET_KEY peuvent être utilisés à la place de using-aws-credentials. Ce profil s’appelle K8sMasterProfile.

       {
           "Version": "2012-10-17",
           "Statement": [
               {
                   "Effect": "Allow",
                   "Action": [
                       "autoscaling:DescribeAutoScalingGroups",
                       "autoscaling:DescribeLaunchConfigurations",
                       "autoscaling:DescribeTags",
                       "ec2:DescribeInstances",
                       "ec2:DescribeRegions",
                       "ec2:DescribeRouteTables",
                       "ec2:DescribeSecurityGroups",
                       "ec2:DescribeSubnets",
                       "ec2:DescribeVolumes",
                       "ec2:CreateSecurityGroup",
                       "ec2:CreateTags",
                       "ec2:CreateVolume",
                       "ec2:ModifyInstanceAttribute",
                       "ec2:ModifyVolume",
                       "ec2:AttachVolume",
                       "ec2:AuthorizeSecurityGroupIngress",
                       "ec2:CreateRoute",
                       "ec2:DeleteRoute",
                       "ec2:DeleteSecurityGroup",
                       "ec2:DeleteVolume",
                       "ec2:DetachVolume",
                       "ec2:RevokeSecurityGroupIngress",
                       "ec2:DescribeVpcs",
                       "elasticloadbalancing:AddTags",
                       "elasticloadbalancing:AttachLoadBalancerToSubnets",
                       "elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
                       "elasticloadbalancing:CreateLoadBalancer",
                       "elasticloadbalancing:CreateLoadBalancerPolicy",
                       "elasticloadbalancing:CreateLoadBalancerListeners",
                       "elasticloadbalancing:ConfigureHealthCheck",
                       "elasticloadbalancing:DeleteLoadBalancer",
                       "elasticloadbalancing:DeleteLoadBalancerListeners",
                       "elasticloadbalancing:DescribeLoadBalancers",
                       "elasticloadbalancing:DescribeLoadBalancerAttributes",
                       "elasticloadbalancing:DetachLoadBalancerFromSubnets",
                       "elasticloadbalancing:DeregisterInstancesFromLoadBalancer",
                       "elasticloadbalancing:ModifyLoadBalancerAttributes",
                       "elasticloadbalancing:RegisterInstancesWithLoadBalancer",
                       "elasticloadbalancing:SetLoadBalancerPoliciesForBackendServer",
                       "elasticloadbalancing:AddTags",
                       "elasticloadbalancing:CreateListener",
                       "elasticloadbalancing:CreateTargetGroup",
                       "elasticloadbalancing:DeleteListener",
                       "elasticloadbalancing:DeleteTargetGroup",
                       "elasticloadbalancing:DescribeListeners",
                       "elasticloadbalancing:DescribeLoadBalancerPolicies",
                       "elasticloadbalancing:DescribeTargetGroups",
                       "elasticloadbalancing:DescribeTargetHealth",
                       "elasticloadbalancing:ModifyListener",
                       "elasticloadbalancing:ModifyTargetGroup",
                       "elasticloadbalancing:RegisterTargets",
                       "elasticloadbalancing:SetLoadBalancerPoliciesOfListener",
                       "iam:CreateServiceLinkedRole",
                       "ecr:GetAuthorizationToken",
                       "ecr:BatchCheckLayerAvailability",
                       "ecr:GetDownloadUrlForLayer",
                       "ecr:GetRepositoryPolicy",
                       "ecr:DescribeRepositories",
                       "ecr:ListImages",
                       "ecr:BatchGetImage",
                       "kms:DescribeKey"
                   ],
                   "Resource": [
                       "*"
                   ]
               }
           ]
       }
    • Rôle IAM : K8sMasterRole: [K8sMasterProfile,K8sAutoscalerProfile].

    • Groupe de sécurité : K8sMasterSg. More info at RKE2 ports (custom nodes tab)

    • Balises : kubernetes.io/cluster/<clusterID>: owned

    • Données utilisateur : K8sMasterUserData Ubuntu 18.04(ami-0e11cbb34015ff725), installe Docker et ajoute un nœud etcd+plan de contrôle au cluster K8s.

      #!/bin/bash -x
      
      cat <<EOF > /etc/sysctl.d/90-kubelet.conf
      vm.overcommit_memory = 1
      vm.panic_on_oom = 0
      kernel.panic = 10
      kernel.panic_on_oops = 1
      kernel.keys.root_maxkeys = 1000000
      kernel.keys.root_maxbytes = 25000000
      EOF
      sysctl -p /etc/sysctl.d/90-kubelet.conf
      
      curl -sL https://releases.rancher.com/install-docker/19.03.sh | sh
      sudo usermod -aG docker ubuntu
      
      TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
      PRIVATE_IP=$(curl -H "X-aws-ec2-metadata-token: ${TOKEN}" -s http://169.254.169.254/latest/meta-data/local-ipv4)
      PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: ${TOKEN}" -s http://169.254.169.254/latest/meta-data/public-ipv4)
      K8S_ROLES="--etcd --controlplane"
      
      sudo docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run rancher/rancher-agent:<RANCHER_VERSION> --server https://<RANCHER_URL> --token <RANCHER_TOKEN> --ca-checksum <RANCHER_CA_CHECKSUM> --address ${PUBLIC_IP} --internal-address ${PRIVATE_IP} ${K8S_ROLES}
  3. Groupe de travail : Nœuds qui feront partie du plan de nœuds de travail k8s. Les nœuds de travail seront mis à l’échelle par le cluster-autoscaler en utilisant l’ASG.

    • Profil IAM : Fournit l’intégration des nœuds de travail du fournisseur de cloud. Ce profil s’appelle K8sWorkerProfile.

       {
           "Version": "2012-10-17",
           "Statement": [
               {
                   "Effect": "Allow",
                   "Action": [
                       "ec2:DescribeInstances",
                       "ec2:DescribeRegions",
                       "ecr:GetAuthorizationToken",
                       "ecr:BatchCheckLayerAvailability",
                       "ecr:GetDownloadUrlForLayer",
                       "ecr:GetRepositoryPolicy",
                       "ecr:DescribeRepositories",
                       "ecr:ListImages",
                       "ecr:BatchGetImage"
                   ],
                   "Resource": "*"
               }
           ]
       }
    • Rôle IAM : K8sWorkerRole: [K8sWorkerProfile].

    • Groupe de sécurité : K8sWorkerSg Plus d’infos sur ports RKE2 (onglet nœuds en aval personnalisés).

    • Balises :

      • kubernetes.io/cluster/<clusterID>: owned

      • k8s.io/cluster-autoscaler/<clusterName>: true

      • k8s.io/cluster-autoscaler/enabled: true

    • Données utilisateur : K8sWorkerUserData Ubuntu 18.04(ami-0e11cbb34015ff725), installe Docker et ajoute le nœud de travail au cluster K8s.

        #!/bin/bash -x
      
        cat <<EOF > /etc/sysctl.d/90-kubelet.conf
        vm.overcommit_memory = 1
        vm.panic_on_oom = 0
        kernel.panic = 10
        kernel.panic_on_oops = 1
        kernel.keys.root_maxkeys = 1000000
        kernel.keys.root_maxbytes = 25000000
        EOF
        sysctl -p /etc/sysctl.d/90-kubelet.conf
      
        curl -sL https://releases.rancher.com/install-docker/19.03.sh | sh
        sudo usermod -aG docker ubuntu
      
        TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
        PRIVATE_IP=$(curl -H "X-aws-ec2-metadata-token: ${TOKEN}" -s http://169.254.169.254/latest/meta-data/local-ipv4)
        PUBLIC_IP=$(curl -H "X-aws-ec2-metadata-token: ${TOKEN}" -s http://169.254.169.254/latest/meta-data/public-ipv4)
        K8S_ROLES="--worker"
      
        sudo docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run rancher/rancher-agent:<RANCHER_VERSION> --server https://<RANCHER_URL> --token <RANCHER_TOKEN> --ca-checksum <RANCHER_CA_CHECKCSUM> --address ${PUBLIC_IP} --internal-address ${PRIVATE_IP} ${K8S_ROLES}

3. Déployer des nœuds

Une fois que nous avons configuré AWS, créons des VM pour démarrer notre cluster :

  • maître (etcd+plan de contrôle) : En fonction de vos besoins, déployez trois instances maîtres de taille appropriée. Plus d’infos sur les recommandations pour des clusters prêts pour la production.

    • Rôle IAM : K8sMasterRole

    • Groupe de sécurité : K8sMasterSg

    • Balises :

      • kubernetes.io/cluster/<clusterID>: owned

    • Données utilisateur : K8sMasterUserData

  • travailleur : Définir un ASG sur EC2 avec les paramètres suivants :

    • Nom : K8sWorkerAsg

    • Rôle IAM : K8sWorkerRole

    • Groupe de sécurité : K8sWorkerSg

    • Balises :

      • kubernetes.io/cluster/<clusterID>: owned

      • k8s.io/cluster-autoscaler/<clusterName>: true

      • k8s.io/cluster-autoscaler/enabled: true

    • Données utilisateur : K8sWorkerUserData

    • Instances :

      • minimum : 2

      • souhaité : 2

      • maximum : 10

Une fois que les VMs sont déployées, vous devriez avoir un cluster personnalisé Rancher opérationnel avec trois nœuds maîtres et deux nœuds de travail.

4. Installer Cluster-autoscaler

À ce stade, nous devrions avoir le cluster Rancher opérationnel. Nous allons installer cluster-autoscaler sur les nœuds maîtres et dans l’espace de noms kube-system, conformément aux recommandations de cluster-autoscaler.

Paramètres

Ce tableau montre les paramètres de cluster-autoscaler pour un réglage fin :

Paramètre Par défaut Description

cluster-name

-

Nom du cluster autoscalé, si disponible

address

:8085

L’adresse pour exposer les métriques Prometheus

kubernetes

-

Emplacement du maître Kubernetes. Laissez vide pour utiliser la valeur par défaut

kubeconfig

-

Chemin vers le fichier kubeconfig avec les informations d’autorisation et d’emplacement du maître

cloud-config

-

Le chemin vers le fichier de configuration du fournisseur de cloud. Chaîne vide pour aucun fichier de configuration

namespace

"kube-system"

Espace de noms dans lequel cluster-autoscaler s’exécute

scale-down-enabled

true

Le CA doit-il réduire l’échelle du cluster ?

scale-down-delay-after-add

"10m"

Combien de temps après l’augmentation d’échelle la réévaluation de la réduction d’échelle reprend-elle ?

scale-down-delay-after-delete

0

Combien de temps après la suppression d’un nœud la réévaluation de la réduction d’échelle reprend-elle, par défaut à intervalleDeScan ?

scale-down-delay-after-failure

"3m"

Combien de temps après un échec de réduction d’échelle la réévaluation de la réduction d’échelle reprend-elle ?

temps-non-nécessaire-pour-réduction

"10m"

Combien de temps un nœud doit-il être non nécessaire avant d’être éligible pour une réduction d’échelle ?

temps-non-prêt-pour-réduction

"20m"

Combien de temps un nœud non prêt doit-il être non nécessaire avant d’être éligible pour une réduction d’échelle ?

seuil-d’utilisation-pour-réduction

0,5

Somme de l’UC ou de la mémoire de tous les pods fonctionnant sur le nœud divisée par la ressource allouable correspondante du nœud, en dessous de laquelle un nœud peut être considéré pour une réduction d’échelle.

seuil-d’utilisation-gpu-pour-réduction

0,5

Somme des demandes de GPU de tous les pods fonctionnant sur le nœud divisée par la ressource allouable du nœud, en dessous de laquelle un nœud peut être considéré pour une réduction d’échelle.

scale-down-non-empty-candidates-count

30

Nombre maximum de nœuds non vides considérés en une seule itération comme candidats pour la réduction d’échelle avec drainage.

scale-down-candidates-pool-ratio

0,1

Un ratio de nœuds considérés comme candidats non vides supplémentaires pour la réduction d’échelle lorsque certains candidats de l’itération précédente ne sont plus valides.

nombre-minimal-de-candidats-dans-le-pool-de-réduction

50

Nombre minimum de nœuds considérés comme candidats supplémentaires non vides pour la réduction d’échelle lorsque certains candidats de l’itération précédente ne sont plus valides

node-deletion-delay-timeout

"2m"

Temps maximum que le CA attend pour supprimer les annotations delay-deletion.cluster-autoscaler.kubernetes.io/ avant de supprimer le nœud

intervalle-de-scanning

"10s"

À quelle fréquence le cluster est réévalué pour une montée ou une descente d’échelle

max-nodes-total

0

Nombre maximum de nœuds dans tous les groupes de nœuds. L’autoscaler de cluster ne fera pas croître le cluster au-delà de ce nombre

cores-total

"0:320000"

Nombre minimum et maximum de noyaux dans le cluster, au format <min>:<max>. L’autoscaler de cluster ne fera pas évoluer le cluster au-delà de ces chiffres

memory-total

"0:6400000"

Nombre minimum et maximum de gigaoctets de mémoire dans le cluster, au format <min>:<max>. L’autoscaler de cluster ne fera pas évoluer le cluster au-delà de ces chiffres

fournisseur-de-cloud

-

Type de fournisseur de cloud

max-bulk-soft-taint-count

10

Nombre maximum de nœuds pouvant être teintés/non teintés en PreferNoSchedule en même temps. Définir à 0 pour désactiver ce type de teinture

max-bulk-soft-taint-time

"3s"

Durée maximale de teinture/non teinture des nœuds en tant que PreferNoSchedule en même temps

max-empty-bulk-delete

10

Nombre maximum de nœuds vides pouvant être supprimés en même temps

max-graceful-termination-sec

600

Nombre maximum de secondes que CA attend pour la terminaison du pod lors de la tentative de réduction d’un nœud

max-total-unready-percentage

45

Pourcentage maximum de nœuds non prêts dans le cluster. Après cela, CA interrompt les opérations

ok-total-unready-count

3

Nombre de nœuds non prêts autorisés, indépendamment du pourcentage maximum de nœuds non prêts

scale-up-from-zero

true

Le CA doit-il augmenter la capacité lorsqu’il n’y a aucun nœud prêt ?

max-node-provision-time

"15m"

Temps maximum que CA attend pour qu’un nœud soit provisionné

nœuds

-

définit la taille min, max et d’autres données de configuration pour un groupe de nœuds dans un format accepté par le fournisseur de cloud. Peut être utilisé plusieurs fois. Format : <min>:<max>:<other…​>

découverte-auto-groupe-nœuds

-

Une ou plusieurs définition(s) de la découverte automatique du groupe de nœuds. Une définition est exprimée <name of discoverer>:[<key>[=<value>]]

estimator

"binpacking"

Type d’estimateur de ressources à utiliser lors de l’augmentation de l’échelle. Valeurs disponibles : ["binpacking"]

expander

"aléatoire"

Type de groupe de nœuds expanseur à utiliser lors de l’augmentation de l’échelle. Valeurs disponibles : ["random","most-pods","least-waste","price","priority"]

ignorer-l’utilisation-des-daemonsets

false

Le CA doit-il ignorer les pods DaemonSet lors du calcul de l’utilisation des ressources pour la réduction de l’échelle ?

ignorer-l’utilisation-des-pods-miroir

false

Le CA doit-il ignorer les pods Miroir lors du calcul de l’utilisation des ressources pour la réduction de l’échelle ?

write-status-configmap

true

Le CA doit-il écrire des informations d’état dans un configmap ?

inactivité-maximale

"10m"

Temps maximum depuis la dernière activité d’autoscaler enregistrée avant le redémarrage automatique

max-failing-time

"15m"

Temps maximum depuis la dernière exécution réussie de l’autoscaler enregistrée avant le redémarrage automatique

balance-similar-node-groups

false

Détecter les groupes de nœuds similaires et équilibrer le nombre de nœuds entre eux

node-autoprovisioning-enabled

false

Le CA doit-il autoprovisionner des groupes de nœuds si nécessaire ?

max-autoprovisioned-node-group-count

15

Le nombre maximum de groupes auto-provisionnés dans le cluster

unremovable-node-recheck-timeout

"5m"

Le délai avant que nous vérifions à nouveau un nœud qui n’a pas pu être supprimé auparavant

expendable-pods-priority-cutoff

-10

Les pods avec une priorité inférieure au seuil seront considérés comme jetables. Ils peuvent être supprimés sans aucune considération lors de la réduction d’échelle et ils ne provoquent pas d’augmentation d’échelle. Les pods avec une priorité nulle (priorité des pods désactivée) ne sont pas jetables.

régional

false

Le cluster est régional

new-pod-scale-up-delay

"0s"

Les pods de moins de cet âge ne seront pas pris en compte pour l’augmentation d’échelle

ignore-taint

-

Spécifie un taint à ignorer dans les modèles de nœuds lors de la considération pour l’augmentation d’un groupe de nœuds

ignorer-l’étiquette-d’équilibrage

-

Spécifie une étiquette à ignorer en plus de l’ensemble de base et de l’ensemble d’étiquettes du fournisseur de cloud lors de la comparaison de la similarité de deux groupes de nœuds

aws-use-static-instance-list

false

Le CA doit-il récupérer les types d’instances à l’exécution ou utiliser une liste statique ? AWS uniquement

profilage

false

Le point de terminaison debug/pprof est-il activé ?

Déploiement

Sur la base de l’exemple cluster-autoscaler-run-on-control-plane.yaml, nous avons créé notre propre cluster-autoscaler-deployment.yaml pour utiliser la configuration de auto-découverte préférée, en mettant à jour les tolérances, le sélecteur de nœuds, la version de l’image et la commande :

---
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    k8s-addon: cluster-autoscaler.addons.k8s.io
    k8s-app: cluster-autoscaler
  name: cluster-autoscaler
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-autoscaler
  labels:
    k8s-addon: cluster-autoscaler.addons.k8s.io
    k8s-app: cluster-autoscaler
rules:
  - apiGroups: [""]
    resources: ["events", "endpoints"]
    verbs: ["create", "patch"]
  - apiGroups: [""]
    resources: ["pods/eviction"]
    verbs: ["create"]
  - apiGroups: [""]
    resources: ["pods/status"]
    verbs: ["update"]
  - apiGroups: [""]
    resources: ["endpoints"]
    resourceNames: ["cluster-autoscaler"]
    verbs: ["get", "update"]
  - apiGroups: [""]
    resources: ["nodes"]
    verbs: ["watch", "list", "get", "update"]
  - apiGroups: [""]
    resources:
      - "pods"
      - "services"
      - "replicationcontrollers"
      - "persistentvolumeclaims"
      - "persistentvolumes"
    verbs: ["watch", "list", "get"]
  - apiGroups: ["extensions"]
    resources: ["replicasets", "daemonsets"]
    verbs: ["watch", "list", "get"]
  - apiGroups: ["policy"]
    resources: ["poddisruptionbudgets"]
    verbs: ["watch", "list"]
  - apiGroups: ["apps"]
    resources: ["statefulsets", "replicasets", "daemonsets"]
    verbs: ["watch", "list", "get"]
  - apiGroups: ["storage.k8s.io"]
    resources: ["storageclasses", "csinodes"]
    verbs: ["watch", "list", "get"]
  - apiGroups: ["batch", "extensions"]
    resources: ["jobs"]
    verbs: ["get", "list", "watch", "patch"]
  - apiGroups: ["coordination.k8s.io"]
    resources: ["leases"]
    verbs: ["create"]
  - apiGroups: ["coordination.k8s.io"]
    resourceNames: ["cluster-autoscaler"]
    resources: ["leases"]
    verbs: ["get", "update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cluster-autoscaler
  namespace: kube-system
  labels:
    k8s-addon: cluster-autoscaler.addons.k8s.io
    k8s-app: cluster-autoscaler
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["create","list","watch"]
  - apiGroups: [""]
    resources: ["configmaps"]
    resourceNames: ["cluster-autoscaler-status", "cluster-autoscaler-priority-expander"]
    verbs: ["delete", "get", "update", "watch"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-autoscaler
  labels:
    k8s-addon: cluster-autoscaler.addons.k8s.io
    k8s-app: cluster-autoscaler
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-autoscaler
subjects:
  - kind: ServiceAccount
    name: cluster-autoscaler
    namespace: kube-system

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cluster-autoscaler
  namespace: kube-system
  labels:
    k8s-addon: cluster-autoscaler.addons.k8s.io
    k8s-app: cluster-autoscaler
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: cluster-autoscaler
subjects:
  - kind: ServiceAccount
    name: cluster-autoscaler
    namespace: kube-system

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: cluster-autoscaler
  namespace: kube-system
  labels:
    app: cluster-autoscaler
spec:
  replicas: 1
  selector:
    matchLabels:
      app: cluster-autoscaler
  template:
    metadata:
      labels:
        app: cluster-autoscaler
      annotations:
        prometheus.io/scrape: 'true'
        prometheus.io/port: '8085'
    spec:
      serviceAccountName: cluster-autoscaler
      tolerations:
        - effect: NoSchedule
          operator: "Equal"
          value: "true"
          key: node-role.kubernetes.io/controlplane
      nodeSelector:
        node-role.kubernetes.io/controlplane: "true"
      containers:
        - image: eu.gcr.io/k8s-artifacts-prod/autoscaling/cluster-autoscaler:<VERSION>
          name: cluster-autoscaler
          resources:
            limits:
              cpu: 100m
              memory: 300Mi
            requests:
              cpu: 100m
              memory: 300Mi
          command:
            - ./cluster-autoscaler
            - --v=4
            - --stderrthreshold=info
            - --cloud-provider=aws
            - --skip-nodes-with-local-storage=false
            - --expander=least-waste
            - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<clusterName>
          volumeMounts:
            - name: ssl-certs
              mountPath: /etc/ssl/certs/ca-certificates.crt
              readOnly: true
          imagePullPolicy: "Always"
      volumes:
        - name: ssl-certs
          hostPath:
            path: "/etc/ssl/certs/ca-certificates.crt"

Une fois le fichier manifeste préparé, déployez-le dans le cluster Kubernetes (l’interface utilisateur Rancher peut être utilisée à la place) :

kubectl -n kube-system apply -f cluster-autoscaler-deployment.yaml

Le déploiement du cluster-autoscaler peut également être configuré en utilisant manual configuration

Tests

À ce stade, nous devrions avoir un cluster-scaler opérationnel dans notre cluster personnalisé Rancher. Le cluster-scale doit gérer K8sWorkerAsg ASG pour augmenter et diminuer entre 2 et 10 nœuds, lorsque l’une des conditions suivantes est vraie :

  • Il y a des pods qui n’ont pas pu s’exécuter dans le cluster en raison de ressources insuffisantes. Dans ce cas, le cluster est agrandi.

  • Il y a des nœuds dans le cluster qui ont été sous-utilisés pendant une période prolongée et leurs pods peuvent être placés sur d’autres nœuds existants. Dans ce cas, le cluster est réduit.

Génération de charge

Nous avons préparé un test-deployment.yaml juste pour générer une charge sur le cluster Kubernetes et voir si le cluster-autoscaler fonctionne correctement. Le déploiement de test demande 1000m d’UC et 1024Mi de mémoire pour trois réplicas. Ajustez les ressources demandées et/ou le nombre de réplicas pour vous assurer d’épuiser les ressources du cluster Kubernetes :

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: hello-world
  name: hello-world
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-world
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - image: rancher/hello-world
        imagePullPolicy: Always
        name: hello-world
        ports:
        - containerPort: 80
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1024Mi
          requests:
            cpu: 1000m
            memory: 1024Mi

Une fois le déploiement de test préparé, déployez-le dans l’espace de noms par défaut du cluster Kubernetes (l’interface utilisateur Rancher peut être utilisée à la place) :

kubectl -n default apply -f test-deployment.yaml

Vérification de l’échelle

Une fois que les ressources Kubernetes sont épuisées, le cluster-autoscaler doit augmenter le nombre de nœuds de travail où les pods n’ont pas pu être planifiés. Il doit augmenter jusqu’à ce que tous les pods soient planifiés. Vous devriez voir les nouveaux nœuds sur l’ASG et sur le cluster Kubernetes. Vérifiez les journaux du pod kube-system cluster-autoscaler.

Une fois l’augmentation de l’échelle vérifiée, vérifions la réduction de l’échelle. Pour ce faire, réduisez le nombre de réplicas sur le déploiement de test jusqu’à ce que vous libériez suffisamment de ressources du cluster Kubernetes pour réduire l’échelle. Vous devriez voir des nœuds disparaître sur l’ASG et sur le cluster Kubernetes. Vérifiez les journaux du pod kube-system cluster-autoscaler.