Définition du déploiement de GitLab CI pour NodeJS dans l’instance AWS Ubuntu

J’ai une instance AWS Ubuntu sur laquelle GitLab CE est configuré. Maintenant, je veux configurer GitLab CI pour déployer mon application NodeJS après chaque validation. Je n’ai pas de solution pas à pas pour cela.

Mon application NodeJS s’exécutant dans /var/www/mean/my-app sur http://myapp.mydomain.com et l’hébergement est géré par Apache Proxy,

  ServerAdmin [email protected] ServerName gitlab.mydomain.com ServerAlias www.gitlab.mydomain.com ServerSignature Off ProxyPreserveHost On AllowEncodedSlashes NoDecode  Require all granted ProxyPassReverse http://localhost:8080 ProxyPassReverse http://gitlab.mydomain.com/  RewriteEngine on RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR] RewriteCond %{REQUEST_URI} ^/uploads/.* RewriteRule .* http://127.0.0.1:8080%{REQUEST_URI} [P,QSA,NE] DocumentRoot /home/git/gitlab/public LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b" common_forwarded ErrorLog /var/log/apache2/gitlab_error.log CustomLog /var/log/apache2/gitlab_forwarded.log common_forwarded CustomLog /var/log/apache2/gitlab_access.log combined env=!dontlog CustomLog /var/log/apache2/gitlab.log combined  

Et l’application est initialisée en utilisant pour toujours module

 forever start app.js 

La configuration de gitlab vérifie sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production donne,

 Checking GitLab Shell ... GitLab Shell version >= 4.0.0 ? ... OK (4.0.0) Repo base directory exists? default... yes Repo storage directories are symlinks? default... no Repo paths owned by git:git? default... yes Repo paths access is drwxrws---? default... yes hooks directories in repos are links: ... dev / my-app ... ok Running /home/git/gitlab-shell/bin/check Check GitLab API access: OK Access to /home/git/.ssh/authorized_keys: OK Send ping to redis server: OK gitlab-shell self-check successful Checking GitLab Shell ... Finished Checking Sidekiq ... Running? ... yes Number of Sidekiq processes ... 1 Checking Sidekiq ... Finished Checking Reply by email ... Reply by email is disabled in config/gitlab.yml Checking Reply by email ... Finished Checking LDAP ... LDAP is disabled in config/gitlab.yml Checking LDAP ... Finished Checking GitLab ... Git configured with autocrlf=input? ... yes Database config exists? ... yes All migrations up? ... yes Database contains orphaned GroupMembers? ... no GitLab config exists? ... yes GitLab config outdated? ... no Log directory writable? ... yes Tmp directory writable? ... yes Uploads directory setup correctly? ... yes Init script exists? ... yes Init script up-to-date? ... yes projects have namespace: ... dev / my-app ... yes Redis version >= 2.8.0? ... yes Ruby version >= 2.1.0 ? ... yes (2.3.1) Your git bin path is "/usr/bin/git" Git version >= 2.7.3 ? ... yes (2.7.4) Active users: 1 Checking GitLab ... Finished 

Je me connectais à l’instance en utilisant SSH depuis mon système,

 ssh -i API-Key.pem [email protected] 

Clé créée en utilisant la commande

 ssh-keygen -t rsa 

/etc/gitlab-runner/config.toml coureur sur /etc/gitlab-runner/config.toml

 concurrent = 1 check_interval = 0 [[runners]] name = "Production Runner" url = "http://gitlab.mydomain.com/ci" token = "xxxxxxxxxxxxxxxxxxxxxxxxxxx" executor = "ssh" [runners.ssh] user = "ubuntu" host = "ip-XXX-XX-XX-XXX" identity_file = "/home/ubuntu/.ssh/id_rsa" [runners.cache] 

Code sur .gitlab-ci.yml

 test_async: script: - npm install 

A cause de ma mauvaise configuration, le coureur commet une erreur,

 Running with gitlab-ci-multi-runner 1.7.1 (f896af7) Using SSH executor... ERROR: Preparation failed: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain Will be resortinged in 3s ... 

Mes confusions sont:

Quel devrait être le contenu du fichier .gitlab-ci.yml pour déployer le code engagé dans l’emplacement de l’application?

Et comment configurer un coureur pour cela? Si je dois utiliser un ssh runner, quelles devraient être les configurations là-bas?

Mettre à jour:

Après avoir fourni le fichier .pem sous le nom identity_file , obtenez l’erreur suivante

 Running with gitlab-ci-multi-runner 1.7.1 (f896af7) Using SSH executor... Running on ip-xxx-xx-xx-xxx via ip-xxx-xx-xx-xxx... Cloning repository... Cloning into 'builds/a92f1b91/0/dev/my-app'... fatal: unable to access 'http://gitlab-ci-token:[email protected]/dev/my-app.git/': The requested URL returned error: 500 ERROR: Build failed: Process exited with: 1. Reason was: () 

Maintenant, il y a un problème, clone git avec http ne fonctionne pas mais le clonage ssh fonctionne.

Remarque: les deux environnements gitlab et build sont les mêmes hôtes (même instance de aws)

Bug également signalé dans GitLab (problème de clone http).

Dans votre /etc/gitlab-runner/config.toml

 concurrent = 1 check_interval = 0 [[runners]] name = "Production Runner" url = "http://gitlab.mydomain.com/ci" token = "xxxxxxxxxxxxxxxxxxxxxxxxxxx" executor = "ssh" [runners.ssh] user = "ubuntu" host = "ip-XXX-XX-XX-XXX" identity_file = "/home/ubuntu/.ssh/id_rsa" [runners.cache] 

Vous définissez

  • hôte
  • utilisateur
  • et fichier d’identité

host devrait être votre adresse IP d’hôte Build (en d’autres termes, vous allez exécuter votre build)
L’utilisateur doit être votre utilisateur sur Build host . Pas sur l’hôte gitlab .

Vous pouvez tester le fonctionnement de votre mot de passe sans ssh

  1. Connectez-vous à l’hôte gitlab en tant que root
  2. ssh -i /home/ubuntu/.ssh/id_rsa ubuntu @ ip-XXX-XX-XX-XXX

Si cela fonctionne et ne vous demande pas de mot de passe, tout va bien.
Si cela casse, cela signifie que vous n’avez pas configuré le mot de passe avec moins d’authentification correctement.

La méthode la plus simple pour configurer un mot de passe sans authentification basée sur une clé publique consiste à utiliser la commande appelée

 ssh-copy-id 

Par exemple, je veux configurer le mot de passe moins l’authentification ssh entre mon gitlab et mon hôte de compilation.
Mon ip hôte de compilation est 192.168.0.42 et le nom d’hôte est build.home
J’ai déjà mes id_rsa et id_rsa.pub générés sous /home/ubuntu/.ssh sur l’hôte gitlab.

Poussons maintenant notre clé publique de l’hôte gitlab vers notre hôte de compilation. La première fois, il vous demandera un mot de passe.

 [root@gitlab ~]# ssh-copy-id -i /home/ubuntu/.ssh/id_rsa.pub [email protected] /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys [email protected]'s password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh '[email protected]'" and check to make sure that only the key(s) you wanted were added. 

Notez que dans l’exemple ci-dessus, je poussais la clé publique sur l’hôte distant.

Mais quand je vais maintenant me connecter à cet hôte distant, je spécifierai ma clé privée.

 [root@gitlab ~]# ssh -i /home/ubuntu/.ssh/id_rsa [email protected] [ubuntu@build ~]$ hostname build.home 

Essayez de tester l’authentification de votre clé publique entre l’hôte gitlab et l’hôte distant et mettez à jour votre question.

Ressources:

Edit 1:

Voici ma config.
Mon hôte gitlab s’appelle gitlab.home 192.168.0.41
Et j’ai une autre VM appelée sshbuild.home 192.168.0.43

Voici comment j’ai ajouté ssh runner

Étape 1. Installez sur mon gitlab.home yum install gitlab-ci-multi-runner et enregistrez ma VM sshbuild.home distante en tant que ssh runner

entrer la description de l'image ici

entrer la description de l'image ici

Je dois aussi m’assurer que le mot de passe moins l’auth fonctionne entre mes gitlab.home et sshbuild.home, donc

 [root@gitlab gitlab-runner]# ssh-copy-id 192.168.0.43 The authenticity of host '192.168.0.43 (192.168.0.43)' can't be established. ECDSA key fingerprint is b4:6a:1b:72:d1:7d:1f:34:f7:bb:ef:ad:69:42:11:13. Are you sure you want to continue connecting (yes/no)? yes /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys [email protected]'s password: Number of key(s) added: 1 Now try logging into the machine, with: "ssh '192.168.0.43'" and check to make sure that only the key(s) you wanted were added. [root@gitlab gitlab-runner]# ssh 192.168.0.43 Last login: Fri Nov 18 17:05:06 2016 from 192.168.0.101 [root@sshbuild ~]# exit 

Ensuite, j’ai désactivé mon autre runner (shell runner) et rendu le nouveau projet de runner SSH spécifique afin de m’assurer que lorsque je me lance, il sera exécuté sur le serveur SSH.

entrer la description de l'image ici

Et je commets et voila – nous avons notre test réussi qui a été exécuté sur l’hôte sshbuild.home

entrer la description de l'image ici

Voici plusieurs liens qui pourraient aider à mieux comprendre ce sujet

PS: Et voici mon fichier /etc/gitlab-runner/config.toml

 [root@gitlab gitlab-runner]# cat /etc/gitlab-runner/config.toml concurrent = 1 check_interval = 0 [[runners]] name = "sshbuild" url = "http://gitlab.home/" token = "2bc1825d8fbde09fd632637c60e9e7" executor = "ssh" [runners.ssh] user = "root" host = "192.168.0.43" port = "22" identity_file = "/root/.ssh/id_rsa" [runners.cache] 

PS: J’ai une erreur similaire si vous désactivez HTTP pour mon repo sous Paramètres dans l’interface Web. Cependant l’erreur n’est pas 500 mais 403.

entrer la description de l'image ici

Edit 2:

Je vais maintenant couvrir .gitlab-ci.yml basé sur un simple projet HelloWorld
Dans mon HelloWorld, j’ai un fichier appelé server.js qui, lorsqu’il est exécuté à partir de node, créera simplement Web Server sur le port 3000 et répondra avec “Hello World” sur les requêtes GET.

  1 const http = require('http'); 2 3 const hostname = '0.0.0.0'; 4 const port = 3000; 5 6 const server = http.createServer((req, res) => { 7 res.statusCode = 200; 8 res.setHeader('Content-Type', 'text/plain'); 9 res.end('Hello World!\n'); 10 }); 11 12 server.listen(port, hostname, () => { 13 console.log(`Server running at http://${hostname}:${port}/`); 14 }); 

Mon objective est de pouvoir exécuter un test élémentaire. Dans ce cas je vais courir simple

 curl localhost:3000 | grep "Hello World" 

Mais je dois le mettre dans un script distinct qui aura le statut de sortie 0 en cas de succès et non nul en cas d’échec

 cat -n simpletest.sh 1 #!/bin/bash 2 3 cleanup () 4 { 5 count=`netstat -anp|grep ":3000"|grep LISTEN|awk '{print $NF}'|cut -d\/ -f1|wc -l` 6 if [ $count -ne 0 ] 7 then 8 pid=`netstat -anp|grep ":3000"|grep LISTEN|awk '{print $NF}'|cut -d\/ -f1`; 9 echo "Need to kill PID $pid"; 10 kill $pid 11 fi 12 } 13 14 echo "Running simple test" 15 curl localhost:3000|grep "Hello World" 16 if [ $? -eq 0 ] 17 then 18 echo "Test was successfull" 19 echo "Clean up node.js process" 20 cleanup 21 exit 0 22 else 23 echo "Test failed" 24 echo "Clean up node.js process" 25 cleanup 26 exit 1 27 fi 

Maintenant, couvrons mon .gitlab-ci.yml

 cat -n .gitlab-ci.yml 1 test: 2 3 before_script: 4 - echo "Before script" 5 - hostname 6 - /bin/bash cleanup.sh 7 8 script: 9 - echo "Main Script" 10 - node server.js & 11 - sleep 3 12 - /bin/bash simpletest.sh 

J’ai un seul travail appelé test.
Dans before_script, il exécute le script cleanup.sh qui supprime simplement l’écoute du PID sur le port 3000, au cas où cela serait trouvé.

 cat -n cleanup.sh 1 #!/bin/bash 2 count=`netstat -anp|grep ":3000"|grep LISTEN|awk '{print $NF}'|cut -d\/ -f1|wc -l` 3 if [ $count -ne 0 ] 4 then 5 pid=`netstat -anp|grep ":3000"|grep LISTEN|awk '{print $NF}'|cut -d\/ -f1`; 6 echo "Need to kill PID $pid"; 7 kill $pid 8 fi 9 exit 0 

Et sous script: il exécute node avec mon server.js, lui donne 3 secondes pour démarrer et exécute ensuite le test.
Ce test prendra également en charge la destruction du noeud PID après le test.

Donc, validons et vérifions l’état de la construction

entrer la description de l'image ici

Et maintenant, changeons notre server.js pour ne pas afficher “Hello World” mais “HelloWorld”, donc il n’y a pas d’espace entre les deux. Je pense que mon test échouera car il attend littéralement “Hello World”. Et ça échoue.

entrer la description de l'image ici

C’est le cas d’utilisation CI le plus simpliste que je puisse trouver.
Maintenant, si vous vous basez sur le statut du cas de test, vous souhaitez déployer du code dans un autre environnement – vous devez commencer à utiliser

  • étapes et
  • environnement

Donc, votre fichier .gitlab-ci.yml deviendrait quelque chose comme ça (exemple de travail réel)

 cat -n .gitlab-ci.yml 1 stages: 2 - test 3 - deploy 4 5 run_test_case: 6 stage: test 7 before_script: 8 - echo "Before script" 9 - hostname 10 - /bin/bash cleanup.sh 11 12 script: 13 - echo "Main Script" 14 - node server.js & 15 - sleep 3 16 - /bin/bash simpletest.sh 17 18 deploy_to_production: 19 stage: deploy 20 script: 21 - echo "Run code here to do production deployment" 22 environment: 23 name: production 

Qui sur git push réussira.
Sur la ligne 21, j’ai simplement lancé echo, mais cela pourrait être remplacé par un script qui transmettrait votre environnement de stockage intermédiaire ou de production à distance.

entrer la description de l'image ici

entrer la description de l'image ici