El alojamiento estático con dominio es un creador de sitios web estáticos simple que crea un sitio simple con un bucket de almacenamiento para entregar el sitio web:
- Almacenamiento: Almacenamiento de archivos: Cloud Storage
- Redes: Balanceo de cargas: Cloud Load Balancer
- Redes - DNS - Cloud DNS
- Administración de dominios: Registrador: Cloud Domains
Comenzar
Haz clic en el siguiente vínculo para obtener una copia del código fuente en Cloud Shell. Una vez allí, un solo comando iniciará una copia de trabajo de la aplicación en tu proyecto.
Ver el código fuente en GitHub
Hosting estático con componentes de dominio
La arquitectura de hosting estático con dominio usa varios productos. A continuación, se enumeran los componentes, junto con más información sobre ellos, incluidos vínculos a videos relacionados, documentación del producto y explicaciones interactivas.Secuencias de comandos
La secuencia de comandos de instalación usa un ejecutable escrito en go
y herramientas de la CLI de Terraform para tomar un proyecto vacío e instalar la aplicación en él. El resultado debe ser una aplicación que funcione y una URL para la dirección IP del balanceador de cargas.
./main.tf
Habilitar servicios
Los servicios de Google Cloud están inhabilitados en un proyecto de forma predeterminada. Para usar cualquiera de las soluciones que se indican a continuación, debemos activar lo siguiente:
- Cloud Domains: Registro de dominios
- Cloud Storage: aloja los archivos estáticos
- Cloud Compute: Proporciona acceso a los balanceadores de cargas.
- Cloud DNS: Proporciona administración de 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 una zona de DNS
Crea una zona DNS para administrar registros, apuntarlos a balanceadores de cargas, interactuar con registradores de dominios y entregar solicitudes de DNS a otros servidores 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}"
}
Cómo crear un certificado SSL
Los certificados SSL son obligatorios para las solicitudes de protocolo HTTPS. Esto genera uno que se adjuntará al balanceador de cargas en un comando posterior.
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 una dirección IP externa
Se necesita para vincular un host al nombre de dominio y comunicarse en general en Internet.
resource "google_compute_global_address" "ip" {
project = var.project_id
name = "${local.basename}-ip"
ip_version = "IPV4"
}
Cree un bucket de almacenamiento
Esto crea un bucket con el nombre del dominio y, luego, lo configura con la configuración adecuada para que funcione como servidor web. Por último, copia la plantilla simple para el sitio.
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,
]
}
Cómo configurar un balanceador de cargas
Esto crea el balanceador de cargas y configura el bucket de almacenamiento como la fuente del contenido al que el balanceador de cargas proporcionará acceso.
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]
}
Habilita HTTP
Crea las reglas de red necesarias para apuntar el puerto 80 del balanceador de cargas al servicio que ejecutamos.
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]
}
Habilita HTTPS
Crea las reglas de red necesarias para que el puerto 443 del balanceador de cargas apunte al servicio que ejecutamos. También asocia el certificado correctamente.
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]
}
Cómo configurar un registro A
Crea la regla adecuada en Cloud DNS que hará que el nombre de dominio se resuelva en la dirección IP que creamos.
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
Consulta la disponibilidad del dominio
Obtiene información sobre la disponibilidad del dominio que se solicita.
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
}
Consulta la propiedad del dominio
Obtiene información sobre si el usuario actual es propietario del dominio solicitado o no.
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 un dominio con Cloud Domains
Realiza la operación para comprar el dominio al registrador.
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
}
Conclusión
Ahora tienes un pequeño sitio web configurado con un dominio y un sitio estático y seguro. Además, debes tener todo el código para modificar o extender esta solución para que se adapte a tu entorno.