Article
· Déc 14, 2023 10m de lecture

Diffusion continue de votre solution InterSystems à l'aide de GitLab - Partie VIII : CD utilisant l'ICM

Dans cette série d'articles, j'aimerais présenter et discuter de plusieurs approches possibles pour le développement de logiciels avec les technologies d'InterSystems et GitLab. J'aborderai des sujets tels que:

  • Git 101
  • Flux Git (processus de développement)
  • Installation de GitLab
  • Flux de travail GitLab
  • Diffusion continue
  • Installation et configuration de GitLab
  • GitLab CI/CD
  • Pourquoi des conteneurs?
  • Infrastructure de conteneurs
  • CD utilisant des conteneurs
  • CD utilisant ICM

Dans cet article, nous allons créer une diffusion continue avec InterSystems Cloud Manager. ICM est une solution de déploiement et de provisionnement en nuage pour les applications basées sur InterSystems IRIS. Il vous permet de définir la configuration de déploiement souhaitée et ICM la provisionne automatiquement. Pour plus d'informations, consultez : First Look : ICM.

Flux de Travail

Dans notre Diffusion continue, nous allons :

  • Introduire le code dans le référentiel GitLab
  • Construire l' image docker
  • Publier l'image dans le registre docker
  • La tester sur un serveur de test
  • Si les tests sont positifs, déployer sur un serveur de production

Ou en format graphique :

Comme vous pouvez le voir, c'est à peu près la même chose, sauf que nous utiliserons ICM au lieu de gérer les conteneurs Docker manuellement.

Configuration ICM

Avant de commencer à mettre à jour les conteneurs, il faut les provisionner. Pour ce faire, il faut déterminer les fichiers defaults.json et definitions.json, qui décrivent notre architecture. Je fournirai ces 2 fichiers pour un serveur LIVE, les definitions pour un serveur TEST sont les mêmes, les valeurs defaults sont les mêmes à l'exception des valeurs Tag et SystemMode .

defaults.json:

{
    "Provider": "GCP",
    "Label": "gsdemo2",
    "Tag": "LIVE",
    "SystemMode": "LIVE",
    "DataVolumeSize": "10",
    "SSHUser": "sample",
    "SSHPublicKey": "/icmdata/ssh/insecure.pub",
    "SSHPrivateKey": "/icmdata/ssh/insecure",
    "DockerImage": "eduard93/icmdemo:master",
    "DockerUsername": "eduard93",
    "DockerPassword": "...",
    "TLSKeyDir": "/icmdata/tls",
    "Credentials": "/icmdata/gcp.json",
    "Project": "elebedyu-test",
    "MachineType": "n1-standard-1",
    "Region": "us-east1",
    "Zone": "us-east1-b",
    "Image": "rhel-cloud/rhel-7-v20170719",
    "ISCPassword": "SYS",
    "Mirror": "false"
}

definitions.json

[
    {
    "Role": "DM",
    "Count": "1",
    "ISCLicense": "/icmdata/iris.key"
    }
]

Dans le conteneur ICM, le dossier /icmdata est installé à partir de l'hôte et :

  • Les définitions du serveur TEST sont placées dans le dossier /icmdata/test
  • Les définitions du serveur LIVE sont placées dans le dossier /icmdata/live

Après avoir obtenu toutes les clés requises :

keygenSSH.sh /icmdata/ssh
keygenTLS.sh /icmdata/tls

Et avoir placé les fichiers requis dans /icmdata:

  • iris.key
  • gcp.json (pour le déploiement sur Google Cloud Platform)

Appelez ICM pour provisionner vos instances :

cd /icmdata/test
icm provision
icm run
cd /icmdata/live
icm provision
icm run

Cela permet de provisionner un serveur TEST et un serveur LIVE avec une instance autonome d'InterSystems IRIS sur chacun d'entre eux.

Veuillez vous référer à ICM First Look pour un guide plus détaillé.

Construction

D'abord, nous devons construire notre image.

Notre code sera, comme d'habitude, stocké dans le référentiel, la configuration CD - dans gitlab-ci.yml mais en plus (pour renforcer la sécurité) nous stockerons plusieurs fichiers spécifiques au serveur sur un serveur build.

iris.key

Clé de licence. Elle peut également être téléchargée lors du conteneur build au lieu d'être stockée sur un serveur. Il n'est pas très sûr de la stocker dans le référentiel.

pwd.txt

Fichier contenant le mot de passe par défaut. Encore une fois, il n'est pas très sûr de la stocker dans le référentiel. De plus, si vous hébergez l'environnement de production (prod) sur un serveur séparé, il pourrait avoir un mot de passe par défaut différent.

load_ci_icm.script

Script initial qui :

  • Télécharge l'installateur
  • L'installateur effectue l'initialisation de l'application
  • Télécharge le code
set dir = ##class(%File).NormalizeDirectory($system.Util.GetEnviron("CI_PROJECT_DIR"))
do ##class(%SYSTEM.OBJ).Load(dir _ "Installer/Global.cls","cdk")
do ##class(Installer.Global).init()
halt

Notez que la première ligne est intentionnellement laissée vide.

Certains éléments diffèrent des exemples précédents. Tout d'abord, nous n'activons pas l'authentification du système d'exploitation car ICM interagit avec le conteneur plutôt qu'avec GitLab directement. Ensuite, j'utilise le manifeste de l'installateur pour initialiser notre application afin de montrer différentes approches de l'initialisation. Pour en savoir plus sur Installer, consultez cet article. Enfin, nous publierons notre image dans un Docher Hub en tant que dépôt privé.

 

Installateur/Global.cls

Notre manifeste d'installateur se présente comme suit :

<Manifest>
    <Log Text="Creating namespace ${Namespace}" Level="0"/>
    <Namespace Name="${Namespace}" Create="yes" Code="${Namespace}" Ensemble="" Data="IRISTEMP">
        <Configuration>
            <Database Name="${Namespace}" Dir="${MGRDIR}/${Namespace}" Create="yes" MountRequired="true" Resource="%DB_${Namespace}" PublicPermissions="RW" MountAtStartup="true"/>
        </Configuration>

        <Import File="${Dir}MyApp" Recurse="1" Flags="cdk" IgnoreErrors="1" />
    </Namespace>

    <Log Text="Mapping to USER" Level="0"/>
    <Namespace Name="USER" Create="no" Code="USER" Data="USER" Ensemble="0">
        <Configuration>
            <Log Text="Mapping MyApp package to USER namespace" Level="0"/>
            <ClassMapping From="${Namespace}" Package="MyApp"/>
        </Configuration>

        <CSPApplication  Url="/"      Directory="${Dir}client" AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL"  />
        <CSPApplication  Url="/myApp" Directory="${Dir}"       AuthenticationMethods="64" IsNamespaceDefault="false" Grant="%ALL"  />
    </Namespace>
</Manifest>

Et il implémente les modifications suivants:

  1. Crée l'espace de noms de l'application.
  2. Crée la base de données du code de l'application (les données sont stockées dans la base de données USER).
  3. télécharge le code dans la base de données du code de l'application.
  4. Associe le paquet MyApp à l'espace de noms USER.
  5. Crée 2 applications web: pour HTML et pour REST.

gitlab-ci.yml

Passons maintenant à la configuration de la diffusion continue :

build image:
  stage: build
  tags:
    - master
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci_icm.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t eduard93/icmdemo:$CI_COMMIT_REF_NAME .

Que se passe-t-il ici?

Tout d'abord, comme docker build ne peut accéder qu'aux sous-référentiel d'un référentiel de base build qui est dans notre cas la racine du référentiel, nous devons copier notre référentiel "secret" (celui qui contient  iris.keypwd.txt et load_ci_icm.script) dans le référentiel cloné.

Ensuite, le premier accès au terminal nécessite un utilisateur/pass, nous les ajouterions donc à load_ci.script (c'est ce que la ligne vide au début de load_ci.script est pour btw).

Enfin, nous construisons l'image docker et la balisons de manière appropriée :   eduard93/icmdemo:$CI_COMMIT_REF_NAME

$CI_COMMIT_REF_NAME est le nom d'une branche courante. Notez que la première partie de la balise de l'image doit être nommée de la même manière que le nom du projet dans GitLab, de manière à ce qu'elle puisse être vue dans l'onglet Registre de GitLab (les instructions sur le balisage sont disponibles dans l'onglet Registre).

Dockerfile

La construction de l'image docker se fait en utilisant Dockerfile, la voici :

FROM intersystems/iris:2018.1.1-released

ENV SRC_DIR=/tmp/src
ENV CI_DIR=$SRC_DIR/ci
ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ \
 && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt \
 && iris start $ISC_PACKAGE_INSTANCENAME \
 && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script \
 && iris stop $ISC_PACKAGE_INSTANCENAME quietly

Nous partons du conteneur iris de base.

Tout d'abord, nous copions notre référentiel (ainsi que le référentiel "secret") à l'intérieur du conteneur.

Ensuite, nous copions la clé de licence dans le référentiel mgr.

Ensuite, nous remplaçons le mot de passe par la valeur du fichier pwd.txt. Notez que le fichier pwd.txt est supprimé lors de cette opération.

Ensuite, l'instance est démarrée et le fichier load_ci.script est exécuté.

Finalement, l'instance iris est arrêtée.

Notez que j'utilise l' exécuteur Shell GitLab et non exécuteur Docker. L'exécuteur Docker est utilisé lorsque vous avez besoin de quelque chose de l'intérieur de l'image, par exemple, vous créez une application Android dans un conteneur java et vous n'avez besoin que d'un apk. Dans notre cas, il nous faut un conteneur complet et pour cela nous avons besoin de l'exécuteur Shell. Nous exécutons donc des commandes Docker via l'exécuteur GitLab Shell.

Publication

Maintenant, publions notre image dans un Docker Hub

publish image:
  stage: publish
  tags:
    - master
  script:
    - docker login -u eduard93 -p ${DOCKERPASSWORD}
    - docker push eduard93/icmdemo:$CI_COMMIT_REF_NAME

Notez la variable ${DOCKERPASSWORD}, c'est un GitLab variable secrète. Nous pouvons les ajouter dans GitLab > Projet > Paramètres > CI/CD > Variables:

Les journaux de tâches ne contiennent pas non plus de valeur de mot de passe :

Running with gitlab-runner 10.6.0 (a3543a27)
  on icm 82634fd1
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
HEAD is now at 8e24591 Add deploy to LIVE
Checking out 8e245910 as master...
Skipping Git submodules setup
$ docker login -u eduard93 -p ${DOCKERPASSWORD}
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
Login Succeeded
$ docker push eduard93/icmdemo:$CI_COMMIT_REF_NAME
The push refers to repository [docker.io/eduard93/icmdemo]
master: digest: sha256:d1612811c11154e77c84f0c08a564a3edeb7ddbbd9b7acb80754fda97f95d101 size: 2620
Job succeeded

et sur Docker Hub, nous pouvons voir notre nouvelle image :

 

Exécution

Nous avons notre image, maintenant nous allons l'exécuter sur notre serveur test. Voici le script.

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/test && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"

Avec ICM, il suffit d'exécuter une seule commande (icm upgrade) pour mettre à jour le déploiement existant. Nous l'appelons en exécutant "docker exec icm sh -c " qui exécute une commande spécifiée à l'intérieur du conteneur icm.  D'abord, nous passons à /icmdata/test où notre définition de déploiement ICM est définie pour un serveur TEST. Ensuite nous appelons icm upgrade pour remplacer un conteneur existant par un nouveau conteneur.

Test

Exécutons quelques tests.

test image:
  stage: test
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/test && icm session -namespace USER -command 'do \$classmethod(\"%UnitTest.Manager\",\"RunTest\",\"MyApp/Tests\",\"/nodelete\")' | tee /dev/stderr | grep 'All PASSED' && exit 0 || exit 1"

Encore une fois, nous exécutons une commande à l'intérieur de notre conteneur icm. La session icm exécute une commande sur un nœud déployé. La commande exécute des tests unitaires. Ensuite, il envoie tous les résultats à l'écran et à grep pour trouver les résultats des tests unitaires et quitter le processus avec succès ou avec une erreur.

Déploiement

Le déploiement sur un serveur de production est absolument identique au déploiement sur un serveur test, à l'exception d'un autre répertoire pour la définition du déploiement LIVE. En cas d'échec des tests, cette étape n'est pas exécutée.

deploy image:
  stage: deploy
  environment:
    name: $CI_COMMIT_REF_NAME
  tags:
    - master
  script:
    - docker exec icm sh -c "cd /icmdata/live && icm upgrade -image eduard93/icmdemo:$CI_COMMIT_REF_NAME"

Conclusion

ICM vous offre un moyen simple et intuitif d'approvisionner l'infrastructure en nuage et d'y déployer des services, ce qui vous permet de vous lancer dans le nuage dès maintenant, sans développement ou réoutillage majeur. Les avantages de l'infrastructure en tant que code (IaC) et du déploiement conteneurisé facilitent le déploiement des applications basées sur InterSystems IRIS au sein de plateformes de cloud public telles que Google, Amazon et Azure, ou au sein de votre cloud privé VMware vSphere. Définissez ce que vous voulez, émettez quelques commandes, et ICM fait le reste.
Même si vous utilisez déjà une infrastructure en nuage, des conteneurs ou les deux, ICM réduit considérablement le temps et les efforts nécessaires pour provisionner et déployer votre application en automatisant de nombreuses étapes qui seraient autrement manuelles.
Discussion (0)0
Connectez-vous ou inscrivez-vous pour continuer