D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

Si votre infrastructure informatique se développe trop rapidement, vous serez tôt ou tard confronté à un choix : augmenter linéairement les ressources humaines pour la soutenir ou démarrer l'automatisation. Jusqu’à un certain point, nous avons vécu dans le premier paradigme, puis le long chemin vers l’Infrastructure-as-Code a commencé.

D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

Bien sûr, NSPK n'est pas une startup, mais une telle atmosphère régnait dans l'entreprise dans les premières années de son existence, et ce furent des années très intéressantes. Mon nom est Korniakov Dmitri, je supporte les infrastructures Linux avec des exigences de haute disponibilité depuis plus de 10 ans. Il a rejoint l’équipe NSPK en janvier 2016 et, malheureusement, n’a pas vu le tout début de l’existence de l’entreprise, mais est arrivé à une étape de grands changements.

De manière générale, nous pouvons dire que notre équipe fournit 2 produits pour l'entreprise. Le premier concerne les infrastructures. Le courrier devrait fonctionner, le DNS devrait fonctionner et les contrôleurs de domaine devraient vous permettre d'accéder à des serveurs qui ne devraient pas planter. Le paysage informatique de l’entreprise est immense ! Il s'agit de systèmes critiques pour l'entreprise et la mission, les exigences de disponibilité pour certains sont de 99,999. Le deuxième produit concerne les serveurs eux-mêmes, physiques et virtuels. Les existants doivent être surveillés et les nouveaux doivent être régulièrement livrés aux clients de nombreux départements. Dans cet article, je souhaite me concentrer sur la façon dont nous avons développé l'infrastructure responsable du cycle de vie du serveur.

Début d'un voyage

Au début de notre parcours, notre pile technologique ressemblait à ceci :
Système d'exploitation CentOS 7
Contrôleurs de domaine FreeIPA
Automatisation - Ansible (+ Tour), Cobbler

Tout cela était réparti dans 3 domaines, répartis sur plusieurs centres de données. Dans un centre de données, il y a des systèmes bureautiques et des sites de test, dans le reste il y a PROD.

À un moment donné, la création de serveurs ressemblait à ceci :

D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

Dans le modèle de VM, CentOS est minimal et le minimum requis est comme le bon /etc/resolv.conf, le reste passe par Ansible.

CMDB-Excel.

Si le serveur est physique, au lieu de copier la machine virtuelle, le système d'exploitation y a été installé à l'aide de Cobbler - les adresses MAC du serveur cible sont ajoutées à la configuration de Cobbler, le serveur reçoit une adresse IP via DHCP, puis le système d'exploitation est ajouté.

Au début, nous avons même essayé de faire une sorte de gestion de configuration dans Cobbler. Mais au fil du temps, cela a commencé à poser des problèmes de portabilité des configurations à la fois vers d'autres centres de données et avec le code Ansible pour la préparation des machines virtuelles.

À cette époque, beaucoup d'entre nous percevaient Ansible comme une extension pratique de Bash et ne lésinaient pas sur les conceptions utilisant shell et sed. Globalement bashable. Cela a finalement conduit au fait que si le playbook, pour une raison quelconque, ne fonctionnait pas sur le serveur, il était plus facile de supprimer le serveur, de réparer le playbook et de le réexécuter. Il n’y avait essentiellement aucune gestion des versions des scripts, ni portabilité des configurations.

Par exemple, nous voulions modifier certaines configurations sur tous les serveurs :

  1. Nous modifions la configuration sur les serveurs existants dans le segment logique/data center. Parfois pas en un jour : les exigences d’accessibilité et la loi des grands nombres ne permettent pas d’appliquer tous les changements en même temps. Et certains changements sont potentiellement destructeurs et nécessitent le redémarrage de quelque chose - des services au système d'exploitation lui-même.
  2. Le réparer dans Ansible
  3. Nous le réparons dans Cobbler
  4. Répétez N fois pour chaque segment logique/centre de données

Pour que tous les changements se déroulent sans problème, il a fallu prendre en compte de nombreux facteurs, et des changements se produisent constamment.

  • Refactorisation du code ansible, fichiers de configuration
  • Changer les bonnes pratiques internes
  • Modifications basées sur les résultats de l’analyse des incidents/accidents
  • Changer les normes de sécurité, tant internes qu’externes. Par exemple, PCI DSS est mis à jour chaque année avec de nouvelles exigences.

Croissance des infrastructures et début du voyage

Le nombre de serveurs/domaines logiques/centres de données a augmenté, et avec eux le nombre d'erreurs de configuration. À un moment donné, nous sommes arrivés à trois directions dans lesquelles la gestion de la configuration doit être développée :

  1. Automatisation. L'erreur humaine dans les opérations répétitives doit être évitée autant que possible.
  2. Répétabilité. Il est beaucoup plus facile de gérer une infrastructure lorsqu’elle est prévisible. La configuration des serveurs et des outils pour leur préparation doit être la même partout. Ceci est également important pour les équipes produit : après le test, l'application doit être garantie de se retrouver dans un environnement de production configuré de manière similaire à l'environnement de test.
  3. Simplicité et transparence des modifications dans la gestion de la configuration.

Il reste à ajouter quelques outils.

Nous avons choisi GitLab CE comme référentiel de code, notamment pour ses modules CI/CD intégrés.

Coffre-fort de secrets - Hashicorp Vault, incl. pour la grande API.

Configurations de test et rôles ansible – Molecule+Testinfra. Les tests sont beaucoup plus rapides si vous vous connectez au mitogène ansible. Dans le même temps, nous avons commencé à écrire notre propre CMDB et orchestrateur pour le déploiement automatique (dans l'image ci-dessus Cobbler), mais c'est une histoire complètement différente, que mon collègue et principal développeur de ces systèmes racontera à l'avenir.

Notre choix:

Molécule + Testinfra
Ansible + Tour + AWX
Monde des serveurs + DITNET (Propre développement)
Cobbler
Gitlab + coureur GitLab
Coffre-fort Hashicorp

D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

À propos, à propos des rôles ansibles. Au début, il n'y en avait qu'un, mais après plusieurs refactorisations, il y en avait 17. Je recommande fortement de diviser le monolithe en rôles idempotents, qui peuvent ensuite être lancés séparément ; vous pouvez en outre ajouter des balises. Nous avons divisé les rôles par fonctionnalité : réseau, journalisation, packages, matériel, molécule, etc. En général, nous avons suivi la stratégie ci-dessous. Je n’insiste pas sur le fait que c’est la seule vérité, mais cela a fonctionné pour nous.

  • Copier des serveurs à partir de « l'image dorée » est un mal !Le principal inconvénient est que vous ne savez pas exactement dans quel état se trouvent actuellement les images et que toutes les modifications concerneront toutes les images de toutes les fermes de virtualisation.
  • Utilisez au minimum les fichiers de configuration par défaut et convenez avec les autres services que vous êtes responsable des principaux fichiers système., Par exemple:
    1. Laissez /etc/sysctl.conf vide, les paramètres ne doivent être que dans /etc/sysctl.d/. Votre valeur par défaut dans un fichier, personnalisée pour l'application dans un autre.
    2. Utilisez les fichiers de remplacement pour modifier les unités systemd.
  • Modèlez toutes les configurations et incluez-les entièrement ; si possible, pas de sed ou ses analogues dans les playbooks
  • Refactorisation du code du système de gestion de configuration :
    1. Décomposez les tâches en entités logiques et réécrivez le monolithe en rôles
    2. Utilisez des linters ! Ansible-lint, yaml-lint, etc.
    3. Changez votre approche! Pas de bashsible. Il est nécessaire de décrire l'état du système
  • Pour tous les rôles Ansible, vous devez rédiger des tests en molécule et générer des rapports une fois par jour.
  • Dans notre cas, après avoir préparé les tests (il y en a plus de 100), environ 70000 XNUMX erreurs ont été trouvées. Il a fallu plusieurs mois pour le réparer.D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

Notre mise en œuvre

Ainsi, les rôles ansibles étaient prêts, modélisés et vérifiés par les linters. Et même des connards sont élevés partout. Mais la question de la livraison fiable du code aux différents segments reste ouverte. Nous avons décidé de synchroniser avec des scripts. Ressemble à ça:

D'une « startup » à des milliers de serveurs dans une dizaine de centres de données. Comment nous avons chassé la croissance de l'infrastructure Linux

Une fois le changement arrivé, CI est lancé, un serveur de test est créé, les rôles sont déployés et testés par la molécule. Si tout va bien, le code va dans la branche prod. Mais nous n'appliquons pas de nouveau code aux serveurs existants dans la machine. C'est une sorte de bouchon nécessaire à la haute disponibilité de nos systèmes. Et lorsque l'infrastructure devient énorme, la loi des grands nombres entre en jeu - même si vous êtes sûr que le changement est inoffensif, il peut avoir des conséquences désastreuses.

Il existe également de nombreuses options pour créer des serveurs. Nous avons fini par choisir des scripts Python personnalisés. Et pour CI ansible :

- name: create1.yml - Create a VM from a template
  vmware_guest:
    hostname: "{{datacenter}}".domain.ru
    username: "{{ username_vc }}"
    password: "{{ password_vc }}"
    validate_certs: no
    cluster: "{{cluster}}"
    datacenter: "{{datacenter}}"
    name: "{{ name }}"
    state: poweredon
    folder: "/{{folder}}"
    template: "{{template}}"
    customization:
      hostname: "{{ name }}"
      domain: domain.ru
      dns_servers:
        - "{{ ipa1_dns }}"
        - "{{ ipa2_dns }}"
    networks:
      - name: "{{ network }}"
        type: static
        ip: "{{ip}}"
        netmask: "{{netmask}}"
        gateway: "{{gateway}}"
        wake_on_lan: True
        start_connected: True
        allow_guest_control: True
    wait_for_ip_address: yes
    disk:
      - size_gb: 1
        type: thin
        datastore: "{{datastore}}"
      - size_gb: 20
        type: thin
        datastore: "{{datastore}}"

C’est là que nous en sommes arrivés, le système continue de vivre et de se développer.

  • 17 Rôles Ansible pour la configuration du serveur. Chacun des rôles est conçu pour résoudre une tâche logique distincte (journalisation, audit, autorisation utilisateur, surveillance, etc.).
  • Test de rôle. Molécule + TestInfra.
  • Développement propre : CMDB + Orchestrator.
  • Le temps de création du serveur est d'environ 30 minutes, automatisé et pratiquement indépendant de la file d'attente des tâches.
  • Le même état/dénomination de l'infrastructure dans tous les segments : playbooks, référentiels, éléments de virtualisation.
  • Vérification quotidienne de l'état du serveur avec génération de rapports sur les écarts avec la norme.

J'espère que mon histoire sera utile à ceux qui en sont au début de leur voyage. Quelle pile d'automatisation utilisez-vous ?

Source: habr.com