Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup client deployment #48

Merged
merged 13 commits into from Feb 7, 2022
Merged

Setup client deployment #48

merged 13 commits into from Feb 7, 2022

Conversation

florimondmanca
Copy link
Collaborator

Closes #46

Cette PR étend la configuration Ansible pour déployer le client sur le serveur (en même temps que l'API), incluant :

  • Installation de Node lors du provisioning, installation des dépendances Node et lancée du build lors du deploy
  • Ajout du serveur Node frontend à Supervisor et Nginx
  • Paramétrisation de l'URL lors de requêtes à l'API (avec un setup assez subtil pour faire correspondre SSR/browser x prod/dev)
  • Mise à jour de la doc

Testé en local avec la VM de test, déploiement sur staging à venir.

@florimondmanca florimondmanca added the infra Ce qui attrait aux environnements de déploiement et à l'infrastructure Cloud label Feb 1, 2022
@florimondmanca florimondmanca force-pushed the fm/client-ops branch 2 times, most recently from 4764d68 to 6ae7c9a Compare February 1, 2022 19:36
Copy link
Contributor

@magopian magopian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Je n'y connais pas grand chose à Ansible, mais après avoir fait une passe de relecture, ça m'a l'air solide 👍
Merci !

🚢

Makefile Outdated Show resolved Hide resolved
client/svelte.config.js Outdated Show resolved Hide resolved
client/jest.config.cjs Outdated Show resolved Hide resolved
@magopian
Copy link
Contributor

magopian commented Feb 2, 2022

Pour info il y a un soucis de formatting sur src/__tests__/appMock.cjs (si tu lances npm run format ça devrait te corriger ça tout seul comme un grand).

@florimondmanca
Copy link
Collaborator Author

florimondmanca commented Feb 2, 2022

Test sur staging

Provisioning (installation de Node, etc)

$ make provision-staging
cd ops && make provision-staging
make[1]: Entering directory '/home/florimond/dev/prj-catalogue/catalogage-donnees/ops'
../venv/bin/ansible-playbook -i ansible/hosts_staging -e @ansible/secrets/staging.enc --vault-password-file ansible/secrets/staging.vault-password -t provision ansible/playbook.yml

PLAY [web] *********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************
ok: [web1-staging]

TASK [common : Update system] **************************************************************************************************************************************************************************
changed: [web1-staging]

TASK [pyenv : Install build requirements] **************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Clone pyenv] *****************************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Set path to pyenv binary] ****************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Create .pyenvrc] *************************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Set path to .bashrc] *********************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Load pyenv in .bashrc] *******************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Install interpreter] *********************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Get current global version] **************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Set pyenv_global_active fact] ************************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Check if 'system' version is available] **************************************************************************************************************************************************
ok: [web1-staging]

TASK [pyenv : Remove 'system' from pyenv_global] *******************************************************************************************************************************************************
skipping: [web1-staging]

TASK [pyenv : Set pyenv global version to '3.8.9 system'] **********************************************************************************************************************************************
skipping: [web1-staging]

TASK [nvm : Install nvm] *******************************************************************************************************************************************************************************
changed: [web1-staging]

TASK [nvm : Install Node binary] ***********************************************************************************************************************************************************************
changed: [web1-staging]

TASK [nvm : Get node binary path] **********************************************************************************************************************************************************************
changed: [web1-staging]

TASK [nvm : Set node_bin_path fact] ********************************************************************************************************************************************************************
ok: [web1-staging]

TASK [nvm : Get npm binary path] ***********************************************************************************************************************************************************************
changed: [web1-staging]

TASK [nvm : Set npm_bin_path fact] *********************************************************************************************************************************************************************
ok: [web1-staging]

TASK [nvm : Create node bin symlink] *******************************************************************************************************************************************************************
changed: [web1-staging]

TASK [nvm : Create npm bin symlink] ********************************************************************************************************************************************************************
changed: [web1-staging]

TASK [common : Ensure nginx is installed and up to date] ***********************************************************************************************************************************************
ok: [web1-staging]

TASK [common : Ensure supervisor is installed] *********************************************************************************************************************************************************
ok: [web1-staging]

PLAY RECAP *********************************************************************************************************************************************************************************************
web1-staging               : ok=22   changed=7    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   

make[1]: Leaving directory '/home/florimond/dev/prj-catalogue/catalogage-donnees/ops'

Deploy :

$ EXTRA_OPTS="-e env_branch=fm/client-ops" make deploy-staging
cd ops && make deploy-staging
make[1]: Entering directory '/home/florimond/dev/prj-catalogue/catalogage-donnees/ops'
../venv/bin/ansible-playbook -i ansible/hosts_staging -e @ansible/secrets/staging.enc --vault-password-file ansible/secrets/staging.vault-password -t deploy ansible/playbook.yml -e env_branch=fm/client-ops

PLAY [web] *********************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************
ok: [web1-staging]

TASK [common : Ensure nginx is running] ****************************************************************************************************************************************************************
ok: [web1-staging]

TASK [common : Ensure supervisor is running] ***********************************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Ensure Nginx site configuration is up to date] *********************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure Nginx site is default] **************************************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Git checkout fm/client-ops] ****************************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Check if .env exists] **********************************************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Ensure .env exists] ************************************************************************************************************************************************************************
skipping: [web1-staging]

TASK [web : Ensure database URL is present in .env file] ***********************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Get Python binary path] ********************************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Set python_bin_path fact] ******************************************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Ensure Python dependencies are installed] **************************************************************************************************************************************************
ok: [web1-staging]

TASK [web : Ensure Node dependencies are installed] ****************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure build is up to date] ****************************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure migrations are up to date] **********************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure supervisor configuration is up to date] *********************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure client is running] ******************************************************************************************************************************************************************
changed: [web1-staging]

TASK [web : Ensure server is running] ******************************************************************************************************************************************************************
ok: [web1-staging]

RUNNING HANDLER [common : reload nginx] ****************************************************************************************************************************************************************
changed: [web1-staging]

RUNNING HANDLER [common : reload supervisor] ***********************************************************************************************************************************************************
changed: [web1-staging]

PLAY RECAP *********************************************************************************************************************************************************************************************
web1-staging               : ok=19   changed=10   unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

make[1]: Leaving directory '/home/florimond/dev/prj-catalogue/catalogage-donnees/ops'

Résultat : http://51.159.187.137/

  • ❌ Accéder à /api renvoie vers /docs (manque le préfixe) -> préfixe pas pris en compte par l'API (pb de configuration)
    • On le voie aussi en accédant à /api/docs directement : on obtient une erreur disant que /openapi.json n'a pas été trouvé (logique : il se trouve désormais sur /api/openapi.json)

=> Je viens de push un commit, mais je crois qu'il faudrait que je gère le "déplacement de l'API sur /api/ en prod" dans une PR bien à part.

Edit : voir #51, je vais rollback le dernier commit ici.

@florimondmanca
Copy link
Collaborator Author

florimondmanca commented Feb 3, 2022

@magopian J'ai testé de déployer sur staging. Il y a un problème avec le node ./build, ça réagit pas bien à un reload de Supervisor.

Sur l'instance, lors du deploy, j'obtenais une erreur bizarre du type /_app/blabla.js not found alors que le fichier était bien présent sur le serveur. Le supervisorctl status client me montrait que l'app avait planté. Les logs du client disaient "Address already in use", et pour cause : il y avait toujours bien l'ancien serveur sur le port 3000 (un petit netstat -lp | grep 3000). Après avoir kill cet ancien process, le client a redémarré et plus d'erreur.

En l'absence de doc sur le déploiement par SvelteKit j'ai utilisé ce fichier build/index.js, mais le Supervisor au reload n'a pas l'air de lui faire grand effet. Je ne sais pas s'il faut ajouter quelque chose, ou si c'est "juste" un bug.

Edit : petit morceau d'investigation en plus : d'après la doc Ansible au deploy on exécute l'équivalent de supervisorctl update client puis supervisorctl restart client. Le problème pourrait venir d'un mismatch entre le process qui écoute effectivement, et le process que Supervisor voit. En effet, quand tout fonctionne supervisorctl status client -> par ex pid 509007, mais netstat -lp | grep 3000 -> par ex pid 509019. À l'inverse le server montre le même PID côté Supervisor et côté process qui listen vraiment. Hmm.

root@catalogage-dev:~# ps 509007
    PID TTY      STAT   TIME COMMAND
 509007 ?        Sl     0:00 npm start
root@catalogage-dev:~# ps 509019
    PID TTY      STAT   TIME COMMAND
 509019 ?        Sl     0:00 node ./build

Ça se reproduit en local : un npm start brut (sans passer par make serve-dist-client) démarre bien 2 process, un pour npm start et un pour node. Ça ne devrait théoriquement pas poser de pb à Supervisor car il garde la trace des process enfants partant du process qu'il démarre... Sauf si cette trace est perdue par npm ???

Hé bien... On dirait bien 😱 Preuve en local :

npm start
$ ps -a
    PID TTY          TIME CMD
   2197 tty2     01:18:44 Xorg
   2574 tty2     00:00:00 gnome-session-b
 420891 pts/0    00:00:00 npm start
 420902 pts/0    00:00:00 sh
 420903 pts/0    00:00:00 node
 420948 pts/3    00:00:00 ps

Maintenant on kill npm start (comme le ferait supervisor) :

kill 420891

Et là, catastrophe, node est toujours up...

$ ps -a
    PID TTY          TIME CMD
   2197 tty2     01:18:46 Xorg
   2574 tty2     00:00:00 gnome-session-b
 420903 pts/0    00:00:00 node
 421351 pts/3    00:00:00 ps

Et si j'essaie de npm start j'obtiens bien une EADDRINUSE 🤯

La question reste : est-ce que ce comportement est spécifique au setup Svelte, ou est-ce qu'on peut le reproduire sur un bête serveur Express à la mano ? Est-ce qu'en fait je rate qqc de parfaitement évident ? Est-ce que Supervisor est bien sensé arrêter tous les processus enfants ? Tout ça demande vérification. La suite au prochain épisode (lundi) ...

@magopian
Copy link
Contributor

magopian commented Feb 4, 2022

Eh ben... belle investigation !
Après une recherche google je tombe sur des infos de ce genre :

La solution semble d'être d'utiliser la commande node directement sans passer par npm start, ou d'avoir une magouille du genre lerna/lerna#2284 (comment) (un script shell qui s'occupe de kill les process).

@florimondmanca
Copy link
Collaborator Author

@florimondmanca
Copy link
Collaborator Author

OK, testé sur la VM puis sur staging : command=node ./build lance bien 1 seul process que Supervisor gère correctement lors de l'update/restart. 👍

@florimondmanca
Copy link
Collaborator Author

Allez hop, voyons voir ce que ça donne à l'usage !

@florimondmanca florimondmanca merged commit 99b4753 into master Feb 7, 2022
@florimondmanca florimondmanca deleted the fm/client-ops branch February 7, 2022 12:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
infra Ce qui attrait aux environnements de déploiement et à l'infrastructure Cloud
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Déploiement du client
2 participants