← Cloudflare One / cloudflare-one / networks / connectors / cloudflare-tunnel / deployment-guides
Terraform
Terraform ↗ это программный инструмент для управления инфраструктурой как кодом, который позволяет развёртывать сервисы разных провайдеров с помощью единого синтаксиса конфигурации. При создании файла конфигурации Terraform вы описываете конечное состояние конфигурации, а не пошаговую процедуру его достижения. Это позволяет легко развёртывать, изменять и управлять своими туннелями наряду с остальной инфраструктурой.
В этом руководстве вы используете Terraform, чтобы развернуть:
- Виртуальная машина Google Cloud Project (GCP), на которой выполняется тестовый HTTP-сервер
- Cloudflare Tunnel, который делает сервер доступным через интернет
- Политика Cloudflare Access, определяющая, кто может подключаться к серверу
Предварительные требования
Чтобы выполнить следующую процедуру, вам потребуется:
- Google Cloud Project ↗
- Зона на Cloudflare
- Включено вход по одноразовому PIN-коду или подключили поставщик удостоверений
1. Установите Terraform
См. Руководство по установке Terraform ↗ для вашей операционной системы.
2. Установите gcloud CLI
-
Установите gcloud CLI ↗ чтобы Terraform мог взаимодействовать с вашей учётной записью GCP.
-
Аутентифицируйтесь через CLI, выполнив команду:
gcloud auth application-default login
3. Создайте токен Cloudflare API
Создание API-токена чтобы Terraform мог взаимодействовать с вашей учётной записью Cloudflare. Как минимум токен должен включать следующие разрешения:
| Type | Элемент | Разрешение |
|---|---|---|
| Аккаунт | Cloudflare Tunnel | Изменить |
| Аккаунт | Access: приложения и политики | Изменить |
| Zone | DNS | Изменить |
4. Создайте каталог конфигурации
Terraform работает через рабочий каталог, содержащий файлы конфигурации. Вы можете хранить конфигурацию в нескольких файлах или в одном: Terraform обработает все файлы конфигурации в каталоге так, как если бы они были одним документом.
-
Создайте папку для конфигурации Terraform:
mkdir cloudflare-tf -
Перейдите в каталог:
cd cloudflare-tf
5. Создайте файлы конфигурации Terraform
Определите входные переменные
Указанные ниже переменные будут переданы в конфигурацию GCP и Cloudflare.
-
В своём каталоге конфигурации создайте
.tfфайле:touch variables.tf -
Откройте файл в текстовом редакторе и скопируйте туда следующее:
# GCP variables variable "gcp_project_id" { description = "Google Cloud Platform (GCP) project ID" type = string } variable "zone" { description = "Geographical zone for the GCP VM instance" type = string } variable "machine_type" { description = "Machine type for the GCP VM instance" type = string } # Cloudflare variables variable "cloudflare_zone" { description = "Domain used to expose the GCP VM instance to the Internet" type = string } variable "cloudflare_zone_id" { description = "Zone ID for your domain" type = string } variable "cloudflare_account_id" { description = "Account ID for your Cloudflare account" type = string sensitive = true } variable "cloudflare_email" { description = "Email address for your Cloudflare account" type = string sensitive = true } variable "cloudflare_token" { description = "Cloudflare API token" type = string sensitive = true }
Назначить значения переменным
-
В своём каталоге конфигурации создайте
.tfvarsфайле:touch terraform.tfvarsTerraform автоматически использует эти переменные, если файл называется
terraform.tfvars, иначе файл переменных нужно будет передавать вручную. -
Добавьте следующие переменные в
terraform.tfvars. Обязательно замените в примере значения на свои.cloudflare_zone = "example.com" cloudflare_zone_id = "023e105f4ecef8ad9ca31a8372d0c353" cloudflare_account_id = "372e67954025e0ba6aaa6d586b9e0b59" cloudflare_email = "[email protected]" cloudflare_token = "y3AalHS_E7Vabk3c3lX950F90_Xl7YtjSlzyFn_X" gcp_project_id = "testvm-123" zone = "us-central1-a" machine_type = "e2-medium"
Настройте провайдеры Terraform
Вам нужно будет объявить поставщики ↗ используется для развёртывания инфраструктуры.
-
В своём каталоге конфигурации создайте
.tfфайле:touch providers.tf -
Добавьте следующих поставщиков в
providers.tf.randomпоставщик используется для генерации секрета туннеля.terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" version = ">= 5.8.2" } google = { source = "hashicorp/google" } } required_version = ">= 1.2" } # Providers provider "cloudflare" { api_token = var.cloudflare_token } provider "google" { project = var.gcp_project_id } provider "random" { }terraform { required_providers { cloudflare = { source = "cloudflare/cloudflare" version = ">= 4.40.0, < 5.0.0" } google = { source = "hashicorp/google" } random = { source = "hashicorp/random" } } required_version = ">= 1.2" } # Providers provider "cloudflare" { api_token = var.cloudflare_token } provider "google" { project = var.gcp_project_id } provider "random" { }
Настройте ресурсы Cloudflare
Следующая конфигурация изменит настройки вашего аккаунта Cloudflare.
-
В своём каталоге конфигурации создайте
.tfфайле:touch Cloudflare-config.tf -
Добавьте следующие ресурсы в
Cloudflare-config.tf:# Creates a new remotely-managed tunnel for the GCP VM. resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" { account_id = var.cloudflare_account_id name = "Terraform GCP tunnel" config_src = "cloudflare" } # Reads the token used to run the tunnel on the server. data "cloudflare_zero_trust_tunnel_cloudflared_token" "gcp_tunnel_token" { account_id = var.cloudflare_account_id tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id } # Creates the CNAME record that routes http_app.${var.cloudflare_zone} to the tunnel. resource "cloudflare_dns_record" "http_app" { zone_id = var.cloudflare_zone_id name = "http_app" content = "${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id}.cfargotunnel.com" type = "CNAME" ttl = 1 proxied = true } # Configures tunnel with a published application for clientless access. resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" { tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id account_id = var.cloudflare_account_id config = { ingress = [ { hostname = "http_app.${var.cloudflare_zone}" service = "http://httpbin:80" }, { service = "http_status:404" } ] } } # (Optional) Routes internal IP of GCP instance through the tunnel for private network access using WARP. resource "cloudflare_zero_trust_tunnel_cloudflared_route" "example_tunnel_route" { account_id = var.cloudflare_account_id tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id network = google_compute_instance.http_server.network_interface.0.network_ip comment = "Example tunnel route" } # Creates a reusable Access policy. resource "cloudflare_zero_trust_access_policy" "allow_emails" { account_id = var.cloudflare_account_id name = "Allow email addresses" decision = "allow" include = [ { email = { email = var.cloudflare_email } }, { email_domain = { domain = "@example.com" } } ] } # Creates an Access application to control who can connect to the public hostname. resource "cloudflare_zero_trust_access_application" "http_app" { account_id = var.cloudflare_account_id type = "self_hosted" name = "Access application for http_app.${var.cloudflare_zone}" domain = "http_app.${var.cloudflare_zone}" policies = [ { id = cloudflare_zero_trust_access_policy.allow_emails.id precedence = 1 } ] }# Generates a 32-byte secret for the tunnel. resource "random_bytes" "tunnel_secret" { byte_length = 32 } # Creates a new remotely-managed tunnel for the GCP VM. resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" { account_id = var.cloudflare_account_id name = "Terraform GCP tunnel" secret = random_bytes.tunnel_secret.base64 } # Creates the CNAME record that routes http_app.${var.cloudflare_zone} to the tunnel. resource "cloudflare_record" "http_app" { zone_id = var.cloudflare_zone_id name = "http_app" content = "${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.cname}" type = "CNAME" proxied = true } # Configures tunnel with a published application for clientless access. resource "cloudflare_zero_trust_tunnel_cloudflared_config" "gcp_tunnel_config" { tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id account_id = var.cloudflare_account_id config { ingress_rule { hostname = "${cloudflare_record.http_app.hostname}" service = "http://httpbin:80" } ingress_rule { service = "http_status:404" } } } # (Optional) Route internal IP of GCP instance through the tunnel for private network access using WARP. resource "cloudflare_zero_trust_tunnel_route" "example_tunnel_route" { account_id = var.cloudflare_account_id tunnel_id = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id network = google_compute_instance.http_server.network_interface.0.network_ip comment = "Example tunnel route" } # Creates an Access application to control who can connect to the public hostname. resource "cloudflare_zero_trust_access_application" "http_app" { account_id = var.cloudflare_account_id name = "Access application for http_app.${var.cloudflare_zone}" domain = "http_app.${var.cloudflare_zone}" } # Creates a (legacy) Access policy for the Access application. resource "cloudflare_zero_trust_access_policy" "allow_emails" { application_id = cloudflare_zero_trust_access_application.http_app.id account_id = var.cloudflare_account_id name = "Example policy for http_app.${var.cloudflare_zone}" precedence = "1" decision = "allow" include { email = [var.cloudflare_email] } }
Чтобы узнать больше об этих ресурсах, см. документация провайдера Cloudflare ↗.
Настройте ресурсы GCP
Следующая конфигурация задаёт характеристики виртуальной машины GCP и настраивает сценарий запуска, который выполняется при загрузке.
-
В своём каталоге конфигурации создайте
.tfфайле:touch GCP-config.tf -
Добавьте следующее содержимое в
GCP-config.tf:# OS the server will use data "google_compute_image" "image" { family = "ubuntu-2204-lts" project = "ubuntu-os-cloud" } # GCP Instance resource resource "google_compute_instance" "http_server" { name = "test" machine_type = var.machine_type zone = var.zone tags = [] boot_disk { initialize_params { image = data.google_compute_image.image.self_link } } network_interface { network = "default" access_config { //Ephemeral IP } } // Optional config to make instance ephemeral /* scheduling { preemptible = true automatic_restart = false } */ // Pass the tunnel token to the GCP server so that the server can install and run the tunnel upon startup. metadata_startup_script = templatefile("./install-tunnel.tftpl", { tunnel_token = data.cloudflare_zero_trust_tunnel_cloudflared_token.gcp_tunnel_token.token }) }# OS the server will use data "google_compute_image" "image" { family = "ubuntu-2204-lts" project = "ubuntu-os-cloud" } # GCP Instance resource resource "google_compute_instance" "http_server" { name = "test" machine_type = var.machine_type zone = var.zone tags = [] boot_disk { initialize_params { image = data.google_compute_image.image.self_link } } network_interface { network = "default" access_config { //Ephemeral IP } } // Optional config to make instance ephemeral /* scheduling { preemptible = true automatic_restart = false } */ // Pass the tunnel token to the GCP server so that the server can install and run the tunnel upon startup. metadata_startup_script = templatefile("./install-tunnel.tftpl", { tunnel_token = cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.tunnel_token }) }
Создать скрипт запуска
Следующий скрипт устанавливает cloudflared и запустите туннель как службу. В этом примере также устанавливается легковесное HTTP-приложение, которое можно использовать для проверки подключения.
-
В своём каталоге конфигурации создайте файл шаблона Terraform:
touch install-tunnel.tftpl -
Откройте файл в текстовом редакторе и скопируйте туда следующий bash-скрипт:
# Script to install Cloudflare Tunnel and Docker resources # Docker configuration cd /tmp sudo apt-get install software-properties-common # Retrieving the docker repository for this OS curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" # The OS is updated and docker is installed sudo apt update -y && sudo apt upgrade -y sudo apt install docker docker-compose -y # Add the HTTPBin application and run it on localhost:8080. cat > /tmp/docker-compose.yml << "EOF" version: '3' services: httpbin: image: kennethreitz/httpbin restart: always container_name: httpbin ports: - 8080:80 cloudflared: image: cloudflare/cloudflared:latest restart: always container_name: cloudflared command: tunnel run --token ${tunnel_token} EOF cd /tmp sudo docker-compose up -d
6. Разверните Terraform
Чтобы развернуть файлы конфигурации:
-
Инициализируйте каталог конфигурации:
terraform init -
Предварительный просмотр всего, что будет создано:
terraform plan -
Примените конфигурацию:
terraform apply
Активация экземпляра GCP и туннеля может занять несколько минут. Просмотреть новый туннель можно в Панель управления Cloudflare ↗ в разделе Сеть > Tunnels, а также приложение и политику Access в разделе Zero Trust > Контроль доступа > Приложения. Новые DNS-записи доступны на DNS-записи страница.
7. Проверьте подключение
-
В Сеть > Tunnels, убедитесь, что ваш туннель активен.
-
В Контроль доступа > Приложения, убедитесь, что ваш адрес электронной почты Cloudflare разрешён политикой Access.
-
С любого устройства откройте браузер и перейдите по адресу
http_app.<CLOUDFLARE_ZONE>(например,http_app.example.com).Если вы недавно не выполняли вход, откроется страница входа Access.
-
Войдите с помощью своей электронной почты Cloudflare.
Вы должны увидеть HTTPBin ↗ домашняя страница.