CérénIT - gitlabLe blog tech de Nicolas Steinmetz (Time Series, IoT, Web, Ops, Data)Zola2020-12-08T21:00:00+01:00https://cerenit.fr/tags/gitlab/atom.xmlDocker et déploiement distant : tout est histoire de contexte2020-12-08T21:00:00+01:002020-12-08T21:00:00+01:00
Unknown
https://cerenit.fr/blog/docker-context-remote-deployment/<p>Kubernetes, c'est bien mais parfois on veut faire des choses plus simples et on n'a pas forcément besoin d'avoir un système distribué ou d'une forte disponibilité. Pour autant, il est agréable avec kubernetes de pouvoir interagit à distance avec l'API au travers de <code>kubectl</code>. Je me suis donc mis en <a rel="noopener" target="_blank" href="https://twitter.com/nsteinmetz/status/1328093089815273478">quête d'une alternative</a>. Partir sur k3s avec un déploiement mono-node ? Partir sur docker/docker-compose/docker-swarm ?</p>
<p>Je me souvenais que l'on pouvait exposer la socket docker sur le réseau en TCP et authentification par certificat mais cela ne me plaisait pas beaucoup. Je me suis alors rappelé que l'on pouvait interagir avec un hote docker via une connection ssh. En continuant à creuser, je suis tomber sur <a rel="noopener" target="_blank" href="https://docs.docker.com/engine/context/working-with-contexts/">les contextes dans Docker</a> et ce billet <a rel="noopener" target="_blank" href="https://www.docker.com/blog/how-to-deploy-on-remote-docker-hosts-with-docker-compose/">How to deploy on remote Docker hosts with docker-compose</a>. Et là : 🤩</p>
<p>Alors, certes, pas de secrets, configmaps ou cronjobs mais un déploiement remote que je peux automatiser dans gitlab et/ou avec lequel je peux interagir à distance 😍</p>
<p>Création d'un contexte puis utilisation d'un contexte :</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span># Création du contexte docker
</span><span>docker context create mon-serveur ‐‐docker “host=ssh://user@monserveur”
</span><span>
</span><span># Lister les contextes docker existant
</span><span>docker context ls
</span><span>
</span><span># Utiliser un contexte
</span><span>docker context use mon-serveur
</span><span>
</span><span># Vérifier le bon fonctionnement de la cli docker
</span><span>docker ps
</span><span>[liste de conteneurs tournant sur la machine "mon-serveur"]
</span><span>
</span><span># Vérifier le bon fonctionnement de la cli docker-compose
</span><span>cd /path/to/docker/compose/project
</span><span>docker-compose ps
</span></code></pre>
<p>Pour que cela fonctionne, en plus des versions récentes de <code>docker</code> et <code>docker-compose</code> coté client et serveur. Il vous faut aussi une version récent de <code>paramiko</code> coté client. Celle présente dans Debian 10 n'est pas assez à jour par ex, il a fallu passer par <code>pip3 install paramiko</code>. Il faut aussi avoir une authentification par clé pour se simplifier la vie.</p>
<p>Pour <code>docker-compose</code>, vous avez deux solutions pour utiliser un contexte distant :</p>
<pre style="background-color:#2b303b;color:#c0c5ce;"><code><span># En deux commandes
</span><span>docker context use <remote context>
</span><span>docker-compose <command>
</span><span>
</span><span># En une commande
</span><span>docker-compose --context <remote context> <command>
</span></code></pre>
<p>Dans gitlab, dans le fichier <code>.gitlab-ci.yml</code>, on peut alors profiter de cette intégration de la façon suivante ; je prends l'exemple du déploiement du site du <a rel="noopener" target="_blank" href="https://www.ptsm.io/">Paris Time Series Meetup</a>.</p>
<p>Tout d'abord, dans mon fichier <code>docker-compose.yml</code>, j'ai mis un place holder <code>IMAGE</code> qui sera remplacé par la référence de mon image docker fabriquée par gitlab-ci :</p>
<pre data-lang="yaml" style="background-color:#2b303b;color:#c0c5ce;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="color:#bf616a;">version</span><span>: '</span><span style="color:#a3be8c;">3.8</span><span>'
</span><span style="color:#bf616a;">services</span><span>:
</span><span> </span><span style="color:#bf616a;">web</span><span>:
</span><span> </span><span style="color:#bf616a;">image</span><span>: </span><span style="color:#a3be8c;">IMAGE
</span><span> </span><span style="color:#bf616a;">labels</span><span>:
</span><span> [</span><span style="color:#d08770;">...</span><span>]
</span><span> </span><span style="color:#bf616a;">restart</span><span>: </span><span style="color:#a3be8c;">always
</span></code></pre>
<p>Ensuite, dans gitlab-ci :</p>
<ul>
<li>le job "publish" génère la version html du site et le stock dans un artefact gitlab.</li>
<li>le job "kaniko" va générer l'image docker contenant la version html du site. Pour passer la version de l'image, je stocke l'information dans un fichier <code>docker.env</code>. Ce fichier sera sauvegardé en fin de job sous la forme d'un artefact disponible pour le job "docker".</li>
<li>le job "docker" recupère ce qui était dans le <code>docker.env</code> sous la forme de variable d'environnement. Il remplace ensuite <code>IMAGE</code> par sa vraie valeur. On initialise le contexte docker pour se connecter au serveur cible et on peut alors réaliser les actions habituelles avec <code>docker-compose</code>.</li>
</ul>
<pre data-lang="yaml" style="background-color:#2b303b;color:#c0c5ce;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span>---
</span><span style="color:#bf616a;">stages</span><span>:
</span><span> - </span><span style="color:#a3be8c;">publish
</span><span> - </span><span style="color:#a3be8c;">image
</span><span> - </span><span style="color:#a3be8c;">deploy
</span><span>
</span><span style="color:#bf616a;">publish</span><span>:
</span><span> </span><span style="color:#bf616a;">image</span><span>: </span><span style="color:#a3be8c;">$CI_REGISTRY/nsteinmetz/hugo:latest
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>:
</span><span> </span><span style="color:#bf616a;">paths</span><span>:
</span><span> - </span><span style="color:#a3be8c;">public
</span><span> </span><span style="color:#bf616a;">expire_in</span><span>: </span><span style="color:#a3be8c;">1 day
</span><span> </span><span style="color:#bf616a;">only</span><span>:
</span><span> - </span><span style="color:#a3be8c;">master
</span><span> - </span><span style="color:#a3be8c;">web
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">hugo
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">publish
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">hugo
</span><span>
</span><span style="color:#bf616a;">kaniko</span><span>:
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">image
</span><span> </span><span style="color:#bf616a;">image</span><span>:
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">gcr.io/kaniko-project/executor:debug
</span><span> </span><span style="color:#bf616a;">entrypoint</span><span>: [""]
</span><span> </span><span style="color:#bf616a;">variables</span><span>:
</span><span> </span><span style="color:#bf616a;">RELEASE_IMAGE</span><span>: </span><span style="color:#a3be8c;">$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA-$CI_PIPELINE_ID-$CI_JOB_ID
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">echo "IMAGE=${RELEASE_IMAGE}" >> docker.env
</span><span> - </span><span style="color:#a3be8c;">mkdir -p /kaniko/.docker
</span><span> - </span><span style="color:#a3be8c;">echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
</span><span> - </span><span style="color:#a3be8c;">/kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $RELEASE_IMAGE
</span><span> </span><span style="color:#bf616a;">only</span><span>:
</span><span> - </span><span style="color:#a3be8c;">master
</span><span> - </span><span style="color:#a3be8c;">web
</span><span> </span><span style="color:#bf616a;">when</span><span>: </span><span style="color:#a3be8c;">on_success
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">kaniko
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>:
</span><span> </span><span style="color:#bf616a;">reports</span><span>:
</span><span> </span><span style="color:#bf616a;">dotenv</span><span>: </span><span style="color:#a3be8c;">docker.env
</span><span>
</span><span style="color:#bf616a;">docker</span><span>:
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">deploy
</span><span> </span><span style="color:#bf616a;">before_script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">sed -i -e "s|IMAGE|${IMAGE}|g" docker-compose.yml
</span><span> - </span><span style="color:#a3be8c;">docker context use mon-serveur
</span><span> - </span><span style="color:#a3be8c;">docker-compose pull
</span><span> - </span><span style="color:#a3be8c;">docker-compose up -d
</span><span> </span><span style="color:#bf616a;">needs</span><span>:
</span><span> - </span><span style="color:#bf616a;">job</span><span>: </span><span style="color:#a3be8c;">kaniko
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>: </span><span style="color:#d08770;">true
</span><span> </span><span style="color:#bf616a;">when</span><span>: </span><span style="color:#a3be8c;">on_success
</span><span> </span><span style="color:#bf616a;">only</span><span>:
</span><span> - </span><span style="color:#a3be8c;">master
</span><span> - </span><span style="color:#a3be8c;">web
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">shell
</span><span> </span><span style="color:#bf616a;">environment</span><span>:
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">production
</span><span> </span><span style="color:#bf616a;">url</span><span>: </span><span style="color:#a3be8c;">https://www.ptsm.io/
</span></code></pre>
<p>Et voilà ! 😎</p>
<p>Avec ces contextes (que l'on peut utiliser aussi avec swarm et kubernetes), on a donc un moyen simple et efficace pour déployer des conteneurs à distance et de façon automatisée.</p>
Web, Ops & Data - Octobre 20202020-10-28T09:30:00+01:002020-10-28T09:30:00+01:00
Unknown
https://cerenit.fr/blog/web-ops-and-data-octobre-2020/<p>Des nouvelles du Paris Time Series Meetup : <a rel="noopener" target="_blank" href="https://www.ptsm.io/#ptsm-6">l'éditions 6 sur TimescaleDB</a> et <a rel="noopener" target="_blank" href="https://www.ptsm.io/#ptsm-7">l'édition 7 sur QuestDB</a></p>
<h3 id="ci-cd">CI/CD</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://about.gitlab.com/blog/2020/10/01/three-yaml-tips-better-pipelines/">3 YAML tips for better pipelines</a> : la troisième est certainement la plus intéressante - il est possible d'avoir des mécanismes de "composabilité" / "héritage" avec YAML et Gitlab. Si les <code>include</code> et <code>extends</code> sont déjà sympathiques, les <a rel="noopener" target="_blank" href="https://docs.gitlab.com/ee/ci/yaml/README.html#anchors"><code>anchors</code></a> ont l'air de faire des choses intéressantes aussi !</li>
</ul>
<h3 id="code">Code</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://docs.python.org/3.9/whatsnew/3.9.html">What’s New In Python 3.9</a> et <a rel="noopener" target="_blank" href="https://twitter.com/svpino/status/1313202874487312387">un thread twitter</a> qui donne des exemples des principales nouveautés : au programme nouvelle syntaxe pour la fuston des dictionnaires, des méthides pour supprimer des suffixes/préfixes sur les strings, du typage et plein d'autres améliorations et corrections.</li>
<li><a rel="noopener" target="_blank" href="https://blog.ploeh.dk/2020/10/05/fortunately-i-dont-squash-my-commits/">Fortunately, I don't squash my commits</a> : s'il peut être tentant sur une MR/PR de faire un squash des commits, l'article vous confortera dans l'idée que ce n'est pas une bonne idée. En écrasant l'historique des commits, on y perd sur nos capacités de debug. Par ailleurs, il est conseillé de faire des petits commits pour capturer un ensemble de changements traduisant un moment précis du développement.</li>
</ul>
<h3 id="container-et-orchestration">Container et orchestration</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://opensource.googleblog.com/2020/09/kubernetes-ingress-goes-ga.html">Kubernetes Ingress Goes GA</a> : l'apparition de IngressClassName dans k8s 1.19 va plus loin qu'un simple renommage de champ comme je l'avais compris initialement. C'est une vraie ressource et cela ouvre aussi des possibilités. Avant de l'utiliser, vérifiez aussi que vos ingress controller le supporte (en plus d'attendre d'être en 1.19)</li>
<li><a rel="noopener" target="_blank" href="https://traefik.io/blog/houston-we-have-plugins-traefik-2-3-announcement/">Houston, we have Plugins! Traefik 2.3 Announcement</a> : la version 2.3 dont on a déjà parlé ici, est arrivé en version stable avec son support des plugins, son intégration avec Traefik Pilot, le support d'Amazone ECS et le support de la ressource IngressClassName. Au passage, Containous, la société éditrice de Traefik s'appelle maintenant Traefik Labs.</li>
<li><a rel="noopener" target="_blank" href="https://traefik.io/blog/introducing-traefik-pilot-1-0-one-place-to-manage-all-your-traefik-instances/">Introducing Traefik Pilot 1.0: the Traefik Control Center</a> : Version 1.0 de ce nouveau "Control Plane" de Traefik qui permet d'avoir une vision globale sur ses instances traefik, d'utiliser les plugins et d'avoir un monitoring et des alertes autour de la disponibilité, des performances et de la sécurité.</li>
<li><a rel="noopener" target="_blank" href="https://github.com/kubernetes/enhancements/issues/2033">Rootless mode</a> : A voir si cela pourra être inclus dans la version 1.20 mais le rootless mode est clairement une tendance de fond dans kubernetes et les conteneurs en général. Si vous ne vous y êtes pas déjà mis, ne tardez pas !</li>
<li><a rel="noopener" target="_blank" href="https://traefik.io/blog/announcing-traefik-mesh-1-4-new-name-new-features/">Announcing Traefik Mesh 1.4 - New Name, New Features</a> : nouvelle version du service mesh par Traefik Labs et qui s'appelle maintenant Traefik Mesh (et non uniquement Maesh). Le reste des améliorations semble porter sur le filtrage des headers et des paths.</li>
<li><a rel="noopener" target="_blank" href="https://dev.to/vikcodes/yq-a-command-line-tool-that-will-help-you-handle-your-yaml-resources-better-8j9">yq : A command line tool that will help you handle your YAML resources better </a> : vous voulez faire des opératoins sur des fichiers YAML sans faire un chart helm ou sortir <a rel="noopener" target="_blank" href="https://kustomize.io/">kustomize</a>, vous pouvez faire des choses minimalistes avec <a rel="noopener" target="_blank" href="https://github.com/mikefarah/yq">yq</a> (le pendant yaml de <a rel="noopener" target="_blank" href="https://stedolan.github.io/jq/">jq</a>).</li>
<li><a rel="noopener" target="_blank" href="https://devblogs.microsoft.com/visualstudio/bridge-to-kubernetes-ga/">Bridge to Kubernetes GA</a>, "bridge to kubernetes" est une extension pour vscode permettant de connecter une application tournant en local avec d'autres applications situées dans un ckuster kubernetes et faciliter ainsi l'expérience des développeurs.</li>
</ul>
<h3 id="culture-devops">Culture DevOps</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://medium.com/@polomarcus/la-culture-de-la-r%C3%A9silience-%C3%A0-travers-le-devops-devpo-et-devqa-5792168380a9">La culture de la résilience à travers le DevOps, DevPO, et DevQA</a> : article intéressant de Paul Leclerq sur la résilience et la collaboration au sein d'une équipe.</li>
</ul>
<h3 id="data">Data</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://towardsdatascience.com/how-to-measure-your-organizations-data-maturity-2352cbaf1896">How to Measure Your Organization’s Data Maturity</a> : les différents stade de maturité de votre organisation concernant la gestion et l'exploitation des données.</li>
<li><a rel="noopener" target="_blank" href="https://streamnative.io/blog/tech/2020-09-28-announcing-mqtt-on-pulsar">Announcing MQTT-on-Pulsar: Bringing Native MQTT Protocol Support to Apache Pulsar</a>: <a rel="noopener" target="_blank" href="http://pulsar.apache.org/">Apache Pulsar</a>, la plateforme de message distribué et de streaming, se dote d'un plugin "MQTT On Pulsar" (MoP) permettant ainsi de migrer vos applications MQTT sur Apache Pulsar. Après le <a rel="noopener" target="_blank" href="https://streamnative.io/blog/tech/2020-03-24-bring-native-kafka-protocol-support-to-apache-pulsar/">plugin Kafka</a> (KoP) il y a quelques mois en partenariat avec OVHCloud, Pulsar ajoute une corde à son arc pour devenir la plateforme universelle. Le <a rel="noopener" target="_blank" href="https://streamnative.io/blog/tech/2020-06-15-announcing-aop-on-pulsar">protocole AMQP</a> est déjà aussi supporté depuis plusieurs mois.</li>
<li><a rel="noopener" target="_blank" href="https://medium.com/@gillesbarbier/building-an-event-driven-orchestration-engine-bf62d45aef5d">Building An Event-Driven Orchestration Engine</a> : retour d'expérience sur les raisons de la migration à Apache Pulsar e la simplificaiton apportée en ayant une platforme riche et complète (streaming + queue + fonctions + data tiering sur S3 + ...)</li>
</ul>
<h3 id="hardware">Hardware</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://thenewstack.io/nvidias-planned-acquisition-of-arm-portends-radical-data-center-changes/">NVidia’s Planned Acquisition of Arm Portends Radical Data Center Changes</a> : une analyse assez en profondeur sur le rachat d'arm par nvidia et les autres acteurs du marché comme AMD.</li>
</ul>
<h3 id="iac">IaC</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.hashicorp.com/blog/announcing-hashicorp-terraform-0-14-beta">Announcing HashiCorp Terraform 0.14 Beta</a>: la capacité à marquer des variables comme sensibles pour éviter que leur valeur soit visible dans les logs/diff/..., un diff plus concis, un lock sur les providers et des binaires disponibles pour arm64.</li>
</ul>
<h3 id="monitoring">Monitoring</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://blog.timescale.com/blog/promscale-analytical-platform-long-term-store-for-prometheus-combined-sql-promql-postgresql/">Long-term store for Prometheus, with the combined power of SQL and PromQL</a> : Timescale s'ajoute à la liste des solutions permettant un stockage long terme à vos données Prometheus. En plus de ce stockage long terme, elle fournit une couche d'analytics. Un connecteur récupère les données dans Prometheus et les injecte dans TimescaleDB. On en parle dans <a rel="noopener" target="_blank" href="https://www.ptsm.io/#ptsm-6">l'édition 6 du PTSM</a>.</li>
</ul>
<h3 id="pratique">Pratique</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://endoflife.date/">endoflife.date</a> : recense les dates de fin de support de vos langages et technologies préférées. Tout n'est pas complètement à jour mais cela permet de récupérer rapidement les informations.</li>
</ul>
<h3 id="sql">SQL</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.percona.com/blog/2020/10/02/exciting-and-new-features-in-mariadb-10-5/">Exciting and New Features in MariaDB 10.5</a> : évoqué <a href="/blog/web-ops-and-data-aout-2020/">au mois d'aout</a>, le support de S3 dans MariaDB est disponible en version GA dans la version 10.5. D'autres améliorations existent comme le support du type INET6, des améliorations sur ColumnStore, la gestion des privilèges, le cluster Galera supporte complètement le GTID, du refactoring au niveau d'InnoDB et enfin les binaires mariadb vont enfin s'appeler mariadb et non plus mysql (avec une couche de compatibilité via des liens symboliques)</li>
</ul>
<h3 id="time-series">Time Series</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://blog.senx.io/introducing-flows/">Introducing FLoWS, a functional language for Time Series Analytics</a> : <a rel="noopener" target="_blank" href="https://warpfleet.senx.io/browse/io.warp10/warp10-ext-flows">FLoWS</a> est arrivé - il vous faudra utiliser une version 2.7.1+ de Warp10 pour profiter de cette approche fonctionnelle en alternative à Warpscript.</li>
<li><a rel="noopener" target="_blank" href="https://blog.senx.io/which-time-series-database-suited-to-your-needs">How can you tell which Time Series Database is suited to your needs?</a> : un petit rappel sur les critères à prendre en compte pour choisir une base de données séries temporelles ; j'avais déjà parlé du guide de Senx sur le sujet - il est disponible en fin de billet.</li>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/influxdb-2-0-release-candidate-now-available/">InfluxDB 2.0 Release Candidate Now Available</a> : la première Relese Candidate (RC0) pour InfluxDB 2.0 OSS avec le retour du moteur de stockage de la V1 - qui contrairement à ce que j'ai pu dire le mois dernier ne concernerait que la façon dont les données sont stockées sur disque et pas le reste d'une part et sera maintenu et amélioré par Influxdata d'autre part. Quelques changements sur le port (retour au port 8086). Pour ceux qui étaient en version alpha/beta, il faudra suivre une procédure de migration. La migration depuis une version 1.x n'est pas encore disponible, cela devrait être dans une prochaine RC. Vous pourrez tester néanmoins les API 1.x, les templates, une version récente de Flux ou encore les améliorations de la CLI.</li>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-influxdb-2-0-0-rc-1/">Release Announcement: InfluxDB 2.0.0 RC 1</a> : cette version apporte essentiellement l'upgrade des données 1.x vers 2.x et une mise à jour de Flux.</li>
<li><a rel="noopener" target="_blank" href="https://aws.amazon.com/fr/blogs/aws/store-and-access-time-series-data-at-any-scale-with-amazon-timestream-now-generally-available/">Store and Access Time Series Data at Any Scale with Amazon Timestream – Now Generally Available</a> - <a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=8RHFPNReylI">Getting Started with Amazon Timestream</a> - <a rel="noopener" target="_blank" href="https://www.infoq.com/news/2020/10/aws-amazon-timestream-ga/">AWS Releases Amazon Timestream into General Availability </a> : AWS sort enfin son produit orienté time series après l'avoir annoncé il y a deux ans.</li>
</ul>
<p>Sur la base des informations disponibles pour le moment :</p>
<ul>
<li>vous définissez une période de rétention en mémoire (entre 1h et 1 an) et une période de rétention sur stockage magnétique (1 jour à 200 ans),</li>
<li>le requêtage des données se fait en SQL (via Presto ?),</li>
<li>les données à requêter communément sont à mettre dans la même table,</li>
<li>le join est limité à la même table,</li>
<li>des mesures simples (pas de multi mesures pour un même enregistrement),</li>
<li>une intégration avec l'écosystème comme <a rel="noopener" target="_blank" href="https://github.com/aws/telegraf">telegraf</a>, <a rel="noopener" target="_blank" href="https://grafana.com/blog/2020/09/30/now-you-can-add-amazon-timestream-to-your-grafana-observability-dashboard/">grafana</a>, etc en plus de l'intégration avec différents composants AWS</li>
</ul>
<p>Pour les moins bons côtés :</p>
<ul>
<li>pas d'UPDATE/DELETE sur vos données ; en cas de doublons, c'est le premier arrivé qui gagne</li>
<li>pas de bulk import de vos données, donc pas de reprise de vos données existantes. En effet, il n'est pas possible d'ingérer des données plus vieille que la période en mémoire,</li>
<li>dans la même veine, si un incident de production dépasse votre période de rétention, vous ne pourrez pas réinjecter vos données</li>
<li>il ne semble pas possible de mettre à jour ses durées de rétention - donc pas de ménage possible ou d'ajustements en cours de route</li>
</ul>
<p>Une solution a priori très orienté pour du monitoring et qui semble souffir des mêmes travers qu'InfluxDB avec InfluxQL et pourtant en passe d'être résolus avec Flux.</p>
<p>On devrait en parler plus en détail dans une <a rel="noopener" target="_blank" href="https://www.ptsm.io/">prochaine édition du Paris Time Series Meetup</a> avec <a rel="noopener" target="_blank" href="https://twitter.com/ParisTimeSeries/status/1312719321458712576">des personnes de chez AWS</a> ;-)</p>
<h1 id="work">Work</h1>
<ul>
<li><a rel="noopener" target="_blank" href="https://blog.dropbox.com/topics/company/dropbox-goes-virtual-first">Virtual First Toolkit</a> : toolkit proposé par Dropbox dans le cadre de leur passage non pas à Remote first mais à <a rel="noopener" target="_blank" href="https://blog.dropbox.com/topics/company/dropbox-goes-virtual-first">virtual first</a>.</li>
</ul>
Intégration Gitlab dans Kubernetes pour automatiser ses déploiements2020-06-08T17:00:00+02:002020-06-08T17:00:00+02:00
Unknown
https://cerenit.fr/blog/gitlab-kubernetes-integration-deployment-automatisation/<p>Depuis que j'ai migré des sites sous kubernetes, j'avais perdu l'automatisation du déploiement de mes conteneurs. Pour ce site, je modifiais donc le site et une fois le <code>git push</code> realisé, j'attendais que Gitlab-CI crée mon conteneur. Je récupérai alors le tag du conteneur que je mettais dans le dépôt git où je stocke mes fichiers de configuration pour kubernetes. Une fois le tag mis à jour, je pouvais procéder au déploiement de mon conteneur. Il était temps d'améliorer ce workflow.</p>
<p>Gitlab propose depuis un moment une <a rel="noopener" target="_blank" href="https://about.gitlab.com/solutions/kubernetes/">intégration avec kubernetes</a> mais je lui trouve quelques inconvénients au regard de mes besoins :</p>
<ul>
<li>Il faut créer un compte avec un ClusterRole cluster-admin et je ne suis pas super à l'aise avec cette idée,</li>
<li>Il est nécessaire de déployer Helm encore en version 2 alors que je suis passé en version 3 pour les rares projets où je l'utilise,</li>
<li>L'ingress s'appuie sur nginx-ingress, alors que j'utilise Traefik,</li>
<li>Je n'ai pas l'usage des autres fonctionnalités fournies par Gitlab dans mon contexte de "cluster de test" hébergeant quelques sites et applications web.</li>
</ul>
<p>Mon besoin pourrait se résumer à pouvoir interagir avec mon cluster au travers de kubectl et de pouvoir y déployer la nouvelle version du conteneur que je viens de créer. Cela suppose alors d'avoir 3 choses :</p>
<ul>
<li>le binaire kubectl accessible sous la forme d'un conteneur ou directement en shell dans le runner,</li>
<li>un fichier <code>kubeconfig</code> pour m'authentifier auprès du cluster et interagir avec,</li>
<li>la référence de l'image docker fraichement crée par Gitlab-CI à appliquer sur un Deployment kubernetes.</li>
</ul>
<h3 id="creation-d-un-compte-de-service-avec-authentification-par-token">Création d'un compte de service avec authentification par token</h3>
<p>Utilisant le service managé d'OVH, je n'ai pas accès à tous les certificats du cluster permettant de créer de nouveaux comptes utilisateurs. Par ailleurs, pour les intégrations comme Gitlab, il est <a rel="noopener" target="_blank" href="https://kubernetes.io/docs/reference/access-authn-authz/authentication/#users-in-kubernetes">recommandé</a> d'utiliser des Service Accounts. C'est ce que nous allons faire.</p>
<p>En plus du Service Account, il nous faut donner un rôle à notre compte pour qu'il puisse réaliser des actions sur le cluster. Par simplicité pour ce billet, je vais lui donner les droits d'admin au sein d'un namespace. Le compte de service pourra alors faire ce qu'il veut mais <em>uniquement</em> au sein du namespace en question. En cas de fuite du compte, les dégats potentiels sont donc moindres qu'avec un compter qui est admin global du cluster. Le <a rel="noopener" target="_blank" href="https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles">rôle admin existe déjà sous kubernetes</a>, il s'agit du ClusteRole admin mais qui est restreint à un namespace via le RoleBinding.</p>
<p>Créons le fichier <code>gitlab-integtration.yml</code> avec ces éléments :</p>
<pre data-lang="yaml" style="background-color:#2b303b;color:#c0c5ce;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span>---
</span><span style="color:#bf616a;">apiVersion</span><span>: </span><span style="color:#a3be8c;">v1
</span><span style="color:#bf616a;">kind</span><span>: </span><span style="color:#a3be8c;">ServiceAccount
</span><span style="color:#bf616a;">metadata</span><span>:
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">gitlab-example
</span><span> </span><span style="color:#bf616a;">namespace</span><span>: </span><span style="color:#a3be8c;">example
</span><span>---
</span><span style="color:#bf616a;">apiVersion</span><span>: </span><span style="color:#a3be8c;">rbac.authorization.k8s.io/v1beta1
</span><span style="color:#bf616a;">kind</span><span>: </span><span style="color:#a3be8c;">RoleBinding
</span><span style="color:#bf616a;">metadata</span><span>:
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">gitlab-admin
</span><span style="color:#bf616a;">roleRef</span><span>:
</span><span> </span><span style="color:#bf616a;">apiGroup</span><span>: </span><span style="color:#a3be8c;">rbac.authorization.k8s.io
</span><span> </span><span style="color:#bf616a;">kind</span><span>: </span><span style="color:#a3be8c;">ClusterRole
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">admin
</span><span style="color:#bf616a;">subjects</span><span>:
</span><span>- </span><span style="color:#bf616a;">kind</span><span>: </span><span style="color:#a3be8c;">ServiceAccount
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">gitlab-example
</span><span> </span><span style="color:#bf616a;">namespace</span><span>: </span><span style="color:#a3be8c;">example
</span></code></pre>
<p>Déployons notre configuration sur le cluster :</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># Apply yml file on the cluster
</span><span style="color:#bf616a;">kubectl</span><span> apply</span><span style="color:#bf616a;"> -f</span><span> gitlab-integration.yml
</span><span style="color:#bf616a;">serviceaccount/gitlab-example</span><span> created
</span><span style="color:#bf616a;">rolebinding.rbac.authorization.k8s.io/gitlab-admin</span><span> created
</span></code></pre>
<p>Pour alimenter notre fichier kubeconfig, il nous faut récupérer le token :</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># Get secret's name from service account
</span><span style="color:#bf616a;">SECRETNAME</span><span>=`</span><span style="color:#bf616a;">kubectl -n</span><span> example get sa/gitlab-example</span><span style="color:#bf616a;"> -o</span><span> jsonpath='</span><span style="color:#a3be8c;">{.secrets[0].name}</span><span>'`
</span><span style="color:#65737e;"># Get token from secret, encoded in base64
</span><span style="color:#bf616a;">TOKEN</span><span>=`</span><span style="color:#bf616a;">kubectl -n</span><span> example get secret $</span><span style="color:#bf616a;">SECRETNAME -o</span><span> jsonpath='</span><span style="color:#a3be8c;">{.data.token}</span><span>'`
</span><span style="color:#65737e;"># Decode token
</span><span style="color:#bf616a;">CLEAR_TOKEN</span><span>=`</span><span style="color:#96b5b4;">echo </span><span>$</span><span style="color:#bf616a;">TOKEN </span><span>|</span><span style="color:#bf616a;">base64 --decode</span><span>`
</span></code></pre>
<p>En prenant votre fichier kubeconfig de référence, vous pouvez alors créer une copie sous le nom <code>kubeconfig-gitlab-example.yml</code> et l'éditer de la façon suivante :</p>
<pre data-lang="yaml" style="background-color:#2b303b;color:#c0c5ce;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span style="color:#bf616a;">apiVersion</span><span>: </span><span style="color:#a3be8c;">v1
</span><span style="color:#bf616a;">clusters</span><span>:
</span><span>- </span><span style="color:#bf616a;">cluster</span><span>:
</span><span> </span><span style="color:#bf616a;">certificate-authority-data</span><span>: </span><span style="color:#a3be8c;"><Existing certificate in a base64 format from your original kubeconfig file>
</span><span> </span><span style="color:#bf616a;">server</span><span>: </span><span style="color:#a3be8c;"><url of your k8s http endpoint like https://localhost:6443/ >
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">kubernetes </span><span style="color:#65737e;"># adjust your cluster name
</span><span style="color:#bf616a;">contexts</span><span>:
</span><span>- </span><span style="color:#bf616a;">context</span><span>:
</span><span> </span><span style="color:#bf616a;">cluster</span><span>: </span><span style="color:#a3be8c;">kubernetes </span><span style="color:#65737e;"># adjust your cluster name
</span><span> </span><span style="color:#bf616a;">namespace</span><span>: </span><span style="color:#a3be8c;">example </span><span style="color:#65737e;"># adjust your namespace
</span><span> </span><span style="color:#bf616a;">user</span><span>: </span><span style="color:#a3be8c;">gitlab-example </span><span style="color:#65737e;"># adujust your user
</span><span> </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">kubernetes-ovh </span><span style="color:#65737e;"># adujust your context
</span><span style="color:#bf616a;">current-context</span><span>: </span><span style="color:#a3be8c;">kubernetes-ovh </span><span style="color:#65737e;"># adujust your context
</span><span style="color:#bf616a;">kind</span><span>: </span><span style="color:#a3be8c;">Config
</span><span style="color:#bf616a;">preferences</span><span>: {}
</span><span style="color:#bf616a;">users</span><span>:
</span><span>- </span><span style="color:#bf616a;">name</span><span>: </span><span style="color:#a3be8c;">gitlab-example </span><span style="color:#65737e;"># adujust your user
</span><span> </span><span style="color:#bf616a;">user</span><span>:
</span><span> </span><span style="color:#bf616a;">token</span><span>: </span><span style="color:#a3be8c;"><Content of the CLEAR_TOKEN variable>
</span></code></pre>
<p>Vous pouvez tester son bon fonctionnement via :</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># Fetch example resources if any:
</span><span style="color:#bf616a;">kubectl --kubeconfig</span><span>=./kubeconfig-gitlab-example.yml get all
</span><span style="color:#bf616a;">...
</span><span style="color:#65737e;"># Check you can't access other namespaces information, like kube-system:
</span><span style="color:#bf616a;">kubectl --kubeconfig</span><span>=./kubeconfig-gitlab-example.yml get all</span><span style="color:#bf616a;"> -n</span><span> kube-system
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> pods is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">pods</span><span>" in API group "" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> replicationcontrollers is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">replicationcontrollers</span><span>" in API group "" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> services is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">services</span><span>" in API group "" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> daemonsets.apps is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">daemonsets</span><span>" in API group "</span><span style="color:#a3be8c;">apps</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> deployments.apps is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">deployments</span><span>" in API group "</span><span style="color:#a3be8c;">apps</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> replicasets.apps is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">replicasets</span><span>" in API group "</span><span style="color:#a3be8c;">apps</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> statefulsets.apps is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">statefulsets</span><span>" in API group "</span><span style="color:#a3be8c;">apps</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> horizontalpodautoscalers.autoscaling is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">horizontalpodautoscalers</span><span>" in API group "</span><span style="color:#a3be8c;">autoscaling</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> jobs.batch is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">jobs</span><span>" in API group "</span><span style="color:#a3be8c;">batch</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span><span style="color:#bf616a;">Error</span><span> from server (Forbidden)</span><span style="color:#96b5b4;">:</span><span> cronjobs.batch is forbidden: User "</span><span style="color:#a3be8c;">system:serviceaccount:example:gitlab-example</span><span>" cannot list resource "</span><span style="color:#a3be8c;">cronjobs</span><span>" in API group "</span><span style="color:#a3be8c;">batch</span><span>" in the namespace "</span><span style="color:#a3be8c;">kube-system</span><span>"
</span></code></pre>
<h3 id="integration-gitlab-stocker-le-kubeconfig">Integration Gitlab : stocker le kubeconfig</h3>
<p>Gitlab permet de stocker des variables. Dans le cas d'un fichier kubeconfig, on va vouloir ne jamais afficher son contenu dans les logs ou autre. Pour cela il est possible de <a rel="noopener" target="_blank" href="https://docs.gitlab.com/ee/ci/variables/#masked-variable-requirements">masquer</a> vos variables en respectant quelques contraintes et notamment que la valeur de la variable tienne sur une seule ligne.</p>
<p>Nous allons donc encoder le fichier en base64 et rajouter un argument pour que tout soit sur une seule ligne (et non pas sur plusieurs lignes par défaut):</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#65737e;"># create a one line base64 version of kubeconfig file
</span><span style="color:#bf616a;">cat</span><span> kubeconfig-gitlab-example.yml | </span><span style="color:#bf616a;">base64 -w</span><span> 0
</span></code></pre>
<p>Copier le contenu obtenu dans une variable que nous appelerons <code>KUBECONFIG</code> et dont on cochera bien la case "Mask variable". Une fois la variable sauvée, vous avez ceci :</p>
<p><img src="/blog/gitlab_ci_cd_masked_variable.png" alt="gitlab ci masked variable" /></p>
<h3 id="integration-gitlab-passer-la-reference-de-l-image-au-job-de-deploiement">Intégration Gitlab : passer la référence de l'image au job de déploiement</h3>
<p>Soit le fichier <code>.gitlab-ci.yml</code> suivant:</p>
<pre data-lang="yaml" style="background-color:#2b303b;color:#c0c5ce;" class="language-yaml "><code class="language-yaml" data-lang="yaml"><span>---
</span><span style="color:#bf616a;">stages</span><span>:
</span><span> - </span><span style="color:#a3be8c;">publish
</span><span> - </span><span style="color:#a3be8c;">image
</span><span> - </span><span style="color:#a3be8c;">deploy
</span><span>
</span><span style="color:#bf616a;">publish</span><span>:
</span><span> </span><span style="color:#bf616a;">image</span><span>: </span><span style="color:#a3be8c;">$CI_REGISTRY/nsteinmetz/hugo:latest
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>:
</span><span> </span><span style="color:#bf616a;">paths</span><span>:
</span><span> - </span><span style="color:#a3be8c;">public
</span><span> </span><span style="color:#bf616a;">expire_in</span><span>: </span><span style="color:#a3be8c;">1 day
</span><span> </span><span style="color:#bf616a;">only</span><span>:
</span><span> - </span><span style="color:#a3be8c;">master
</span><span> - </span><span style="color:#a3be8c;">web
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">hugo
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">publish
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">go
</span><span>
</span><span style="color:#bf616a;">docker</span><span>:
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">image
</span><span> </span><span style="color:#bf616a;">image</span><span>: </span><span style="color:#a3be8c;">docker:stable
</span><span> </span><span style="color:#bf616a;">services</span><span>:
</span><span> - </span><span style="color:#a3be8c;">docker:dind
</span><span> </span><span style="color:#bf616a;">variables</span><span>:
</span><span> </span><span style="color:#bf616a;">DOCKER_HOST</span><span>: </span><span style="color:#a3be8c;">tcp://docker:2375
</span><span> </span><span style="color:#bf616a;">DOCKER_DRIVER</span><span>: </span><span style="color:#a3be8c;">overlay2
</span><span> </span><span style="color:#bf616a;">RELEASE_IMAGE</span><span>: </span><span style="color:#a3be8c;">$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA-$CI_PIPELINE_ID-$CI_JOB_ID
</span><span> </span><span style="color:#bf616a;">before_script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">echo "IMAGE=${RELEASE_IMAGE}" >> docker.env
</span><span> - </span><span style="color:#a3be8c;">docker build --pull -t $RELEASE_IMAGE .
</span><span> - </span><span style="color:#a3be8c;">docker push $RELEASE_IMAGE
</span><span> </span><span style="color:#bf616a;">when</span><span>: </span><span style="color:#a3be8c;">on_success
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">go
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>:
</span><span> </span><span style="color:#bf616a;">reports</span><span>:
</span><span> </span><span style="color:#bf616a;">dotenv</span><span>: </span><span style="color:#a3be8c;">docker.env
</span><span>
</span><span style="color:#bf616a;">kube</span><span>:
</span><span> </span><span style="color:#bf616a;">stage</span><span>: </span><span style="color:#a3be8c;">deploy
</span><span> </span><span style="color:#bf616a;">script</span><span>:
</span><span> - </span><span style="color:#a3be8c;">echo $KUBECONFIG | base64 --decode > kubeconfig
</span><span> - </span><span style="color:#a3be8c;">export KUBECONFIG=`pwd`/kubeconfig
</span><span> - </span><span style="color:#a3be8c;">sed -i -e "s|IMAGE|${IMAGE}|g" deployment.yml
</span><span> - </span><span style="color:#a3be8c;">kubectl apply -f deployment.yml
</span><span> </span><span style="color:#bf616a;">needs</span><span>:
</span><span> - </span><span style="color:#bf616a;">job</span><span>: </span><span style="color:#a3be8c;">docker
</span><span> </span><span style="color:#bf616a;">artifacts</span><span>: </span><span style="color:#d08770;">true
</span><span> </span><span style="color:#bf616a;">when</span><span>: </span><span style="color:#a3be8c;">on_success
</span><span> </span><span style="color:#bf616a;">tags</span><span>:
</span><span> - </span><span style="color:#a3be8c;">shell
</span></code></pre>
<p>Petite explication rapide :</p>
<ul>
<li>l'étape <code>publish</code> va générer la version html du site et la stocker sous la forme d'un artefact qui sera passé aux jobs suivants,</li>
<li>l'étape <code>docker</code> va créer l'image en mettant l'artefact du job précédent dans un conteneur nginx et le publier dans la registry gitlab avec le nom suivant <code>gitlab.registry/group/project:<short commit>-<pipeline id>-<job id></code></li>
<li>l'étape <code>kube</code> va récupérer le contenu de la variable <code>KUBECONFIG</code>, le décoder et créer un fichier <code>kubeconfig</code>. On initialise la variable d'environnement <code>KUBECONFIG</code> pour que kubectl puisse l'utiliser. On met à jour la référence de l'image docker obtenue précédemment dans le fichier <code>deployment.yml</code> qui sert de modèle de déploiement. On applique le fichier obtenu sur le cluster kubernetes pour mettre à jour le déploiement.</li>
</ul>
<p>Le point d'attention ici est que le passage de la variable <code>RELEASE_IMAGE</code> se fait via un <code>dotenv</code> qui est créé sous la forme d'un artefact à l'étape <code>docker</code> et est donc disponible à l'étape <code>kube</code>. Cela devrait être automatique mais j'ai ajouté une dépendance explicite via la directive <code>needs</code>. Lors de l'étape <code>kube</code>, le contenu du fichier <code>docker.env</code> est disponible sous la forme de variables d'environnement. On peut alors faire la substitution de notre placeholder par la valeur voulue dans <code>deployment.yml</code>.</p>
<p>Tout ce mécanisme est expliqué dnas la doc des variables gitlab et sur les <a rel="noopener" target="_blank" href="https://docs.gitlab.com/ee/ci/variables/#inherit-environment-variables">variables d'environnement héritées</a>. Attention, il vous faut Gitlab 13.0+ pour avoir cette fonctionnalité et en plus, il faut préalablement <a rel="noopener" target="_blank" href="https://docs.gitlab.com/ee/ci/variables/#enable-inherited-environment-variables-core-only">activer ce feature flag</a>.</p>
<pre data-lang="bash" style="background-color:#2b303b;color:#c0c5ce;" class="language-bash "><code class="language-bash" data-lang="bash"><span style="color:#bf616a;">sudo</span><span> gitlab-rails console
</span><span style="color:#bf616a;">Feature.enable</span><span>(:ci_dependency_variables)
</span></code></pre>
<p>En conclusion, nous avons vu comment :</p>
<ul>
<li>Créer un compte de service (Service Account) sous kubernetes avec un rôle d'administrateur de namespace,</li>
<li>Stocker le fichier <code>kubeconfig</code> utilisant notre service account dans Gitlab sous la forme d'une variable masquée,</li>
<li>Passer une référence d'un job à un autre via les dotenv au niveau du job amont et les variables d'environnement au niveau du job en aval,</li>
<li>Récupérer le contenu de la variable kubeconfig pour créer une variable d'environnement et être en mesure d'utiliser kubectl.</li>
</ul>
<p>Ainsi, toute mise à jour de master conduira à une mise à jour du déploiement associé au sein du cluster kubernetes et ne nécessitera plus d'interventions manuelles comme précédemment. Avec un service account lié à un namespace, on évite aussi de s'exposer inutilement en cas de fuite des identifiants.</p>
Web, Ops & Data - Avril 20202020-04-29T21:30:00+02:002020-04-29T21:30:00+02:00
Unknown
https://cerenit.fr/blog/web-ops-and-data-avril-2020/<h3 id="code-et-outillage">Code et Outillage</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://about.gitlab.com/blog/2020/03/30/new-features-to-core/">18 GitLab features are moving to open source</a> : Gitlab va rendre disponible dans sa version Open Source 18 fonctionnalités de sa version payante. C'est un peu la lutte avec Github et ses Github Actions ou <a rel="noopener" target="_blank" href="https://github.blog/2020-04-14-github-is-now-free-for-teams/">ses dernières évolutions tarifaires</a>.</li>
</ul>
<h3 id="container-orchestration">Container & orchestration</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.docker.com/blog/announcing-the-compose-specification/">Announcing the Compose Specification</a> : Docker Inc vient de lancer une spécificiation officielle autour de Compose (celle derrière les <code>docker-compose.yml</code>) pour la rendre plus "cloud native" et plus générique avec une extension au provider cloud d'une part et d'autre part à des solutions comme kubernetes ou Amazone ECS par ex.</li>
<li><a rel="noopener" target="_blank" href="https://containo.us/blog/traefik-2-2-ingress/">Announcing Traefik 2.2</a>, ainsi que la <a rel="noopener" target="_blank" href="https://containo.us/blog/traefik-enterprise-edition-2-1-now-available/">version Entreprise TraefikEE 2.1</a> basée dessus : on notera le retour du support des annotations pour gérer les Ingress, le support de l'UDP (en plus de HTTP et TCP), le support d'Elastic APM, le support des stores KV (Consul, Etcd, Redis, etc) et le Dark Mode.</li>
<li><a rel="noopener" target="_blank" href="https://www.scaleway.com/en/kubernetes-kapsule/">Scaleway Kubernetes Kapsule</a> : l'offre managée kubernetes de Scaleway est disponible. Dommage que les CPU des profils de machine <code>DEV*</code> soient surprovisionnés et qu'il faille envisager des profils <code>GP*</code> pour avoir des performances correctes. L'offre est du coup moins compétitive en termes de prix pour des petits clusters.</li>
<li><a rel="noopener" target="_blank" href="https://kubernetes.io/blog/2020/03/25/kubernetes-1-18-release-announcement/">Kubernetes 1.18 : Fit & Finish</a> : une version de consolidation</li>
<li><a rel="noopener" target="_blank" href="https://opensource.com/article/20/3/deprek8">How to detect outdated Kubernetes APIs</a> : présentation de <a rel="noopener" target="_blank" href="https://github.com/naquada/deprek8">Deprek8</a> et de <a rel="noopener" target="_blank" href="https://github.com/instrumenta/conftest">Conftest</a> pour vous permettre d'évaluer les ressources kubernetes pour lesquelles vous n'êtes pas à jour au niveau des API.</li>
<li><a rel="noopener" target="_blank" href="https://github.com/helm/helm/releases/tag/v3.2.0">Helm 3.2.0</a> avec un correctif de sécurité sur les versions 3.0.x et 3.1.x et d'autres améliorations (comme le retour de certaines fonctionnalités non encore migrées depuis la 2.x)</li>
<li><a rel="noopener" target="_blank" href="https://grafana.com/blog/2020/04/02/cortex-v1.0-released-the-highly-scalable-fast-prometheus-implementation-is-generally-available-for-production-use/">Cortex v1.0 released: The highly scalable, fast Prometheus implementation is generally available for production use</a> : la solution de monitoring distribuée et avec un stockage de long terme basée sur Prometheus arrive en version 1.0. C'est l'occasion de se repencher sur son <a rel="noopener" target="_blank" href="https://cortexmetrics.io/docs/architecture/">architecture</a> et son fonctionnement.</li>
<li><a rel="noopener" target="_blank" href="https://kauri.io/build-your-very-own-selfhosting-platform-with-rasp/5e1c3fdc1add0d0001dff534/c">Build your very own self-hosting platform with Raspberry Pi and Kubernetes</a> : une série d'articles pour déployer un cluster kubernetes sur vos raspberrypi avec la distributions k3s et y déployer différentes applications.</li>
<li><a rel="noopener" target="_blank" href="https://blog.rook.io/rook-v1-3-storage-operator-improvements-8c3f1c94592a">Rook v1.3: Storage Operator Improvements</a> : si vous n'êtes pas dans un environnement cloud, il y a de fortes chances pour que vous utilisiez Rook. La version 1.3 vient de sortir et apporte son lot d'améliorations.</li>
<li><a rel="noopener" target="_blank" href="https://banzaicloud.com/blog/k8s-sidecars/">Sidecar container lifecycle changes in Kubernetes 1.18</a> : dans la version 1.19, le cycle de vie des sidecars dans kubernetes sera améliorée. Ainsi, ils démarreront avant le conteneur principal et s'arrêteront après. Le billet revient sur les problèmes existant et comment ce nouveau cycle de vie va améliorer la situation.</li>
</ul>
<h3 id="big-data">(Big) Data</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.confluent.io/blog/series-e-round-metamorphosis/">Confluent Raises $250M and Kicks Off Project Metamorphosis</a> : Confluent, la soéciété éditrice de la Confluent Platform et d'Apache Kafka, vient de lever 250 millions de dollars et annonce le projet Metamorphosis et prévoit des annonces tous les mois sur Apache Kafka, Confluent Platform et ce projet à compter du mois de Mai. On en reparlera très certainement sur <a rel="noopener" target="_blank" href="https://www.bigdatahebdo.com/">BigData Hebdo</a>.</li>
<li><a rel="noopener" target="_blank" href="https://www.oreilly.com/library/view/cassandra-the-definitive/9781098115159/">Cassandra: The Definitive Guide, 3rd Edition</a> : nouvelle édition de l'ouvrage de référence sur Cassandra, mis à jour notamment pour Cassandra 4.0 (version à venir)</li>
<li><a rel="noopener" target="_blank" href="https://streamnative.io/blog/tech/2020-03-24-bring-native-kafka-protocol-support-to-apache-pulsar/">Announcing Kafka-on-Pulsar: bring native Kafka protocol support to Apache Pulsar</a> : On en parle dans le prochain épisode de <a rel="noopener" target="_blank" href="https://www.bigdatahebdo.com/">BigData Hebdo</a>, mais <a rel="noopener" target="_blank" href="http://pulsar.apache.org/">Pulsar</a> est une plateforme vraiment intéressante (Pulsar 101 en <a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=5fqhT82wghY">français</a> ou en <a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=De6avNyQUMw">anglais</a>) et les équipes d'OVHCloud viennent de publier un connecteur qui permet d'utliser l'API Kafka mais que les messages soient stockés dans Pulsar. Il existe aussi une vidéo sur <a rel="noopener" target="_blank" href="https://www.youtube.com/watch?v=gL6hzRtij8M">Kafka on Pulsar</a> et un article sur le <a rel="noopener" target="_blank" href="https://www.ovh.com/blog/announcing-kafka-on-pulsar-bring-native-kafka-protocol-support-to-apache-pulsar/">blog d'OVHCloud</a>.</li>
</ul>
<h3 id="time-series">Time Series</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-telegraf-1-14-0/">Release Announcement: Telegraf 1.14.0</a> : 9 nouveaux inputs, 3 nouveaux processors et 1 nouvel output <a rel="noopener" target="_blank" href="https://warp10.io">warp10</a> sont au programme de cette version. Les versions <a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-telegraf-1-14-1/">1.14.1</a> et <a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-telegraf-1-14-2/">1.14.2</a> sont sorties également avec quelques corrections.</li>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-influxdb-with-long-awaited-features/">Release Announcement: InfluxDB 1.8.0 with Long-Awaited Features</a> : la branche 1.x d'InfluxDB se voit donc dotée d'une version récente de flux qui se veut "production ready" et les endpoints d'InfluxDB 2.x sont aussi disponibles. Ce qui permet d'utiliser les nouveaux clients officiels InfluxDB prévus pour la 2.x d'une part et de faire des requêtes en Flux d'autre part.</li>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/release-announcement-influxdb-2-0-0-beta-9/">Release Announcement: InfluxDB 2.0.0 Beta 9</a> : mise à jour de Flux, autocomplétion flux dans l'éditeur de requêtes et amélioration de la CLI.</li>
<li><a rel="noopener" target="_blank" href="https://www.influxdata.com/blog/influxdb-templates-share-monitoring-expertise/">InfluxDB Templates: Easily Share Your Monitoring Expertise</a> : le billet a pour intérêt de présenter des bonnes pratiques sur la réalisation de <a rel="noopener" target="_blank" href="https://www.influxdata.com/products/influxdb-templates/">templates InfluxDB</a>. Pour rappel, les templates InfluxDB sont des "ressources" que l'on peut déclarer, exporter et importer dans une instance InfluxDB 2.x. Cela concerne des variables, labels, tasks, dashboards, alertes, etc.</li>
<li><a rel="noopener" target="_blank" href="https://blog.senx.io/warp-10-release-2-5-0/">April 2020: Warp 10 release 2.5.0</a> : La version 2.5 de <a rel="noopener" target="_blank" href="https://warp10.io/">Warp10</a> apporte notamment un <a rel="noopener" target="_blank" href="https://blog.senx.io/warp-10-accelerator/">Accelerator</a> c'est à dire un cache en mémoire pour les versions standalones. D'autres corrections et améliorations font également partie de cette release.</li>
<li><a rel="noopener" target="_blank" href="https://blog.senx.io/warpscript-loves-kafka-streams/">WarpScript ❤️ Kafka Streams</a> : si vous utiliser Kafka Streams et que vous voulez utiliser Warpscript pour consommer, processer et envoyer des données vers Kafka, c'est possible.</li>
<li><a rel="noopener" target="_blank" href="https://microsoft.github.io/forecasting/">Forecasting</a> : Microsoft publie des exemples et des bonnes pratiques autour de la prévision à base de séries temporelles. Il y a des exemples en Python / R et quelques exemples avec Azure-ML.</li>
<li><a rel="noopener" target="_blank" href="https://blog.timescale.com/blog/timescaledb-1-7-fast-continuous-aggregates-with-real-time-views-postgresql-12-support-and-more-community-features/">TimescaleDB 1.7: fast continuous aggregates with real-time views, PostgreSQL 12 support, and more Community features</a> : Nouvelle version de TimeScaleDB apportant la compatibilité avec Postgresql 12.x, des aggrégats en temps réel et des fonctionnalités de gestion de données (réordonnancement et rétention) de la version Entreprise sont maintenant disponibles dans la version Community.</li>
</ul>
<h3 id="web">Web</h3>
<ul>
<li><a rel="noopener" target="_blank" href="http://blog.jquery.com/2020/04/10/jquery-3-5-0-released/">jQuery 3.5.0 Released!</a> : une faille XSS a été identifiée sur <code>jQuery.htmlFilter</code> pour toutes les versions inférieures à 3.5.0 ; il est vivement encouragé de mettre à jour vos sites. Pour le reste, je vous renvoie à la lecture de l'article.</li>
</ul>
Web, Ops & Data - Aout 20192019-08-31T15:30:00+02:002019-08-31T15:30:00+02:00
Unknown
https://cerenit.fr/blog/web-ops-and-data-aout-2019/<p>Surveillez le <a rel="noopener" target="_blank" href="https://www.meetup.com/fr-FR/Paris-Time-Series-Meetup/">Time Series Paris Meetup</a>, car la première édition du Meetup sera annoncée mardi avec une présentation des usages avancées des séries temporelles avec <a rel="noopener" target="_blank" href="https://warp10.io/">Warp10</a> (comprendre au-delà du monitoring classique) et une présentation par les équipes OVH sur du monitoring de datacenter aidé par du machine learning et leur offre Préscience. </p>
<h3 id="ci-cd">CI/CD</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://about.gitlab.com/2019/07/24/cross-project-pipeline/">How to trigger multiple pipelines using GitLab CI/CD</a> : depuis une pipeline d'un dépôt gitlab, il va être possible d'appeler les pipelines des autres projets gitlab. Une fonctionnalité intéressante et qui pourrait lever la dépendance à Jenkins lorsque l'on a des pipelines un peu complexes et inter-projets.</li>
<li><a rel="noopener" target="_blank" href="https://about.gitlab.com/2019/08/07/a-look-ahead-for-gitlab-cicd/">New up and coming GitLab CI/CD Features</a> : bilan et perspectives par le responsable produit de gitlab sur les fonctionnalités CI/CD qui ont été rajoutées cette année et celles à venir.</li>
</ul>
<h3 id="code">Code</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://github.blog/2019-08-16-highlights-from-git-2-23/">Highlights from Git 2.23</a> : Tentative de remplacement de <code>git checkout</code> par <code>git switch</code>et <code>git restore</code> pour mieux encadrer les usages</li>
<li><a rel="noopener" target="_blank" href="https://drunkenmonkey.at/blog/diffs_with_proper_function_context">Create Git diffs with proper function context</a> : améliorer vos diff git avec une meilleure prise en compte du langage avec lequel vous travaillez.</li>
</ul>
<h3 id="conteneurs-orchestration">Conteneurs & orchestration</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://blog.hypriot.com/post/releasing-HypriotOS-1-11/">Releasing HypriotOS 1.11.0: Docker 19.03.0 CE from Raspberry Pi Zero to 4 B</a> : la distribution HypriotOS, pour raspberry pi, sort une nouvelle version avec les dernières versions de docker, docker-compose, etc.</li>
<li><a rel="noopener" target="_blank" href="https://twitter.com/thms_cdrt/status/1153290370668814336">OVH 1.15 Certified</a> : Le service managé kubernetes d'OVH passe en version 1.15</li>
<li><a rel="noopener" target="_blank" href="https://community.containo.us/t/traefik-release-v2-0-0-beta1/951">Traefik Release: v2.0.0-beta1</a> & <a rel="noopener" target="_blank" href="https://community.containo.us/t/traefik-release-v2-0-0-rc1/1341">Traefik Release: v2.0.0-rc1</a> : Traefik 2.0 commence à pointer le bout de son nez et les connecteurs docker / kubernetes notamment sont prêts, ainsi que plein d'autres choses.</li>
<li><a rel="noopener" target="_blank" href="https://github.com/helm/helm/releases/tag/v3.0.0-beta.1">Helm 3.0.0-beta.1</a> : Helm 3.0 émerge doucement et on commence à se rendre compte des petits changements qui vont arriver...</li>
</ul>
<h3 id="sql">SQL</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://www.percona.com/blog/2019/08/19/percona-distribution-for-postgresql-11-beta-is-now-available/">Percona Distribution for PostgreSQL 11 (Beta) Is Now Available</a> : Percona est connu pour son expertise autour de MySQL, de leur serveur et des outils qu'ils ont créés autour. Ils semblent vouloir faire la même chose avec Postgres. Cela semble prometteur !</li>
<li><a rel="noopener" target="_blank" href="https://aws.amazon.com/fr/blogs/opensource/announcing-partiql-one-query-language-for-all-your-data/">Announcing PartiQL: One query language for all your data</a> : AWS lance un langage visant à être un requêteur universel de données structurées et non structurées en SQL. C'est en open source et pour le moment cela traite surtout les données des services AWS, ainsi que Couchbase.</li>
</ul>
<h3 id="time-series">time series</h3>
<ul>
<li><a rel="noopener" target="_blank" href="https://redislabs.com/blog/redistimeseries-ga-making-4th-dimension-truly-immersive/">RedisTimeSeries GA – Making the 4th dimension truly immersive</a> : RedisLabs met à disposition un module permettant d'améliorer l'expérience utilisateur des développeurs manipulant des séries temporelles dans Redis. Ce module n'a a priori pas pour vocation à ce stade d'intégrer le coeur du produit.</li>
<li><a rel="noopener" target="_blank" href="https://medium.com/hulu-tech-blog/how-hulu-uses-influxdb-and-kafka-to-scale-to-over-1-million-metrics-a-second-1721476aaff5">How Hulu Uses InfluxDB and Kafka to Scale to Over 1 Million Metrics a Second</a> : retour d'expérience sur l'utilisation d'influxdb et kafka chez Hulu pour ingérer et apporter de la résilience à leurs données temporelles.</li>
<li><a rel="noopener" target="_blank" href="https://about.gitlab.com/2019/07/23/anomaly-detection-using-prometheus/">How to use Prometheus for anomaly detection in GitLab</a> : retour d'expérience de gitlab sur l'utilisation de Prometheus dans un contexte de détection d'anomalies.</li>
</ul>