使用网域的静态托管

架构

“Static Hosting with Domain”是一个简单的静态网站创建工具,可创建一个简单的网站, 来为网站提供服务:

  • 存储 - 文件存储 - Cloud Storage
  • 网络 - 负载均衡 - Cloud Load Balancing
  • 网络 - DNS - Cloud DNS
  • 域名管理 - 注册商 - Cloud Domains

开始使用

点击以下链接,获取 Cloud Shell 中的源代码副本。一次 只需一个命令,即可启动 项目...

在 Cloud Shell 中打开

在 GitHub 上查看源代码


使用网域组件的静态托管

借助“带网域的静态托管”架构,您可以使用多种产品。 下面列出了这些组件,以及有关 包括指向相关视频、产品文档和 互动演示。
视频 文档 演示
Cloud Storage Cloud Storage 通过 http(s) 提供文件存储和图片公开传送服务。
Cloud DNS Cloud DNS 提供 DNS 管理功能,可让您使用 Google 现有的 DNS 基础架构运行自己的 DNS 基础架构。
Cloud Load Balancing 借助 Google Cloud 负载均衡器,您可以在存储桶前面放置负载均衡器,从而使用 SSL 证书、日志记录和监控功能。
Cloud 网域 借助 Cloud Domains,您可以像域名注册商一样购买域名,但购买域名后,您可以通过您的 Google Cloud 账号管理这些域名并处理结算。

脚本

安装脚本使用以 go 和 Terraform CLI 工具编写的可执行文件 选取一个空项目并在其中安装应用。输出应为 以及负载均衡 IP 地址的网址。

./main.tf

启用服务

默认情况下,Google Cloud 服务在项目中处于停用状态。要使用 此处的任何解决方案,我们都必须启用以下内容:

  • Cloud Domains - 域名注册
  • Cloud Storage - 托管静态文件
  • Cloud Compute - 提供对负载均衡器的访问权限。
  • Cloud DNS - 提供 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
}

创建 DNS 区域

创建 DNS 区域以管理记录、将记录指向负载均衡器、与域名注册商互动,以及将 DNS 请求提供给其他 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}"
}

创建 SSL 证书

https 协议请求需要 SSL 证书。这会生成一个 该负载均衡器将在稍后的命令中挂接到负载均衡器。

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

创建外部 IP 地址

用于将主机绑定到域名,并在互联网上进行常规通信。

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

创建存储桶

这会创建一个以网域命名的存储桶,然后使用适当的配置将该存储桶设置为 Web 服务器。最后,它会为网站复制简单模板。

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

设置负载均衡器

这会创建负载均衡器,并将存储桶设置为负载均衡器将提供访问权限的内容来源。

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

启用 HTTP

创建必要的网络规则,将负载均衡器上的端口 80 指向我们正在运行的服务。

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

启用 HTTPS

创建必要的网络规则,将负载均衡器上的端口 443 指向我们正在运行的服务。此外,还要正确关联证书。

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

设置 A 记录

在 Cloud DNS 中创建适当的规则,以便将域名解析为我们创建的 IP 地址。

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

查询网域可用性

获取所请求域名的可用性信息

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
}

查询域名所有权

获取当前用户是否拥有所请求网域的信息。

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
}

使用 Cloud Domains 注册域名

实际执行从注册商处购买域名的操作。

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
}


总结

现在,您已经设置了一个小型网站,其中包含域名和安全的静态网站。 此外,您应该拥有修改或扩展 解决方案。