Nouveau : Datasets open source gratuits disponibles !Decouvrir →
☁️
Intermediaire 25 min Go

Deployer Go sur GCP

Pourquoi Déployer Go sur GCP ?

Deployer une application Go sur Google Cloud Platform (GCP) est un choix populaire pour les développeurs, car GCP offre des services robustes et scalables qui peuvent gérer la charge de travail d'une application Go efficacement. Voici un contexte réel : imaginez que vous développez une application de microservices backend pour une entreprise croissante. Vous avez besoin d'une infrastructure fiable qui peut s'échelle à mesure du nombre d'utilisateurs et de demandes.

Un cas concret serait la création d'une API de blog. L'application doit être capable de gérer des millions de requêtes par jour, en traitant des opérations CRUD sur les articles de blog. En déployant cette application Go sur GCP, vous bénéficiez d'un stockage fiable et rapide, d'un réseau mondial pour l'accelération du trafic, ainsi que d'une infrastructure auto-géante pour la mise à l'échelle.

Prérequis

Pour suivre ce tutoriel, vous aurez besoin des connaissances suivantes :

  • Connaissance de base en Go
  • Compréhension des concepts fondamentaux de GCP (Cloud Storage, Cloud Functions, App Engine)

Les outils que vous devez installer sont les suivants :

  • Google Cloud SDK v300.0.0 ou ultérieure
  • Go v1.16 ou ultérieure

Concepts Fondamentaux

1. Cloud Functions

Cloud Functions est un service qui permet d'exécuter des fonctions serverless sur GCP. Ce service est parfait pour les applications Go qui nécessitent une mise à l'échelle automatique et une infrastructure sans état.

Schema Mental

+-------------------+
|    Trigger        |
| (HTTP, Pub/Sub, etc.)|
+--------+----------+
         |
         v
+--------v----------+
|   Function       |
| (Go Code)      |
+-------------------+
         |
         v
+--------v----------+
|  Execution      |
|  Management     |
+-------------------+
go
// main.go
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    port := "8080"
    if envPort := os.Getenv("PORT"); envPort != "" {
        port = envPort
    }
    log.Printf("Listening on :%s...", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatalf("Could not listen on %s: %v\n", port, err)
    }
}

2. App Engine

App Engine est un service qui permet de déployer des applications web et mobiles. Il prend en charge les langages Go et offre une mise à l'échelle automatique.

Schema Mental

+-------------------+
|   Application     |
| (Go Code)        |
+--------+----------+
         |
         v
+--------v----------+
|  Deployment      |
|  Management    |
+-------------------+
         |
         v
+--------v----------+
|  Instances       |
| (Auto-scaled)    |
+-------------------+
go
// app.yaml
runtime: go115

instance_class: F2

automatic_scaling:
  target_cpu_utilization: 0.65
  min_instances: 1
  max_instances: 10

env_variables:
  GCP_PROJECT: your-gcp-project-id
go
// main.go
package main

import (
    "fmt"
    "net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello from App Engine!")
}

func main() {
    http.HandleFunc("/", helloHandler)
    port := "8080"
    if envPort := os.Getenv("PORT"); envPort != "" {
        port = envPort
    }
    log.Printf("Listening on :%s...", port)
    if err := http.ListenAndServe(":"+port, nil); err != nil {
        log.Fatalf("Could not listen on %s: %v\n", port, err)
    }
}

3. Cloud Storage

Cloud Storage est un stockage d'objets à grande échelle et hautement disponible, qui est idéal pour stocker des fichiers binaires ou textuels.

Schema Mental

+-------------------+
|   Bucket          |
| (Cloud Storage)  |
+--------+----------+
         |
         v
+--------v----------+
|   Objects        |
| (Files)        |
+-------------------+
         |
         v
+--------v----------+
|  Access          |
|  Management      |
+-------------------+
go
// main.go
package main

import (
    "context"
    "fmt"
    "cloud.google.com/go/storage"
)

func uploadFile(bucketName, objectName, filePath string) error {
    ctx := context.Background()
    client, err := storage.NewClient(ctx)
    if err != nil {
        return fmt.Errorf("storage.NewClient: %w", err)
    }
    defer client.Close()

    bucket := client.Bucket(bucketName)
    obj := bucket.Object(objectName)

    w := obj.NewWriter(ctx)
    f, err := os.Open(filePath)
    if err != nil {
        return fmt.Errorf("os.Open: %w", err)
    }
    if _, err := io.Copy(w, f); err != nil {
        return fmt.Errorf("io.Copy: %w", err)
    }

    if err := w.Close(); err != nil {
        return fmt.Errorf("Writer.Close: %w", err)
    }
    fmt.Printf("Uploaded %s to gs://%s/%s\n", filePath, bucketName, objectName)
    return nil
}

func main() {
    bucketName := "your-bucket-name"
    objectName := "your-object-name"
    filePath := "path/to/your/file"

    if err := uploadFile(bucketName, objectName, filePath); err != nil {
        fmt.Println("Error:", err)
        return
    }
}

Mise en Pratique : Projet Fil Rouge

Nous allons créer un gestionnaire de tâches simple en Go qui utilise Cloud Functions pour les exécuter.

Étape 1 : Création du projet et initialisation d'App Engine

  1. Créez un nouveau projet GCP et notez le nom du projet.
  2. Activez les services nécessaires (Cloud Functions, App Engine).
gcloud projects create your-gcp-project-id --name "Your Project Name"
gcloud config set project your-gcp-project-id

gcloud services enable cloudfunctions.googleapis.com
gcloud services enable appengine.googleapis.com
  1. Initialisez un nouveau projet Go.
mkdir task-manager
cd task-manager
go mod init github.com/yourusername/task-manager

Étape 2 : Création de la fonction serverless

Créez un fichier main.go pour votre application Go.

// main.go
package main

import (
    "context"
    "encoding/json"
    "fmt"
    "log"
    "net/http"

    "cloud.google.com/go/functions/v2beta1/functionframework"
)

type Task struct {
    ID     string `json:"id"`
    Title  string `json:"title"`
    Done   bool   `json:"done"`
}

var tasks = []Task{
    {ID: "1", Title: "Buy groceries", Done: false},
    {ID: "2", Title: "Clean the house", Done: true},
}

func listTasks(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodGet {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    json.NewEncoder(w).Encode(tasks)
}

func createTask(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPost {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    var task Task
    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
        http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
        return
    }

    tasks = append(tasks, task)
    w.WriteHeader(http.StatusCreated)
}

func updateTask(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodPut {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    var task Task
    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
        http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
        return
    }

    for i, t := range tasks {
        if t.ID == task.ID {
            tasks[i] = task
            break
        }
    }
}

func deleteTask(w http.ResponseWriter, r *http.Request) {
    if r.Method != http.MethodDelete {
        http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        return
    }

    var task Task
    if err := json.NewDecoder(r.Body).Decode(&task); err != nil {
        http.Error(w, fmt.Sprintf("Invalid JSON: %v", err), http.StatusBadRequest)
        return
    }

    for i, t := range tasks {
        if t.ID == task.ID {
            tasks = append(tasks[:i], tasks[i+1:]...)
            break
        }
    }
}

func main() {
    functionframework.Handle("/tasks", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        switch r.Method {
        case http.MethodGet:
            listTasks(w, r)
        case http.MethodPost:
            createTask(w, r)
        case http.MethodPut:
            updateTask(w, r)
        case http.MethodDelete:
            deleteTask(w, r)
        default:
            http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
        }
    })

    if err := functionframework.Start(); err != nil {
        log.Fatalf("functionframework.Start: %v", err)
    }
}

Étape 3 : Déploiement sur Cloud Functions

  1. Créez une fonction serverless pour gérer les tâches.
gcloud functions deploy taskManager --runtime go115 --trigger-http --allow-unauthenticated --entry-point main
  1. Testez la fonction en utilisant curl.
curl -X GET https://REGION-PROJECT_ID.cloudfunctions.net/taskManager/tasks
curl -X POST -H "Content-Type: application/json" -d '{"id": "3", "title": "Walk the dog", "done": false}' https://REGION-PROJECT_ID.cloudfunctions.net/taskManager/tasks

Étape 4 : Déploiement sur App Engine

  1. Créez un fichier app.yaml pour configurer App Engine.
## app.yaml
runtime: go115

instance_class: F2

automatic_scaling:
  target_cpu_utilization: 0.65
  min_instances: 1
  max_instances: 10

env_variables:
  GCP_PROJECT: your-gcp-project-id
  1. Déployez l'application sur App Engine.
gcloud app deploy
  1. Testez l'application en accédant à l'URL affichée par la commande gcloud app browse.

Erreurs Fréquentes et Debugging

1. Erreur : functionframework: Unable to invoke function

## ❌ Mauvais
func main() {
    http.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
        // Your code here
    })
}

## ✅ Correct
func main() {
    functionframework.Handle("/tasks", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        // Your code here
    })

    if err := functionframework.Start(); err != nil {
        log.Fatalf("functionframework.Start: %v", err)
    }
}

2. Erreur : failed to create client: transport: dial tcp [::]:8080: connect: connection refused

## ❌ Mauvais
func main() {
    http.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
        // Your code here
    })

    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatalf("Could not listen on :8080: %v\n", err)
    }
}

## ✅ Correct
func main() {
    functionframework.Handle("/tasks", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        // Your code here
    })

    if err := functionframework.Start(); err != nil {
        log.Fatalf("functionframework.Start: %v", err)
    }
}

3. Erreur : failed to create client: transport: dial tcp [::]:8081: connect: connection refused

## ❌ Mauvais
func main() {
    http.HandleFunc("/tasks", func(w http.ResponseWriter, r *http.Request) {
        // Your code here
    })

    if err := http.ListenAndServe(":8081", nil); err != nil {
        log.Fatalf("Could not listen on :8081: %v\n", err)
    }
}

## ✅ Correct
func main() {
    functionframework.Handle("/tasks", func(ctx context.Context, w http.ResponseWriter, r *http.Request) {
        // Your code here
    })

    if err := functionframework.Start(); err != nil {
        log.Fatalf("functionframework.Start: %v", err)
    }
}

Pour Aller Plus Loins

1. Utiliser Firestore pour le stockage

Firestore est un service de base de données NoSQL sur GCP qui peut être utilisé pour stocker et gérer des données en temps réel.

2. Intégrer Cloud Pub/Sub

Cloud Pub/Sub est un service de messagerie fiable et évolutif, qui peut être utilisé pour publier et abonner des messages à travers votre application.

3. Développer une API GraphQL

GraphQL est un langage de requête pour les APIs et un serveur d'exécution pour traiter ces requêtes avec vos données existantes. Vous pouvez utiliser GraphQL avec Go en utilisant des bibliothèques comme graphql-go.

Challenge Pratique

  1. Développez une API de blog en utilisant Go, Cloud Functions et Firestore.
  2. Ajoutez l'intégration de Cloud Pub/Sub pour publier des notifications lorsqu'un nouvel article est créé ou mis à jour.
  3. Utilisez GraphQL pour exposer votre API de blog.

En suivant ces étapes, vous serez en mesure de créer une application robuste et scalable en utilisant Go sur GCP.

Besoin d'aide sur Go ?

Besoin d'aide sur un projet technique ? Decrivez-le pour des conseils personnalises.

Recevoir des conseils

Questions frequentes

Comment installer Go sur Google Cloud Platform (GCP) ?
Pour installer Go sur GCP, vous pouvez utiliser l'outil 'gcloud compute ssh' pour accéder à une instance virtuelle et y installer Go via les commandes 'wget' ou 'curl' pour télécharger le binaire officiel de Go, puis exécuter './go install' pour l'installer.
Quelle est la configuration recommandée pour un projet Go sur GCP ?
La configuration recommandée pour un projet Go sur GCP inclut l'utilisation d'un service de stockage comme Google Cloud Storage pour gérer les fichiers et les données, et des instances Compute Engine pour exécuter le code. Vous pouvez également utiliser des services d'orchestration comme Kubernetes Engine pour faciliter le déploiement et la gestion des applications Go à grande échelle.
Comment configurer l'environnement de développement Go sur GCP ?
Pour configurer l'environnement de développement Go sur GCP, vous devez d'abord installer le SDK Google Cloud et authentifier votre compte. Ensuite, vous pouvez créer une instance Compute Engine avec des images préconfigurées pour Go ou installer les outils Go directement sur une machine virtuelle existante. Assurez-vous également de configurer les variables d'environnement Go appropriées pour votre projet.

Pages liees

Chaque semaine, le meilleur de la tech francaise

Tendances, salaires, outils et opportunites — directement dans votre boite mail.

Gratuit. Desabonnement en un clic. Pas de spam.