BT

Diffuser les Connaissances et l'Innovation dans le Développement Logiciel d'Entreprise

Contribuez

Sujets

Sélectionner votre région

Accueil InfoQ Articles Tutoriel Spring Boot : Création De Microservices Déployés Sur Google Cloud

Tutoriel Spring Boot : Création De Microservices Déployés Sur Google Cloud

Points Clés

  • L'utilisation de Google Kubernetes Engine (GKE) avec Spring Boot vous permet de configurer rapidement et facilement des microservices.
  • Jib est un excellent moyen de conteneuriser votre application Java. Il vous permet de créer des images optimisées sans Docker en utilisant Maven ou Gradle.
  • L'implémentation de Google Cloud Spring GCP permet aux développeurs de tirer parti des services Google Cloud Platform (GCP) avec peu de configuration et en utilisant certains des patterns de Spring.
  • La configuration de Skaffold avec Cloud Code permet aux développeurs d'avoir un cycle de développement agréable. Ceci est particulièrement utile pour commencer à créer un prototype d'un nouveau service.

Introduction

Avec la popularité croissante des microservices dans l'industrie, il y a eu un boom des technologies et des plates-formes à partir desquelles choisir de créer des applications. Parfois, il est difficile de choisir quelque chose pour commencer. Dans cet article, je vais vous montrer comment créer une application basée sur Spring Boot qui tire parti de certains des services offerts par Google Cloud. C'est l'approche que nous utilisons dans notre équipe chez Google depuis un certain temps. J'espère que vous trouverez cela utile.

Les bases

Commençons par définir ce que nous allons construire. Nous allons commencer par une application basique basée sur Spring Boot écrite en Java. Spring est un framework mature qui nous permet de créer rapidement des applications très puissantes et riches en fonctionnalités.

Nous apporterons ensuite quelques modifications pour conteneuriser l'application à l'aide de Jib (crée des images Docker et OCI optimisées pour vos applications Java sans Docker) et une version distroless de Java 11. Jib fonctionne à la fois avec Maven et Gradle. Nous utiliserons Maven pour cet exemple.

Ensuite, nous allons créer un projet Google Cloud Platform (GCP) et utiliser Spring Cloud GCP pour tirer parti de Cloud Firestore. Spring Cloud GCP permet aux applications basées sur Spring de consommer facilement les services Google comme les bases de données (Cloud Firestore, Cloud Spanner ou même Cloud SQL), Google Cloud Pub/Sub, Stackdriver pour la journalisation et le traçage, etc.

Après cela, nous apporterons des modifications à notre application pour la déployer sur Google Kubernetes Engine (GKE). GKE est un environnement géré et prêt pour la production pour le déploiement d'applications conteneurisées basées sur Kubernetes.

Enfin, nous utiliserons Skaffold et Cloud Code pour faciliter le développement. Skaffold gère le workflow pour créer, pousser et déployer votre application. Cloud Code est un plugin pour VS Code et IntelliJ qui fonctionne avec Skaffold et votre IDE afin que vous puissiez faire des choses comme déployer sur GKE en un seul clic. Dans cet article, je vais utiliser IntelliJ avec Cloud Code.

Configuration de nos outils

Avant d'écrire un code, assurez-vous d'avoir un projet Google Cloud et tous les outils installés.

Création d'un Google Cloud Project

La configuration d'une instance GCP est simple. Vous pouvez accomplir cela en suivant ces instructions. Ce nouveau projet nous permettra de déployer notre application sur GKE, d'avoir accès à une base de données (Cloud Firestore) et nous permettra également d'avoir un endroit où nous pouvons pousser nos images lorsque nous conteneurisons l'application.

Installer Cloud Code

Ensuite, nous allons installer Cloud Code. Vous pouvez suivre ces instructions sur la façon d'installer Cloud Code dans IntelliJ. Cloud Code gère l'installation de Skaffold et du SDK Google que nous utiliserons plus loin dans l'article. Cloud Code nous permet également d'inspecter nos déploiements et services GKE. Plus important encore, il dispose également d'un mode de développement GKE intelligent qui écoute en continu les modifications de votre code lorsqu'il détecte un changement, il crée l'application, crée l'image, pousse l'image dans votre registre, déploie l'application sur votre cluster GKE, commence à streamer les logs et ouvre un tunnel localhost afin que vous puissiez tester votre service localement. C'est comme de la magie !

Pour utiliser Cloud Code et continuer avec notre application, assurez-vous de vous connecter en utilisant le plugin Cloud Code en cliquant sur l'icône qui devrait apparaître en haut à droite de votre fenêtre IntelliJ :

De plus, nous exécuterons certaines commandes pour nous assurer que l'application s'exécute sur votre machine et peut communiquer avec les services exécutés sur votre projet dans Google Cloud. Assurons-nous que nous pointons vers le bon projet et authentifions-nous en utilisant :

gcloud config set project <YOUR PROJECT ID>
gcloud auth login

Ensuite, nous nous assurerons que votre machine dispose des informations d'identification d'application pour exécuter votre application localement :

gcloud auth application-default login

Activation des API

Maintenant que nous avons tout configuré, nous devons activer les API que nous utiliserons dans notre application :

  • API Google Container Registry - Cela nous permettra d'avoir un registre où nous pouvons pousser nos images en privé.
  • Cloud Firestore en mode Datastore - Cela nous permettra de stocker des entités dans une base de données NoSQL. Assurez-vous de sélectionner le mode Datastore afin que nous puissions utiliser la prise en charge de Spring Cloud GCP pour cela.

Vous pouvez gérer les API activées dans votre projet en visitant le tableau de bord API de votre projet .

Création de notre service

Tout d'abord! Nous devons commencer avec une application simple que nous pouvons exécuter localement. Nous allons créer quelque chose d'important comme un microservice Dog. Puisque j'utilise IntelliJ Ultimate, je vais aller dans `Fichier -> Nouveau -> Projet ...` et sélectionner "Spring Initializr". Je vais sélectionner Maven, Jar, Java 11 et changer le nom en quelque chose d'important comme `dog` comme indiqué ci-dessous :


 
Cliquez sur Suivant et ajoutez Lombok, Spring Web et GCP Support :


Si tout s'est bien passé, vous devriez maintenant avoir une application que vous pouvez exécuter. Si vous ne souhaitez pas utiliser IntelliJ pour cela, utilisez l'équivalent sur votre IDE ou utilisez Initializr de Spring.

Ensuite, nous ajouterons un POJO pour notre service Dog et quelques endpoints REST pour tester notre application. Notre objet Dog aura un nom et un âge et nous utiliserons l'annotation @Data de Lombok pour nous éviter d'écrire des setters, des getters, etc. Nous utiliserons également l'annotation @AllArgsConstructor pour créer un constructeur pour nous. Nous l'utiliserons plus tard lorsque nous créerons des chiens.

@Data
@AllArgsConstructor
public class Dog {
 private String name;
 private int age;
}

Nous allons créer une classe contrôleur pour les endpoints Dog et REST :

@RestController
@Slf4j
public class DogController {

  @GetMapping("/api/v1/dogs")
  public List<Dog> getAllDogs() {
    log.debug("->getAllDogs");
    return ImmutableList.of(new Dog("Fluffy", 5),
        new Dog("Bob", 6),
        new Dog("Cupcake", 11));
  }

  @PostMapping("/api/v1/dogs")
  public Dog saveDog(@RequestBody Dog dog) {
    log.debug("->saveDog {}", dog);
    return dog;
  }
}

Les endpoints renvoient une liste de chiens prédéfinis et le saveDog ne fait pas vraiment grand-chose, mais cela nous suffit pour commencer.

Utilisation de Cloud Firestore

Maintenant que nous avons un squelette d'application, essayons d'utiliser certains des services de GCP. Spring Cloud GCP ajoute la prise en charge de Spring Data pour Google Cloud Firestore en mode Datastore. Nous allons l'utiliser pour stocker nos chiens au lieu d'utiliser une simple liste. Les utilisateurs pourront désormais également enregistrer un chien dans notre base de données.

Pour commencer, nous ajouterons la dépendance Spring Cloud GCP Data Datastore à notre POM :

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-gcp-data-datastore</artifactId>
</dependency>

Maintenant, nous pouvons modifier notre classe Dog afin qu'elle puisse être stockée. Nous allons ajouter une annotation @Entity et une annotation @Id à une valeur de type Long pour agir comme identifiant pour l'entité :

@Entity
@Data
@AllArgsConstructor
public class Dog {
  @Id private Long id;
  private String name;
  private int age;
}

Nous pouvons maintenant créer une classe Spring Repository classique comme suit :

@Repository
public interface DogRepository extends DatastoreRepository<Dog, Long> {}

Comme d'habitude avec Spring Repositories, il n'est pas nécessaire d'écrire des implémentations pour cette interface car nous utiliserons des méthodes très basiques.

Nous pouvons maintenant modifier la classe du contrôleur. Nous injecterons le DogRepository dans le DogController puis modifierons la classe pour utiliser le référentiel comme suit :

@RestController
@Slf4j
@RequiredArgsConstructor
public class DogController {

  private final DogRepository dogRepository;

  @GetMapping("/api/v1/dogs")
  public Iterable<Dog> getAllDogs() {
    log.debug("->getAllDogs");
    return dogRepository.findAll();
  }

  @PostMapping("/api/v1/dogs")
  public Dog saveDog(@RequestBody Dog dog) {
    log.debug("->saveDog {}", dog);
    return dogRepository.save(dog);
  }
}

Notez que nous utilisons @RequiredArgsConstructor de Lombok pour créer un constructeur pour injecter notre DogRepository. Lorsque vous exécutez votre application, les endpoints appellent votre service Dog qui tentera d'utiliser Cloud Firestore pour récupérer ou stocker les chiens.

CONSEIL : Pour tester rapidement cela, vous pouvez créer une requête HTTP dans IntelliJ avec les éléments suivants :

POST http://localhost:8080/api/v1/dogs
Content-Type: application/json

{
  "name": "bob",
  "age": 5
}

En seulement quelques étapes, nous avons maintenant l'application en cours d'exécution et de consommation des services à partir de GCP. Impressionnant! Maintenant, transformons cela en conteneur et déployons-le!

Conteneuriser le service Dog

À ce stade, vous pouvez commencer à écrire un Dockerfile pour conteneuriser l'application que nous avons créée ci-dessus. Utilisons plutôt Jib. L'une des choses que j'aime avec Jib, c'est qu'il sépare votre application en plusieurs couches, séparant les dépendances des classes. Cela nous permet d'avoir des builds plus rapides afin que vous n'ayez pas à attendre que Docker reconstruise l'intégralité de votre application Java - déployez simplement les couches qui ont changé. De plus, Jib dispose d'un plugin Maven qui facilite la configuration en modifiant simplement le fichier POM dans votre application.

Pour commencer à utiliser le plugin, nous devons modifier notre fichier POM pour ajouter ce qui suit :

<plugin>
        <groupId>com.google.cloud.tools</groupId>
        <artifactId>jib-maven-plugin</artifactId>
        <version>1.8.0</version>
        <configuration>
          <from>
            <image>gcr.io/distroless/java:11</image>
          </from>
          <to>
            <image>gcr.io/<YOUR_GCP_REGISTRY>/${project.artifactId}</image>
          </to>
        </configuration>
</plugin>

Notez que nous utilisons l'image distroless de Google pour Java 11. Les images "distroless" contiennent uniquement votre application et ses dépendances d'exécution. Ils ne contiennent pas de gestionnaires de packages, de shells ou d'autres programmes que vous attendez d'une distribution Linux standard.

Restreindre ce qui se trouve dans votre conteneur d'exécution à ce qui est précisément nécessaire pour votre application est une bonne pratique employée par Google et d'autres géants de la technologie qui utilisent des conteneurs en production depuis de nombreuses années. Il améliore le rapport signal-to-noise des scanners (par exemple CVE) et réduit la charge d'établir la provenance à ce dont vous avez besoin.

Assurez-vous de remplacer votre registre GCP dans le code ci-dessus pour correspondre au nom de votre projet.

Après cela, vous pouvez essayer de créer et de pousser l'image de l'application en exécutant une commande comme :

$ ./mvnw install jib:build

Cela va générer et tester l'application. Créez l'image, puis enfin poussez l'image nouvellement créée dans votre registre.

Remarque : c'est généralement une bonne pratique courante d'utiliser une distribution avec un tag spécifique au lieu d'utiliser «latest». Je laisse au lecteur le soin de décider quelle image de base et quel tag utiliser en fonction de la version de Java que vous utilisez.

Déployer le service Dog

À ce stade, nous sommes presque prêts à déployer notre application. Pour ce faire, créons d'abord un cluster GKE où nous déploierons notre application.

Création d'un cluster GKE

Pour créer un cluster GKE, suivez ces instructions. Vous voudrez essentiellement visiter la page GKE, attendre que l'API soit activée, puis cliquer sur le bouton pour créer un cluster. Vous pouvez utiliser les paramètres par défaut, mais assurez-vous simplement de cliquer sur le bouton "Plus d'options" pour permettre un accès complet à toutes les API Cloud :

Cela permet à vos nœuds GKE d'avoir des autorisations pour accéder au reste des services Google Cloud. Après quelques instants, le cluster sera créé :

Applications exécutées dans Kubernetes

Kubernetes aime surveiller votre application pour s'assurer qu'elle est opérationnelle. En cas d'échec, Kubernetes sait que votre application est en panne et qu'il doit faire tourner une nouvelle instance. Pour ce faire, nous devons nous assurer que notre application est capable de répondre lorsque Kubernetes l'interroge. Ajoutons un actuator et Spring Cloud Kubernetes.

Ajoutez les dépendances suivantes à votre fichier POM :

<dependency>
    <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Si votre application possède un fichier application.properties dans le répertoire src/main/resources, supprimez-le et créez un fichier application.yaml avec le contenu suivant :

spring:
  application:
    name: dog-service

management:
  endpoint:
    health:
      enabled: true

Cela ajoute un nom à notre application et expose le endpoint de santé mentionné ci-dessus. Pour vérifier que cela fonctionne, vous pouvez visiter votre application sur localhost:8080/actuator/health. Vous devriez voir quelque chose comme :

{
    "status": "UP"
}

Configuration pour s'exécuter dans Kubernetes

Pour déployer notre application sur notre nouveau cluster GKE, nous devons écrire du YAML supplémentaire. Nous devons créer deux fichiers deployment et service. Utilisez le fichier deployement qui suit. N'oubliez pas de remplacer le nom GCR par celui de votre projet :

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: dog-service
spec:
  selector:
    matchLabels:
      app: dog-service
  replicas: 1
  template:
    metadata:
      labels:
        app: dog-service
    spec:
      containers:
        - name: dog-service
          image: gcr.io/<YOUR GCR REGISTRY NAME>/dog
          ports:
            - containerPort: 8080
          livenessProbe:
            initialDelaySeconds: 20
            httpGet:
              port: 8080
              path: /actuator/health
          readinessProbe:
            initialDelaySeconds: 30
            httpGet:
              port: 8080
              path: /actuator/health

Ajoutez un fichier service.yaml avec les éléments suivants :

apiVersion: v1
kind: Service
metadata:
  name: dog-service
spec:
  type: NodePort
  selector:
    app: dog-service
  ports:
    - port: 8080
      targetPort: 8080

Le déploiement contient quelques modifications pour la sonde (probe) de disponibilité et de vivacité. C'est ainsi que Kubernetes utilise ces endpoints pour interroger l'application pour voir si elle est vivante. Le service expose le déploiement afin que d'autres services puissent le consommer.

Après cela, nous pouvons maintenant commencer à utiliser le plugin Cloud Code que nous avons installé au début de cet article. Dans le menu Tools, sélectionnez : Cloud Code -> Kubernetes -> Add Kubernetes Support. Cela ajoutera automatiquement un Skaffold YAML à votre application et configurera quelques éléments pour vous afin que vous puissiez déployer sur votre cluster en cliquant sur un bouton. Pour confirmer que tout cela a fonctionné, vous pouvez inspecter la configuration à partir de la section Configurations de Run/Debug dans IntelliJ. Si vous cliquez sur Develop on Kubernetes, il devrait avoir automatiquement récupéré votre cluster GKE et les fichiers de configuration de Kubernetes et devrait ressembler à ceci :

Cliquez sur OK puis sur le bouton vert "Play" en haut à droite :

Après cela, Cloud Code créera l'application, créera l'image, déploiera l'application sur votre cluster GKE et diffusera les journaux de Stackdriver sur votre machine locale. Il ouvrira également un tunnel afin que vous puissiez consommer votre service via localhost:8080. Vous pouvez également effectuer un pic sur la page des charges de travail dans la console Google Cloud :

Conclusions

Félicitations si vous êtes arrivé jusqu'ici! L'application que nous avons créée dans cet article présente certaines technologies clés que la plupart des applications basées sur les microservices utiliseraient : une base de données documentaire NoSQL rapide, entièrement gérée, sans serveur (Cloud Firestore), GKE un environnement géré et prêt pour la production pour le déploiement basées sur Kubernetes pour des applications conteneurisées et enfin une construction simple de microservice cloud natif avec Spring Boot. En cours de route, nous avons également appris à utiliser quelques outils comme Cloud Code pour rationaliser votre workflow de développement et Jib pour créer des applications conteneurisées à l'aide de patterns Java courants.

J'espère que vous avez trouvé l'article utile et que vous essayez ces technologies. Si vous avez trouvé cela intéressant, jetez un oeil à aux codelabs que Google propose où vous pouvez en apprendre davantage sur les produits Spring et Google Cloud.

A propos de l'auteur

Sergio Felix est ingénieur logiciel chez Google Cloud, où il travaille pour Cloud Engineering Productivity, une organisation au sein de Google Cloud qui se concentre sur le développement sans friction et l'amélioration de l'excellence des produits et des ingénieurs.

 

Evaluer cet article

Pertinence
Style

Contenu Éducatif

BT