Hébergement statique avec domaine

Architecture

Static Hosting with Domain est un simple créateur de sites Web statiques, qui rend un site simple à l'aide d'un bucket Cloud Storage pour desservir le site Web:

  • Stockage – Stockage de fichiers – Cloud Storage
  • Mise en réseau – Équilibrage de charge – Équilibreur de charge cloud
  • Mise en réseau – DNS – Cloud DNS
  • Gestion de domaines – Bureau d'enregistrement – Cloud Domains

Premiers pas

Cliquez sur le lien suivant pour obtenir une copie du code source dans Cloud Shell. Une fois une seule commande lance une copie de travail de l'application projet...

Ouvrir dans Cloud Shell

Afficher le code source sur GitHub


Hébergement statique avec composants de domaine

L'architecture d'hébergement statique avec domaine utilise plusieurs produits. Voici la liste des composants, ainsi que des informations complémentaires sur les des composants, y compris des liens vers des vidéos similaires, la documentation du produit et des tutoriels interactifs.
Vidéo Docs Tutoriels
Cloud Storage Cloud Storage permet de stocker des fichiers et de diffuser des images au public via HTTP(S).
Cloud DNS Cloud DNS assure la 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 L'équilibreur de charge Google Cloud vous permet de placer un équilibreur de charge devant le bucket de stockage, ce qui vous permet d'utiliser des certificats SSL, ainsi que Logging et Monitoring.
Cloud Domains Cloud Domains vous permet d'acheter des domaines en agissant comme un service d'enregistrement de noms de domaine. Une fois cette opération effectuée, vous pouvez les gérer et gérer la facturation via votre compte Google Cloud.

Scripts

Le script d'installation utilise un exécutable écrit dans go et les outils de la CLI Terraform pour prendre un projet vide et y installer l'application. La sortie doit être une une application opérationnelle 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 présentées ici pour 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 la gestion 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, en les pointant vers des équilibreurs de charge ; interagissant avec les services d’enregistrement de noms de domaine et en envoyant des requêtes DNS à d’autres de 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

Des certificats SSL sont requis pour les requêtes de protocole HTTPS. Cela en génère un qui sera attaché à 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écessité de lier un hôte au nom de domaine et de communiquer en général sur le Internet.

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

Créer un bucket de stockage

Cette commande crée un bucket nommé d'après le domaine, puis le configure la configuration appropriée pour agir en tant que serveur Web. Enfin, il copie les requêtes 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,
    ]
}

Équilibreur de charge Stand Up

Cela crée l'équilibreur de charge et configure le bucket Storage comme source le 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

Il crée les règles de mise en 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

Il crée les règles de mise en réseau nécessaires pour faire pointer le port 443 de l'équilibreur de charge vers le service que nous exécutons. Associe également correctement le certificat.

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

Il crée la règle appropriée dans Cloud DNS qui associe le nom de domaine à l'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é du domaine

Récupère 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

Récupère des informations indiquant si l'utilisateur actuel est propriétaire ou non 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

Elle 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 disposez maintenant d'un petit site Web, d'un domaine et d'un site statique sécurisé. En outre, vous devez disposer de tout le code nécessaire pour modifier ou étendre adaptée à votre environnement.