Hosting statico con dominio

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

Architettura

Static Hosting with Domain è un semplice creatore di siti web statici che crea un sito semplice utilizzando un bucket di archiviazione per la gestione del sito web.

  • Spazio di archiviazione - Archiviazione di file - Cloud Storage
  • Networking - Bilanciamento del carico - Bilanciatore del carico Cloud
  • Networking - DNS - Cloud DNS
  • Gestione del dominio - Registrar - Cloud Domains

Inizia

Fai clic sul seguente link che rimanda a una copia del codice sorgente in Cloud Shell. Una volta eseguito l'accesso, un singolo comando genererà una copia funzionante dell'applicazione nel tuo progetto.

Apri in Cloud Shell

Visualizza il codice sorgente su GitHub


Hosting statico con componenti di dominio

L'architettura di hosting statico con dominio utilizza diversi prodotti. Di seguito sono elencati i componenti, insieme a ulteriori informazioni sui componenti, inclusi i link ai video correlati, la documentazione del prodotto e le procedure dettagliate interattive.
Video Documenti Procedure dettagliate
Cloud Storage Cloud Storage offre archiviazione di file e pubblicazione pubblica di immagini su http(s).
Cloud DNS Cloud DNS offre la gestione DNS, che ti consente di eseguire la tua infrastruttura DNS utilizzando l'infrastruttura DNS esistente di Google.
Cloud Load Balancing Il bilanciatore del carico Google Cloud ti consente di posizionare un bilanciatore del carico davanti al bucket di archiviazione, consentendoti di utilizzare i certificati SSL, Logging e Monitoring.
Domini Cloud Cloud Domains ti consente di acquistare domini, agendo come un registrar di domini, ma una volta fatto, puoi gestirli e gestire la fatturazione tramite il tuo account Google Cloud.

Script

Lo script di installazione utilizza un file eseguibile scritto in strumenti go dell'interfaccia a riga di comando di Terraform e Terraform per eseguire un progetto vuoto e installare l'applicazione al suo interno. L'output dovrebbe essere un'applicazione funzionante e un URL per l'indirizzo IP di bilanciamento del carico.

./main.tf

Attiva i servizi

I servizi Google Cloud sono disabilitati per impostazione predefinita in un progetto. Per utilizzare una qualsiasi delle soluzioni qui, dobbiamo attivare quanto segue:

  • Cloud Domains - Registrazione del dominio
  • Cloud Storage: hosting dei file statici
  • Cloud Compute: fornisce l'accesso ai bilanciatori del carico.
  • Cloud DNS: offre la gestione del 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
}

Crea zona DNS

Crea una zona DNS per la gestione dei record, indirizzandoli verso i bilanciatori del carico, interagendo con i registrar di domini e erogando le richieste DNS ad altri server 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}"
}

Crea certificato SSL

Per le richieste di protocollo https sono necessari i certificati SSL. Questo genera uno che verrà collegato al bilanciatore del carico in un comando successivo.

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
    }
}

Crea indirizzo IP esterno

necessaria per associare un host al nome di dominio e comunicare in generale su Internet.

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

Crea bucket di archiviazione

Viene creato un bucket denominato in base al dominio, quindi viene configurato con la configurazione adeguata per agire come un server web. Infine, copia il modello semplice per il sito

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,
    ]
}

Bilanciatore del carico

Questo crea il bilanciatore del carico e configura il bucket di archiviazione come l'origine dei contenuti a cui il bilanciatore del carico fornirà l'accesso.

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]
}

Attiva HTTP

Crea le regole di networking necessarie per indirizzare la porta 80 sul bilanciatore del carico al servizio in esecuzione.

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]
}

Attiva HTTPS

Crea le regole di networking necessarie per indirizzare la porta 443 sul bilanciatore del carico al servizio in esecuzione. Inoltre, associa il certificato correttamente.

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]
}

Imposta un record

Crea la regola corretta in Cloud DNS che consentirà la risoluzione del nome di dominio nell'indirizzo IP che abbiamo creato.

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

Disponibilità del dominio della query

Recupera le informazioni sulla disponibilità del dominio richiesto

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
}

Esegui query su proprietà dominio

Recupera le informazioni che indicano se l'utente corrente possiede o meno il dominio richiesto.

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
}

Registra dominio con Cloud Domains

Di fatto esegue l'operazione per acquistare il dominio dal registrar.

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
}


Conclusione

Ora hai una configurazione del sito web di piccole dimensioni con un dominio e un sito statico e sicuro. Inoltre, dovresti avere tutto il codice per modificare o estendere questa soluzione in base all'ambiente.