Ansible
Ansibleは、インフラストラクチャの大規模管理を可能にするソフトウェアツールです。Ansibleはエージェントレスであり、機能するために必要なのは、ターゲットへのSSH接続とターゲットにインストールされたPythonだけです。
AnsibleはTerraformと連携して、Cloudflare Tunnelのセットアッププロセスを効率化します。このガイドでは、Terraformを使用してGoogle CloudにSSHサーバーをデプロイし、サーバーをインターネット上で利用可能にするローカル管理トンネルを作成します。Terraformは自動的に、サーバー上にcloudflaredをインストールおよび構成するAnsibleプレイブックを実行します。
このガイドの手順を完了するには、以下が必要です:
- Google Cloudプロジェクト ↗とGCP CLIのインストールと認証 ↗。
- Terraformの基本知識とTerraformのインストール ↗。
- Cloudflareのゾーン。
Cloudflare TunnelおよびDNSの権限を持つCloudflare APIトークン。
Ansibleのインストール手順 ↗を参照してください。
TerraformとAnsibleは、GCPサーバーに接続するために暗号化されていないSSHキーを必要とします。まだキーを持っていない場合は、以下の手順で生成できます:
-
ターミナルを開き、次のコマンドを入力します:
Terminal window ssh-keygen -t rsa -f ~/.ssh/gcp_ssh -C <username in GCP> -
パスフレーズの入力を求められたら、Enterを2回押して空白のままにします。Terraformは暗号化された秘密鍵をデコードできません。
2つのファイルが生成されます:gcp_ssh(秘密鍵を含む)とgcp_ssh.pub(公開鍵を含む)。
-
TerraformとAnsibleの設定ファイル用のフォルダーを作成します:
Terminal window mkdir ansible-tunnel -
新しいディレクトリに移動します:
Terminal window cd ansible-tunnel
The following variables will be passed into your GCP and Cloudflare configuration.
-
In your configuration directory, create a
.tffile:Terminal window touch variables.tf -
Open the file in a text editor and copy and paste the following:
# GCP variablesvariable "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 variablesvariable "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 = stringsensitive = true}variable "cloudflare_email" {description = "Email address for your Cloudflare account"type = stringsensitive = true}variable "cloudflare_token" {description = "Cloudflare API token created at https://dash.cloudflare.com/profile/api-tokens"type = stringsensitive = true}
-
In your configuration directory, create a
.tfvarsfile:Terminal window touch terraform.tfvarsTerraform will automatically use these variables if the file is named
terraform.tfvars, otherwise the variable file will need to be manually passed in. -
Add the following variables to
terraform.tfvars. Be sure to modify the example with your own values.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"
インフラストラクチャをプロビジョニングするために使用されるプロバイダー ↗を宣言する必要があります。
-
設定ディレクトリ内に
.tfファイルを作成します:Terminal window touch providers.tf -
providers.tfに以下のプロバイダーを追加します。randomプロバイダーはトンネルの秘密を生成するために使用されます。terraform {required_providers {cloudflare = {source = "cloudflare/cloudflare"}google = {source = "hashicorp/google"}random = {source = "hashicorp/random"}}required_version = ">= 0.13"}# プロバイダーprovider "cloudflare" {api_token = var.cloudflare_token}provider "google" {project = var.gcp_project_id}provider "random" {}
以下の設定は、Cloudflareアカウントの設定を変更します。
-
設定ディレクトリ内に
.tfファイルを作成します:Terminal window touch Cloudflare-config.tf -
Cloudflare-config.tfに以下のリソースを追加します:# トンネル用の64文字の秘密を生成します。# `random_password`を使用すると、結果は機密として扱われ、コンソール出力には表示されません。参照:https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/passwordresource "random_password" "tunnel_secret" {length = 64}# GCP VM用の新しいローカル管理トンネルを作成します。resource "cloudflare_tunnel" "auto_tunnel" {account_id = var.cloudflare_account_idname = "Ansible GCP tunnel"secret = base64sha256(random_password.tunnel_secret.result)}# ssh_app.${var.cloudflare_zone}をトンネルにルーティングするCNAMEレコードを作成します。resource "cloudflare_record" "ssh_app" {zone_id = var.cloudflare_zone_idname = "ssh_app"value = "${cloudflare_argo_tunnel.auto_tunnel.id}.cfargotunnel.com"type = "CNAME"proxied = true}
以下の設定は、GCP仮想マシンの仕様を定義し、マシンにPython3をインストールします。Python3は、起動時にスタートアップスクリプトを実行する代わりに、AnsibleがGCPインスタンスを構成できるようにします。
-
設定ディレクトリ内に
.tfファイルを作成します:Terminal window touch GCP-config.tf -
テキストエディタでファイルを開き、以下の例をコピーして貼り付けます。自分のGCPユーザー名とSSHキーのペアを挿入してください。
# GCP VMのOSを選択します。data "google_compute_image" "image" {family = "ubuntu-minimal-2004-lts"project = "ubuntu-os-cloud"}# GCP VMインスタンスをセットアップします。resource "google_compute_instance" "origin" {name = "ansible-inst"machine_type = var.machine_typezone = var.zonetags = []boot_disk {initialize_params {image = data.google_compute_image.image.self_link}}network_interface {network = "default"access_config {// 一時IP}}scheduling {preemptible = trueautomatic_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_ipuser = "<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_emailcf-zone = var.cloudflare_zonessh-keys = "<username in GCP>:${file("<path to public key>")}"}depends_on = [local_file.tf_ansible_vars_file]}
以下のTerraformリソースは、トンネルIDやその他の変数をtf_ansible_vars_file.ymlにエクスポートします。Ansibleはこのデータを使用して、サーバー上でcloudflaredを構成および実行します。
-
設定ディレクトリ内に新しい
tfファイルを作成します:Terminal window touch export.tf -
export.tfに以下の内容をコピーして貼り付けます:resource "local_file" "tf_ansible_vars_file" {content = <<-DOC# Terraformからの変数値を含むAnsible vars_file。tunnel_id: ${cloudflare_argo_tunnel.auto_tunnel.id}account: ${var.cloudflare_account_id}tunnel_name: ${cloudflare_argo_tunnel.auto_tunnel.name}secret: ${random_id.tunnel_secret.b64_std}zone: ${var.cloudflare_zone}DOCfilename = "./tf_ansible_vars_file.yml"}
Ansibleプレイブックは、Ansibleがデプロイする構成を宣言するYAMLファイルです。
-
新しい
.ymlファイルを作成します:Terminal window touch playbook.yml -
テキストエディタでファイルを開き、以下の内容をコピーして貼り付けます:
---- 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: cloudflaredサービスディレクトリを作成します。 shell: mkdir -p /etc/cloudflared/ - name: cloudflaredの設定ファイルを作成し、トンネルのイングレスルールを定義します。 copy: dest: "/etc/cloudflared/config.yml" content: | tunnel: "{{ tunnel_id }}" credentials-file: /etc/cloudflared/cert.json logfile: /var/log/cloudflared.log loglevel: info ingress: - hostname: "ssh_app.{{ zone }}" service: ssh://localhost:22 - service: http_status:404 - name: cloudflaredのトンネル認証情報ファイルを作成します。 copy: dest: "/etc/cloudflared/cert.json" content: | { "AccountTag" : "{{ account | quote }}", "TunnelID" : "{{ tunnel_id | quote }}", "TunnelName" : "{{ tunnel_name | quote }}", "TunnelSecret" : "{{ secret | quote }}" } - name: トンネルをsystemdサービスとしてインストールします。 shell: cloudflared service install - name: トンネルを開始します。 systemd: name: cloudflared state: started enabled: true masked: noキーワード ↗は、Ansibleが構成を実行する方法を定義します。上記の例では、vars_filesキーワードは変数定義が保存されている場所を指定し、tasksキーワードはAnsibleが実行するアクションを指定します。
モジュール ↗は、完了すべきタスクを指定します。この例では、copyモジュールがファイルを作成し、その内容を埋め込みます。
構成ファイルを作成したら、Terraformを通じてデプロイできます。Ansibleのデプロイは、ansible-playbookコマンドが実行されるときにTerraformのデプロイ内で行われます。
-
設定ディレクトリを初期化します:
Terminal window terraform init -
(オプション) 作成されるすべてのものをプレビューします:
Terminal window terraform plan -
構成をデプロイします:
Terminal window terraform apply
GCPインスタンスとトンネルがオンラインになるまでに数分かかる場合があります。新しいトンネルは、Zero Trust ↗のNetworks > Tunnelsで確認できます。
新しいssh_app.<zone>ホスト名を介してGCPサーバーにSSH接続できるようになりました。接続方法については、SSHガイドを参照してください。