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
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
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:
https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/executors/ssh.md
PS: Je posterai mon environnement de travail un peu plus tard aujourd’hui quand je rentrerai chez moi.
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
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.
Et je commets et voila – nous avons notre test réussi qui a été exécuté sur l’hôte sshbuild.home
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.
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
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.
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
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.