Hébergement statique avec un domaine

+

Architecture

L'hébergement statique avec domaine est un outil de création de sites Web statiques simple qui crée un site simple à l'aide d'un bucket Storage pour diffuser le site Web:

  • Stockage - Stockage de fichiers - Cloud Storage
  • Mise en réseau - Équilibrage de charge - Cloud Load Balancing
  • Mise en réseau - DNS - Cloud DNS
  • Gestion des domaines - Bureau d'enregistrement - Cloud Domains

Premiers pas

Cliquez sur le lien suivant pour obtenir une copie du code source dans Cloud Shell. Une seule commande permet de démarrer une copie fonctionnelle de l'application dans votre projet.

Ouvrir dans Cloud Shell

Afficher le code source sur GitHub


Hébergement statique avec des composants de domaine

L'architecture d'hébergement statique avec domaine utilise plusieurs produits. Vous trouverez ci-dessous la liste des composants, ainsi que des informations supplémentaires à leur sujet, y compris des liens vers des vidéos, des documentations produit et des tutoriels interactifs associés.
Vidéo Docs Tutoriels
Cloud Storage Cloud Storage permet de stocker des fichiers et de diffuser des images publiquement via HTTP(S).
Cloud DNS Cloud DNS fournit une gestion DNS, ce qui vous permet d'exécuter votre propre infrastructure DNS à l'aide de l'infrastructure DNS existante de Google.
Cloud Load Balancing Google Cloud Load Balancing vous permet de placer un équilibreur de charge devant le bucket Storage. Vous pouvez ainsi utiliser des certificats SSL, la journalisation et la surveillance.
Cloud Domains Cloud Domains vous permet d'acheter des domaines, comme un bureau d'enregistrement de noms de domaine. Une fois que vous avez acheté un domaine, vous pouvez le gérer et gérer la facturation via votre compte Google Cloud.

Scripts

Le script d'installation utilise un exécutable écrit en go et des outils de la CLI Terraform pour prendre un projet vide et y installer l'application. La sortie doit être une application fonctionnelle et une URL pour l'adresse IP d'équilibrage de charge.

./main.tf

Activer les services

Les services Google Cloud sont désactivés par défaut dans un projet. Pour utiliser l'une des solutions ci-dessous, vous devez activer les éléments suivants:

  • Cloud Domains : enregistrement de domaine
  • Cloud Storage : hébergement des fichiers statiques
  • Cloud Compute : permet d'accéder aux équilibreurs de charge.
  • Cloud DNS : permet de gérer le DNS
variable "gcp_service_list" {
    description = "The list of apis necessary for the project"
    type        = list(string)
    default = [
        "domains.googleapis.com",
        "storage.googleapis.com",
        "compute.googleapis.com",
        "dns.googleapis.com",
        "appengine.googleapis.com",
    ]
}

resource "google_project_service" "all" {
    for_each                   = toset(var.gcp_service_list)
    project                    = var.project_number
    service                    = each.key
    disable_dependent_services = false
    disable_on_destroy         = false
}

Créer une zone DNS

Crée une zone DNS pour gérer les enregistrements, les diriger vers des équilibreurs de charge, interagir avec les bureaux d'enregistrement de domaine et diffuser des requêtes DNS vers d'autres serveurs DNS.

resource "google_dns_managed_zone" "dnszone" {
    project     = var.project_id
    name        = local.clouddnszone
    dns_name    = "${var.domain}."
    description = "A DNS Zone for managing ${var.domain}"
}

Créer un certificat SSL

Les certificats SSL sont obligatoires pour les requêtes du protocole HTTPS. Cela génère un équilibreur de charge qui sera associé à l'équilibreur de charge dans une commande ultérieure.

resource "google_compute_managed_ssl_certificate" "cert" {
    name        = "${local.basename}-cert"
    description = "Cert for ${local.basename}-microsite"
    project     = var.project_id

    managed {
        domains = [var.domain]
    }

    lifecycle {
        create_before_destroy = true
    }
}

Créer une adresse IP externe

Nécessaire pour associer un hôte au nom de domaine et communiquer en général sur Internet.

resource "google_compute_global_address" "ip" {
    project    = var.project_id
    name       = "${local.basename}-ip"
    ip_version = "IPV4"
}

Créer un bucket de stockage

Un bucket nommé d'après le domaine est créé, puis configuré pour servir de serveur Web. Enfin, il copie le modèle simple pour le site.

resource "google_storage_bucket" "http_bucket" {
    name     = local.bucket
    project  = var.project_id
    location = var.location
    
    website {
        main_page_suffix = "index.html"
        not_found_page   = "404.html"
    }
}

resource "google_storage_bucket_iam_binding" "policy" {
    bucket = google_storage_bucket.http_bucket.name
    role   = "roles/storage.objectViewer"
    members = [
      "allUsers",
    ]
    depends_on = [google_storage_bucket.http_bucket]
  }

resource "google_storage_bucket_object" "archive" {
    name   = "index.html"
    bucket = google_storage_bucket.http_bucket.name
    source = "code/${var.yesorno}/index.html"
    depends_on = [
        google_project_service.all,
        google_storage_bucket.http_bucket,
    ]
}

Configurer un équilibreur de charge

L'équilibreur de charge est ainsi créé et le bucket de stockage est configuré comme source du contenu auquel l'équilibreur de charge fournira l'accès.

resource "google_compute_backend_bucket" "be" {
    project     = var.project_id
    name        = "${local.basename}-be"
    bucket_name = google_storage_bucket.http_bucket.name
    depends_on = [google_storage_bucket.http_bucket]
}

resource "google_compute_url_map" "lb" {
    project         = var.project_id
    name            = "${local.basename}-lb"
    default_service = google_compute_backend_bucket.be.id
    depends_on = [google_compute_backend_bucket.be]
}

Activer HTTP

Crée les règles réseau nécessaires pour faire pointer le port 80 de l'équilibreur de charge vers le service que nous exécutons.

resource "google_compute_target_http_proxy" "lb-proxy" {
    project = var.project_id
    name    = "${local.basename}-lb-proxy"
    url_map = google_compute_url_map.lb.id
    depends_on = [google_compute_url_map.lb]
}

resource "google_compute_forwarding_rule" "http-lb-forwarding-rule" {
    project               = var.project_id
    name                  = "${local.basename}-http-lb-forwarding-rule"
    provider              = google-beta
    region                = "none"
    load_balancing_scheme = "EXTERNAL"
    port_range            = "80"
    target                = google_compute_target_http_proxy.lb-proxy.id
    ip_address            = google_compute_global_address.ip.id
    depends_on = [google_compute_target_http_proxy.lb-proxy]
}

Activer HTTPS

Crée les règles réseau nécessaires pour rediriger le port 443 de l'équilibreur de charge vers le service que nous exécutons. Associe également le certificat correctement.

resource "google_compute_target_https_proxy" "ssl-lb-proxy" {
    project          = var.project_id
    name             = "${local.basename}-ssl-lb-proxy"
    url_map          = google_compute_url_map.lb.id
    ssl_certificates = [google_compute_managed_ssl_certificate.cert.id]
    depends_on = [google_compute_url_map.lb,google_compute_managed_ssl_certificate.cert ]
}

resource "google_compute_forwarding_rule" "https-lb-forwarding-rule" {
    project               = var.project_id
    name                  = "${local.basename}-https-lb-forwarding-rule"
    provider              = google-beta
    region                = "none"
    load_balancing_scheme = "EXTERNAL"
    port_range            = "443"
    target                = google_compute_target_https_proxy.ssl-lb-proxy.id
    ip_address            = google_compute_global_address.ip.id
    depends_on = [google_compute_target_https_proxy.ssl-lb-proxy]
}

Définir un enregistrement A

Crée la règle appropriée dans Cloud DNS qui permettra de résoudre le nom de domaine en adresse IP que nous avons créée.

resource "google_dns_record_set" "a" {
    project      = var.project_id
    name         = "${var.domain}."
    managed_zone = google_dns_managed_zone.dnszone.name
    type         = "A"
    ttl          = 60


    rrdatas = [google_compute_global_address.ip.address]
    depends_on = [google_compute_global_address.ip]
}

./deploystack.go

Interroger la disponibilité d'un domaine

Obtient des informations sur la disponibilité du domaine demandé

func domainsSearch(project, domain string) ([]*domainspb.RegisterParameters, error) {
    ctx := context.Background()

    c, err := domains.NewClient(ctx)
    if err != nil {
        return nil, err
    }
    defer c.Close()

    req := &domainspb.SearchDomainsRequest{
        Query:    domain,
        Location: fmt.Sprintf("projects/%s/locations/global", project),
    }
    resp, err := c.SearchDomains(ctx, req)
    if err != nil {
        return nil, err
    }

    return resp.RegisterParameters, nil
}

func domainIsAvailable(project, domain string) (*domainspb.RegisterParameters, error) {
    list, err := domainsSearch(project, domain)
    if err != nil {
        return nil, err
    }
    for _, v := range list {
        if v.DomainName == domain {
            return v, err
        }
    }

    return nil, err
}

Interroger la propriété du domaine

Indique si l'utilisateur actuel est propriétaire du domaine demandé.

func domainsIsVerified(project, domain string) (bool, error) {
    ctx := context.Background()

    c, err := domains.NewClient(ctx)
    if err != nil {
        return false, err
    }
    defer c.Close()

    req := &domainspb.ListRegistrationsRequest{
        Filter: fmt.Sprintf("domainName=\"%s\"", domain),
        Parent: fmt.Sprintf("projects/%s/locations/global", project),
    }
    it := c.ListRegistrations(ctx, req)
    for {
        resp, err := it.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            return false, err
        }

        if resp.DomainName == domain {
            return true, nil
        }
    }

    return false, nil
}

Enregistrer un domaine avec Cloud Domains

Effectue l'opération d'achat du domaine auprès du bureau d'enregistrement.

func domainRegister(project string, domaininfo *domainspb.RegisterParameters, contact ContactData) error {
    ctx := context.Background()

    parent := fmt.Sprintf("projects/%s/locations/global", project)

    c, err := domains.NewClient(ctx)
    if err != nil {
        return err
    }
    defer c.Close()

    dnscontact, err := contact.DomainContact()
    if err != nil {
        return err
    }

    req := &domainspb.RegisterDomainRequest{
        Registration: &domainspb.Registration{
            Name:       fmt.Sprintf("%s/registrations/%s", parent, domaininfo.DomainName),
            DomainName: domaininfo.DomainName,
            DnsSettings: &domainspb.DnsSettings{
                DnsProvider: &domainspb.DnsSettings_CustomDns_{
                    CustomDns: &domainspb.DnsSettings_CustomDns{
                        NameServers: []string{
                            "ns-cloud-e1.googledomains.com",
                            "ns-cloud-e2.googledomains.com",
                            "ns-cloud-e3.googledomains.com",
                            "ns-cloud-e4.googledomains.com",
                        },
                    },
                },
            },
            ContactSettings: &dnscontact,
        },
        Parent:      parent,
        YearlyPrice: domaininfo.YearlyPrice,
    }

    if _, err := c.RegisterDomain(ctx, req); err != nil {
        return err
    }

    return nil
}


Conclusion

Vous avez maintenant configuré un petit site Web avec un domaine et un site statique sécurisé. De plus, vous devez disposer de tout le code nécessaire pour modifier ou étendre cette solution en fonction de votre environnement.