<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Yohann Gueguin, auteur/autrice sur EKITE</title>
	<atom:link href="https://ekite.info/author/yohanngueguin/feed/" rel="self" type="application/rss+xml" />
	<link>https://ekite.info</link>
	<description>Vos défis, notre passion</description>
	<lastBuildDate>Wed, 08 Apr 2026 14:17:47 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.3</generator>

<image>
	<url>https://ekite.info/wp-content/uploads/2023/06/cropped-favicon2-150x150.png</url>
	<title>Yohann Gueguin, auteur/autrice sur EKITE</title>
	<link>https://ekite.info</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Terraform custom provider</title>
		<link>https://ekite.info/2024/11/20/terraform-custom-provider/</link>
		
		<dc:creator><![CDATA[Yohann Gueguin]]></dc:creator>
		<pubDate>Wed, 20 Nov 2024 07:46:25 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=1570</guid>

					<description><![CDATA[<p>Terraform, provider personnalisé ou comment consommer de l&#8217;API autrement Terraform est devenu un outil incontournable dans le monde du DevOps, plus particulièrement dans l&#8217;univers de l&#8217;infrastructure as code. Dans cet article, nous mettrons en évidence une autre manière de penser l&#8217;utilisation de Terraform, le « service as code ». On oublie souvent que Terraform fonctionne grâce aux [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2024/11/20/terraform-custom-provider/">Terraform custom provider</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h1>Terraform, provider personnalisé ou comment consommer de l&rsquo;API autrement</h1>
<div>
<div>Terraform est devenu un outil incontournable dans le monde du DevOps, plus particulièrement dans l&rsquo;univers de l&rsquo;infrastructure as code.</div>
<div>Dans cet article, nous mettrons en évidence une autre manière de penser l&rsquo;utilisation de Terraform, le « service as code ». On oublie souvent que Terraform fonctionne grâce aux différentes APIs fournies par des tiers. Mais comment tout cela fonctionne ? C&rsquo;est ce que nous verrons ici. À la fin de cet article, vous aurez développé un provider Terraform simple et connecté à une API basique.</div>
<div>
<p>Pour mieux appréhender cet article, il est préférable d’être déjà initié à Terraform et de manière plus générale d&rsquo;avoir une connaissance de l’infrastructure as code. Ne vous inquiétez pas, même si vous n’êtes pas familier avec ces concepts, nous commencerons tout de même par des petits rappels, qui vous permettront de suivre ce guide pas à pas.</p>
<p>&nbsp;</p>
<div>
<h2>Petits rappels</h2>
<h3>Terraform</h3>
<div>
<div>Terraform est un outil qui permets de créer, mettre à jour et versionner vos infrastructures de manière sécurisée et efficiente. Une infrastructure composée de ressources cloud, comme des bases de données, des machines virtuelles ou n’importe quel service de votre fournisseur cloud préféré.</div>
<div>
<p>Il peut aussi déployer des ressources « maison », via du développement custom, qui seront propres à vos besoins et c&rsquo;est justement tout l&rsquo;objet de cet article !</p>
<p>&nbsp;</p>
<div>
<h3>Terraform provider</h3>
</div>
<div>
<div>Les providers Terraform vous permettront d&rsquo;intéragir avec un service tiers (ex : GCP, GitHub, etc&#8230;). On pourrait comparer les providers Terraform avec des librairies dans les langages de développement. Ces interactions seront réalisées via les différentes ressources fournies par ces providers, par exemple le provider Terraform de GitHub fournit une ressource « github_team » qui permet de créer, modifier ou supprimer une team GitHub.</div>
<div>Si vous n&rsquo;avez jamais manipulé Terraform, je vous conseille d&rsquo;aller voir ce <a href="https://github.com/ekit3/terraform-scaleway">guide</a> dans un premier temps avant de continuer celui-ci.</div>
<div></div>
<div></div>
</div>
</div>
</div>
</div>
<div>
<h2>Mais à quoi bon un provider custom ?</h2>
<div>Comme je l&rsquo;ai dit en introduction, on peut voir Terraform comme une autre manière de consommer de l&rsquo;API. Dans la plupart des cas, quand on veut consommer une API, que ce soit pour de la lecture ou de l&rsquo;écriture, on développera soit une autre API, soit un batch. Ce qui demande déjà (selon les besoins) une certaine expertise et un certain nombre de resources (temps, matériels, humains). Cela peut vite devenir un frein à la consommation de vos services.</div>
<div>Avec un provider propre à vos services, vous offrez la possibilité à vos utilisateurs de consommer directement et simplement votre ou vos APIs, le code Terraform étant très descriptif.</div>
<div>En plus de cela vous bénéficiez des autres avantages de Terraform, l&rsquo;état de votre utilisation des services correspond à votre code. La persistance de l&rsquo;état des objets créés plus tôt est pratique dans les cas de DRP par exemple.</div>
<div></div>
</div>
</div>
<div>
<div>
<h2>J’en veux un, comment je fais ?</h2>
<div>Ici nous réaliserons un guide pas à pas, pour développer ce fameux provider custom. Pour cela dans le repository git, il y a un fichier docker-compose.yml qui vous permettra de lancer une base de données, une API et une application web pour visualiser le contenu de cette base de données.</div>
<div>Cette API n&rsquo;est qu&rsquo;un simple CRUD sur un objet « Cour », qui possède plusieurs champs : un nom, une durée et une description.</div>
<div></div>
</div>
<div>
<div>
<h3>Prérequis</h3>
<p>&#8211; <a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli">Terraform CLI</a><br />
&#8211; <a href="https://docs.docker.com/compose/install/#scenario-one-install-docker-desktop">Docker Compose</a><br />
&#8211; <a href="https://go.dev/doc/install">Golang</a></p>
<p>&nbsp;</p>
</div>
</div>
<div>
<div>
<h3>On code !! ??????</h3>
<div>Hashicorp fournit différentes librairies pour faciliter le développement de providers Terraform, il fournit également des repositories d&rsquo;exemples qui permettent de commencer rapidement le développement d&rsquo;un provider et tout un ensemble de guides très complets.</div>
</div>
</div>
<div>
<h4>Pas à pas</h4>
<p>Dans un premier temps, on se crée un petit répertoire tout propre, et on y clone le projet</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">mkdir demo-custom-provider &amp;&amp; cd demo-custom-provider
git clone git@github.com:ekit3/terraform-custom-provider.git</pre>
<p>Vous retrouvez dans ce repo différentes choses,</p>
<ul>
<li>un dossier « custom-provider »: qui contient le résultat final du provider que l&rsquo;on développera dans le dossier « final-code », mais aussi un boilerplate pour vous permettre de commencer le guide, dans le dossier &lsquo;ressource&rsquo;</li>
<li>un dossier « docs »: qui contient le code du provider et des exemples Terraform pour chaque étape que l&rsquo;on réalisera, en quelque sorte : les solutions</li>
<li>et pour finir, une API et un front qui vont de pair avec le docker-compose.</li>
</ul>
<p>Le front ne sert qu&rsquo;à visualiser les actions, qui seront exécutées par le provider Terraform, même si on pourrait se contenter des résultats des commandes Terraform. Mais voir le résultat sur un front vous fera prendre conscience que vous pouvez bien créer n&rsquo;importe quelle ressource. L&rsquo;API quant à elle est <strong>OBLIGATOIRE, </strong>vu qu&rsquo;un provider Terraform fonctionne forcément avec une API. N&rsquo;hésitez pas à utiliser une de vos propres APIs, et à adapter les bouts de code qui suivront celle ci.</p>
</div>
</div>
</div>
<p>Dans un premier temps, placez-vous dans le dossier, « custom-provider/resources/terraform-provider-courses », il s&rsquo;agit du boilerplate de départ.<br />
<em><br />
Explication du contenu de ce dossier.<br />
</em>Le dossier « courses » contient le premier fichier de code go pour notre futur provider. Celui-ci initialise un provider, mais vide !</p>
<pre class="EnlighterJSRAW" data-enlighter-language="golang">package courses

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Provider -
func Provider() *schema.Provider {
    return &amp;schema.Provider{
        ResourcesMap:   map[string]*schema.Resource{},
        DataSourcesMap: map[string]*schema.Resource{},
    }
}
</pre>
<p>Le fichier « main.go », est le point d&rsquo;entrée de notre provider.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">package main

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
    "github.com/hashicorp/terraform-plugin-sdk/v2/plugin"

    "terraform-provider-courses/courses"
)

func main() {
    plugin.Serve(&amp;plugin.ServeOpts{
        ProviderFunc: func() *schema.Provider {
            return courses.Provider()
        },
    })
}</pre>
<p>Le dossier « terraform », contient le code Terraform qui appelera notre custom provider.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform {
  required_providers {
    courses = {
      version = "0.1"
      source  = "hashicorp.com/ekite/courses"
    }
  }
}

provider "courses" {}</pre>
<p>Le « Makefile », qui lui nous permettra de build et installer notre provider sur notre machine. Vous remarquerez que les informations décrites dans ce fichier correspondent à l&rsquo;appel du provider, dans le fichier ci-dessus.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">TEST?=$$(go list ./... | grep -v 'vendor')
HOSTNAME=hashicorp.com
NAMESPACE=ekite
NAME=courses
BINARY=terraform-provider-${NAME}
VERSION=0.1
OS_ARCH=darwin_amd64

default: install

build:
    go build -o ${BINARY}

release:
    GOOS=darwin GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_darwin_amd64
    GOOS=freebsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_freebsd_386
    GOOS=freebsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_freebsd_amd64
    GOOS=freebsd GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_freebsd_arm
    GOOS=linux GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_linux_386
    GOOS=linux GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_linux_amd64
    GOOS=linux GOARCH=arm go build -o ./bin/${BINARY}_${VERSION}_linux_arm
    GOOS=openbsd GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_openbsd_386
    GOOS=openbsd GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_openbsd_amd64
    GOOS=solaris GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_solaris_amd64
    GOOS=windows GOARCH=386 go build -o ./bin/${BINARY}_${VERSION}_windows_386
    GOOS=windows GOARCH=amd64 go build -o ./bin/${BINARY}_${VERSION}_windows_amd64

install: build
    mkdir -p ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}
    mv ${BINARY} ~/.terraform.d/plugins/${HOSTNAME}/${NAMESPACE}/${NAME}/${VERSION}/${OS_ARCH}

test: 
    go test -i $(TEST) || exit 1                                                   
    echo $(TEST) | xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4                    

testacc: 
    TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m</pre>
<p>Nous allons maintenant build cette première version de notre provider, pour ce faire placez vous dans le dossier « custom-provider/resources/terraform-provider-courses »</p>
<p>On initialise notre module go. Le nom choisi ici doit matcher le nom choisi dans le &lsquo;main.go&rsquo; au niveau des imports.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">go mod init terraform-provider-courses</pre>
<p>On installe les dépendances, de notre module</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">go mod tidy</pre>
<p>Après cela, nous pouvons utiliser notre Makefile pour build et installer notre module</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">make build &amp;&amp; make install</pre>
<div>
<h1><img loading="lazy" decoding="async" class="alignnone wp-image-2361 size-large" src="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_1-1024x247.png" alt="" width="1024" height="247" srcset="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_1-980x236.png 980w, https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_1-480x116.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></h1>
<p>Vous pouvez ouvrir une autre console et vous placer dans le dossier « terraform ». Nous allons vérifier le build et l&rsquo;install de ce provider.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform init
terraform plan</pre>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-2363 size-large" src="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_2-1024x645.png" alt="" width="1024" height="645" srcset="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_2-980x617.png 980w, https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_2-480x302.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p>Nous avons donc notre custom provider configuré et fonctionnel, même si pour le moment il ne fait pas grand chose !</p>
<p>Nous allons maintenant entrer dans le vif du sujet, mais allons-y étape par étape. Nous commençons par développer une première « data » Terraform qui correspondra à l&rsquo;ensemble des cours renvoyés par l&rsquo;API. Pour rappel Terraform a deux types d&rsquo;objets qu&rsquo;on manipule à travers les providers:</p>
<ul>
<li>les ressources, qui correspondent aux objets que vous créez. Par exemple, une adresse IP ou un repository GitHub.</li>
<li>les datas, qui correspondent à des informations renvoyées par un provider. Par exemple, une data qui contiendra la liste des membres d&rsquo;une équipe GitHub.</li>
</ul>
<p>Commençons par lancer notre docker-compose.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">docker-compose up -d</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">Ces routes sont disponibles dans l'api,
GET   http://localhost:4000/cours, renvoie une liste de cours
POST http://localhost:4000/cours, crée un cour avec ce body 
{
    "name": "Petit intervention",
    "time": 60,
    "summary": "intervention sur sujet tech"
}
PUT http://localhost:4000/cours/651fc2f3970d6264792bf49e, avec le même body que pour le POST
DELETE http://localhost:4000/cours/65201115d9a28e309a48d610, qui supprime le cours.</pre>
<p>Vous pouvez maintenant copier coller les fichiers du dossier « docs/providers/step1 », dans le dossier « custom-provider/resources/terraform-provider-courses/courses »</p>
<p>Le fichier, « data_source_courses.go », contient la définition de notre data source pour les cours.<br />
Il existe deux méthodes importantes. « dataSourceCourses », qui est le point d&rsquo;entré pour terraform pour comprendre comment interagir avec cette « data ». Dans cette méthode vous avez deux options, « ReadContext », qui prend en valeur la fonction qui sera exécutée pour renvoyer la valeur de cette data, et « Schema », qui sert à définir le schéma de la donnée renvoyée par le provider.<br />
Dans ce même fichier, vous avez la méthode « dataSourceCoursesRead », qui sera appelée pour récupérer la data. Dans celle-ci vous remarquerez que ce n&rsquo;est qu&rsquo;un bout de code qui fait un appel à notre API (cf ligne 57). Autre ligne intéressante, la ligne 79. Sur celle-ci, nous voyons que nous associons un id à notre data, primordial à Terraform ! Je vous invite maintenant à builder la version 0.2 de votre provider (n&rsquo;oubliez pas de monter la version dans le Makefile !)<br />
Vous trouverez également les fichiers Terraform pour tester cette nouvelle version. Utilisez les fichiers dans le dossier docs, example1.tf. Vous pouvez créer un ou plusieurs cours via l&rsquo;API. Utilisez les commandes suivantes pour installer la nouvelle version du module et lancer le plan Terraform. Vous pouvez l&rsquo;apply si vous le souhaitez. (/!\ pour la suite, si vous appliquez des objects entre différentes versions du provider ou si vous relancez le docker compose, n&rsquo;oubliez pas de clean vos states Terraform, pour repartir de zéro)</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform init --upgrade
terraform plan</pre>
<h3><img loading="lazy" decoding="async" class="alignnone wp-image-2371 size-large" style="color: #666666; font-size: 14px;" src="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_3-1024x448.png" alt="" width="1024" height="448" srcset="https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_3-980x429.png 980w, https://ekite.info/wp-content/uploads/2024/01/wordpress_custom_tf_3-480x210.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></h3>
<p>Maintenant nous nous attaquons à la création de ressources! Nous commençons par la création d&rsquo;un cours!<br />
Comme pour l&rsquo;étape précédente, vous pouvez prendre les fichiers dans les ressources step2 et example2!</p>
<p>Comme vous pouvez le constater le main.tf ne va pas changer, seul le provider.tf va subir une modification. En plus de la partie data, nous rajoutons maintenant notre ressource « ekite_cour », qui va nous permettre de créer, récupérer, mettre à jour ou supprimer un cours dans notre API.<br />
C&rsquo;est la méthode dataSourceCour(), qui va contenir toutes les méthodes nécessaires aux actions d&rsquo;une ressource Terraform, celle-ci implémentant les méthodes fournies par Hashicorp.<br />
On peut voir que la méthode DataSourceCour(), renvoie un objet *schema.Resource qui prend en paramètre des méthodes de « Contexte », qui implémentent le code qui va être lié aux actions sur la ressource. C&rsquo;est pour cela qu&rsquo;on en retrouve une pour Create Read Update Delete.<br />
Dans ces méthodes, je vais seulement implémenter des calls à mon API, et le code nécessaire à Terraform pour garantir la consistance des ressources maintenues par ce provider. Ce code n&rsquo;étant que le set d&rsquo;un id à la ressource Terrafom, qui lui permet de l&rsquo;identifier dans son backend Terraform.<br />
On peut voir que j&rsquo;utilise la variable « d » qui correspond à la ressource qu&rsquo;on est en train de manipuler. Je peux récupérer les différentes valeurs poussées dans la définition de la ressource.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">package courses

import (
    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// Provider -
func Provider() *schema.Provider {
    return &amp;schema.Provider{
        ResourcesMap: map[string]*schema.Resource{
            "ekite_cour": dataSourceCour(),
        },
        DataSourcesMap: map[string]*schema.Resource{
            "ekite_courses": dataSourceCourses(),
        },
    }
}
</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">package courses

import (
    "bytes"
    "context"
    "encoding/json"
    "log"
    "net/http"

    "github.com/hashicorp/terraform-plugin-sdk/v2/diag"

    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

type Cour struct {
    Id      string `json:"_id"`
    Name    string `json:"name"`
    Time    int    `json:"time"`
    Summary string `json:"summary"`
}

func dataSourceCour() *schema.Resource {
    return &amp;schema.Resource{
        CreateContext: resourceCourCreate,
        ReadContext:   resourceCourRead,
        UpdateContext: resourceCourUpdate,
        DeleteContext: resourceCourDelete,

        Schema: map[string]*schema.Schema{
            "_id": &amp;schema.Schema{
                Type:     schema.TypeString,
                Optional: true,
            },
            "name": &amp;schema.Schema{
                Type:     schema.TypeString,
                Required: true,
            },
            "time": &amp;schema.Schema{
                Type:     schema.TypeInt,
                Required: true,
            },
            "summary": &amp;schema.Schema{
                Type:     schema.TypeString,
                Required: true,
            },
        },
    }
}

func resourceCourCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

    var diags diag.Diagnostics

    name := d.Get("name").(string)
    time := d.Get("time").(int)
    summary := d.Get("summary").(string)

    data := map[string]interface{}{
        "name":    name,
        "time":    time,
        "summary": summary,
    }

    jsonData, err := json.Marshal(data)

    resp, err := http.Post("http://localhost:4000/cours", "application/json", bytes.NewBuffer(jsonData))

    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    cour := &amp;Cour{}
    err = json.NewDecoder(resp.Body).Decode(&amp;cour)
    if err != nil {
        return diag.FromErr(err)
    }
    // THIS IS MANDATORY FOR TERRAFORM TO BE ABLE TO GARANT CONSISTENCY OF YOUR RESOURCES
    d.SetId(cour.Id)
    return diags
}

func resourceCourRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

    return nil
}

func resourceCourUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

    return nil
}

func resourceCourDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

    return nil
}
</pre>
<p>&nbsp;</p>
<p>Vu que dans cette étape nous n&rsquo;implémentons que la méthode de création, si vous vous amusez à éditer ou supprimer la ressource, rien ne se passera, même pas une erreur ! Par contre, vos states Terraform seront complètement corrompus. Si c&rsquo;est le cas n&rsquo;hésitez pas à tout supprimer et réinitialiser votre workspace Terraform. Pour créer la ressource, comme d&rsquo;habitude, montez la version, réinstallez votre provider local, votre petit « terraform init &#8211;upgrade » et prenez le contenu du fichier exemple2.tf. Vous venez de mettre en place la création d&rsquo;une ressource par Terraform.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform {
  required_providers {
    courses = {
      version = "0.0.2"
      source  = "hashicorp.com/ekite/courses"
    }
  }
}

resource "ekite_cour" "mon_cour" {
  provider = courses
  name = "Cour créé depuis terraform"
  time = 60
  summary = "Un simple exemple"
}
</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2586" src="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.14.41-1024x455.png" alt="" width="1024" height="455" srcset="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.14.41-980x435.png 980w, https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.14.41-480x213.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p>Maintenant vous pouvez soit aller directement à l&rsquo;étape 4, qui finit par implémenter la suppression de ressource, soit passer par la 3 qui commence par implémenter les méthodes de lecture et de mise à jour. Dans mon cas je vais aller à l&rsquo;étape 4 et expliquer le code final qui comprend les deux.<br />
Donc maintenant je voudrais pouvoir éditer mes ressources Terraform, et pour ce faire je pensais qu&rsquo;implémenter la méthode « resourceCourUpdate » suffirait. Mais non, cela dépend de la méthode « read », puisque Terraform, avant de mettre à jour votre ressource, va aller la lire dans votre système d&rsquo;information.<br />
La méthode de lecture a été la plus simple a implémenter, dans le sens où il n&rsquo;y pas de spécificité propre à Terraform, comme on la vu précédemment avec le set de l&rsquo;id dans la méthode de create. En revanche, dans la méthode d&rsquo;update, nous retrouvons une instruction spécifique à Terraform, « d.Set(« last_updated », time.Now().Format(time.RFC850)) ». Celle-ci est indispensable à Terraform. Encore une fois pour garantir la persistance et la cohérence de vos ressources Terraform. Du côté du delete, on retrouve la même idée que pour le create, mais ici nous allons juste supprimer l&rsquo;id de notre ressource.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">package courses

import (
    "bytes"
    "context"
    "encoding/json"
    "log"
    "net/http"
    "time"

    "github.com/hashicorp/terraform-plugin-sdk/v2/diag"

    "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

type Cour struct {
    Id      string `json:"_id"`
    Name    string `json:"name"`
    Time    int    `json:"time"`
    Summary string `json:"summary"`
}

func dataSourceCour() *schema.Resource {
    return &amp;schema.Resource{
        CreateContext: resourceCourCreate,
        ReadContext:   resourceCourRead,
        UpdateContext: resourceCourUpdate,
        DeleteContext: resourceCourDelete,

        Schema: map[string]*schema.Schema{
            "_id": &amp;schema.Schema{
                Type:     schema.TypeString,
                Optional: true,
            },
            "name": &amp;schema.Schema{
                Type:     schema.TypeString,
                Required: true,
            },
            "time": &amp;schema.Schema{
                Type:     schema.TypeInt,
                Required: true,
            },
            "summary": &amp;schema.Schema{
                Type:     schema.TypeString,
                Required: true,
            },
            "last_updated": &amp;schema.Schema{
                Type:     schema.TypeString,
                Optional: true,
                Computed: true,
            },
        },
    }
}

func resourceCourCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {

    var diags diag.Diagnostics

    name := d.Get("name").(string)
    time := d.Get("time").(int)
    summary := d.Get("summary").(string)

    data := map[string]interface{}{
        "name":    name,
        "time":    time,
        "summary": summary,
    }

    jsonData, err := json.Marshal(data)

    resp, err := http.Post("http://localhost:4000/cours", "application/json", bytes.NewBuffer(jsonData))

    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    cour := &amp;Cour{}
    err = json.NewDecoder(resp.Body).Decode(&amp;cour)
    if err != nil {
        return diag.FromErr(err)
    }
    // THIS IS MANDATORY FOR TERRAFORM TO BE ABLE TO GARANT CONSISTENCY OF YOUR RESOURCES
    d.SetId(cour.Id)
    return diags
}

func resourceCourRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
    var diags diag.Diagnostics
    client := &amp;http.Client{Timeout: 10 * time.Second}

    url := "http://localhost:4000/cours/" + d.Id()

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return diag.FromErr(err)
    }

    r, err := client.Do(req)
    if err != nil {
        return diag.FromErr(err)
    }
    defer r.Body.Close()
    cour := &amp;Cour{}
    err = json.NewDecoder(r.Body).Decode(&amp;cour)
    if err != nil {
        return diag.FromErr(err)
    }
    d.Set("name", cour.Name)
    d.Set("time", cour.Time)
    d.Set("summary", cour.Summary)

    return diags
}

func resourceCourUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
    client := &amp;http.Client{Timeout: 10 * time.Second}
    name := d.Get("name").(string)
    timeobj := d.Get("time").(int)
    summary := d.Get("summary").(string)

    data := map[string]interface{}{
        "name":    name,
        "time":    timeobj,
        "summary": summary,
    }

    jsonData, err := json.Marshal(data)

    url := "http://localhost:4000/cours/" + d.Id()

    req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonData))
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Content-Type", "application/json; charset=utf-8")
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    // THIS IS MANDATORY FOR TERRAFORM TO BE ABLE TO GARANT CONSISTENCY OF YOUR RESOURCES
    d.Set("last_updated", time.Now().Format(time.RFC850))
    return resourceCourRead(ctx, d, m)
}

func resourceCourDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
    var diags diag.Diagnostics
    client := &amp;http.Client{}
    url := "http://localhost:4000/cours/" + d.Id()
    req, err := http.NewRequest("DELETE", url, nil)
    if err != nil {
        panic(err)
    }
    resp, err := client.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()
    // THIS IS MANDATORY FOR TERRAFORM TO BE ABLE TO GARANT CONSISTENCY OF YOUR RESOURCES
    d.SetId("")
    return diags
}
</pre>
<p>Une fois que vous avez mis à jour votre code, même chose, on rebuild on réinstalle et on réinitialise et vous pouvez vous amuser avec votre provider.<br />
<img loading="lazy" decoding="async" class="alignnone size-large wp-image-2587" src="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.17-1024x455.png" alt="" width="1024" height="455" srcset="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.17-980x435.png 980w, https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.17-480x213.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2588" src="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.41-1024x460.png" alt="" width="1024" height="460" srcset="https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.41-980x440.png 980w, https://ekite.info/wp-content/uploads/2024/03/Capture-decran-2024-03-08-a-15.15.41-480x216.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p>Si vous voulez un résumé vous pouvez trouver le déroulé de ce pas à pas ici: https://www.youtube.com/watch?v=hVoPL61x5dI</p>
<h1>Conseils et conclusion</h1>
<div>
<div>Nous venons, en quelques minutes, de donner la possibilité de consommer un service, et le tout as code, je vous laisse imaginer les possibilités qui s&rsquo;ouvrent à vous.</div>
<div>
<p>Nous permettrons ainsi à nos utilisateurs de consommer notre service de manière très simple, via le code déclaratif de Terraform, pouvant automatiser tout son processus de validation Terraform via des CI les plus utilisés. Ceci pourrait vous débloquer dans la mise en place de vos processus DevOps 😉</p>
<p>Dans un futur article, nous verrons comment configurer nos custom providers&#8230;</p>
</div>
</div>
</div>
<p>L’article <a href="https://ekite.info/2024/11/20/terraform-custom-provider/">Terraform custom provider</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1570</post-id>	</item>
		<item>
		<title>Du green dans ton Cloud</title>
		<link>https://ekite.info/2024/10/31/du-green-dans-ton-cloud/</link>
		
		<dc:creator><![CDATA[Martin Sojka]]></dc:creator>
		<pubDate>Thu, 31 Oct 2024 12:55:09 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=2645</guid>

					<description><![CDATA[<p>Le green IT, c’est bien. Travailler sur sa façon de concevoir et d’utiliser des logiciels en ayant en tête les questions d’environnement et de développement durable, on commence à comprendre l’idée. Quand bien même ça n’apparait pas toujours dans les critères principaux du développement ou du déploiement d’une solution, le sujet se répand et aujourd’hui la [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2024/10/31/du-green-dans-ton-cloud/">Du green dans ton Cloud</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p id="bsutm" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []"><strong>Le <em>green IT</em>, c’est bien</strong>. Travailler sur sa façon de concevoir et d’utiliser des logiciels en ayant en tête les questions d’environnement et de développement durable, on commence à comprendre l’idée. Quand bien même ça n’apparait pas toujours dans les critères principaux du développement ou du déploiement d’une solution, le sujet se répand et aujourd’hui la plupart des personnes qui travaillent dans le domaine de l’ingénierie logicielle connaissent ce principe (pour ce qui est d’avoir des convictions sur le sujet, c’est propre à chaque individu, en tout cas ça met un peu de temps à faire consensus). En parallèle, on constate également une utilisation croissante des services de Cloud Computing, qui permettent en général de faire des économies sur les coûts d’hébergement et d’apporter de nouvelles fonctionnalités aussi bien aux équipes de développement, qu’aux organisations qui s’en servent.</p>
<p id="mon1c84" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []"><strong>Problème </strong>: bien souvent, ces solutions Cloud sont une boîte noire et au-delà de la facture correspondant aux ressources utilisées, il est à minima difficile d’en savoir plus sur la façon dont fonctionnent les fournisseurs de service Cloud, notamment sur le sujet du green IT. Parce que oui, si vous passez des heures à retravailler et limiter vos requêtes, que vos fonctionnalités sont sobres mais que l’hébergement Cloud que vous utilisez a pour principale source d’énergie une centrale à charbon, c’est pour le moins dommage. De même, si vos instances sont montées en permanence alors qu’elles connaissent des périodes de moindre utilisation (voire d’absence totale), on perd un peu de l’intérêt du green IT. Et enfin, il n’est pas toujours facile de se faire entendre sur ces questions, surtout quand les objectifs (de sprint, de produit, de politique d’entreprise)<strong> sont plus focalisés sur la performance économique que sur la préservation de la planète. </strong></p>
<p id="d1h8191" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Aujourd’hui, l’objectif est donc d’aborder ces différents sujets. D’une part, comment améliorer la consommation de ressources d’un cluster Cloud et de l’autre, comment adapter les KPI traditionnels, prisés par les directions financières, afin de les mettre au service d’une cause plus grande.</p>
<h3 id="t6nuf93" class="rObS6 atKDY" dir="auto" data-pm-slice="1 1 []">« C’est pas Versailles ici », ou comment optimiser son Cloud</h3>
<p id="m1bhp1530" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class="size-medium wp-image-2648 alignleft" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-24-at-10.39.43-300x291.png" alt="Logo Kube Green" width="300" height="291" />Si la lecture du titre de cette partie vous a rappelé des souvenirs ou que vous vous êtes vous-même surpris ou surprise à prononcer ces mots, ces quelques paragraphes devraient vous parler. En effet, alors qu’on éteint la lumière lorsqu’on quitte une pièce, comment justifier de laisser des ressources informatiques allumées en continu, même lorsqu’elles ne sont pas utilisées ? Prenons l’exemple de vos environnements de recette et de développement : en dehors des heures de bureau, y a-t-il le moindre intérêt à les faire fonctionner, si ce n’est brûler (<em>littéralement</em>) du gaz et remplir les poches de Google et Amazon ? Des améliorations concrètes et rapides sont donc faciles à aller chercher (dans un premier temps). C’est le service que propose <a class="VKazi _08uVf" href="https://kube-green.dev/" target="_blank" rel="noreferrer noopener" data-hook="WebLink"><strong><u>Kube-green</u></strong></a>, plug-in rapide à mettre en place (en 30 minutes c’est largement fait) et diablement efficace. Dans l’exemple qu’on trouve dans leur documentation, la mise en place d’une gestion très simple d’un cluster permet de réduire de près de <strong>30% les émissions de gaz à effet de serre</strong> (GES) et jusqu&rsquo;à 37% sur un cluster plus important. <strong>Rendez-vous compte : cela fait plus d’un tiers d’économie en quelques réglages. </strong></p>
<p id="0lq5o1627" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []"><strong>Remarque</strong> : le calcul de l’empreinte carbone se base sur <a class="VKazi _08uVf" href="https://www.goclimate.com/blog/the-carbon-footprint-of-servers/#:~:text=Cloud%20server%20using%20100%25%20green%20electricity:%20160%20kg%20CO2e%20/%20year%20and%20server" target="_blank" rel="noreferrer noopener" data-hook="WebLink"><u>un article rédigé par GoClimate</u></a> et qui donne des estimations en fonction du type d’hébergement choisi.</p>
<h5 class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">OK, qu&rsquo;est-ce que ça donne concrètement ?</h5>
<p id="c469228776" class="_9HeWj _8tluJ" dir="auto">Pour le tester, j’ai démarré un cluster Kubernetes en local, sur lequel j’ai créé un namespace, au sein duquel j’ai déployé une API, un front et une base de données. Ensuite, il m&rsquo;a de lancer cette commande :</p>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">kubectl apply -f https://github.com/kube-green/kube-green/releases/latest/download/kube-green.yaml</pre>
<p id="htcjk28924" class="_9HeWj _8tluJ" dir="auto">Après quelques secondes, <strong>Kube-green</strong> était déployé dans mon cluster, au niveau global. J’ai ensuite appliqué ce fichier, dans le même namespace où j’ai déployé mes applications.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">apiVersion: kube-green.com/v1alpha1
kind: SleepInfo 
metadata: 
  name: sleep-test 
  Namespace: app-example 
spec: 
  weekdays: "*" 
  sleepAt: "*:*/5" 
  wakeUpAt: "*:*/7"</pre>
<p id="jlgws36562" class="_9HeWj _8tluJ" dir="auto">Dans celui-ci est écrit que je souhaite scale down tous les déploiements de ce namespace, tous les jours, à chaque 5ème minute de chaque heure et de la même manière, scale up à chaque 7ème minute (l’exemple n’a pas vraiment de sens, il s’agit là plutôt d’illustrer la syntaxe, il y a évidemment d’autres manières de configurer cette partie). On peut décider d’ignorer certaines ressources, ou de stopper également ou uniquement des cronjobs. Vous pouvez trouver ces informations dans la doc de <strong>Kube-green</strong>, que l’on peut remercier pour sa clarté. Si on observe les Pods du namespace ,on voit bien qu’ils se coupent et s’allument comme désiré :</p>
<p dir="auto"><img loading="lazy" decoding="async" class=" wp-image-2650 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.29.20-296x300.png" alt="" width="462" height="468" /></p>
<p id="zlza91631" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Certes, cette solution n’est qu’un début, mais pourquoi ne pas aller plus loin ? On peut imaginer répliquer ce système pour ajouter les jours fériés, les pauses-repas, et ensuite en production, en adaptant le nombre de nœuds disponibles en fonction de l’activité prévue.</p>
<p id="lylpe1635" class="_9HeWj _8tluJ" dir="auto">Il existe encore d’autres solutions, comme <a class="VKazi _08uVf" href="https://keda.sh/" target="_blank" rel="noreferrer noopener" data-hook="WebLink"><strong><u>KEDA</u></strong></a>, qui permettent d’être encore plus flexible dans les choix de scalabilité. Cet outil, en plus de reprendre les fonctionnalités de <strong>Kube-green</strong>, permet d’allumer et d&rsquo;éteindre nos composants Kubernetes en suivant des métriques que vous pouvez personnaliser à volonté, au lieu de vous baser sur des métriques classiques, comme le niveau d’activité du CPU ou de la RAM. On peut imaginer <em>scale</em> sur un indicateur qui mesure le trafic, ou bien qui va chercher des informations en base de données. Par exemple une quantité de data à intégrer, ou encore une métrique personnalisée qui remonterait la consommation en euros (ou en CO2 ?) pour les limiter. <strong>KEDA</strong> est certes plus compliqué à mettre en place et à tester mais il vaut le coup qu’on s’y intéresse.</p>
<h3 id="dwr6n9082" class="rObS6 atKDY" dir="auto">C’est bien beau vos histoires mais comment je vends ça moi ?</h3>
<p id="uzb7c66458" class="_9HeWj _8tluJ" dir="auto">Ce qui est certain c’est qu’aujourd’hui les directions financières ont un objectif sur les questions d&rsquo;argent plutôt que sur celles de la biodiversité ou de la sobriété énergétique (et en même temps, tant qu&rsquo;on les appellera des directions financières&#8230;). <strong>C’est pour ça qu’il va falloir ruser</strong> : plutôt que de mentionner la diminution du bilan carbone de votre application, il vaudra toujours mieux mettre en avant la baisse de la facture de votre infrastructure (forcément, si on utilise moins de ressources, on émet moins de GES et on paie moins cher). En revanche, pour donner un objectif à vos équipes sensibles à ces questions, d’autres outils existent et notamment <strong>Kube Carbon</strong>.</p>
<p id="bx5l866800" class="_9HeWj _8tluJ" dir="auto">Introduit en 2019 par <strong>Adam Hevenor</strong>, cet outil permet facilement de générer des courbes et des métriques suivant les émissions de GES de votre activité. <a class="VKazi _08uVf" href="https://medium.com/@aHev/introducing-kube-carbon-72aea7d828b1" target="_blank" rel="noreferrer noopener" data-hook="WebLink"><u>Dans un article partagé sur Medium</u></a>, il détaille son calcul de manière à faire le lien entre volume d’opérations informatiques et émission de gaz à effet de serre. La méthodologie n’est pas parfaite, et certains chiffres mériteraient sans doute d’être revus (la publication date déjà d’octobre 2019), mais elle explore néanmoins les différentes questions qui se posent à l’heure où l’usage du Cloud se démocratise. Quelle est l’empreinte carbone des services Cloud de Google ou d’Amazon ? Les deux vous répondront qu’ils sont neutres en carbone mais ce tour de passe-passe n’est possible que grâce à l’achat de crédits carbone et autres compensations, le tout sans avoir la moindre transparence concernant les volumes d’équivalent CO2 produits. C’est d’ailleurs la conclusion de l’article d’Adam qui appelle de ses vœux les grands du Cloud à plus de transparence sur ces questions (d’ailleurs ils pourraient intégrer à leur service le même type de graphes de façon native). Surtout, dans une période qui appelle à la sobriété, tout ce qu&rsquo;il n&rsquo;est pas nécessaire de compenser est bon à prendre.</p>
<p id="unu96116787" class="_9HeWj _8tluJ" dir="auto"><strong>Kube Carbon</strong> a donc cet avantage de fournir une vision chiffrée de votre impact carbone, avec pour objectif de devenir un indicateur important pour l&rsquo;ensemble des acteurs.</p>
<h5 id="ft22f171155" class="a0sZJ atKDY" dir="auto">OK, vous pouvez me refaire un topo pratique aux petits oignons comme pour Kube-green ?</h5>
<p id="jw0jd192768" class="_9HeWj _8tluJ" dir="auto"><strong>Kube Carbon</strong>, techniquement, se résume à un <em>dashboard</em> <strong>Grafana</strong>, qui, dans l’état, ne fait que prendre des métriques, les transformer et nous les afficher. Ce qu’il faut retenir c’est la réflexion qu’a eu <strong>Adam Hevenor</strong> autour de ces indicateurs. Pour mieux me rendre compte de ce que cela représente, j’ai quand même déployé <strong>Prometheus</strong>, <strong>Grafana</strong> et importé ce <em>dashboard</em>.</p>
<p id="ogg69193015" class="_9HeWj _8tluJ" dir="auto">Toujours sur mon cluster k8s local, j’ai exécuté ces commandes :</p>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">// create dedicated namespace and switch to it 
k create ns prometheus 
kubens prometheus 
// helm install for prometheus &amp; grafana 
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts  
helm repo update 
helm install prometheus prometheus-community/prometheus 
helm repo add grafana https://grafana.github.io/helm-charts  
helm repo update 
// Expose grafana svc to local access 
kubectl expose service grafana --type=NodePort --target-port=3000 --name=grafana-ext 
// Get svc port for access</pre>
<div dir="auto" data-pm-slice="1 1 []">
<pre class="_5WAbL YJSb9"><img loading="lazy" decoding="async" class=" wp-image-2653 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.37.48-300x34.png" alt="" width="688" height="78" /></pre>
<div dir="auto" data-pm-slice="1 1 []">
<pre class="EnlighterJSRAW" data-enlighter-language="shell">// Get secret data to log in grafana 
k get secret  grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo</pre>
<p id="glk9d200414" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Maintenant qu’on a une stack <strong>Prometheus</strong> / <strong>Grafana</strong> qui fonctionne, on peut y accéder pour la paramétrer.</p>
<p dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class=" wp-image-2655 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.39.41-300x173.png" alt="" width="731" height="422" /></p>
<p id="j7n1h207221" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">On peut remplir l’url de Prometheus avec son url de service Kubernetes, <em>service:port </em>comme <a class="VKazi _08uVf" href="http://prometheus-server:80" target="_blank" rel="noopener" data-hook="WebLink"><em><u>http://prometheus-server:80</u></em></a></p>
<p id="1bx0d206676" class="_9HeWj _8tluJ" dir="auto">Il ne nous reste plus qu’à importer le dashboard de Kube Carbon qu’on retrouve <a class="VKazi _08uVf" href="https://grafana.com/grafana/dashboards/11010-kube-carbon/" target="_blank" rel="noreferrer noopener" data-hook="WebLink"><u>ici.</u></a> Nous n’avons besoin que de son ID.</p>
<p dir="auto"><img loading="lazy" decoding="async" class=" wp-image-2656 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.43.07-300x167.png" alt="" width="730" height="406" /></p>
<p id="0rzih215724" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">On se rend dans Grafana, dans la partie <em>dashboard</em> puis Nouveau/New</p>
<p dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class=" wp-image-2657 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.44.42-300x87.png" alt="" width="731" height="212" /></p>
<p id="mfnht218603" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Et on vient importer notre <em>dashboard.</em></p>
<p dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class=" wp-image-2658 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.45.01-300x245.png" alt="" width="736" height="601" /></p>
<p id="b5jtz221304" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Et nous voici avec le <em>dashboard</em> pensé par son auteur pour évaluer le bilan carbone des ressources que nous utilisons. On trouve un résumé des métriques et des valeurs utilisées pour celles-ci dans son calcul.</p>
<p dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class=" wp-image-2659 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.47.19-300x108.png" alt="" width="736" height="265" /></p>
<p id="n7lms224375" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Ensuite nous avons un résumé de notre consommation totale, et un détail par Pod.</p>
<p dir="auto" data-pm-slice="1 1 []"><img loading="lazy" decoding="async" class="wp-image-2660 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.47.31-300x156.png" alt="" width="738" height="384" /></p>
<p id="kjmf6227688" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">Avec ces quelques manipulations, nous voilà déjà avec un outil qui commence à donner une idée de notre consommation. Pour rappel, le plus intéressant dans ces éléments, ce sont les choix au niveau des données en entrée et la formule que l&rsquo;outil applique :</p>
<pre class="EnlighterJSRAW" data-enlighter-language="shell">sum(container_cpu_usage_seconds_total * (.001/$flops_per_watt*$carbon_per_watt*$clock_speed)) / 1000000000</pre>
<p id="0rl62228283" class="_9HeWj _8tluJ" dir="auto">On note déjà une baisse à un instant précis, qui coïncide avec le moment où s’est appliqué mon fichier SleepInfo de <strong>Kube green</strong>, j&rsquo;ai donc voulu remonter d&rsquo;un cran au niveau de mon namespace de test, ce qui m’a amené à dupliquer la visualisation et faire les modifications nécessaires, pour aboutir à ce résultat :</p>
<p dir="auto"><img loading="lazy" decoding="async" class="wp-image-2662 aligncenter" src="https://ekite.info/wp-content/uploads/2024/03/Screenshot-2024-01-11-at-11.47.42-300x157.png" alt="" width="739" height="387" /></p>
<p id="zmihz244877" class="_9HeWj _8tluJ" dir="auto" data-pm-slice="1 1 []">On voit encore plus l’impact de la mise en place de <strong>Kube green</strong> au niveau de ce <em>namespace</em>, ça donne une idée de ce qu’il serait possible de faire en travaillant plus finement.  Vu la flexibilité qu’offrent <strong>Grafana</strong> et <strong>Prometheus</strong>, on peut très bien imaginer adapter ce <em>dashboard</em> à nos besoins et mettre à jour les indicateurs de base avec les nouvelles informations à notre disposition (encore faut-il qu&rsquo;elles soient fournies, que ce soit <strong>Scaleway</strong>, <strong>GCP</strong> ou <strong>Amazon</strong>, aucune information précise n’est trouvable à ce sujet, pas même une estimation).</p>
<p id="6dzig244221" class="_9HeWj _8tluJ" dir="auto">On peut imaginer un <em>dashboard</em> par fournisseur Cloud par exemple, avec ses propres informations en entrée, variabiliser les <em>dashboards</em> selon des tags ou des labels propres à nos besoins, pour mieux identifier qui consomme ou non.</p>
</div>
</div>
<p>L’article <a href="https://ekite.info/2024/10/31/du-green-dans-ton-cloud/">Du green dans ton Cloud</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2645</post-id>	</item>
		<item>
		<title>Scaleway et Terraform</title>
		<link>https://ekite.info/2024/07/22/scaleway-et-terraform/</link>
		
		<dc:creator><![CDATA[Yohann Gueguin]]></dc:creator>
		<pubDate>Mon, 22 Jul 2024 10:07:50 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=2596</guid>

					<description><![CDATA[<p>Vous avez dû remarquer que le sujet de l’infrastructure as code est devenu omniprésent dans le déploiement d’infrastructures, que ce soit des ressources physiques ou déployées chez un fournisseur Cloud. Dans cet article, nous allons découvrir comment utiliser Terraform, notre outil d’infrastructure as code, pour déployer des ressources chez un fournisseur Cloud, ici Scaleway.Pour mieux [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2024/07/22/scaleway-et-terraform/">Scaleway et Terraform</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<div>
<p>Vous avez dû remarquer que le sujet de l’infrastructure as code est devenu omniprésent dans le déploiement d’infrastructures, que ce soit des ressources physiques ou déployées chez un fournisseur Cloud. Dans cet article, nous allons découvrir comment utiliser Terraform, notre outil d’infrastructure as code, pour déployer des ressources chez un fournisseur Cloud, ici Scaleway.Pour mieux appréhender cet article, il est préférable d’être déjà initié à Terraform et de manière plus générale, d’avoir une connaissance de l’infrastructure as code. Ne vous inquiétez pas, même si vous n’êtes pas familier avec ces concepts, nous allons tout de même commencer par des petits rappels, qui vous permettront de suivre le guide pas à pas.À la fin de cet article nous aurons déployé, chez Scaleway, une base de données managée et une application conteneurisée connectée à celle-là.</p>
<p>&nbsp;</p>
<h2>Petits rappels</h2>
<p>&nbsp;</p>
<h3>Terraform</h3>
<p>Terraform est un outil qui va permettre de créer, mettre à jour et versionner vos infrastructures de manière sécurisée et efficiente. Une infrastructure composée de ressources Cloud, comme des bases de données, des machines virtuelles ou n’importe quel service de votre fournisseur Cloud préféré.</p>
<p>Il peut aussi déployer des ressources «?maison?», via du développement custom, qui seront propres à vos besoins.</p>
<h3>Scaleway</h3>
<p>Contrairement aux fournisseurs Cloud les plus connus, comme GCP, AWS, ou encore Azure, Scaleway est un fournisseur de services Cloud estampillé Cloud français.</p>
<p>Il va fournir des services que vous pouvez retrouver chez d’autres fournisseurs, comme la création de machines virtuelles, du Kubernetes, du serverless, des bases de données managées, etc.</p>
<p>&nbsp;</p>
<h2>Guide pas à pas</h2>
<p>&nbsp;</p>
<p>L’ensemble des actions sera réalisé sur Ubuntu22.04.2LTS.</p>
<h3>Setup Terraform</h3>
<p>&nbsp;</p>
<p>Nous allons tout d’abord installer Terraform :</p>
</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">sudo apt-get update &amp;&amp; sudo apt-get install -y gnupg software-properties-common

wget -O- https://apt.releases.hashicorp.com/gpg | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg

gpg --no-default-keyring \
--keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \
--fingerprint

echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \
https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \
sudo tee /etc/apt/sources.list.d/hashicorp.list

sudo apt update &amp;&amp; apt-get install terraform</pre>
<div></div>
</div>
<div>
<div>
<div>
<p>Vous pouvez retrouver toutes les instructions dans le lien en bas de l&rsquo;article.</p>
<p>&nbsp;</p>
<h3>Provider Scaleway</h3>
<p>Terraform utilise des composants appelés des «?providers?», qu’on pourrait apparenter à des librairies dans le monde du développement.</p>
<p>Ces providers vont vous permettre d’interagir facilement avec les ressources que vous voulez maintenir. Il existe énormément de providers officiels pour des solutions connues, par exemple pour GCP, Github, Datadog et j’en passe.</p>
<p>Pour en revenir à l’utilisation de Terraform pour des ressources custom, nous ne sommes pas limités à l’utilisation des providers officiels. N’importe qui peut développer son provider custom pour répondre à ses propres besoins.</p>
<p>Ici nous allons nous intéresser exclusivement au provider officiel Scaleway. Vous pouvez aller sur la?Terraform Registry?pour avoir un détail complet de son utilisation.</p>
<p>&nbsp;</p>
<h3>La pratique</h3>
<p>La première étape est de configurer le provider Scaleway. Les providers Terraform ont des paramètres obligatoires, et d’autres qui ne le sont pas. Dans le cas de ce provider, les paramètres obligatoires correspondent à vos informations d’identification Scaleway. Vous allez avoir besoin de ces informations?:</p>
<p>Votre organisation id, que vous pouvez retrouver dans l’interface Scaleway.</p>
</div>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2603" src="https://ekite.info/wp-content/uploads/2024/03/img1-1024x322.png" alt="" width="1024" height="322" srcset="https://ekite.info/wp-content/uploads/2024/03/img1-980x308.png 980w, https://ekite.info/wp-content/uploads/2024/03/img1-480x151.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
</div>
<div>
<div><span class="TextRun SCXW244160045 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW244160045 BCX0">Le </span></span><em><span class="TextRun SCXW244160045 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SpellingErrorV2Themed SCXW244160045 BCX0">project</span><span class="NormalTextRun SCXW244160045 BCX0"> id</span></span></em><span class="TextRun SCXW244160045 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW244160045 BCX0"> dans lequel vous voulez créer vos ressources.</span></span></div>
<div><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2604" src="https://ekite.info/wp-content/uploads/2024/03/img2-1024x273.png" alt="" width="1024" height="273" srcset="https://ekite.info/wp-content/uploads/2024/03/img2-980x261.png 980w, https://ekite.info/wp-content/uploads/2024/03/img2-480x128.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></div>
<div>
<div>
<div><span class="TextRun SCXW15201512 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW15201512 BCX0">Et enfin, </span><span class="NormalTextRun SCXW15201512 BCX0">une clé d’API </span><span class="NormalTextRun SpellingErrorV2Themed SCXW15201512 BCX0">Scaleway</span><span class="NormalTextRun SCXW15201512 BCX0"> composée d’une </span></span><span class="TextRun SCXW15201512 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SpellingErrorV2Themed SCXW15201512 BCX0">access</span><span class="NormalTextRun SCXW15201512 BCX0"> key</span></span><span class="TextRun SCXW15201512 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW15201512 BCX0"> et d’une </span></span><span class="TextRun SCXW15201512 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW15201512 BCX0">secret key</span></span><span class="TextRun SCXW15201512 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW15201512 BCX0">.</span></span><span class="EOP SCXW15201512 BCX0" data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></div>
<div><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2605" src="https://ekite.info/wp-content/uploads/2024/03/img3-1024x421.png" alt="" width="1024" height="421" srcset="https://ekite.info/wp-content/uploads/2024/03/img3-980x403.png 980w, https://ekite.info/wp-content/uploads/2024/03/img3-480x197.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /> <img loading="lazy" decoding="async" class="alignnone size-large wp-image-2606" src="https://ekite.info/wp-content/uploads/2024/03/img4-1024x615.png" alt="" width="1024" height="615" srcset="https://ekite.info/wp-content/uploads/2024/03/img4-1024x615.png 1024w, https://ekite.info/wp-content/uploads/2024/03/img4-980x588.png 980w, https://ekite.info/wp-content/uploads/2024/03/img4-480x288.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></div>
</div>
<div>
<div><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW93964584 BCX0">Maintenant que vous avez ces informations, nous pouvons commencer à écrire nos fichiers </span><span class="NormalTextRun SpellingErrorV2Themed SCXW93964584 BCX0">T</span><span class="NormalTextRun SpellingErrorV2Themed SCXW93964584 BCX0">erraform</span><span class="NormalTextRun SCXW93964584 BCX0">. </span></span></div>
<div><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentStart CommentHighlightPipeRestV2 CommentHighlightRest SCXW93964584 BCX0">Il y a trois façons de déclarer ces paramètres: </span></span></div>
<ul>
<li><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentStart CommentHighlightPipeRestV2 CommentHighlightRest SCXW93964584 BCX0">soit en dur dans le fichier</span></span></li>
<li><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentStart CommentHighlightPipeRestV2 CommentHighlightRest SCXW93964584 BCX0">soit définis par des variables </span><span class="NormalTextRun SpellingErrorV2Themed CommentHighlightRest SCXW93964584 BCX0">T</span><span class="NormalTextRun SpellingErrorV2Themed CommentHighlightRest SCXW93964584 BCX0">erraform</span><span class="NormalTextRun CommentHighlightRest SCXW93964584 BCX0"> que vous passerez au moment de l’exécution</span></span></li>
<li><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentHighlightRest SCXW93964584 BCX0"> la plus sécurisée </span></span><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentHighlightRest SCXW93964584 BCX0">via</span></span><span class="TextRun SCXW93964584 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun CommentHighlightRest SCXW93964584 BCX0"> des variables d’environnement.</span></span><span class="EOP CommentHighlightPipeRestV2 SCXW93964584 BCX0" data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></li>
</ul>
<div>
<p>Avec les variables terraform:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">// Préférez utiliser la var. d’env. SCW_ACCESS_KEY
variable "access_key" {
  type = string
  description = "Notre identifiant de clé d'API"
}

// Preferez utiliser la var d'env SCW_SECRET_KEY
variable "secret_key" {
  type = string
  description = "Notre clé d'API"
}

// Préférez utiliser la var. d’env. SCW_DEFAULT_PROJECT_ID
// Pour trouver votre project_id rendez vous sur le dashboard de votre projet
variable "project_id" {
  type = string
  description = "Notre id de projet"
}

// Préférez utiliser la var. d’env. SCW_DEFAULT_PROJECT_ID.
// Pour trouver votre organization_id rendez-vous sur le dashboard de votre organisation
variable "organization_id" {
  type = string
  description = "Notre id d'organisation"
}

terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
    }
  }
required_version = "&gt;= 0.13"
}
// Preferez utiliser les variables d'environnement pour plus de sécurité
// remplacer le provider par provisioner "scaleway" {}

provider "scaleway" {
  access_key = var.access_key
  secret_key = var.secret_key
  project_id = var.project_id
  organization_id = var.organization_id
  region = var.region
  zone = var.zone
}</pre>
<p>&nbsp;</p>
<div>
<div><em>Avec les variables d’environnement:</em></div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="bash">export SCW_ACCESS_KEY="xxx"
export SCW_SECRET_KEY="xxx"
export SCW_DEFAULT_PROJECT_ID="xxx"
export SCW_DEFAULT_ORGANIZATION_ID="xxx"</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">terraform {
  required_providers {
    scaleway = {
      source = "scaleway/scaleway"
    }
  }
  required_version = "&gt;= 0.13"
}
provider "scaleway" {}</pre>
<div>
<p><span data-contrast="auto">Le </span><i><span data-contrast="auto">provider</span></i><span data-contrast="auto"> permet également de configurer des paramètres qui vont être réutilisés pour les autres ressources, par exemple la région et la zone dans lesquelles nous allons les déployer.</span><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></p>
<p><span data-contrast="auto">Ici j’ai choisi de passer par des variables avec des valeurs par défaut, qui vont me permettre de surcharger ces paramètres à ma convenance. Nous pouvons imaginer lancer deux déploiements en parallèle?: l’un sur fr-par et l’autre vers nl-ams.</span> <span style="background-color: #f9f9f9; color: #000000; font-family: 'Source Code Pro', 'Liberation Mono', 'Courier New', Courier, monospace; font-size: 0.7em; white-space-collapse: preserve;">variable « region » {</span></p>
</div>
<div>
<div>
<div>
<p>Maintenant que nous avons configuré notre provider, nous allons nous amuser à déployer un petit conteneur WordPress, et pour cela nous allons commencer par créer notre base de données? !</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">variable "region" { 
  type = string 
  description = "La région dans laquelle nous allons créer nos ressources"  
  default = "fr-par" 
} 

variable "zone" { 
  type = string description = "La zone de la région dans laquelle nous allons créer nos ressources" default = "fr-par-1" 
} 

terraform { 
  required_providers { 
    scaleway = { 
      source = "scaleway/scaleway" 
    } 
  } 
  required_version = "&gt;= 0.13" 
} 

provider "scaleway" { 
  region = var.region 
  zone = var.zone 
}</pre>
<p>&nbsp;</p>
<h3>Managed Datadase</h3>
<p>Nous allons commencer par créer un fichier dédié à cette ressource, disons mysql.tf.</p>
<p>D’abord nous allons créer quelques variables qui vont nous être utiles, comme le nom de la base de données et notre nom d’utilisateur pour celle-là.</p>
<p>Nous allons utiliser une ressource bien utile de Terraform pour générer un mot de passe complexe pour notre utilisateur de base de données. Nous nous assurons au passage de respecter les conditions imposées par Scaleway quant à la politique de mot de passe.</p>
<p>Ensuite nous allons créer notre instance de serveur de base de données. Les paramètres utilisés ici correspondent, bien sûr, à des exemples pour un environnement de développement.</p>
</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">variable "wp_username" {
  type        = string
  default     = "wp-admin"
}


variable "wp_db_name" {
  type        = string
  default     = "wordpress"
}

resource "random_password" "wp_sql_pwd_db" {
  length  = 16
  special = true
  min_lower = 1
  min_numeric = 1
  min_special = 1
  min_upper = 1
}

resource "scaleway_rdb_instance" "wp_sql" {
  name           = "wp-mysql"
  node_type      = "DB-DEV-S"
  engine         = "MySQL-8"
  is_ha_cluster  = true
  disable_backup = true
  user_name      = var.wp_username
  password       = random_password.wp_sql_pwd_db.result
}</pre>
<div>
<p><span data-contrast="auto">Comme vous le voyez, il ne faut pas énormément de lignes pour créer une nouvelle instance. Cette instance sera automatiquement déployée sur fr-par-1 grâce à la configuration appliquée sur le </span><i><span data-contrast="auto">provider</span></i><span data-contrast="auto"> dans le main.tf.</span><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></p>
<p><span data-contrast="auto">Il ne nous reste plus qu’à créer notre base de données?! Ajoutons quelques lignes.</span><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></p>
</div>
</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">variable "wp_username" {
  type        = string
  default     = "wp-admin"
}

variable "wp_db_name" {
  type        = string
  default     = "wordpress"
}

resource "random_password" "wp_sql_pwd_db" {
  length  = 16
  special = true
  min_lower = 1
  min_numeric = 1
  min_special = 1
  min_upper = 1
}

resource "scaleway_rdb_instance" "wp_sql" {
  name           = "wp-mysql"
  node_type      = "DB-DEV-S"
  engine         = "MySQL-8"
  is_ha_cluster  = true
  disable_backup = true
  user_name      = var.wp_username
  password       = random_password.wp_sql_pwd_db.result
}

resource "scaleway_rdb_database" "wp_sql_db" {
  instance_id    = scaleway_rdb_instance.wp_sql.id
  name           = var.wp_db_name
}</pre>
<div>
<div>
<div>
<p>Nous n’avons qu’à récupérer l’id de notre instance fraîchement créée et lui donner le nom que nous souhaitons.<br />
Et voilà?! Nous avons écrit le code représentant notre serveur de base de données.<br />
Passons maintenant à notre WordPress.</p>
<p>&nbsp;</p>
<h3>Serverless Container</h3>
<p>Scaleway propose différentes solutions pour déployer nos applications, du Kubernetes, des serverless functions et containers ou encore des machines virtuelles. Ici nous allons utiliser les serverless containers. Nous allons avoir besoin uniquement de deux ressources?: un namespace dans lequel nous allons déployer notre 2e ressource, notre conteneur. Ajoutons un nouveau fichier, wordpress.tf?:</p>
</div>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">variable "container_name" {
  type        = string
  default     = "wordpress-example"
}

resource "scaleway_container_namespace" "wp_namespace" {
  name        = "wp-namespace"
  description = "namespace dédié au conteneur wordpress-example"
}

resource "scaleway_container" "wp_container" {
    name = var.container_name
    description = "wordpress container"
    namespace_id = scaleway_container_namespace.wp_namespace.id
    registry_image = "bitnami/wordpress:latest"
    port = 3000
    cpu_limit = 1120
    memory_limit = 2048
    min_scale = 1
    max_scale = 2
    timeout = 600
    max_concurrency = 10
    protocol = "h2c"
    deploy = true

    environment_variables = {
        "WORDPRESS_DEBUG" = "1" 
    }
    secret_environment_variables = {
      "WORDPRESS_DATABASE_HOST" = scaleway_rdb_instance.wp_sql.endpoint_ip
      "WORDPRESS_DATABASE_PORT_NUMBER" = scaleway_rdb_instance.wp_sql.endpoint_port
      "WORDPRESS_DATABASE_NAME" = var.wp_db_name
      "WORDPRESS_DATABASE_USER" = var.wp_username
      "WORDPRESS_DATABASE_PASSWORD" = random_password.wp_sql_pwd_db.result
    }
    depends_on = [
      scaleway_rdb_instance.wp_sql,
      random_password.wp_sql_pwd_db
    ]
}</pre>
<div>
<div>
<p><span data-contrast="auto">Le </span><i><span data-contrast="auto">provider</span></i><span data-contrast="auto"> Scaleway facilite la configuration de ce conteneur. Vous retrouvez ici tous les paramètres existants. Nous pouvons retrouver des classiques comme, bien sûr, l’image de notre conteneur, les ressources allouées, le </span><i><span data-contrast="auto">scaling, etc.</span></i><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></p>
<p><span data-contrast="auto">Mais un paramètre a attiré mon attention, le «?secret_environment_variables?». Celui-ci nous permet de passer facilement des secrets qui seront chargés en variables, ce qui est très utile niveau sécurité?!</span><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></p>
</div>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-2612" src="https://ekite.info/wp-content/uploads/2024/03/gif1.gif" alt="" width="690" height="388" /></p>
</div>
</div>
<div>
<div>
<p>&nbsp;</p>
<h3>A l&rsquo;action !</h3>
<p>&nbsp;</p>
</div>
</div>
<div>
<div>
<p><span data-contrast="auto">Nous y voilà, nous avons terminé de décrire notre infrastructure, il ne nous reste plus qu’à la créer?!</span><span data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"><br />
</span><span data-contrast="auto">Je vais créer un fichier de variable</span><span data-contrast="auto">s</span><span data-contrast="auto">, uncommited.tfvars.</span></p>
</div>
<div>
<pre class="EnlighterJSRAW" data-enlighter-language="generic">wp_username = "test"
wp_db_name = "dbtest"
access_key = "xxx"
secret_key = "xxx"
project_id = "xxx"
organization_id = "xxx"</pre>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2613" src="https://ekite.info/wp-content/uploads/2024/03/cmd1-1024x368.png" alt="" width="1024" height="368" srcset="https://ekite.info/wp-content/uploads/2024/03/cmd1-980x352.png 980w, https://ekite.info/wp-content/uploads/2024/03/cmd1-480x173.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<div>
<div>Il ne nous reste plus qu&rsquo;à appliquer nos fichiers Terraform</div>
<div><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2614" src="https://ekite.info/wp-content/uploads/2024/03/cmd2-1024x178.png" alt="" width="1024" height="178" srcset="https://ekite.info/wp-content/uploads/2024/03/cmd2-980x171.png 980w, https://ekite.info/wp-content/uploads/2024/03/cmd2-480x84.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /> <img loading="lazy" decoding="async" class="alignnone size-large wp-image-2615" src="https://ekite.info/wp-content/uploads/2024/03/cmd3-1024x118.png" alt="" width="1024" height="118" srcset="https://ekite.info/wp-content/uploads/2024/03/cmd3-980x113.png 980w, https://ekite.info/wp-content/uploads/2024/03/cmd3-480x55.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></div>
<div>
<div>
<div><span class="TextRun SCXW47185782 BCX0" lang="FR-FR" xml:lang="FR-FR" data-contrast="auto"><span class="NormalTextRun SCXW47185782 BCX0">Après avoir accepté le </span><span class="NormalTextRun SCXW47185782 BCX0">p</span><span class="NormalTextRun SCXW47185782 BCX0">lan de </span><span class="NormalTextRun SpellingErrorV2Themed SCXW47185782 BCX0">T</span><span class="NormalTextRun SpellingErrorV2Themed SCXW47185782 BCX0">erraform</span><span class="NormalTextRun SCXW47185782 BCX0">, il ne vous reste plus qu’à patienter et regarder vos ressources se créer.</span></span><span class="EOP SCXW47185782 BCX0" data-ccp-props="{&quot;201341983&quot;:2,&quot;335559739&quot;:0,&quot;335559740&quot;:432}"> </span></div>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2616" src="https://ekite.info/wp-content/uploads/2024/03/cmd4-1024x239.png" alt="" width="1024" height="239" srcset="https://ekite.info/wp-content/uploads/2024/03/cmd4-980x228.png 980w, https://ekite.info/wp-content/uploads/2024/03/cmd4-480x112.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
</div>
<div><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2618" src="https://ekite.info/wp-content/uploads/2024/03/img5-1024x326.png" alt="" width="1024" height="326" srcset="https://ekite.info/wp-content/uploads/2024/03/img5-980x312.png 980w, https://ekite.info/wp-content/uploads/2024/03/img5-480x153.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /> <img loading="lazy" decoding="async" class="alignnone size-large wp-image-2619" src="https://ekite.info/wp-content/uploads/2024/03/img6-1024x398.png" alt="" width="1024" height="398" srcset="https://ekite.info/wp-content/uploads/2024/03/img6-980x380.png 980w, https://ekite.info/wp-content/uploads/2024/03/img6-480x186.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /> <img loading="lazy" decoding="async" class="alignnone size-large wp-image-2620" src="https://ekite.info/wp-content/uploads/2024/03/img7-1024x478.png" alt="" width="1024" height="478" srcset="https://ekite.info/wp-content/uploads/2024/03/img7-980x458.png 980w, https://ekite.info/wp-content/uploads/2024/03/img7-480x224.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></div>
</div>
</div>
</div>
</div>
</div>
<div>
<div>
<h2></h2>
<h2>Le mot de la fin</h2>
<p>Nous y voilà, en quelques minutes nous avons pu déployer notre infrastructure et notre application.<br />
Le provider Terraform Scaleway est de mon point de vue efficace, très bien documenté et donc facile à prendre en main.<br />
Je n’ai pas trouvé plus difficile d’utiliser ce provider comparé à ses concurrents, même si l’interface des logs pour les serverless containers n’est pas des plus efficaces.</p>
</div>
<div>
<blockquote>
<div>Liens utiles:</div>
<div></div>
<div><a href="https://registry.terraform.io/providers/scaleway/scaleway/latest/docs">provider scaleway</a></div>
<div><a href="https://console.scaleway.com/iam/api-keys">access key</a></div>
<div><a href="https://console.scaleway.com/project/settings">project id</a></div>
<div><a href="https://console.scaleway.com/organization/settings">organisation id</a></div>
<div><a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli">terraform</a></div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
<div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<p>L’article <a href="https://ekite.info/2024/07/22/scaleway-et-terraform/">Scaleway et Terraform</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2596</post-id>	</item>
		<item>
		<title>Terraform custom provider, la suite !</title>
		<link>https://ekite.info/2024/04/26/terraform-custom-provider-la-suite/</link>
		
		<dc:creator><![CDATA[Maxime Montagne]]></dc:creator>
		<pubDate>Fri, 26 Apr 2024 12:01:35 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=2782</guid>

					<description><![CDATA[<p>Terraform custom provider, c&#8217;est bien mais comment on le configure ? Dans le précédent article intitulé « Terraform custom provider » que vous pouvez retrouver ici : https://ekite.info/2024/04/05/terraform-custom-provider/ vous avez pu apprendre et créer votre propre provider personnalisé pas à pas. Cependant, ne manquait-il pas quelque chose ? Faire une requête HTTP avec une URL en « dur » [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2024/04/26/terraform-custom-provider-la-suite/">Terraform custom provider, la suite !</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>Terraform custom provider, c&rsquo;est bien mais comment on le configure ?</h2>
<p>Dans le précédent article intitulé « Terraform custom provider » que vous pouvez retrouver ici : <a href="https://ekite.info/2024/11/20/terraform-custom-provider/">https://ekite.info/2024/04/05/terraform-custom-provider/ </a>vous avez pu apprendre et créer votre propre provider personnalisé pas à pas. Cependant, ne manquait-il pas quelque chose ? Faire une requête HTTP avec une URL en « dur » n&rsquo;est franchement pas très utile et sécurisé&#8230;</p>
<p>Dans ce second article, nous vous présenterons comment configurer correctement votre provider afin de lui passer tous les paramètres que vous souhaitez. Que ce soit pour la configuration de variables d&rsquo;environnement telles qu&rsquo;une URL pouvant être dupliquée sur des environnements différents selon l&rsquo;utilisation que l&rsquo;on fait de notre provider, ou alors des secrets qui ne peuvent pas, par définition, être mis en clair directement dans un repository Git.</p>
<p>Vous trouverez les évolutions dans la <a href="https://github.com/ekit3/terraform-custom-provider/pull/1/files">pull request </a>liée à cet article.</p>
<p>Cependant, nous vous proposons de réaliser l&rsquo;exercice vous même comme dans le premier article où nous avons appris à créer notre premier custom provider.. Alors codons ensemble !</p>
<h3>Prérequis</h3>
<p>Avoir réalisé la première partie <a href="https://ekite.info/2024/11/20/terraform-custom-provider/">Terraform custom provider</a></p>
<h3>Pas à pas</h3>
<p>Pour commencer, vous avez trois choix possibles, récupérer le projet depuis Git, reprendre à la fin du guide précédent ou récupérer la branche de la pull request sur le précédent lien.</p>
<p>Afin d&rsquo;avoir un exemple concret, nous avons apporté une petite modification à l&rsquo;API pour qu&rsquo;elle n&rsquo;autorise que les requêtes contenant un certain header avec une valeur précise, qui peut correspondre à une liste de plusieurs clés d’API valides.</p>
<p>La mise en place de la configuration de notre provider se passera uniquement dans le fichier provider.go, et se résumera à deux éléments. D&rsquo;abord un schéma de définition de notre provider, qui corresponds aux paramètres possibles de notre provider, dans notre cas, une URL et un token d&rsquo;accès à une API.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-highlight="3-14" data-enlighter-linenumbers="true">func Provider() *schema.Provider {
    return &amp;schema.Provider{
        Schema: map[string]*schema.Schema{
            "api_token": &amp;schema.Schema{
                Type:        schema.TypeString,
                Required:    true,
                DefaultFunc: schema.EnvDefaultFunc("API_TOKEN", nil),
            },
            "api_url": &amp;schema.Schema{
                Type:        schema.TypeString,
                Required:    true,
                DefaultFunc: schema.EnvDefaultFunc("API_URL", nil),
            },
        },
        ResourcesMap: map[string]*schema.Resource{
            "ekite_cour": dataSourceCour(),
        },
        DataSourcesMap: map[string]*schema.Resource{
            "ekite_courses": dataSourceCourses(),
        },
        ConfigureContextFunc: configure,
    }
}</pre>
<p>Ensuite il nous faudra une méthode permettant de configurer notre provider. Si vous êtes observateur, vous verrez l&rsquo;appel à cette méthode dans l&rsquo;extrait précédent.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-linenumbers="true" data-enlighter-highlight="11-21,34">type Config struct {
    api_token string
    api_url   string
}

func configure(ctx context.Context, d *schema.ResourceData) (interface{}, diag.Diagnostics) {

    var diags diag.Diagnostics
    config := Config{}

    // On essaie de récupérer la valeur passée à notre provider, s'il y arrive il le cast en string, sinon on renvoie un message d'erreur
    if v, ok := d.GetOk("api_token"); ok {
        config.api_token = v.(string)
    } else {
        diags = append(diags, diag.Diagnostic{
            Severity: diag.Error,
            Summary:  "api_token is required",
        })

        return nil, diags
    }

    if v, ok := d.GetOk("api_url"); ok {
        config.api_url = v.(string)
    } else {
        diags = append(diags, diag.Diagnostic{
            Severity: diag.Error,
            Summary:  "api_url is required",
        })

        return nil, diags
    }

    return &amp;config, diags
}</pre>
<p>Cette méthode nous permettra d&rsquo;accéder à notre configuration dans n&rsquo;importe quelle méthode via l&rsquo;interface du provider. On observe d&rsquo;abord une petite structure qui représente notre configuration, puis, le plus intéressant, le contenu de notre méthode. Nous voyons qu&rsquo;elle aussi à un paramètre « d », qui est la variable définie par le schéma que nous avons vu plus haut. Via cette variable nous pourrons interagir avec les valeurs passées par ceux qui utilisent notre provider et les orienter en cas d&rsquo;erreur. Dans notre exemple nous allons juste vérifier la présence d&rsquo;une valeur mais on peut imaginer faire des requêtes pour vérifier les paramètres ou juste les comparer à des listes de valeurs constantes.</p>
<p>Bien, nous avons notre configuration, il est maintenant temps de l&rsquo;utiliser pour nos ressources existantes. Au final, nous avons besoin de ne modifier que les requêtes à notre API pour y ajouter un header, et utiliser l&rsquo;URL d&rsquo;API passée en configuration.</p>
<p>Retournons dans notre fichier data_source_cour.go, et modifions notre CRUD. Pour l&rsquo;exemple je mettrai uniquement la méthode read, mais vous pouvez retrouver le code complet dans le repo.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-highlight="4,5,11" data-enlighter-linenumbers="true">func resourceCourRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
    var diags diag.Diagnostics
    client := &amp;http.Client{Timeout: 10 * time.Second}
    config := m.(*Config)
    url := config.api_url + "/cours/" + d.Id()

    req, err := http.NewRequest("GET", url, nil)
    if err != nil {
        return diag.FromErr(err)
    }
    req.Header.Add("tf-api-key", config.api_token)

    r, err := client.Do(req)
    if err != nil {
        return diag.FromErr(err)
    }
    defer r.Body.Close()
    cour := &amp;Cour{}
    err = json.NewDecoder(r.Body).Decode(&amp;cour)
    if err != nil {
        return diag.FromErr(err)
    }
    d.Set("name", cour.Name)
    d.Set("time", cour.Time)
    d.Set("summary", cour.Summary)

    return diags
}</pre>
<p>Donc dans cette méthode on retrouve l&rsquo;interface de notre provider, via la variable « m », en paramètre de notre méthode. Remarquez comme il est facile d&rsquo;interagir avec cette configuration. Il suffit de récupérer dans une variable « config » les informations passées par l&rsquo;interface (ligne 4). Il ne nous reste plus qu&rsquo;à l&rsquo;utiliser où bon nous semble. Dans la ligne qui suit nous créons notre URL avec la propriété « api_url » et ligne 11 nous créons le header et lui attribuons la valeur passée avec la propriété « api_token ». Il ne nous reste plus qu&rsquo;à tester tout ça !</p>
<p>Vous connaissez la chanson, on change la version de notre provider dans notre Makefile, et on lance un « make install ». Maintenant, rendez-vous dans le main.tf pour y apporter les modifications nécessaire. Une fois cela fait on lance notre commande<strong> « tf init &#8211;upgrade »</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-highlight="4,11,12" data-enlighter-linenumbers="true">terraform {
  required_providers {
    courses = {
      version = "0.5.8"
      source  = "hashicorp.com/ekite/courses"
    }
  }
}

provider "courses" {
  api_url = "http://localhost:4000"
  api_token = "1234-5678-910-abCd"
}

resource "ekite_cour" "example" {
  provider = courses
  name = "test from tf update"
  time = 60
  summary = "summary from tf"
}
</pre>
<p>Vous pouvez maintenant jouer avec ces paramètres pour observer les différents comportements.</p>
<p><strong><em>Quand on ne remplit pas les paramètres :</em></strong><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2795" src="https://ekite.info/wp-content/uploads/2024/04/no_param_tf-1024x269.png" alt="" width="1024" height="269" data-wp-editing="1" srcset="https://ekite.info/wp-content/uploads/2024/04/no_param_tf-1024x269.png 1024w, https://ekite.info/wp-content/uploads/2024/04/no_param_tf-980x257.png 980w, https://ekite.info/wp-content/uploads/2024/04/no_param_tf-480x126.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p><strong><em>Quand on set de mauvais paramètres :</em></strong></p>
<p><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2794" src="https://ekite.info/wp-content/uploads/2024/04/wrong_param_tf-1024x583.png" alt="" width="1024" height="583" srcset="https://ekite.info/wp-content/uploads/2024/04/wrong_param_tf-980x558.png 980w, https://ekite.info/wp-content/uploads/2024/04/wrong_param_tf-480x273.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<p><strong>Et bien sùr avec les bons paramètres, un résultat en success</strong><img loading="lazy" decoding="async" class="alignnone size-large wp-image-2803" src="https://ekite.info/wp-content/uploads/2024/04/Capture-decran-2024-04-24-a-17.32.54-1024x530.png" alt="" width="1024" height="530" srcset="https://ekite.info/wp-content/uploads/2024/04/Capture-decran-2024-04-24-a-17.32.54-980x507.png 980w, https://ekite.info/wp-content/uploads/2024/04/Capture-decran-2024-04-24-a-17.32.54-480x248.png 480w" sizes="auto, (min-width: 0px) and (max-width: 480px) 480px, (min-width: 481px) and (max-width: 980px) 980px, (min-width: 981px) 1024px, 100vw" /></p>
<h2>Conclusion</h2>
<p>À la fin de cette suite de deux articles, vous êtes maintenant capable de réaliser vos propres custom providers Terraform, ainsi que la configuration associée. La prochaine étape sera de voir comment nous pouvons mettre en place une intégration continue autour du développement de ce provider et comment le mettre facilement à disposition d&rsquo;utilisateurs.</p>
<p>Cet exemple simple nous a permis de voir comment réaliser et configurer un provider custom. Il vous a permis de voir toute la puissance de Terraform dont la customization peut aller jusqu&rsquo;à l&rsquo;extrême limite de votre imagination et de vos besoins&#8230; Alors allez-y, codez !</p>
<p>&nbsp;</p>
<p>L’article <a href="https://ekite.info/2024/04/26/terraform-custom-provider-la-suite/">Terraform custom provider, la suite !</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2782</post-id>	</item>
		<item>
		<title>Kafka</title>
		<link>https://ekite.info/2023/05/11/kafka/</link>
					<comments>https://ekite.info/2023/05/11/kafka/#respond</comments>
		
		<dc:creator><![CDATA[Yohann Gueguin]]></dc:creator>
		<pubDate>Thu, 11 May 2023 10:02:01 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=1011</guid>

					<description><![CDATA[<p>Introduction à Kafka Bienvenue dans cette vidéo ! Ici nous allons vulgariser les concepts de bases liés à Kafka, et vous donner une idée des cas dans lesquels il est justifié de l’utiliser. Après cette vidéo vous en aurez appris davantage sur les principes de base de Kafka, les différentes briques qui le composent, leurs [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2023/05/11/kafka/">Kafka</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2 style="text-align: justify;">Introduction à Kafka</h2>
<p class="post-header" style="text-align: justify;">Bienvenue dans cette vidéo ! Ici nous allons vulgariser les concepts de bases liés à Kafka, et vous donner une idée des cas dans lesquels il est justifié de l’utiliser. Après cette vidéo vous en aurez appris davantage sur les principes de base de Kafka, les différentes briques qui le composent, leurs fonctionnement et interactions ainsi que les alternatives existantes.</p>
<p>&nbsp;</p>
<div class="extract" style="text-align: justify;">
<p>&nbsp;</p>
<p><iframe loading="lazy" title="Découverte de Kafka" width="1080" height="608" src="https://www.youtube.com/embed/1I8oVv7LNUM?feature=oembed"  allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></p>
</div>
<p>L’article <a href="https://ekite.info/2023/05/11/kafka/">Kafka</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ekite.info/2023/05/11/kafka/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1011</post-id>	</item>
		<item>
		<title>PWA : Innovation ou solution de consolation ?</title>
		<link>https://ekite.info/2021/09/29/pwa-innovation-ou-solution-de-consolation/</link>
					<comments>https://ekite.info/2021/09/29/pwa-innovation-ou-solution-de-consolation/#respond</comments>
		
		<dc:creator><![CDATA[Romain Vermeeren]]></dc:creator>
		<pubDate>Wed, 29 Sep 2021 12:45:20 +0000</pubDate>
				<category><![CDATA[Tech]]></category>
		<guid isPermaLink="false">https://ekite.info/?p=990</guid>

					<description><![CDATA[<p>Le terme PWA est entré depuis quelques années dans le long répertoire des acronymes liés au numérique. Mais qu’est ce qu’une Progressive Web App ? Pour certains c’est la promesse d’une expérience mobile responsive boostée par les fonctionnalités de votre téléphone. Elle serait facile à mettre en place, de faible coût et elle n’aurait plus rien à [&#8230;]</p>
<p>L’article <a href="https://ekite.info/2021/09/29/pwa-innovation-ou-solution-de-consolation/">PWA : Innovation ou solution de consolation ?</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: justify;"><img decoding="async" src="https://ekite.tech/articles/front-end/pwa-innovation-or-consolation//pwa-dbz-img.jpg" alt="image" /></p>
<p style="text-align: justify;">Le terme PWA est entré depuis quelques années dans le long répertoire des acronymes liés au numérique. Mais qu’est ce qu’une <code class="highlighter-rouge">Progressive Web App</code> ?</p>
<p style="text-align: justify;">Pour certains c’est la promesse d’une expérience mobile responsive boostée par les fonctionnalités de votre téléphone. Elle serait facile à mettre en place, de faible coût et elle n’aurait plus rien à envier aux applications natives.</p>
<p style="text-align: justify;">Afin de vous éclairer sur le sujet et de vous permettre de vous faire votre propre avis, vous trouverez ici les informations qui nous paraissent pertinentes pour une première approche fonctionnelle du sujet.</p>
<p style="text-align: justify;"><img decoding="async" src="https://ekite.tech/articles/front-end/pwa-innovation-or-consolation//pwa-logo.png" alt="image" /></p>
<h2 id="mais-doù-ça-vient-" style="text-align: justify;">Mais d’où ça vient ?</h2>
<p style="text-align: justify;">La PWA est une suite logique de l’évolution du web sur mobile. Avant 2007 et l’arrivée des smartphones, l’accès mobile au web se fait par le WAP (Wireless Application Protocol). Il permet le téléchargement d’applications hors ligne non, dépendantes d’un réseau instable et peu performant.</p>
<p style="text-align: justify;">Après 2007 et avec la popularisation des smartphones arrive l’essor du développement mobile. Dès lors des solutions WEB tournent sur des technologies dynamiques exécutées côté serveur. Steve Jobs imagine déjà des applications proches du principe de la PWA mais les principaux acteurs du marché font alors le choix de partir sur le développement d’applications natives permettant une meilleure UX et une meilleure intégration avec nos téléphones.</p>
<p style="text-align: justify;">C’est en 2010 que l’arrivée de HTML5 et CSS3 va relancer les travaux autour d’applications hybrides et la mise en place de design responsive. On cherche alors à mutualiser le développement desktop et mobile.</p>
<p style="text-align: justify;">Le terme PWA arrive en 2015 grâce à Alex Russell, l’un des ingénieurs ayant conceptualisé la solution chez Google. PWA: “Progressive Web Apps: Escaping Tabs Without Losing Our Soul”</p>
<p style="text-align: justify;">Aujourd’hui les PWA sont supportées par une majorité de grandes entreprises de la tech (Google, Microsoft, Samsung, Mozilla, etc.) et utilisées par de nombreuses marques grand public (Starbucks, Pinterest, Spotify, etc.).</p>
<h2 id="oui-mais-ça-consiste-en-quoi-" style="text-align: justify;">Oui mais ça consiste en quoi ?</h2>
<p style="text-align: justify;">Les Progressive Web Apps sont des versions optimisées d’un site web pour le mobile. Elles intégrent des fonctionnalités du téléphone, qui, jusqu’à aujourd’hui étaient réservées aux applications natives : appareil photo, mode hors ligne, raccourci écran d’accueil etc. Elles sont considérées comme des <code class="highlighter-rouge">solutions Hybrides</code>. Supportées par le navigateur du téléphone, elles ne nécessitent pas de développement spécifique à l’OS et permettent la mutualisation des coûts de développement mobile et desktop.</p>
<h3 id="1--un-service-worker-au-coeur-de-lapplication" style="text-align: justify;">1- Un service Worker au coeur de l’application</h3>
<p style="text-align: justify;">Composant fondamental de la PWA, le service Worker est un script exécuté en tâche de fond qui va apporter toute l’intelligence à la PWA. Il intercepte les requêtes réseaux et y applique des configurations. Il permet :</p>
<ul style="text-align: justify;">
<li>Mise en cache du contenu</li>
<li>Synchronisation des données en arrière plan</li>
<li>Push de notifications</li>
<li>L’utilisation des fonctionnalités de votre téléphone</li>
<li>L’exécution d’actions hors ligne (comme pousser une bannière lorsque le téléphone est hors ligne)</li>
<li>…</li>
</ul>
<h3 id="2--un-manifest-pour-une-expérience-mobile" style="text-align: justify;">2- Un Manifest pour une expérience mobile</h3>
<p style="text-align: justify;">Le manifest, en plus du service worker, va permettre de transformer un site en PWA et de simuler une expérience native. Il s’agit d’un simple fichier JSON dans lequel est configuré l’application et qui permet de la personnaliser. Les utilisateurs pourront également installer directement un site web sur leur mobile ou leur desktop sans passer par les stores d’applications.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="json">{
    "name": "Blog Ekite",
    "short_name": "Blog Ekite",
    "description": "Blog Ekite.",
    "icons": [
        {
            "src": "assets/images/icons/icon-48.png",
            "sizes": "48x48",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-72.png",
            "sizes": "72x72",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-96.png",
            "sizes": "96x96",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-128.png",
            "sizes": "128x128",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-192.png",
            "sizes": "192x192",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-384.png",
            "sizes": "384x384",
            "type": "image/png"
        },
        {
            "src": "assets/images/icons/icon-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ],
    "start_url": "/jekyll-site/",
    "display": "fullscreen",
    "theme_color": "#000000",
    "background_color": "#000000"
}
</pre>
<p style="text-align: justify;">Configuration du raccourci de l’application mobile</p>
<ul style="text-align: justify;">
<li>Nom</li>
<li>URL</li>
<li>Icone</li>
<li>etc.</li>
</ul>
<h3 id="3--des-apis-html5-pour-les-fonctionnalités" style="text-align: justify;">3- Des APIs HTML5 pour les fonctionnalités</h3>
<p style="text-align: justify;">Le développement de PWA est grandement facilité par HTML5 qui propose la mise à disposition de nombreuses API aux navigateurs. Ces API permettent, entre autres choses, l’utilisation de fonctionnalités telles que la géolocalisation, le push, le statut de la batterie, le presse papier, l’orientation de l’écran, les vibrations du mobile etc. La liste détaillée de ces fonctionnalités est disponible sur ce <a href="https://whatwebcando.today/" target="_blank" rel="noopener">site</a>.</p>
<p style="text-align: justify;"><img decoding="async" src="https://ekite.tech/articles/front-end/pwa-innovation-or-consolation//pwa-lighthouse.png" alt="image" /></p>
<p style="text-align: justify;">Lighthouse est un plugin Chrome qui permet d’auditer un site web et qui indique son niveau de compatibilité avec la PWA. Ce plugin liste l’ensemble des caractéristiques officielles qui permettent d’évaluer la performance des applications.</p>
<p style="text-align: justify;"><b>Progressive</b></p>
<blockquote><p>Les applications web progressives fonctionnent sur n’importe quel périphérique et intègrent les fonctionnalités disponibles du navigateur et de l’appareil utilisé.</p></blockquote>
<p style="text-align: justify;"><b>Sécurisée</b></p>
<blockquote><p>La mise en place d’un protocole HTTPS permet aux PWA d’être fiables et sûres, ce qui répond aux problématiques de sécurité des échanges entre les utilisateurs et les sites</p></blockquote>
<p style="text-align: justify;"><b>Engageante</b></p>
<blockquote><p>Elles proposent une expérience utilisateur immersive en plein écran et facilitent le réengagement grâce à l’envoi de notifications push web.</p></blockquote>
<p style="text-align: justify;"><b>Installable</b></p>
<blockquote><p>L’utilisation d’un fichier Manifest permet aux PWA de proposer, à l’instar d’une application mobile native, l’installation de l’application sur l’écran d’accueil du mobile.</p></blockquote>
<p style="text-align: justify;"><b>Rapidité</b></p>
<blockquote><p>D’après Google, 53 % des internautes abandonnent un site si son chargement prend plus de trois secondes. Une fois le site chargé, la navigation doit se faire de manière rapide et fluide.</p></blockquote>
<p style="text-align: justify;"><b>Optimisation pour le référencement</b></p>
<blockquote><p>Utilisant les technologies du web, les progressive web app peuvent être référencées sur les moteurs de recherche de la même manière que n’importe quel site web classique.</p></blockquote>
<p style="text-align: justify;"><b>Indépendante de la connexion</b></p>
<blockquote><p>Grâce à la gestion du cache via l’utilisation d’un Service Worker, une fois le contenu chargé, il sera possible de le consulter même dans les zones de faible connexion réseau.</p></blockquote>
<p style="text-align: justify;">Sur le sujet de la mise en place et de la compatibilité avec les langages du marché, rien de particulier, la liste des frameworks est disponible ici : <a href="https://www.hnpwa.com/" target="_blank" rel="noopener">HNPWA</a></p>
<h2 id="donc-pas-mal-davantages-" style="text-align: justify;">Donc pas mal d’avantages !</h2>
<p style="text-align: justify;">Les solutions PWA sont assez simples à mettre en place. Elles ont une marge d’évolution relativement importante selon le temps et l’argent qui y sont consacrés. D’un point de vue utilisateur, l’installation se fait de façon intuitive, sans même devoir passer par les stores. L’expérience utilisateur peut devenir aussi immersive que sur une application native.</p>
<p style="text-align: justify;">Les principaux avantages de la PWA sont, sans aucun doute, la fluidité, la fiabilité et la capacité à proposer des parcours hors ligne (grâce au chargement progressif) ainsi que l’optimisation de l’affichage sur mobile. La co-construction avec le site web facilite l’organisation des équipes et permet la mutualisation des coûts de développement.</p>
<p style="text-align: justify;">Sur un marché qui ne pense plus seulement à l’expérience utilisateur mais aussi à l’impact environnemental, ces différents avantages s’ancrent parfaitement dans des projets d’éco-conception : moins de données à héberger, un design optimisé pour une utilisation réduite de la batterie du mobile et surtout des phases de développement réduites contrairement à des projets d’application native.</p>
<h2 id="mais-aussi-des-limites" style="text-align: justify;">Mais aussi des limites.</h2>
<p style="text-align: justify;">Vous avez peut-être entendu qu’Apple et PWA ne faisaient pas bon ménage. Malheureusement comme vous pourrez le constater dans ce <a href="https://www.goodbarber.com/widget/browsers/" target="_blank" rel="noopener">tableau des compatibilités</a>, les fonctionnalités disponibles sur Iphone et Safari sont, aujourd’hui encore, très limitées. Il s’agit là du principal frein à la substitution des applications natives pour les entreprises fortement implantées sur mobile.</p>
<p style="text-align: justify;">Il est également à noter que la mise en place d’une PWA nécessite une sécurisation de l’ensemble des pages de votre site par le protocole https.</p>
<h2 id="qui-fait-de-la-pwa-" style="text-align: justify;">Qui fait de la PWA ?</h2>
<p style="text-align: justify;">Voici 2 exemples de PWA réussies:</p>
<p style="text-align: justify;"><b>Twitter avec twitter lite:</b></p>
<p style="text-align: justify;">Objectifs:</p>
<ul style="text-align: justify;">
<li>Améliorer l’expérience sur les connexions limitées.</li>
<li>Simplifier l’accès sans téléchargement sur les stores</li>
<li>Optimiser par le cache et la taille des images</li>
<li>Charger en amont pour une navigation hors ligne</li>
</ul>
<p style="text-align: justify;">Résultat:</p>
<ul style="text-align: justify;">
<li>65 % d’augmentation de pages vues par session</li>
<li>75 % d’augmentation de tweets envoyés</li>
<li>20 % de baisse du taux de rebond (comparé au site mobile avant PWA)</li>
</ul>
<p style="text-align: justify;"><b>ALIBABA (2016)</b> Objectifs:</p>
<ul style="text-align: justify;">
<li>Augmenter le taux de conversion sur mobile</li>
<li>Personnaliser l’ergonomie et le design sur la PWA</li>
<li>Optimiser le chargement des images (nombreuses) pour se déployer sur les pays à faibles connections</li>
<li>Fidéliser avec la proposition d’ajout du site sur l’écran d’accueil</li>
</ul>
<p style="text-align: justify;">Résultat:</p>
<ul style="text-align: justify;">
<li>76% de plus sur le taux de conversions sur tous les navigateurs (30% sur Android)</li>
<li>14% d’utilisateurs actifs mensuels en plus sur iOS</li>
<li>4X plus d’ajout à l’écran d’accueil</li>
</ul>
<h2 id="en-conclusion" style="text-align: justify;">En conclusion</h2>
<p style="text-align: justify;">La PWA n’est ni une évolution des solutions mobiles natives ni une solution de consolation.<br />
Il s’agit d’une vraie réponse à des problématiques de déploiement sur mobile.<br />
Elle offre une expérience immersive et intuitive pour l’utilisateur. Sa mise en place est accessible à n’importe quelle taille de projet web.</p>
<p style="text-align: justify;">Elle permet de rapidement mutualiser les coûts grâce à sa facilité de transformation. Malheureusement son utilisation pour le développement de parcours innovants reste restreinte à cause de sa non-compatibilité avec les fonctionnalités natives des appareils IOS.</p>
<p style="text-align: justify;">Aujourd’hui, la montée en puissance de cette technologie semble être conditionnée par Apple et leur volonté ou non d’améliorer la prise en charge des PWA. Après 5 ans d’existence, cette technologie n’a toujours pas réussi à percer.</p>
<h4 style="text-align: justify;">Glossaire:</h4>
<p style="text-align: justify;"><b>WAP:</b>C’est le premier protocole de communication qui a permis de relier le réseau mobile à internet</p>
<p style="text-align: justify;"><b>Application Hybride:</b> contrairement aux applications natives qui utilisent directement les composants du device (mobile/tablette..), les applications hybrides utilisent le navigateur WEB embarqué dans le device et les technologies qu’on y retrouve pour le développement web, HTML, CSS, JavaScript</p>
<p style="text-align: justify;"><b>Responsive:</b> le Responsive Web Design (RWD) est une technique qui consiste à ajuster automatiquement l’affichage d’une page web à la taille de l’écran du terminal utilisé</p>
<p style="text-align: justify;"><b>Script:</b> suite de commandes qui permettent d’automatiser une tâche</p>
<p style="text-align: justify;"><b>Stores d’application:</b> bibliothèque telle que l’Apple store ou le Play store qui permettent de trouver et d’installer des applications sur un téléphone</p>
<p style="text-align: justify;"><b>Framework:</b> le regroupement d’outils qui facilitent le développement de logiciels et la création de systèmes (aussi appelé environnement de développement)</p>
<h4 style="text-align: justify;">Sources:</h4>
<ul>
<li style="text-align: justify;">https://blog.octo.com/cest-quoi-une-progressive-web-app-pwa/</li>
<li style="text-align: justify;">https://fr.wikipedia.org/wiki/Progressive_web_app</li>
<li style="text-align: justify;">https://developer.mozilla.org/fr/docs/Web/Progressive_web_apps</li>
<li style="text-align: justify;">https://www.novaway.fr/blog/tech/3-exemples-pwa</li>
<li style="text-align: justify;">https://www.goodbarber.com/blog/progressive-web-apps-browser-support-compatibility-a883/</li>
<li style="text-align: justify;">https://developers.google.com/web/showcase/2017/twitter</li>
<li style="text-align: justify;">https://developers.google.com/web/showcase/2016/flipkart</li>
</ul>
<p>L’article <a href="https://ekite.info/2021/09/29/pwa-innovation-ou-solution-de-consolation/">PWA : Innovation ou solution de consolation ?</a> est apparu en premier sur <a href="https://ekite.info">EKITE</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://ekite.info/2021/09/29/pwa-innovation-ou-solution-de-consolation/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">990</post-id>	</item>
	</channel>
</rss>
