hoge-hogeoのひきこもごも

インフラエンジニアだけど形を持ったインフラを触ったことがない人の徒然

Terraform: Tableau用のプロキシサーバを立てたい

やりたきこと

TableauでDBに繋ぎたいけど、DBがprivate subnetにあるからproxyサーバ経由でアクセスしたい

っていうのをTerraformで書きたい。

f:id:hoge-hogeo:20190205183627p:plain

資源

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する。

f:id:hoge-hogeo:20190205185405p:plain

terraformでapt-get update -y したけど、grubの更新でバグったファミコンみたいになる

apt-get-upgrade内のgrub更新の際、対応をn択で迫られるのだけど、GUIライクなCUIで聞かれるため標準出力がひどくなる。

そして、Terraformで答えられないので、time out待ちになってしまう。(9分待ってtime outしなかったけど)

一旦、脳死grubの更新は省く

  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.

Upload failed: scp: /etc/init.d/sample: Permission denied in file provisioning · Issue #8238 · hashicorp/terraform · GitHub

↓のように修正

  • 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にアクセスしてみる

f:id:hoge-hogeo:20190205182107p:plain

行けてそう。(繋ぎたい案件対応で入れただけなので使い方は分からない)

DBがWordpressなのは、RDSが別件で検証用に立てたこやつしかいなかったから。。。 f:id:hoge-hogeo:20190205182346p:plain

出来上がった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するみたいな構文あった気がするけど、この場合はずっと待ちなわけで、スキップするようなやつないかな。

Terraform: サンプルが難しい〜aws_autoscaling_groupが上手くいかない話〜

Placement groups may not be used with instances of typeの話

↓のサンプルやれば、オートスケールできるようになるんじゃね、って軽いノリで検証し始めたけど、見事にはまった。

www.terraform.io

ソースは上記リンク先のページをそのまま。

* aws_autoscaling_group.bar: 1 error(s) occurred:

* aws_autoscaling_group.bar: "foobar3-terraform-test": Waiting up to 10m0s: Need at least 4 healthy instances in ASG, have 0. Most recent activity: {
  ActivityId: "94f5a09e-6491-f883-31fc-9a67b6e36d34",
  AutoScalingGroupName: "foobar3-terraform-test",
  Cause: "At 2019-01-07T09:16:12Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 4.",
  Description: "Launching a new EC2 instance.  Status Reason: Placement groups may not be used with instances of type 't2.micro'. Launching EC2 instance failed.",
  Details: "{\"Subnet ID\":\"subnet-0f8f0e78e2f93e59e\",\"Availability Zone\":\"ap-northeast-1c\"}",
  EndTime: 2019-01-07 09:16:14 +0000 UTC,
  Progress: 100,
  StartTime: 2019-01-07 09:16:14.334 +0000 UTC,
  StatusCode: "Failed",
  StatusMessage: "Placement groups may not be used with instances of type 't2.micro'. Launching EC2 instance failed."
}

多分、こんな感じのことを言われてる気がする。

10分待った、最低4台のインスタンスがいるはずなんだけど、1台もいないよ。
t2.microでPlacement groupsが使われてないかもよ。上がらんし

知らんし。

1台だけEC2インスタンス上がってる。 f:id:hoge-hogeo:20190107182339p:plain

10分待ったけど、って待ちすぎ。と思って画面見てたら、↓こんなんあった。

wait_for_capacity_timeout "" =>"10m"

何も指定してないとデフォ10分になるっぽい。これはとりあえず5mに変えておこう。

あと、health_check_typeがELBになっていたけど、ELB作る設定は書いてないのでEC2に変更してみる。

変更後
wait_for_capacity_timeout  = "5m"
health_check_type          = "EC2

再度実行

$ terraform apply
〜略〜
health_check_type:                                         "" => "EC2"
〜略〜
  wait_for_capacity_timeout:                                 "" => "5m"
〜略〜

* aws_autoscaling_group.bar: 1 error(s) occurred:

* aws_autoscaling_group.bar: "foobar3-terraform-test": Waiting up to 5m0s: Need at least 4 healthy instances in ASG, have 0. Most recent activity: {
  ActivityId: "da95a09e-e5cd-0267-43c3-ff43250264a2",
  AutoScalingGroupName: "foobar3-terraform-test",
  Cause: "At 2019-01-07T09:51:30Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 4.",
  Description: "Launching a new EC2 instance.  Status Reason: Placement groups may not be used with instances of type 't2.micro'. Launching EC2 instance failed.",
  Details: "{\"Subnet ID\":\"subnet-05082e304ca64329e\",\"Availability Zone\":\"ap-northeast-1c\"}",
  EndTime: 2019-01-07 09:51:31 +0000 UTC,
  Progress: 100,
  StartTime: 2019-01-07 09:51:31.648 +0000 UTC,
  StatusCode: "Failed",
  StatusMessage: "Placement groups may not be used with instances of type 't2.micro'. Launching EC2 instance failed."
}

変更はちゃんと適用されたけど、問題はここじゃないくさい。

1台目が起動したあとのヘルスチェックかな???

Placement Groupに対応しているEC2インスタンスタイプの話

docs.aws.amazon.com

調べてたら、たまたま引っかかった。クラスタープレイスメントグループの制約だった。

懐を気にしてinstance_type = t2.microにしてたけど、サポートされていなかった。

そして、オレオレ和訳も間違っていた。

× t2.microでPlacement groupsが使われてないかもよ。上がらんし
○ t2.microでPlacement groupsが使われないかもよ。上がらんし

↓のようにaws_launch_configurationを修正したら無事上がった。

$ cat launch_config.tf 

resource "aws_launch_configuration" "foobar" {
  name          = "test-launch-config"
  image_id      = "ami-092834f1e5079fb84"
  # AWS Placement_Groupがt2とか対応してないっぽい
  instance_type = "m5.large"
  #instance_type = "t2.micro"
  key_name      = "${var.key_name}"
}

m5を4台とか要らん。。。 f:id:hoge-hogeo:20190108165523p:plain

現状、まだヘルスチェックが上手く引っかからず、意図せずdesired_capacityまでスケールアウトしてしまう。

Error: Error applying plan:

1 error(s) occurred:

* aws_autoscaling_group.bar: 1 error(s) occurred:

* aws_autoscaling_group.bar: "foobar3-terraform-test": Waiting up to 5m0s: Need at least 1 healthy instances in ASG, have 0. Most recent activity: {
  ActivityId: "ea15a0b3-2f8a-d85e-a6e4-d86b1f95e8fa",
  AutoScalingGroupName: "foobar3-terraform-test",
  Cause: "At 2019-01-08T09:29:43Z a user request update of AutoScalingGroup constraints to min: 0, max: 5, desired: 1 changing the desired capacity from 0 to 1.  At 2019-01-08T09:29:44Z an instance was started in response to a difference between desired and actual capacity, increasing the capacity from 0 to 1.",
  Description: "Launching a new EC2 instance: i-039eb1472280c5749",
  Details: "{\"Subnet ID\":\"subnet-0720c7a4238f0fd26\",\"Availability Zone\":\"ap-northeast-1c\"}",
  Progress: 40,
  StartTime: 2019-01-08 09:29:45.911 +0000 UTC,
  StatusCode: "MidLifecycleAction"
}

引き続き、検証しよう・・・。

その他:terraform destroyしたときにEBSが消えない話

消されなかったEBSが大量に残ってるんだけど・・・。

f:id:hoge-hogeo:20190108173033p:plain

delete_on_terminationオプションだろうな、あとで入れとこう。

www.terraform.io

忘れたままにしといたら、課金が捗りそう。

terraformでaws access_key, secret_keyの指定方法

個人的備忘録。本家のドキュメントが英語なので。

IAMの指定の仕方はいくつかある

  1. tfファイルに直書きする
  2. コマンド実行時にオプションで渡す
  3. ファイルに書いておく

1. tfファイルに直書きする

本家のexampleに一番最初に出てくる書き方。

どやーってgithubとかに上げたら後悔するやつ。

$ cat example.tf
provider "aws" {
  access_key = "hogeo"
  secret_key = "hogeo_secret"
  region     = "ap-northeast-1"
}

2. コマンド実行時にオプションで渡す

variables.tfをつくる

$ cat variables.tf
variable "access_key" {}
variable "secret_key" {}
variable "region" {
  default = "ap-northeast-1"
}

example.tfは変数に置き換える。

$ cat example.tf
provider "aws" {
  access_key = "${var.access_key}"
  secret_key = "${var.secret_key}"
  region     = "${var.region}"
}

apply実行時に-varオプションで渡す。

$ terraform apply -var 'access_key=hogeo' -var 'secret_key=hogeo_secret'

オプション忘れても、入力待ちになる

$ terraform apply
var.access_key
  Enter a value:

3. ファイルに書いておく

variables.tf書くのと、example.tfの変数化までは一緒だけど、コマンドラインのオプションで渡すんじゃなくて、ファイルに書くパターン。

terraform.tfvarsというファイル名をカレントにおいて、中にaccess_key, secret_keyを書くことで、IAMをレシピ?に書かずに済む。

$ cat terraform.tfvars
access_key = "hogeo"
secret_key = "hogeo_secret"

terraform.tfvarsというファイル名じゃないと、勝手に読んでくれないので、別のファイル名にしたいときは-var-fileオプションで指定してあげる。

↓はファイル名に「_org」とかつけちゃったのd、-var-fileオプションで指定したとき。

$ terraform destroy -var-file="terraform.tfvars_org"

今日はここまで。全然進まない。。。

本日の一言

勉強してると、部屋の片づけ始めて、カメラのSDカードとか見つかっちゃって、いつの間にか昔の写真見返して時間が過ぎてるよね。

雑記:terraformちょっと触ってる

  1. EC2 FullAccessだけつけたIAMユーザつくる
  2. ↓本家を見ながらつくってく

learn.hashicorp.com

  1. depends_onでS3出たあたりで、IAMユーザにS3 FullAccessつける

↓の途中で止まってるなう。
https://learn.hashicorp.com/terraform/getting-started/dependencies

beanstalk触ってる話

概要

さわってみた系の話

検証

.ebextensitonを使ってみる

プロジェクトのソースコードの最上位に.ebextensionsを掘れ?

掘って、ファイル置いてデプロイしたら変わるのだろうか。

f:id:hoge-hogeo:20180928172355p:plain

healthcheckurl.configを置いてみる

f:id:hoge-hogeo:20180928172413p:plain

hello/.ebextensions配下に上記ファイルを置いてzip化する

マネコンからアップロードして、beanstalkにデプロイさせる

エラーが出る

/healthというパスはないからね

つらい

とりあえず1台に適当な静的ファイルを置いてみる

$ sudo sh -c "echo ok >> /var/www/html/hello/public/health"

f:id:hoge-hogeo:20180928172626p:plain

直った。(実は直ってなかった)

とにかく、この使い方でいいということが分かった。

2台目にも手動でhealthファイルを配置した、がエラーが解けない。

f:id:hoge-hogeo:20180928174843p:plain

アプリケーションのバージョンが合わないと。これはもしかしてデプロイ諦めた結果?

もたついてる間にローリングデプロイがAbortされたらしい。

During an aborted deployment, some instances may have deployed the new application version. To ensure all instances are running the same version, re-deploy the appropriate application version.

f:id:hoge-hogeo:20180928172646p:plain

ちなみに、.ebextensions/healthcheckurl.configの内容も切り戻されていたので、現象としては

  • .ebextensions/healthcheckurl.configに/healthがヘルスチェックパスだと指定してアプリをデプロイ
  • 1台目に最新アプリをデプロイしたが、/healthのパスがなかったため、ヘルスチェックに失敗
  • もたもたとhealthファイルを作ったが、操作はAbortされた  →.ebextensions等の変更内容も切り戻された。(ヘルスチェックパスが/healthから/に戻っていた)
  • 最新のアプリが1台目にデプロイ済みのため、その1台目の状態が「低下」になった
  • 少し↑で直ったと思ったのは、デプロイをAbortされて古いままになっていた2台目の状態が「Ok」になっているだけだった

healthの静的ファイルもアプリ内に配置して、再デプロイしてみる。

バージョン情報が分かりにくかったので文字列にしてみる。

f:id:hoge-hogeo:20180928172903p:plain

なんとかなった。実行バージョンも更新された。

f:id:hoge-hogeo:20180928172920p:plain

td-agentを入れてみる

インストール

$ cat hello/.ebextensions/requirement.config
commands:
  command block:
    command: |
      curl -L "https://toolbelt.treasuredata.com/sh/install-amazon1-td-agent3.sh" > td-agent_install.sh
      sh td-agent_install.sh
      td-agent-gem install fluent-plugin-forest

デプロイされたEC2で確認

$ rpm -qa|grep td-a
td-agent-3.2.0-0.el2018.x86_64


$ td-agent-gem list|grep forest
fluent-plugin-forest (0.3.3)

td-agent.confを配布する

$ cat hello/.ebextensions/td-agent_conf.config
files:
    "/etc/td-agent/td-agent.conf" :
        mode: "000644"
        owner: root
        group: root
        content: |
            <source>
              @type tail
              format ltsv
              path /var/www/html/hello/storage/logs/monolog-%Y-%m-%d
              tag local.laravel.log
              pos_file /var/log/td-agent/laravel.log.pos
            </source>
            <filter local.**>
              @type record_transformer
              <record>
                host ${hostname}
              </record>
            </filter>
            <match local.**>
              @type forest
              subtype s3
              <template>
                aws_key_id アイディー
                aws_sec_key キー
                s3_bucket at.test.bucket
                s3_region ap-northeast-1
                path laravel/dt=%Y-%m-%d-%H/
                buffer_path /var/log/td-agent/buffer/laravel.buf
                time_slice_format %Y-%m-%d
                time_slice_wait 10s
                flush_interval 10s
                format ltsv
              </template>
            </match>

ebコマンドを用いたデプロイ

https://docs.aws.amazon.com/ja_jp/elasticbeanstalk/latest/dg/eb-cli3-configuration.html#eb-cli3-artifact

ざっくりイメージ

  • jenkinsでビルド
  • S3アップロード
  • ebコマンドでローリングデプロイ
ebコマンド使ってみる

ebコマンドインストール

本家にあるので省略

使ってみる

eb init

[centos@ip-172-31-10-238 ~]$ eb init

Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-south-1 : Asia Pacific (Mumbai)
7) ap-southeast-1 : Asia Pacific (Singapore)
8) ap-southeast-2 : Asia Pacific (Sydney)
9) ap-northeast-1 : Asia Pacific (Tokyo)
10) ap-northeast-2 : Asia Pacific (Seoul)
11) sa-east-1 : South America (Sao Paulo)
12) cn-north-1 : China (Beijing)
13) cn-northwest-1 : China (Ningxia)
14) us-east-2 : US East (Ohio)
15) ca-central-1 : Canada (Central)
16) eu-west-2 : EU (London)
17) eu-west-3 : EU (Paris)
(default is 3): 9

Select an application to use
1) BGDeploy
2) sample-laravel
3) [ Create new Application ]
(default is 3): 2

Select a platform.
1) Node.js
2) PHP
3) Python
4) Ruby
5) Tomcat
6) IIS
7) Docker
8) Multi-container Docker
9) GlassFish
10) Go
11) Java
12) Packer
(default is 1): 2

Select a platform version.
1) PHP 7.1
2) PHP 7.0
3) PHP 5.6
4) PHP 5.5
5) PHP 5.4
6) PHP 5.3
(default is 1): 1
Cannot setup CodeCommit because there is no Source Control setup, continuing wit                                                           h initialization
Do you want to set up SSH for your instances?
(Y/n): Y

Select a keypair.
1) hoge-hogeo
2) [ Create new KeyPair ]
(default is 1): 1

eb health  →マネコンでみているようなリストが出力された f:id:hoge-hogeo:20180928173243p:plain

memo

aws elasticbeanstalk describe-application-versions

マネコンの「アプリケーションバージョン」で見れるやつ

$ aws --profile eb-cli --region ap-northeast-1 elasticbeanstalk describe-application-versions
{
    "ApplicationVersions": [
        {
            "ApplicationName": "sample-laravel",
            "Status": "UNPROCESSED",
            "VersionLabel": "modify_healthcheck_path",
            "Description": "",
            "ApplicationVersionArn": "arn:aws:elasticbeanstalk:ap-northeast-1:57142996XXXX:applicationversion/sample-laravel/modify_healthcheck_path",
            "DateCreated": "2018-07-19T03:16:14.455Z",
            "DateUpdated": "2018-07-19T03:16:14.455Z",
            "SourceBundle": {
                "S3Bucket": "elasticbeanstalk-ap-northeast-1-57142996XXXX",
                "S3Key": "2018200EjT-hello.zip"
            }
        },

コマンドラインでデプロイしたい

アプリケーションのバージョンを作成
$ aws --profile eb-cli --region ap-northeast-1 elasticbeanstalk create-application-version \
--application-name sample-laravel --version-label 201807201700 \
--source-bundle S3Bucket="__bucket_name__",S3Key="hello.zip" --auto-create-application
{
    "ApplicationVersion": {
        "ApplicationName": "sample-laravel",
        "Status": "UNPROCESSED",
        "VersionLabel": "201807201700",
        "ApplicationVersionArn": "arn:aws:elasticbeanstalk:ap-northeast-1:571429965935:applicationversion/sample-laravel/201807201700",
        "DateCreated": "2018-07-20T08:19:43.496Z",
        "DateUpdated": "2018-07-20T08:19:43.496Z",
        "SourceBundle": {
            "S3Bucket": "__bucket_name__",
            "S3Key": "hello.zip"
        }
    }
}

無事登録された。

f:id:hoge-hogeo:20180928173404p:plain

環境へのデプロイ

201807251600をデプロイする

$ aws --profile eb-cli --region ap-northeast-1 elasticbeanstalk update-environment --environment-name Laravel-env --version-label 201807251600
{
    "ApplicationName": "laravel",
    "EnvironmentName": "Laravel-env",
    "VersionLabel": "201807251600",
    "Status": "Updating",
    "EnvironmentArn": "arn:aws:elasticbeanstalk:ap-northeast-1:571429965935:environment/laravel/Laravel-env",
    "PlatformArn": "arn:aws:elasticbeanstalk:ap-northeast-1::platform/PHP 7.1 running on 64bit Amazon Linux/2.7.1",
    "EndpointURL": "awseb-AWSEB-6T78TTLA31X-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com",
    "SolutionStackName": "64bit Amazon Linux 2018.03 v2.7.1 running PHP 7.1",
    "EnvironmentId": "e-axab792pcj",
    "CNAME": "Laravel-env.XXXXXXXXXX.ap-northeast-1.elasticbeanstalk.com",
    "AbortableOperationInProgress": true,
    "Tier": {
        "Version": "1.0",
        "Type": "Standard",
        "Name": "WebServer"
    },
    "Health": "Grey",
    "DateUpdated": "2018-07-25T06:53:38.215Z",
    "DateCreated": "2018-07-25T02:01:56.666Z"
}

f:id:hoge-hogeo:20180928173934p:plain

アプリケーションバージョンについて

いくらバージョンラベルを切っても、ソースの「アプリ.zip」のパスが一緒だと最新のものが参照されるらしい。(当然といえば当然か)

下記の画像だと、20180725hhmmのバージョンラベルが3つあるが、ソースのパスはS3上で同じパスなので、

最古のバージョンラベルに紐づくソースは最新のバージョンラベルのものと同じになる。

f:id:hoge-hogeo:20180928174026p:plain

requirement.txtってどこで実行されてるの?

command:にtouch hogeとか入れてみる

$cat /var/www/html/hello/requirement.txt
commands:
  command block:
    command: |
      touch hoge
      "curl -L \"https://toolbelt.treasuredata.com/sh/install-amazon1-td-agent3.sh\" > td-agent_install.sh"
      sh td-agent_install.sh


ここがrequirement.txtが読み込まれ、実行されるpwdらしい

$ sudo find / -type f -name hoge
/opt/elasticbeanstalk/eb_infra/hoge

jenkins ジョブの排他実行したい話

概要

アプリケーションのデプロイに3つのジョブを使っている。

  • PHPアプリをビルドする@ビルドサーバ
  • ビルドしたアプリを対象サーバのDocumentRootへscpする
  • 対象サーバのDocumentRootを切り替えてリリースする

資源

資源 モノ 備考
EC2 amzn2-ami-hvm-2.0.20180810-x86_64-gp2 (ami-08847abae18baa040)
MW Jenkins ver. 2.140

検証

ノードを1つにしてみる

とりあえず、1ジョブだけ実行させられるのか確認してみよう。

これを採用すると、常に1ジョブしか実行できないとても使いづらいjenkinsになるけど。

jenkinsの管理→ノードの管理→ノードの歯車 f:id:hoge-hogeo:20180926123110p:plain

これを1にしてみる。 f:id:hoge-hogeo:20180926123146p:plain

実行してみるジョブはこんな感じ


PipelineのBulk-Deploy-API-for-WhiteがJob3つを実行するだけ

Job種
Pipeline Bulk-Deploy-API-for-White
Job Deploy-API-for-White
Job Release-API-to-Server-from-HUB-for-White
Job Change_SymbolicLink_API_for_White

待てど暮らせど始まらない、pipeline中の下流ジョブ f:id:hoge-hogeo:20180926124800p:plain

利用可能なエグゼキューターとは。。。

とりあえず思い当たるのは、ノード実行数を1つだけにしたやつ、戻してみる。 f:id:hoge-hogeo:20180926124926p:plain

動いた。pipelineと下流ジョブで、それぞれエグゼキューターが必要になるらしい。

f:id:hoge-hogeo:20180926130158p:plain

ということは、下流ジョブを複数起動したい場合は、pipline分 + 下流ジョブ並列実行分必要になるのか。。。


Pluginに頼ってみる

kyon-mm.hatenablog.com

Jenkins上からプラグインを探してみたけどなかった、ので変わりに下記のプラグインを入れてみた。

f:id:hoge-hogeo:20180926150335p:plain


パターンマッチで実行中のジョブがあったら、自分をブロックするようなので、雑に「.*」で試してみよう。 f:id:hoge-hogeo:20180926150603p:plain

Bulk-Deploy-Account-for-WhiteとBulk-Deploy-API-for-Whiteを同時実行してみる。

キューに片方が入って、もう片方はビルドが実行中になった。

f:id:hoge-hogeo:20180926151003p:plain

オンマウスで待ってるぜコメントが見れた。

f:id:hoge-hogeo:20180926151009p:plain

詰まることなく、2つのパイプラインジョブが完了した。

f:id:hoge-hogeo:20180926151240p:plain

一旦、これで排他的な動きは実現できた。。。