Terraform: Tableau用のプロキシサーバを立てたい
やりたきこと
TableauでDBに繋ぎたいけど、DBがprivate subnetにあるからproxyサーバ経由でアクセスしたい
っていうのをTerraformで書きたい。
資源
service | OS | subnet | note |
---|---|---|---|
RDS | MySQL(Auroraじゃない) | private | |
EC2 | centos | public | 作業用サーバなのでなんでも |
やること
Terraformで
- EC2立てる(ubuntu t2.micro)
- haproxyインストールする
- 自分用設定ファイルを転送して配置する
- haproxyを再起動する
- Tableau DesktopでRDSにアクセスしてみる
スタート
$ cat main.tf provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" region = "${var.region}" } # SGつくるやつ resource "aws_security_group" "util-server" { name = "example_sg_util_server" description = "terraform example" vpc_id = "${data.aws_vpc.main.id}" ingress { from_port = 3306 to_port = 3306 protocol = "tcp" cidr_blocks = ["許せるIP"] } ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } #EC2つくるやつ resource "aws_instance" "example" { ami = "ami-07ad4b1c3af1ea214" instance_type = "t2.micro" key_name = "${var.key_name}" vpc_security_group_ids = [ "${aws_security_group.util-server.id}", ] provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ "sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy" ] } provisioner "file" { source = "haproxy.cfg" destination = "/etc/haproxy" } tags = { Name = "${var.ec2_nametag}" } } #EIPつくるやつ(PublicIPでもいいなら、別にEIPは不要かも) resource "aws_eip" "ip" { instance = "${aws_instance.example.id}" }
戦った跡
EC2構築時、apt-get内のgrub更新で3択迫られてるうちにtime outする。
terraformでapt-get update -y したけど、grubの更新でバグったファミコンみたいになる
apt-get-upgrade内のgrub更新の際、対応をn択で迫られるのだけど、GUIライクなCUIで聞かれるため標準出力がひどくなる。
そして、Terraformで答えられないので、time out待ちになってしまう。(9分待ってtime outしなかったけど)
provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ ★ "echo grub-pc hold | sudo dpkg --set-selections && sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy" ] }
参考:Vagnrat Ubuntu16.04 apt upgrade のGRUBで更新が止まる時の対策 - Qiita
上手くいったっぽい
aws_instance.example: Still creating... (3m10s elapsed) aws_instance.example: Creation complete after 3m11s (ID: i-0ac91b7d5c7141c5d) aws_eip.ip: Creating... allocation_id: "" => "<computed>" association_id: "" => "<computed>" domain: "" => "<computed>" instance: "" => "i-0ac91b7d5c7141c5d" network_interface: "" => "<computed>" private_ip: "" => "<computed>" public_ip: "" => "<computed>" public_ipv4_pool: "" => "<computed>" vpc: "" => "<computed>"
作成したEC2にログインして確認してみる
$ systemctl list-unit-files|grep haproxy haproxy.service enabled $ ps -ef|grep haproxy root 16460 1 0 04:29 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid haproxy 16461 16460 0 04:29 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid ubuntu 16742 16685 0 04:44 pts/0 00:00:00 grep --color=auto haproxy
haproxyがインストールされてて、起動もされている。
次は自分用のhaproxy設定ファイル置きたい。
file句?とりあえず突っ込んでみる。
provisioner "file" { source = "haproxy.cfg" destination = "/etc/haproxy/" }
ssh: handshake failed: ssh: unable to authenticate
Error: Error applying plan: 1 error(s) occurred: * aws_instance.example: timeout - last error: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none], no supported methods remain
haproxyのインストールは上手くいってる。
ubuntu@ip-172-31-41-172:~$ dpkg -l|grep hapro ii haproxy 1.8.8-1ubuntu0.3 amd64 fast and reliable load balancing reverse proxy ubuntu@ip-172-31-41-172:~$ ps -ef|grep hap root 1993 1 0 07:31 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid haproxy 1994 1993 0 07:31 ? 00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid ubuntu 2256 2241 0 07:40 pts/0 00:00:00 grep --color=auto hap
たぶん二つ目のprovisioner句にConnectionを指定してないからかも。
provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ "echo grub-pc hold | sudo dpkg --set-selections", "sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy" ] } provisioner "file" { source = "haproxy.cfg" destination = "/etc/haproxy/" }
とりあえず、connectionを入れてみる。
provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ "echo grub-pc hold | sudo dpkg --set-selections", "sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy" ] } provisioner "file" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } source = "haproxy.cfg" destination = "/etc/haproxy/" }
二重になってダサいけど、直った。
provisioner "file"のpermission denied
上のsshのエラーは直ったけど、今度はpermission denied。
aws_instance.example: Provisioning with 'file'... Error: Error applying plan: 1 error(s) occurred: * aws_instance.example: Upload failed: scp: /etc/haproxy/haproxy: Permission denied
ファイルは置ける場所に置いて、remote-execでsudo権限を使って置きたい場所に置きましょう、らしい。
If your SSH user doesn't have access, what we recommend is using the file provisioner to upload to a place you can, then the remote shell provisioner to
sudo
(or similar) to move it.
↓のように修正
- haproxyの設定ファイルを転送しておく
- 脳死でapt-get update && upgrade
- haproxyインストール
- 転送しておいたhaproxy設定ファイルを/etc/haproxy/配下に移動
- systemctlで再起動
provisioner "file" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } source = "haproxy.cfg" destination = "/tmp/haproxy.cfg" } provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ "echo grub-pc hold | sudo dpkg --set-selections", "sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy && sudo mv /tmp/haproxy.cfg /etc/haproxy/. && sudo systemctl restart haproxy.service" ] }
再起動されてそう。
Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: Stopping HAProxy Load Balancer... Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: haproxy.service: Main process exited, code=exited, status=143/n/a Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: haproxy.service: Failed with result 'exit-code'. Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: Stopped HAProxy Load Balancer. Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: Starting HAProxy Load Balancer... Feb 5 09:13:59 ip-172-31-47-197 systemd[1]: Started HAProxy Load Balancer.
RDSのSGを開ける
RDSのSGにTerraformで作ったEC2のSGを登録してあげる。
Tableauにアクセスしてみる
行けてそう。(繋ぎたい案件対応で入れただけなので使い方は分からない)
DBがWordpressなのは、RDSが別件で検証用に立てたこやつしかいなかったから。。。
出来上がったtf
$ cat main.tf provider "aws" { access_key = "${var.access_key}" secret_key = "${var.secret_key}" region = "${var.region}" } resource "aws_security_group" "util-server" { name = "example_sg_util_server" description = "terraform example" vpc_id = "${data.aws_vpc.main.id}" ingress { from_port = 3306 to_port = 3306 protocol = "tcp" cidr_blocks = ["許せるIP"] } ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_instance" "example" { ami = "ami-07ad4b1c3af1ea214" instance_type = "t2.micro" key_name = "${var.key_name}" vpc_security_group_ids = [ "${aws_security_group.util-server.id}", ] provisioner "file" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } source = "haproxy.cfg" destination = "/tmp/haproxy.cfg" } provisioner "remote-exec" { connection { type = "ssh" user = "ubuntu" private_key = "${file("${var.key_name_full}")}" } inline = [ "echo grub-pc hold | sudo dpkg --set-selections", "sudo apt-get update -y && sudo apt-get upgrade -y", "sudo apt-get install -y haproxy && sudo mv /tmp/haproxy.cfg /etc/haproxy/. && sudo systemctl restart haproxy.service" ] } tags = { Name = "${var.ec2_nametag}" } } resource "aws_eip" "ip" { instance = "${aws_instance.example.id}" }
$ cat variables.tf variable "access_key" { type = "string" default = "hogehoge" } variable "secret_key" { type = "string" default = "hogehoge" } variable "region" { default = "ap-northeast-1" } variable "key_name" { type = "string" default = "mng" } variable "key_name_full" { type = "string" default = "mng.pem" } variable "vpc_id" { type = "string" default = "vpc-hoge" } variable "ec2_nametag" { type = "string" default = "util-server" }
残ってる課題
RDSに登録したSGを消さないとterraform destroyがスタックする
aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m0s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m10s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m20s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m30s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m40s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 7m50s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 8m0s elapsed) aws_security_group.util-server: Still destroying... (ID: sg-0deaaa83a62085e75, 8m10s elapsed)
terraform destroy時にEC2用に作ったSGの削除を行っているが、RDS側のSGで参照しているとEC2用が削除できない。
エラー時にcontinueするみたいな構文あった気がするけど、この場合はずっと待ちなわけで、スキップするようなやつないかな。