J'adore construire des choses - ce que le développeur n'aime pas? J'adore trouver des solutions à des problèmes intéressants, écrire des implémentations et créer du beau code. Cependant, ce que je n'aime pas, c'est les opérations . Les opérations sont tout ne pas impliquée dans la création de logiciels performants, de la configuration des serveurs à la livraison de votre code à la production.
Ceci est intéressant, car en tant que développeur Ruby on Rails indépendant, je dois souvent créer de nouvelles applications Web et répéter le processus de détermination du DevOps côté des choses. Heureusement, après avoir créé des dizaines d’applications, j’ai finalement choisi une solution parfaite initiale pipeline de déploiement. Malheureusement, tout le monde n’a pas compris comme moi. Finalement, ces connaissances m’ont amené à franchir le pas et à documenter mon processus.
Dans cet article, je vais vous expliquer mon pipeline idéal à utiliser au début de votre projet. Avec mon pipeline, chaque push est testé, la branche principale est déployée en préparation avec une nouvelle sauvegarde de la base de données de la production et les balises versionnées sont déployées en production avec des sauvegardes et des migrations se déroulant automatiquement.
la différence entre s corp et c corp
Remarque, puisque c'est mon pipeline, il est également avisé et adapté à mes besoins; Cependant, vous pouvez échanger tout ce que vous n'aimez pas et le remplacer par ce qui vous plaît. Pour mon pipeline, nous utiliserons:
Tout d'abord, recréons une application typique pour quelqu'un qui n'utilise pas de pipelines CI / CD sophistiqués et qui souhaite simplement déployer son application.
Le type d'application que vous créez n'a pas d'importance, mais vous aurez besoin de Yarn ou de npm. Pour mon exemple, je crée une application Ruby on Rails car elle est fournie avec des migrations et une CLI, et j'ai déjà la configuration écrite pour elle. Vous pouvez utiliser n'importe quel framework ou langage que vous préférez, mais vous aurez besoin de Yarn pour faire le contrôle de version que je ferai plus tard. Je crée une application CRUD simple en utilisant seulement quelques commandes et aucune authentification.
Et testons si notre application fonctionne comme prévu. Je suis allé de l'avant et j'ai créé quelques articles, juste pour m'en assurer.
Et déployons-le sur Heroku en poussant notre code et en exécutant des migrations
$ heroku create toptal-pipeline Creating ⬢ toptal-pipeline... done https://toptal-pipeline.herokuapp.com/ | https://git.heroku.com/toptal-pipeline.git $ git push heroku master Counting objects: 132, done. ... To https://git.heroku.com/toptal-pipeline.git * [new branch] master -> master $ heroku run rails db:migrate Running rails db:migrate on ⬢ toptal-pipeline... up, run.9653 (Free) ...
Enfin, testons-le en production
Et c'est tout! En règle générale, c'est là que la plupart des développeurs abandonnent leurs opérations. À l'avenir, si vous apportez des modifications, vous devrez répéter les étapes de déploiement et de migration ci-dessus. Vous pouvez même exécuter des tests si vous n’êtes pas en retard pour le dîner. C'est un excellent point de départ, mais réfléchissons un peu plus à cette méthode.
Avantages
Les inconvénients
Je vais essayer quelque chose de différent aujourd'hui: ayons une conversation hypothétique. Je vais donner une voix à «vous» et nous parlerons de la manière dont nous pouvons améliorer ce flux actuel. Allez-y, dites quelque chose.
Tu peux répéter s'il te plait? Attends, je peux parler?
Oui, c’est ce que je voulais dire en vous donnant une voix. Comment vas-tu?
Je vais bien. C'est bizarre
Je comprends, mais continuez avec. Parlons maintenant de notre pipeline. Quelle est la partie la plus ennuyeuse de l'exécution de déploiements?
Oh, c’est facile. Le temps que je perds. Avez-vous déjà essayé de pousser vers Heroku?
Ouais, regardez le téléchargement de vos dépendances et l'application en cours de construction dans le cadre de git push
c'est horrible!
N'est-ce pas? C'est fou. J'aurais aimé ne pas avoir à faire ça. Il y a aussi le fait que je dois exécuter des migrations * après * le déploiement, je dois donc regarder l'émission et vérifier que mon déploiement se déroule bien
D'accord, vous pouvez en fait résoudre ce dernier problème en enchaînant les deux commandes avec &&
, comme git push heroku master && heroku run rails db:migrate
, ou simplement en créant un script bash et en le mettant dans votre code, mais quand même, bonne réponse, l'heure et la répétition est une vraie douleur.
Ouais, ça craint vraiment
Et si je vous disais que vous pouvez résoudre ce problème immédiatement avec un pipeline CI / CD?
Un quoi maintenant? Qu'est-ce que c'est?
CI / CD signifie intégration continue (CI) et livraison / déploiement continu (CD). Il était assez difficile pour moi de comprendre exactement ce que c'était quand je commençais parce que tout le monde utilisait des termes vagues comme «fusion du développement et des opérations», mais en d'autres termes:
Oh, je comprends maintenant. Il s’agit de faire en sorte que mon application se déploie comme par magie dans le monde!
Mon article préféré expliquant CI / CD est par Atlassian Ici . Cela devrait éclaircir toutes vos questions. Quoi qu'il en soit, revenons au problème.
Ouais, revenons à ça. Comment éviter les déploiements manuels?
master
Et si je vous disais que vous pouvez réparer ce bit immédiatement avec un CI / CD? Vous pouvez pousser sur votre télécommande GitLab (origin
) et un ordinateur sera généré pour pousser directement votre code vers Heroku.
En aucune façon!
Ouais façon! Revenons au code.
Créez un .gitlab-ci.yml
avec le contenu suivant, échange toptal-pipeline
pour le nom de votre application Heroku:
image: ruby:2.4 before_script: - > : '${HEROKU_EMAIL:?Please set HEROKU_EMAIL in your CI/CD config vars}' - > : '${HEROKU_AUTH_TOKEN:?Please set HEROKU_AUTH_TOKEN in your CI/CD config vars}' - curl https://cli-assets.heroku.com/install-standalone.sh | sh - | cat >~/.netrc <[email protected] ' - git config --global user.name 'CI/CD' variables: APPNAME_PRODUCTION: toptal-pipeline deploy_to_production: stage: deploy environment: name: production url: https://$APPNAME_PRODUCTION.herokuapp.com/ script: - git remote add heroku https://git.heroku.com/$APPNAME_PRODUCTION.git - git push heroku master - heroku pg:backups:capture --app $APPNAME_PRODUCTION - heroku run rails db:migrate --app $APPNAME_PRODUCTION only: - master
Poussez ceci et observez son échec sur la page Pipelines de votre projet. C'est parce qu'il manque les clés d'authentification de votre compte Heroku. La correction est assez simple, cependant. Vous aurez d'abord besoin de votre Heroku Clé API . Obtenez-le du Gérer la page de compte , puis ajoutez ce qui suit variables secrètes dans les paramètres CI / CD de votre dépôt GitLab:
HEROKU_EMAIL
: L'adresse e-mail que vous utilisez pour vous connecter à HerokuHEROKU_AUTH_KEY
: La clé que vous avez obtenue d'Heroku
Cela devrait aboutir à un déploiement de GitLab vers Heroku à chaque poussée. Quant à ce qui se passe:
Déjà, vous pouvez voir que non seulement vous gagnez du temps en automatisant tout en un git push
, mais vous créez également une sauvegarde de votre base de données à chaque déploiement! Si quelque chose ne va pas, vous aurez une copie de votre base de données sur laquelle revenir.
Mais attendez, question rapide, qu'advient-il de vos problèmes spécifiques à la production? Que faire si vous rencontrez un bug étrange parce que votre environnement de développement est trop différent de celui de production? Une fois, j'ai rencontré des problèmes étranges avec SQLite 3 et PostgreSQL lorsque j'ai effectué une migration. Les détails m'échappent, mais c'est tout à fait possible.
J'utilise strictement PostgreSQL dans le développement, je ne mésadapte jamais aux moteurs de base de données comme ça, et je surveille attentivement ma pile pour d'éventuelles incompatibilités.
Eh bien, c’est un travail fastidieux et je salue votre discipline. Personnellement, je suis beaucoup trop paresseux pour faire ça. Cependant, pouvez-vous garantir ce niveau de diligence à tous les futurs développeurs, collaborateurs ou contributeurs potentiels?
Euh, non. Vous m'avez bien eu. D'autres personnes vont tout gâcher. Quel est votre point de vue, cependant?
Mon point est que vous avez besoin d'un environnement de mise en scène. C’est comme la production, mais ce n’est pas le cas. Un environnement de préparation est l'endroit où vous répétez le déploiement en production et détectez toutes vos erreurs tôt. Mes environnements de préparation reflètent généralement la production et je vide une copie de la base de données de production lors du déploiement intermédiaire pour m'assurer qu'aucun cas compliqué ne perturbe mes migrations. Avec un environnement de mise en scène, vous pouvez arrêter de traiter vos utilisateurs comme des cobayes.
C'est logique! Alors comment faire ça?
Voici où cela devient intéressant. J'aime déployer master
directement à la mise en scène.
Attendez, n'est-ce pas là que nous déployons actuellement la production?
Oui, mais maintenant, nous allons déployer à la place.
Mais si master
déploie en staging, comment déployer en production?
En utilisant quelque chose que vous auriez dû faire il y a des années: le versionnage de notre code et l'envoi de balises Git.
Balises Git? Qui utilise les balises Git?! Cela commence à sembler beaucoup de travail.
C'était bien sûr, mais heureusement, j'ai déjà fait tout ce travail et vous pouvez simplement vider mon code et cela fonctionnera.
Tout d'abord, ajoutez un bloc sur le déploiement intermédiaire à votre .gitlab-ci.yml
fichier, j'ai créé une nouvelle application Heroku appelée toptal-pipeline-staging
:
… variables: APPNAME_PRODUCTION: toptal-pipeline APPNAME_STAGING: toptal-pipeline-staging deploy_to_staging: stage: deploy environment: name: staging url: https://$APPNAME_STAGING.herokuapp.com/ script: - git remote add heroku https://git.heroku.com/$APPNAME_STAGING.git - git push heroku master - heroku pg:backups:capture --app $APPNAME_PRODUCTION - heroku pg:backups:restore `heroku pg:backups:url --app $APPNAME_PRODUCTION` --app $APPNAME_STAGING --confirm $APPNAME_STAGING - heroku run rails db:migrate --app $APPNAME_STAGING only: - master - tags ...
Modifiez ensuite la dernière ligne de votre bloc de production pour qu'elle s'exécute sur des balises Git versionnées sémantiquement au lieu de la branche principale:
deploy_to_production: ... only: - /^v(?'MAJOR'(?:0|(?:[1-9]d*))).(?'MINOR'(?:0|(?:[1-9]d*))).(?'PATCH'(?:0|(?:[1-9]d*)))(?:-(?'prerelease'[0-9A-Za-z-]+(.[0-9A-Za-z-]+)*))?(?:+(?'build'[0-9A-Za-z-]+(.[0-9A-Za-z-]+)*))?$/ # semver pattern above is adapted from https://github.com/semver/semver.org/issues/59#issuecomment-57884619
L'exécuter maintenant échouera car GitLab est suffisamment intelligent pour n'autoriser que les branches «protégées» à accéder à nos variables secrètes. Pour ajouter des balises de version, accédez à la page des paramètres du référentiel de votre projet GitLab et ajoutez v*
aux balises protégées.
Récapitulons ce qui se passe actuellement:
Vous sentez-vous puissant maintenant? Je me sens puissant. Je me souviens que la première fois que je suis arrivé aussi loin, j'ai appelé ma femme et lui ai expliqué tout ce pipeline avec des détails atroces. Et elle n’est même pas technique. J'ai été très impressionné par moi-même et vous devriez l'être aussi! Excellent travail à venir jusqu'ici!
Mais il y a plus, puisqu'un ordinateur fait des choses pour vous de toute façon, il peut également exécuter toutes les choses que vous êtes trop paresseux pour faire: des tests, des erreurs de peluchage, à peu près tout ce que vous voulez faire, et si l'un de ces échouent, ils ont gagné ne passe pas au déploiement.
J'adore avoir cela dans mon pipeline, cela rend mes révisions de code amusantes. Si une demande de fusion réussit toutes mes vérifications de code, elle mérite d'être examinée.
Ajouter un test
bloquer:
test: stage: test variables: POSTGRES_USER: test POSTGRES_PASSSWORD: test-password POSTGRES_DB: test DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSSWORD}@postgres/${POSTGRES_DB} RAILS_ENV: test services: - postgres:alpine before_script: - curl -sL https://deb.nodesource.com/setup_8.x | bash - apt-get update -qq && apt-get install -yqq nodejs libpq-dev - curl -o- -L https://yarnpkg.com/install.sh | bash - source ~/.bashrc - yarn - gem install bundler --no-ri --no-rdoc - bundle install -j $(nproc) --path vendor - bundle exec rake db:setup RAILS_ENV=test script: - bundle exec rake spec - bundle exec rubocop
Récapitulons ce qui se passe actuellement:
Prenez du recul et émerveillez-vous devant le niveau d’automatisation que vous avez accompli. À partir de maintenant, il ne vous reste plus qu'à écrire du code et à pousser. Testez votre application manuellement lors de la mise en scène si vous en avez envie, et lorsque vous vous sentez suffisamment en confiance pour la diffuser dans le monde, marquez-la avec le versionnage sémantique!
Ouais, c’est parfait, mais il manque quelque chose. Je n'aime pas rechercher la dernière version de l'application et la baliser explicitement. Cela prend plusieurs commandes et me distrait pendant quelques secondes.
Ok, mec, arrête! C'est assez. Vous êtes juste en train de sur-concevoir maintenant. Cela fonctionne, c'est génial, ne gâchez pas une bonne chose en exagérant.
D'accord, j'ai une bonne raison de faire ce que je vais faire.
Priez, éclairez-moi.
J'étais comme toi. J'étais content de cette configuration, mais ensuite j'ai raté. git tag
répertorie les balises par ordre alphabétique, v0.0.11
est au-dessus de v0.0.2
. Une fois, j'ai accidentellement tagué une version et j'ai continué à le faire pendant environ une demi-douzaine de versions jusqu'à ce que je voie mon erreur. C’est là que j’ai décidé d’automatiser cela aussi.
On y va encore une fois
D'accord, donc, heureusement, nous avons la puissance de npm à notre disposition, alors j'ai trouvé un package approprié: Run yarn add --dev standard-version
et ajoutez ce qui suit à votre package.json
fichier:
'scripts': { 'release': 'standard-version', 'major': 'yarn release --release-as major', 'minor': 'yarn release --release-as minor', 'patch': 'yarn release --release-as patch' },
Maintenant, vous devez faire une dernière chose, configurer Git pour pousser les balises par défaut. Pour le moment, vous devez exécuter git push --tags
pousser une balise vers le haut, mais le faire automatiquement régulièrement git push
est aussi simple que d'exécuter git config --global push.followTags true
.
Pour utiliser votre nouveau pipeline, chaque fois que vous souhaitez créer une version exécutée:
yarn patch
pour les versions de correctifsyarn minor
pour les versions mineuresyarn major
pour les versions majeuresSi vous n'êtes pas sûr de la signification des mots 'majeur', 'mineur' et 'correctif', lisez-en plus à ce sujet sur le site de versionnage sémantique .
Maintenant que vous avez enfin terminé votre pipeline, récapitulons comment l'utiliser!
yarn patch
pour marquer une version de correctif.git push
pour le pousser en production.Je viens d’effleurer la surface de ce qui est possible avec les pipelines CI / CD. C'est un exemple assez simpliste. Vous pouvez faire beaucoup plus en remplaçant Heroku par Kubernetes. Si vous décidez d'utiliser GitLab CI, lisez le documentation yaml car vous pouvez faire beaucoup plus en mettant des fichiers en cache entre les déploiements ou en enregistrant des artefacts!
Un autre énorme changement que vous pourriez apporter à ce pipeline est d'introduire des déclencheurs externes pour exécuter le versionnage et la publication sémantiques. Actuellement, ChatOps fait partie de leur forfait payant, et j'espère qu'ils le publieront dans des forfaits gratuits. Mais imaginez pouvoir déclencher l'image suivante via une seule commande Slack!
Finalement, lorsque votre application commence à devenir complexe et nécessite des dépendances au niveau du système, vous devrez peut-être utiliser un conteneur. Lorsque cela se produit, consultez notre guide: Premiers pas avec Docker: simplifier Devops .
Cet exemple d'application est vraiment en ligne et vous pouvez trouver le code source correspondant Ici .
Un pipeline de développement est la chaîne de tâches et de processus que vous suivez dans votre processus de développement.
Un pipeline de déploiement est la chaîne de tâches et de processus que vous exécutez dans votre processus de déploiement.
CI / CD est l'abréviation de l'intégration continue (intégrant votre code en un seul endroit en continu), de la livraison continue (création de votre produit prêt à être expédié en continu) et du déploiement continu (déploiement de votre produit en production en continu).
GitOps est un DevOps entièrement géré via Git.