🐷

IaC化されていないリソースをdriftctlで検知する

2021/01/20に公開

今時の現場では、管理対象のリソースの大半はIaC(Infrastructure as a Code)化されており、
PRを契機にリソースのプロビジョニングを行うように綺麗に管理されている現場も多いかと思います。

一方で、前任のインフラ担当がリソースをIaC化せずに退職してしまったような荒れた現場や、
あるいはIaC化が浸透しきっておらず、部署によっては担当者がWebコンソールを介してリソースを作ってしまっているような現場もまだまだ存在します。

通常、そのような現場の場合、コード管理されていない野良リソースの追跡は困難を極めますが、
それを手助けするツールとして、driftctlというツールが登場しました。

driftctlとは

driftctlは、IaC化されていない野良リソース——driftctlの文脈で言うところのDrift——を検知するツールです。

https://github.com/cloudskiff/driftctl

また、厳密には異なりますが、Terraformと実際のクラウドの状態との差分を検知するツールとも言い換えられます。
主な特徴としては、次の通りです。

  • IaCと実際のクラウド上のリソースを比較し、差分を分析
  • IaCで管理されていない、あるいは不要なリソースを警告
  • 検知対象リソースのフィルタリング
    • 例: S3のバケットのみ差分を監視
  • 複数の出力フォーマットに対応

理解するにはハンズオンした方が早いので、早速触ってみましょう。

環境

  • AWS
    • リージョン: ap-northeast-1
  • Terraform: v0.14.4
  • driftctl: v0.2.3

ハンズオン

今回は、必要な権限を付与したIAMユーザーのCloudShell上でハンズオンを行います。
必要な権限や認証については、こちらを参考にして準備してください。

  • Webコンソール上でリージョンがap-northeast-1に設定されていることを確認
  • 画面右上のアイコンをクリックし、CloudShellが起動されるまで待機

プロビジョニングに数分かかります。

  • CloudShellが起動したら、Terraformをインストール
$ sudo yum install -y yum-utils && \
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo && \
sudo yum -y install terraform-0.14.4-1
  • driftctlをインストール

driftctlも例によってGo言語製なので、シングルバイナリを配置するだけでインストールが可能です。

$ curl -L https://github.com/cloudskiff/driftctl/releases/download/v0.2.3/driftctl_linux_amd64 -o driftctl && \
sudo mv driftctl /usr/local/bin/ && \
sudo chmod +x /usr/local/bin/driftctl
  • ツール類のインストール確認
$ terraform version
Terraform v0.14.4
$ driftctl version  
v0.2.3
  • 試しにdriftctlを実行

本来、driftctl scanコマンドを実行するとクラウドプロバイダーとの差分が表示されますが、
デフォルトだとカレントディレクトリ内のtfstateとの差分を見る設定になっているため、
次のように怒られます。

$ driftctl scan
Scanning AWS on region: ap-northeast-1
(省略)
open terraform.tfstate: no such file or directory

よって、一度Terraformによるプロビジョニングから行います。

  • 作業用ディレクトリを作成
$ mkdir terraform && cd $_
  • EC2作成用の最小限のtfファイルを作成
$ cat << EOF > ec2.tf
provider "aws" {
  region  = "ap-northeast-1"
}

resource "aws_instance" "driftsandbox" {
  count         = 1
  ami           = "ami-785c491f"
  instance_type = "t2.micro"
}
EOF
  • 初回プロビジョニング
$ terraform init
$ terraform plan
$ terraform apply

特に説明不要かと思われますが、terraform apply後に以下のように表示されたらOKです。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  • 再スキャン

改めてdriftctl scanを実行します。

$ driftctl scan
Scanning AWS on region: ap-northeast-1
Found 2 resource(s)
 - 100% coverage
Congrats! Your infrastructure is fully in sync.

今回の環境では、元々野良リソースが存在しない環境であり、
Terraformによって構築されたEC2しか存在しないため、100% coverageと表示されました。
これが理想の状態となりますが、これでは面白くないので、わざと手動でEC2を構築します。

  • 手動でEC2を構築
AMI: Amazon Linux2(x86)
タイプ: t2.micro
セキュリティグループ: default
キーペア: キーペアなしで続行
  • 再々スキャン

Driftを作成した状態だと、今度は50% coverageと表示されました。

$ driftctl scan
Scanning AWS on region: ap-northeast-1
Found unmanaged resources:
  aws_instance:
    - i-0be9f168de9a1458d
  aws_ebs_volume:
    - vol-0e8325b5a348adb81
Found 4 resource(s)
 - 50% coverage
 - 2 covered by IaC
 - 2 not covered by IaC
 - 0 deleted on cloud provider
 - 0/2 drifted from IaC

また、どのリソースがunmanaged resourceかを分かりやすく表示してくれています。

  • スキャン対象のフィルタリング

先ほどのスキャンでは、EC2と付随するEBSの差分のどちらも表示されましたが、例えばEC2だけチェックしておきたい場合は、
次のようにTerraformのリソース名でフィルタリングすることも可能です。

$ driftctl scan --filter "Type=='aws_instance'"
Scanning AWS on region: ap-northeast-1
Found unmanaged resources:
  aws_instance:
    - i-0be9f168de9a1458d
Found 2 resource(s)
 - 50% coverage
 - 1 covered by IaC
 - 1 not covered by IaC
 - 0 deleted on cloud provider
 - 0/1 drifted from IaC

複雑なフィルタリングを行うことも可能なので、気になった方は公式ドキュメントを覗いてみると良いかと思います。

  • スキャンの出力フォーマットの変更

最後に、スキャン結果の出力フォーマットを変更してみます。
v0.2.3現在では、デフォルトのConsole形式JSONをサポートしているので、
試しにJSONに変更してみます。
変更方法は2つあり、環境変数のDCTL_OUTPUTか、あるいは --output(-o) オプションのいずれかで指定が可能です。

今回は、後者のオプションで指定してみます。

$ driftctl scan -o json://scan.json
Scanning AWS on region: ap-northeast-1
$ cat scan.json 
{
        "summary": {
                "total_resources": 4,
                "total_drifted": 0,
                "total_unmanaged": 2,
                "total_deleted": 0,
                "total_managed": 2
        },
        "managed": [
                {
                        "id": "vol-073238016dbe56a0a",
                        "type": "aws_ebs_volume"
                },
                {
                        "id": "i-00e3af30d0ce7b997",
                        "type": "aws_instance"
                }
        ],
        "unmanaged": [
                {
                        "id": "vol-0e8325b5a348adb81",
                        "type": "aws_ebs_volume"
                },
                {
                        "id": "i-0be9f168de9a1458d",
                        "type": "aws_instance"
                }
        ],
        "deleted": null,
        "differences": null,
        "coverage": 50
}

このように、任意の形式でスキャン結果を書き出すことも可能です。

まとめ

このように、driftctlを使用すれば、簡単に野良リソースを発見することが可能です。
荒れている現場はもちろんですが、すでに綺麗な現場であっても、今ある状態がDesiredであることを監査し続けるために、導入してみるのも良さそうです。

また、Terraformerのような既存のクラウドリソースをIaC化するツールとの違いですが、
driftctlは検知に特化しているため、ガバナンスチェックはdriftctl、実際のIaC化はTerraformerのように住み分けされていくと考えられます。

まだベータ版ということもあり、v0.2.3現在のIaCソースとしてはTerraform、クラウドプロバイダーとしてはAWSのサポートのみですが、
すでに2021年のロードマップの中にAzureGCPも組み込まれているので、この先の発展に期待できそうです。

追記

driftctl公式から当記事についてコメントを頂き、とても嬉しかったので貼っておきます。

https://twitter.com/getdriftctl/status/1352268750599434241?s=20

関連記事

https://zenn.dev/gosarami/articles/0ac4133fb1a49d0db211

Discussion