SonarQubeをインストールしたEC2をTerraformで一発で構築する

# はじめに
SonarQubeの動作検証をたまにやることがあるが、その都度過去にインストールした方法を掘り返すのが面倒になったので、一発で構築できるようにした。
ここまでやるならAMI作れよ……と思わなくもない。

# 全体構成
今回は、AL2 な EC2 上に Docker をインストールして、その上で SonarQube on Postgres のような構成で動かす。docker-compose.yml は、SonarQube と Postgres をまとめて起動するためのファイルだ。

```
terraform/
├── 01_main.tf
├── 02_datasource.tf
├── 03_ec2instance.tf
└── 04_docker-compose.yml
```

01_main.tf はプロバイダ設定、02_datasource.tf は、VPC やセキュリティグループの設定をしている程度なので割愛する。

# EC2インスタンスの作成

```HCL:03_ec2instance.tf
################################################################################
# EC2 Instance                                                                 #
################################################################################
resource "tls_private_key" "sonarqube_instance" {
  algorithm = "RSA"
  rsa_bits  = 2048
}

resource "aws_key_pair" "sonarqube_instance" {
  key_name   = "sonarqube_instance"
  public_key = tls_private_key.sonarqube_instance.public_key_openssh
}

resource "aws_instance" "sonarqube" {
  ami                         = "ami-034968955444c1fd9"
  instance_type               = "t2.small"
  associate_public_ip_address = true

  subnet_id = data.aws_subnet.my_subnet.id
  vpc_security_group_ids = [
    data.aws_security_group.ssh.id,
    data.aws_security_group.http.id,
  ]

  key_name = aws_key_pair.sonarqube_instance.id

  tags = {
    Name = "[インスタンス名]"
  }

  provisioner "file" {
    connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ec2-user"
      private_key = tls_private_key.sonarqube_instance.private_key_pem
    }

    source      = "./04_docker-compose.yml"
    destination = "/home/ec2-user/docker-compose.yml"
  }

  provisioner "remote-exec" {
    connection {
      type        = "ssh"
      host        = self.public_ip
      user        = "ec2-user"
      private_key = tls_private_key.sonarqube_instance.private_key_pem
    }

    inline = [
      "sudo yum update -y",
      "sudo yum install -y docker",
      "sudo service docker start",
      "sudo usermod -a -G docker ec2-user",
      "sudo curl -L \"https://github.com/docker/compose/releases/download/1.9.0/docker-compose-$(uname -s)-$(uname -m)\" -o /usr/local/bin/docker-compose",
      "sudo chmod +x /usr/local/bin/docker-compose",
    ]
  }
}

resource "null_resource" "run_sonarqube" {
  depends_on = [
    aws_instance.sonarqube
  ]

  provisioner "remote-exec" {
    connection {
      type        = "ssh"
      host        = aws_instance.sonarqube.public_ip
      user        = "ec2-user"
      private_key = tls_private_key.sonarqube_instance.private_key_pem
    }

    inline = [
      "sudo /usr/sbin/sysctl -w vm.max_map_count=262144",
      "sudo service docker start",
      "docker-compose up -d",
    ]
  }
}
```

provisioner を使いまくっているが、```aws_instance.sonarqube``` の remote-exec の provisioner では、Docker と docker-compose のインストールをしている。usermod をした後に再接続をしなければならないので、EC2インスタンスの作成後に ```null_resource.run_sonarqube``` で再接続をして、SonarQube のコンテナを起動している。

[以前の記事](https://qiita.com/neruneruo/items/5f4d1562cf758f359997)で書いた通り、```vm.max_map_count``` のパラメータ変更をしなければいけないので、これも Docker 起動前に実施している。他のカーネルパラメータは、docker-compose.yml 内で設定をしている。

```YAML:docker-compose.yml
version: "2"

services:
  sonarqube:
    image: sonarqube:8.2-community
    depends_on:
      - db
    ports:
      - "80:9000"
    networks:
      - sonarnet
    environment:
      SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar
      SONAR_JDBC_USERNAME: sonar
      SONAR_JDBC_PASSWORD: sonar
    volumes:
      - sonarqube_data:/opt/sonarqube/data
      - sonarqube_extensions:/opt/sonarqube/extensions
      - sonarqube_logs:/opt/sonarqube/logs
      - sonarqube_temp:/opt/sonarqube/temp
    ulimits:
      nofile: 65536
      nproc: 4096
  db:
    image: postgres
    networks:
      - sonarnet
    environment:
      POSTGRES_USER: sonar
      POSTGRES_PASSWORD: sonar
    volumes:
      - postgresql:/var/lib/postgresql
      - postgresql_data:/var/lib/postgresql/data

networks:
  sonarnet:
    driver: bridge

volumes:
  sonarqube_data:
  sonarqube_extensions:
  sonarqube_logs:
  sonarqube_temp:
  postgresql:
  postgresql_data:
```

これを ```terraform apply``` すれば、2~3分でサクッとSonarQubeが起動する。