Help us understand the problem. What is going on with this article?

IaCの運用が辛い原因は考え方じゃなくてツールだと言いたい

More than 1 year has passed since last update.

言いたいこと

  • IaCの運用がビジネスのスピードに合わなくなってきている
  • IaCが辛い原因は考え方じゃなくてツールにあると思う
  • Terraform のmoduleの再利用性がないのは DI ができないから
  • DIのできるインフラ構築ツールがでてくれば、インフラ構築の大変さが劇的に変わる(はず)

発端: IaC って辛いよね

発端となったのはこちらのスライドです。
Infrastructure as Codeに疲れたので、僕たちが本来やりたかったことを整理する

簡単に説明すると、「IaCっていい加減つらいよね。なんでもかんでもCode化すればいいってもんじゃないよね。」という話です。
辛みについてはすごく共感できましたが、ただ、ここに語られてることって、 IaCの辛さじゃなくて、terraform の辛さだと思うんです
ツールが現状の運用のニーズに合わなくなってきただけだと思うんです。

Terraform がなぜ辛いのか?

Terraform が辛い原因を一言でいうと、 module のポータビリティーの低さだと私は考えています。

ここからは具体例で説明します。

例: ELB + SecurityGroup + Route53 record からなるモジュール

ELB, ACM, Security Group などの public 層のリソースをまとめたモジュールを作りたいとします。
ELBは以下のような定義であるとします:

elb.tf
resource "aws_elb" "internal" {
  name            = "${var.app_name}-${var.env}-internal"
  security_groups = ["${aws_security_group.internal-elb.id}"]
  subnets         = [
    "${lookup(var.subnet_ids, "private-1a")}",
    "${lookup(var.subnet_ids, "private-1c")}",
  ]
  internal        = true

  listener {
    instance_port      = "${var.listener_port["instance"]}"
    instance_protocol  = "http"
    lb_port            = "${var.listener_port["lb"]}"
    lb_protocol        = "https"
    ssl_certificate_id = "${data.aws_acm_certificate.wildcard.arn}"
  }

  health_check {
    healthy_threshold   = "${var.health_check["healthy_threshold"]}"
    unhealthy_threshold = "${var.health_check["unhealthy_threshold"]}"
    timeout             = "${var.health_check["timeout"]}"
    target              = "${var.health_check["target"]}"
    interval            = "${var.health_check["interval"]}"
  }

  cross_zone_load_balancing   = true
  idle_timeout                = 60
  connection_draining         = true
  connection_draining_timeout = 300

  tags {
    "Name" = "${var.app_name}-${var.env}-internal"
  }

  lifecycle {
    ignore_changes = ["access_logs", "idle_timeout"]
  }
}

このとき、 ELB を internet faced にするか inner にするかくらいなら、 boolean 変数で注入すれば外からコントロールできますよね。

elb.tf
  internal        = "${var.is_internal}"

ところが、ELBのリスナーをサービスAとサービスBで独自のものを作りたい場合があります。
運用に即した例としては、 HTTP から HTTPS にリダイレクトする ELB を作りたいとします。

ところが、現状のterraform はこれを外から注入する手段はありません。

AsIs の解決策

AsIs の解決策としては、以下の2つです(module 使わないは論外として):

  1. ELB の定義をこの moudle から外に出す
  2. ELBのリスナーだけ異なる似たような module を2つ作る

解決策1: ELBの定義を module の外に出す

この方法だと、そもそもALBの定義が module の外に出てしまうのだから、この module には重要なことが書かれなくなるわけです。これは module を使わない、といっているのと似たような感じになります。

解決策2: ELBの定義だけ差し替えた2つの module を作る

以下のような2つのモジュールを作ります。

  • module1: public-elb
  • module2: public-elb-with-redirect

module2 のELBの定義は以下のようになります(module1との差分のみ表示):

public-elb-with-redirect/elb.tf
// ほかはmodule1と同じ
...
  listener {
    instance_port      = "${var.listener_port_ssl["instance"]}"
    instance_protocol  = "http"
    lb_port            = "${var.listener_port_ssl["lb"]}"
    lb_protocol        = "https"
    ssl_certificate_id = "${data.aws_acm_certificate.wildcard.arn}"
  }
...

この方法だと、 似てるけど listner の部分だけ違う module が複数できるわけです。これでは他の部分のコードが二重管理になります。さらに別の部分も変更したいとなると、似てるmoduleがどんどん増えていきます。これは管理がとても煩雑です。

本来やりたいこと = DI (Dependency Injection)

これに対して、listener 定義の部分だけ外部から注入できれば、module は1つですみます。これによって、汎用的な用途で使える public レイヤの module ができるわけです。これはいろんなところに使い回せます。

本来やりたかったこと
// こんな言語はありませんが、あくまでイメージです。。
// public_elb module
const public_elb = new Elb({ listener: new Listener({ redirect: false }) });
// public_elb_with_redirect module
const public_elb_with_redirect = new Elb({ listener: new Listener({ redirect: true }) });

参考: Dependency Injection (依存性の注入)

terraform は module に DI を導入するか?

たぶん No だと思います。
terraform でこれをやろうとすると、根本的にアーキテクチャの変更を強いられると思うんです。だから多分terraform に DI は来ないと思う。
一方で、 pulumiaws-cdk みたいなツールは汎用プログラミング言語でインフラ定義をするので、DIが比較的導入しやすいんじゃないかと思います。だからこれらのツールはこれから有望な選択肢になるんじゃないかと思うんです。
(もちろん、ツール側がDIを導入してくれなかったら意味はないんですが。。)

DIができるツールが出てくればインフラ構築の辛さが劇的に変わる

DIができるツールが出てくれば、moduleに相当するもののポータビリティも上がるので、githubとかでいろいろな開発者がmoduleを公開していくようになると思います。
そうなると、オープンソースの資産が充実してきて、同じ要件をアリもので代用できるようになっていくと思います。つまり、インフラ定義が楽になると思うんです。

終わりに

つまるところ、だからみなさん一緒に aws-cdk や pulumi を勉強しませんか?という話ですw

参考

この一連のツイート

billthelizard
元アプリケーションエンジニアでしたが、 As Code 化の流れにのってインフラエンジニアに転身しました。AWS / IaC / Container 関連技術 をメインに記事を執筆しています。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away