跳转到内容
搜索文档

Ansible

最后更新 查看 MarkdownAgent 设置

Ansible 是一款能够大规模管理基础设施的软件工具。Ansible 是无代理的——它只需要能够 SSH 到目标系统并在目标系统上安装 Python 即可运行。

Ansible 与 Terraform 配合使用可简化 Cloudflare Tunnel 的设置过程。在本指南中,您将使用 Terraform 在 Google Cloud 上部署 SSH 服务器并创建本地管理的隧道,从而使该服务器可通过互联网访问。Terraform 将自动运行 Ansible playbook 并在服务器上安装配置 cloudflared

前提条件

要完成本指南中的步骤,您需要:

1. 安装 Ansible

请参阅 Ansible 安装说明

2. (可选)创建 SSH 密钥对

Terraform 和 Ansible 需要未加密的 SSH 密钥来连接到 GCP 服务器。如果您还没有密钥,可以按如下方式生成:

  1. 打开终端并输入以下命令:

    ssh-keygen -t rsa -f ~/.ssh/gcp_ssh -C <username in GCP>
  2. 当提示输入密码短语(passphrase)时,按两次 Enter 键将其留空。Terraform 无法解码加密的私钥。

将生成两个文件:包含私钥的 gcp_ssh 和包含公钥的 gcp_ssh.pub

3. 创建配置目录

  1. 为您的 Terraform 和 Ansible 配置文件创建一个文件夹:

    mkdir ansible-tunnel
  2. 切换到新目录:

    cd ansible-tunnel

4. 创建 Terraform 配置文件

定义输入变量

以下变量将被传递到您的 GCP 和 Cloudflare 配置中。

  1. 在您的配置目录中,创建一个 .tf 文件:

    touch variables.tf
  2. 在文本编辑器中打开该文件并复制并粘贴以下内容:

    # GCP 变量
    variable "gcp_project_id" {
      description = "Google Cloud Platform (GCP) 项目 ID"
      type        = string
    }
    
    variable "zone" {
      description = "GCP VM 实例的地理区域"
      type        = string
    }
    
    variable "machine_type" {
      description = "GCP VM 实例的机器类型"
      type        = string
    }
    
    # Cloudflare 变量
    variable "cloudflare_zone" {
      description = "用于向互联网公开 GCP VM 实例的域名"
      type        = string
    }
    
    variable "cloudflare_zone_id" {
      description = "您域的区域 (Zone) ID"
      type        = string
    }
    
    variable "cloudflare_account_id" {
      description = "您 Cloudflare 账户(account)的账户 ID"
      type        = string
      sensitive   = true
    }
    
    variable "cloudflare_email" {
      description = "您 Cloudflare 账户(account)的电子邮件地址"
      type        = string
      sensitive   = true
    }
    
    variable "cloudflare_token" {
      description = "Cloudflare API 令牌"
      type        = string
      sensitive   = true
    }

为变量赋值

  1. 在您的配置目录中,创建一个 .tfvars 文件:

    touch terraform.tfvars

    如果该文件命名为 terraform.tfvars,Terraform 将自动使用这些变量,否则需要手动传入该变量文件。

  2. 将以下变量添加到 terraform.tfvars 中。请确保使用您自己的值来修改示例。

    cloudflare_zone           = "example.com"
    cloudflare_zone_id        = "023e105f4ecef8ad9ca31a8372d0c353"
    cloudflare_account_id     = "372e67954025e0ba6aaa6d586b9e0b59"
    cloudflare_email          = "user@example.com"
    cloudflare_token          = "y3AalHS_E7Vabk3c3lX950F90_Xl7YtjSlzyFn_X"
    gcp_project_id            = "testvm-123"
    zone                      = "us-central1-a"
    machine_type              = "e2-medium"

配置 Terraform 提供程序(providers)

您需要声明用于配置基础设施的提供程序(providers)

  1. 在您的配置目录中,创建一个 .tf file:

    touch providers.tf
  2. 将以下提供程序添加到 providers.tfrandom 提供程序用于生成隧道密钥(secret)。

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

配置 Cloudflare 资源

以下配置将修改您的 Cloudflare 账户中的设置。

  1. In your configuration directory, create a .tf file:

    touch Cloudflare-config.tf
  2. 将以下资源添加到 Cloudflare-config.tf

    
    # 为 GCP VM 创建一个新的远程托管隧道。
    resource "cloudflare_zero_trust_tunnel_cloudflared" "gcp_tunnel" {
    	account_id    = var.cloudflare_account_id
    	name          = "Ansible GCP tunnel"
    	config_src    = "cloudflare"
    }
    
    # 读取用于在服务器上运行隧道的令牌。
    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
    }
    
    # 创建将 http_app.${var.cloudflare_zone} 路由到隧道的 CNAME 记录。
    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
    }
    
    # 为隧道配置已发布应用程序,以进行无客户端访问。
    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://localhost:80"
    			},
    			{
    				service  = "http_status:404"
    			}
    		]
    	}
    }

配置 GCP 资源

以下配置定义了 GCP 虚拟机(VM)的规格,并在该机器上安装了 Python3。Python3 允许 Ansible 配置 GCP 实例,而无需在引导时运行启动脚本
  1. 在您的配置目录中,创建一个 .tf file:

    touch GCP-config.tf
  2. 在文本编辑器中打开该文件,然后复制并粘贴以下示例。请务必插入您自己的 GCP 用户名和 SSH 密钥对。

    # 为 GCP VM 选择操作系统。
    data "google_compute_image" "image" {
    family  = "ubuntu-2204-lts"
    project = "ubuntu-os-cloud"
    }
    
    # 设置 GCP VM 实例。
    resource "google_compute_instance" "http_server" {
    name         = "ansible-inst"
    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 {
        // 临时 IP
        }
    }
    scheduling {
        preemptible = true
        automatic_restart = false
    }
    
    // 在 VM 上安装 Python3。
    provisioner "remote-exec" {
        inline = [
        "sudo apt update", "sudo apt install python3 -y",  "echo Done!"
        ]
        connection {
        host = self.network_interface.0.access_config.0.nat_ip
        user = "<username in GCP>"
        type = "ssh"
        private_key= file("<path to private key>")
        }
    }
    provisioner "local-exec" {
        // 如果指定了 SSH 密钥和用户,添加 `--private-key <path to private key> -u var.name`
        command = "ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook -u <username in GCP> --private-key <path to private key> -i ${self.network_interface.0.access_config.0.nat_ip}, playbook.yml"
    }
    
    metadata = {
        cf-email     = var.cloudflare_email
        cf-zone      = var.cloudflare_zone
        ssh-keys     = "<username in GCP>:${file("<path to public key>")}"
    }
    depends_on = [
        local_file.tf_ansible_vars_file
    ]
    }

将变量导出到 Ansible

以下 Terraform 资源将隧道令牌(tunnel token)和其他变量导出到 tf_ansible_vars_file.yml。Ansible 将使用该隧道令牌在服务器上配置并运行 cloudflared
  1. 在您的配置目录中,创建一个新的 tf 文件:

    touch export.tf
  2. 将以下内容复制并粘贴到 export.tf 中:

    resource "local_file" "tf_ansible_vars_file" {
    	content = <<-DOC
    		# 包含来自 Terraform 变量值的 Ansible vars_file。
    		tunnel_id: ${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.id}
    		tunnel_name: ${cloudflare_zero_trust_tunnel_cloudflared.gcp_tunnel.name}
    		tunnel_token: ${data.cloudflare_zero_trust_tunnel_cloudflared_token.gcp_tunnel_token.token}
    		DOC
    
    	filename = "./tf_ansible_vars_file.yml"
    }

5. 创建 Ansible playbook

Ansible playbook 是声明 Ansible 将要部署的配置的 YAML 文件。

  1. 创建一个新的 .yml 文件:

    touch playbook.yml
  2. 在文本编辑器中打开该文件,然后复制并粘贴以下内容:

---
- hosts: all
  become: yes
  # 将隧道变量导入到 VM。
  vars_files:
    - ./tf_ansible_vars_file.yml
  # 在 VM 上执行以下命令。
  tasks:
    - name: 下载 cloudflared Linux 包。
      shell: wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
    - name: 解包 cloudflared。
      shell: sudo dpkg -i cloudflared-linux-amd64.deb
    - name: 将隧道安装为 systemd 服务。
      shell: "cloudflared service install {{ tunnel_token }}"
    - name: 启动隧道。
      systemd:
        name: cloudflared
        state: started
        enabled: true
        masked: no
    - name: 在端口 80 上部署一个示例 Apache Web 服务器。
      shell: apt update && apt -y install apache2
    - name: 编辑默认的 Apache 索引文件。
      copy:
        dest: /var/www/html/index.html
        content: |
          <!DOCTYPE html>
          <html>
          <body>
            <h1>Hello Cloudflare!</h1>
            <p>This page was created for a Cloudflare demo.</p>
          </body>
          </html>

关键字(Keywords)定义了 Ansible 将如何执行配置。在上述示例中,vars_files 关键字指定了存储变量定义的位置,而 tasks 关键字指定了 Ansible 将执行的操作。

模块(Modules)指定了要完成的任务。在此示例中,copy 模块会创建一个文件并用内容填充它。

6. 部署配置

创建配置文件后,您可以通过 Terraform 部署它们。在运行 ansible-playbook 命令时,Ansible 部署会在 Terraform 部署内发生。

  1. 初始化您的配置目录:

    terraform init
  2. (可选)预览将要创建的所有内容:

    terraform plan
  3. 部署配置:

    terraform apply
GCP 实例和隧道可能需要几分钟才能上线。您可以在 Cloudflare 仪表板中的 Networking > Tunnels 下查看您的新隧道。

7. 测试连接

要进行测试,请打开浏览器并访问 http://http_app.<CLOUDFLARE_ZONE>.com(例如 http_app.example.com)。您应该会看到 Hello Cloudflare! 测试页面。

这篇文档对您有帮助吗?