hoge-hogeoのひきこもごも

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

備忘録:HAProxyのtimeoutを伸ばす

Q: オフィスからTableau Desktopを使ってプロキシサーバ経由で本番DBのリードレプリカに繋いでいるけど、1分くらいでタイムアウトしてしまうのでタイムアウトをのばしてください。

A: PRDのDB(リードレプリカとはいえ)にログインしっぱなしはやめてください。

idle timeoutはこの2つっぽい。

listen mysql
        bind *:3306
        timeout connect 10s
        ★timeout client 30m
        ★timeout server 30m
        mode tcp
        server singleMySQL ${DB_ENDPOINT}:3306

Logrotate: dailyとか関係なく、ログサイズでローテートしたい

tl;dr

  • /etc/cron.daily/logrotateは/etc/cron.hourly/に引っ越ししよ
  • maxsize使おうね
  • 1日に何度もローテしたければunixtimeとか使って、ログローテしよ
# cat /etc/logrotate.d/test_hoge 
/var/log/test_hoge/*.log {
        daily
        maxsize 1M⬅︎これ
        dateext
        dateformat -%Y%m%d-%s⬅︎これ
        missingok
        rotate 7
        compress
        notifempty
        create 644 root root
}

検証開始

検証用のログローテ設定

これで、logrotateを1時間置きに回せば、dailyでローテorサイズでローテができるはず。

$ cat /etc/logrotate.d/test_hoge 
/var/log/test_hoge/*.log {
        daily
        maxsize 1M
        missingok
        rotate 7
        compress
        notifempty
        create 644 root root
}

1Mのファイルを作る。

$ dd if=/dev/zero of=test.log bs=1M count=1
1+0 レコード入力
1+0 レコード出力
1048576 バイト (1.0 MB) コピーされました、 0.0025573 秒、 410 MB/秒

#1MBぴったりだとローテされないかもなのでちょっと足した
$ echo hoge >> /var/log/test_hoge/test.log 

$ mv test.log /var/log/test_hoge/

ローテートを手動実行した結果、1MB以上なので、ローテされた。(あ、でもこれ当日初のローテートなので、dailyが効いてるだけかも)

$ /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
$ ls -l /var/log/test_hoge/
合計 4
-rw-r--r--. 1 root   root      0  3月 26 06:44 test.log
-rw-rw-r--. 1 centos centos 1058  3月 26 06:44 test.log-20190326.gz

1M超えていない&&1日前のログをローテするか

これは普通のdailyの検証かな。

statusファイルを1日前に戻して、logrotate.statusファイルのtest.logの日時も1日前(20190325)に偽造。

5バイトのログファイルを作成

# mv /var/log/test_hoge/test.log-20190326.gz /var/log/test_hoge/test.log-20190325.gz
# vim /var/lib/logrotate/logrotate.status
# grep test_hoge /var/lib/logrotate/logrotate.status 
"/var/log/test_hoge/test.log" 2019-3-25-6:46:31

$ sudo sh -c "echo hoge>> /var/log/test_hoge/test.log"
$  ls -l /var/log/test_hoge/
合計 8
-rw-r--r--. 1 root   root      5  3月 26 06:45 test.log
-rw-rw-r--. 1 centos centos 1058  3月 26 06:44 test.log-20190325.gz

logrotateを手動実行した結果、statusファイル内の時刻が更新された。

# /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
# grep test_hoge /var/lib/logrotate/logrotate.status 
"/var/log/test_hoge/test.log" 2019-3-26-6:46:31

1M超えていない&&1日前のログなのでローテされた。

"/var/log/test_hoge/test.log" 2019-3-26-6:46:31
# ls -l /var/log/test_hoge/
total 8
-rw-r--r--. 1 root   root      0 Mar 26 06:46 test.log
-rw-rw-r--. 1 centos centos 1058 Mar 26 06:44 test.log-20190325.gz
-rw-r--r--. 1 root   root     25 Mar 26 06:45 test.log-20190326.gz

当日すでにローテ済み&&1M超えのログをローテするか

当日すでにdailyでのローテートは済んでいるが、ログファイルが1Mを超えた場合に、

cron.hourlyで実行されたlogrotateでちゃんとローテされるか。

2Mのファイルを準備

# ls -l /var/log/test_hoge/
total 2056
-rw-r--r--. 1 root   root   2097152 Mar 26 07:02 test.log
-rw-rw-r--. 1 centos centos    1058 Mar 26 06:44 test.log-20190325.gz
-rw-r--r--. 1 root   root        25 Mar 26 06:45 test.log-20190326.gz

当日分はローテ済みなので

# date
Tue Mar 26 07:04:49 UTC 2019

# grep test_hoge /var/lib/logrotate/logrotate.status 
"/var/log/test_hoge/test.log" 2019-3-26-6:46:31

daily or 1M超えたファイルをローテできるかがこれで分かるはず

# /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf
# grep test_hoge /var/lib/logrotate/logrotate.status 
"/var/log/test_hoge/test.log" 2019-3-26-7:6:55

# ls -l /var/log/test_hoge/
total 2056
-rw-r--r--. 1 root   root   2097152 Mar 26 07:02 test.log
-rw-rw-r--. 1 centos centos    1058 Mar 26 06:44 test.log-20190325.gz
-rw-r--r--. 1 root   root        25 Mar 26 06:45 test.log-20190326.gz

statusは更新されたのに、ローテは走ってない。。。

rotating pattern: /var/log/test_hoge/*.log  after 1 days (7 rotations)
empty log files are not rotated, log files >= 1048576 are rotated earlier, old logs are removed
considering log /var/log/test_hoge/test.log
  log needs rotating
rotating log /var/log/test_hoge/test.log, log->rotateCount is 7
dateext suffix '-20190326'
glob pattern '-[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]'
destination /var/log/test_hoge/test.log-20190326.gz already exists, skipping rotation

date suffixが被ってるからスキップされてた。。。

苦しいけど、unixtimeで回避してみる。

/var/log/test_hoge/*.log {
        daily
        maxsize 1M
        dateext
        dateformat -%Y%m%d-%s
        missingok
        rotate 7
        compress
        notifempty
        create 644 root root
}

これならdate suffixはまず被らない。

# /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf 
# ls -lt /var/log/test_hoge/
total 12
-rw-r--r--. 1 root   root      0 Mar 26 07:16 test.log
-rw-r--r--. 1 root   root   2067 Mar 26 07:02 test.log-20190326-1553584560.gz
-rw-r--r--. 1 root   root     25 Mar 26 06:45 test.log-20190326.gz
-rw-rw-r--. 1 centos centos 1058 Mar 26 06:44 test.log-20190325.gz

すでにローテ済み&&1M超えのログをローテするか:again

もう一度2Mのファイルを準備。

logrotate.stausは変更しない。

# ls -lt /var/log/test_hoge/
total 2060
-rw-r--r--. 1 root   root   2097152 Mar 26 07:20 test.log
-rw-r--r--. 1 root   root      2067 Mar 26 07:02 test.log-20190326-1553584560.gz
-rw-r--r--. 1 root   root        25 Mar 26 06:45 test.log-20190326.gz
-rw-rw-r--. 1 centos centos    1058 Mar 26 06:44 test.log-20190325.gz

# date
Tue Mar 26 07:21:06 UTC 2019

# grep test_hoge /var/lib/logrotate/logrotate.status 
"/var/log/test_hoge/test.log" 2019-3-26-7:16:0

DEKITA!

# /usr/sbin/logrotate -s /var/lib/logrotate/logrotate.status /etc/logrotate.conf 
# ls -lt /var/log/test_hoge/
total 16
-rw-r--r--. 1 root   root      0 Mar 26 07:21 test.log
-rw-r--r--. 1 root   root   2067 Mar 26 07:20 test.log-20190326-1553584904.gz
-rw-r--r--. 1 root   root   2067 Mar 26 07:02 test.log-20190326-1553584560.gz
-rw-r--r--. 1 root   root     25 Mar 26 06:45 test.log-20190326.gz
-rw-rw-r--. 1 centos centos 1058 Mar 26 06:44 test.log-20190325.gz

おまけ

書き方ダメなやつ

*だけで指定するやつ

/home/ubuntu/tools/log/* {
    daily
    missingok
    rotate 3
    compress
    notifempty
}

永遠にローテされる。

-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:06 lifecycle_action_polling_sqs_20190610000601.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:05 lifecycle_action_polling_sqs_20190610000501.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:04 lifecycle_action_polling_sqs_20190610000401.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:03 lifecycle_action_polling_sqs_20190610000301.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:02 lifecycle_action_polling_sqs_20190610000201.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:01 lifecycle_action_polling_sqs_20190610000101.log.1.1.gz.1.gz
-rw-rw-r-- 1 ubuntu ubuntu   343 Jun 10 00:00 lifecycle_action_polling_sqs_20190610000001.log.1.1.gz.1.gz

当然だけど*で引っかかるからひたすらローテート対象になって、圧縮されていく。

正しくは、*.logとかだね。

(ファイルのローテート規則がおかしいのは、途中からdelaycompress外したから)

API Gateway: API Keyを使ってAPI実行をする

雑な備忘録

やりたきこと

API GatewayでLambdaたたきたい(Lambdaでメール飛ばす)

お品書き

  • APIをデプロイする
  • API Keyを作る
  • API Keyにアタッチする使用量プランを作る
  • APIを使用量プランにアタッチする

手順

APIをデプロイする

ここはいつも通り f:id:hoge-hogeo:20190325141420p:plain

ステージは適当に f:id:hoge-hogeo:20190311213013p:plain

API Keyを作る

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

ここもこだわりなければ適当に f:id:hoge-hogeo:20190311213250p:plain

API Keyにアタッチする使用量プランを作る

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

APIを使用量プランにアタッチする

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

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

APIに使用量プランがアタッチされた。 f:id:hoge-hogeo:20190311214012p:plain

なにもないけどPOSTでAPI Gatewayたたく

$ curl -X POST -H 'x-api-key:hogehoge' https://***********.execute-api.ap-northeast-1.amazonaws.com/dev/send
null

Lambdaが実行されて、メールきた。

POSTのメソッドなのにしばらくGETでcurl投げまくってハマってたのは内緒。 f:id:hoge-hogeo:20190311222143p:plain

Docker: 使っていないボリュームを削除してディスク使用量を節約する

dockerコンテナ周りでボリューム食ってるのかなーと調べてたら、こんなコマンド見つけた。

# docker system df -v
Images space usage:

REPOSITORY          TAG                 IMAGE ID            CREATED ago         SIZE                SHARED SIZE         UNIQUE SiZE         CONTAINERS
errbit/errbit       latest              a9d99b72415d        14 months ago ago   312.6MB             136.8MB             175.8MB             1
mongo               3.2                 e326370ecc98        14 months ago ago   301.3MB             0B                  301.3MB             1
redash/redash       latest              8156a8c1b0c6        18 months ago ago   930.1MB             566.1MB             364MB               2
redash_server       latest              5f398543e01d        19 months ago ago   936.1MB             566.1MB             370MB               0
redis               3.0-alpine          856249f48b0c        20 months ago ago   12.63MB             0B                  12.63MB             1
redash/base         latest              9d04584f371a        20 months ago ago   566.1MB             566.1MB             0B                  0
postgres            9.5.6-alpine        cc38b642ca58        21 months ago ago   36.85MB             0B                  36.85MB             1
postgres            9.5.6               52caac8f7edd        21 months ago ago   265.5MB             0B                  265.5MB             1
<none>              <none>              46336a6d9d4c        22 months ago ago   915.4MB             0B                  915.4MB             0
ruby                2.3.3-alpine        9e455f733647        23 months ago ago   136.8MB             136.8MB             0B                  0
redash/nginx        latest              76abf32984e9        3 years ago ago     134.5MB             0B                  134.5MB             1

Containers space usage:

CONTAINER ID        IMAGE                   COMMAND                  LOCAL VOLUMES       SIZE                CREATED ago         STATUS                       NAMES
5f15ff79bc44        errbit/errbit:latest    "bundle exec puma ..."   0                   0B                  3 weeks ago ago     Up 3 weeks (healthy)         errbit_errbit_1
9c876e5f91f4        redash/redash:latest    "/app/bin/docker-e..."   0                   16.5kB              11 months ago ago   Up 18 hours                  redash_worker_1
4b08babe3be6        redash/nginx:latest     "nginx -g 'daemon ..."   0                   38.8MB              11 months ago ago   Up 6 weeks                   redash_nginx_1
862cb38007a3        redash/redash:latest    "/app/bin/docker-e..."   0                   1.16GB              11 months ago ago   Up 7 days                    redash_server_1
098126220a5b        mongo:3.2               "docker-entrypoint..."   2                   0B                  14 months ago ago   Up 3 weeks                   errbit_mongo_1
f6e965d00219        postgres:9.5.6-alpine   "docker-entrypoint..."   0                   28.5kB              17 months ago ago   Up 6 weeks                   redash_postgres_1
03a8de294c69        redis:3.0-alpine        "docker-entrypoint..."   1                   0B                  17 months ago ago   Up 6 weeks                   redash_redis_1
d68b144fc7f3        postgres:9.5.6          "docker-entrypoint..."   0                   1.17GB              17 months ago ago   Exited (137) 17 months ago   bkdb

Local Volumes space usage:

VOLUME NAME                                                        LINKS               SIZE
a746a9e11969121fec6fa9d829501d3ee259b2d1ee4f25023baa1e34bf36f654   0                   24.65kB
b5976d2e3d871820bd35e87d20ac174e08f927d569ed04727d8802fb0034b253   1                   74.73MB
f2cab22375163310d24db55662477203e9b8b37fbec6ef4528cec6ab2fc41133   0                   38.35MB
2fc297e830636a0d9a4b2d0d67c83c33a24b8e6fc768146a7f37ad55b7c57429   0                   8.967kB
8aecf8c34087d426dc4737fa6690be5efd2ecdfff7f4e242eef5f48ac6bfdc15   0                   172B
62cac3cf9d837a22fa835485b17e1c3cb4b7ac0e002f5e08bebfbf7b9076ef74   0                   2.365GB
88f3613372d4950e245a94bec539296eb17c99109370290cf83bdbc210033671   0                   1.931kB
ee9834461c5f561314a20c30e8beee5dcc4f28a5275b89792f20a9d38c39274f   0                   1.937MB
f56dd56299fbc947791fa9c1c9ce3445815db04e9e91a039c76910659de6ef37   1                   0B
ff593cb1ceef802b9223c6cb0f9a184ce9686d9f6fd46558471699cab0e89178   0                   38.49MB
09557be5cec0ec1e30f88e5d1ba65361255eb57dae1ce20f4dfc71c695f6e271   1                   477.2MB
55e03608a3ee112ad7cf592a2057345a15037d29ec136169dab356f03f3f8f04   0                   1.386GB

「Local Volumes space usage:」のLINKS 0が使われていないボリュームらしい

# docker volume ls -f dangling=true
DRIVER              VOLUME NAME
local               2fc297e830636a0d9a4b2d0d67c83c33a24b8e6fc768146a7f37ad55b7c57429
local               55e03608a3ee112ad7cf592a2057345a15037d29ec136169dab356f03f3f8f04
local               62cac3cf9d837a22fa835485b17e1c3cb4b7ac0e002f5e08bebfbf7b9076ef74
local               88f3613372d4950e245a94bec539296eb17c99109370290cf83bdbc210033671
local               8aecf8c34087d426dc4737fa6690be5efd2ecdfff7f4e242eef5f48ac6bfdc15
local               a746a9e11969121fec6fa9d829501d3ee259b2d1ee4f25023baa1e34bf36f654
local               ee9834461c5f561314a20c30e8beee5dcc4f28a5275b89792f20a9d38c39274f
local               f2cab22375163310d24db55662477203e9b8b37fbec6ef4528cec6ab2fc41133
local               ff593cb1ceef802b9223c6cb0f9a184ce9686d9f6fd46558471699cab0e89178

使っていないボリュームを削除する。

# docker volume prune
WARNING! This will remove all volumes not used by at least one container.
Are you sure you want to continue? [y/N] y
Deleted Volumes:
ee9834461c5f561314a20c30e8beee5dcc4f28a527ab89792f20a9d38c39274f
ff593cb1ceef802b9223c6cb0f9a184ce9686a9f6fd46558471699cab0e89178
55e03608a3ee112ad7cf592a2057345a15037d29ec136169dab356f03f3f8f04
62cac3cf9d837a22fa835485b17e1c3cb4b7ac0e002f5e08bebfbf7b9076ef74
88f3613372d4950e245a94bec539296eb17c991a9370290cf83bdbc210033671
f2cab22375163310d24db55662477203e9b8b37fbec6ef4528cec6ab2fc41133
2fc297e830636a0d9a4b2d0d67c83c33a24b8e6fca68146a7f37ad55b7c57429
8aecf8c34087d426dc4737fa6690be5efd2ecdfff7f4e242eef5f48ac6bfdc15
a746a9e11969121fec6fa9d829501d3ee259b2d1ee4f2a023baa1e34bf36f654

LINKS 0のボリュームがなくなったので、アタッチされていないボリュームはちゃんと消されてそう。

# docker system df -v
Images space usage:

REPOSITORY          TAG                 IMAGE ID            CREATED ago         SIZE                SHARED SIZE         UNIQUE SiZE         CONTAINERS
errbit/errbit       latest              a9d99b72415d        14 months ago ago   312.6MB             136.8MB             175.8MB             1
mongo               3.2                 e326370ecc98        14 months ago ago   301.3MB             0B                  301.3MB             1
redash/redash       latest              8156a8c1b0c6        18 months ago ago   930.1MB             566.1MB             364MB               2
redash_server       latest              5f398543e01d        19 months ago ago   936.1MB             566.1MB             370MB               0
redis               3.0-alpine          856249f48b0c        20 months ago ago   12.63MB             0B                  12.63MB             1
redash/base         latest              9d04584f371a        20 months ago ago   566.1MB             566.1MB             0B                  0
postgres            9.5.6-alpine        cc38b642ca58        21 months ago ago   36.85MB             0B                  36.85MB             1
postgres            9.5.6               52caac8f7edd        21 months ago ago   265.5MB             0B                  265.5MB             1
<none>              <none>              46336a6d9d4c        22 months ago ago   915.4MB             0B                  915.4MB             0
ruby                2.3.3-alpine        9e455f733647        23 months ago ago   136.8MB             136.8MB             0B                  0
redash/nginx        latest              76abf32984e9        3 years ago ago     134.5MB             0B                  134.5MB             1

Containers space usage:

CONTAINER ID        IMAGE                   COMMAND                  LOCAL VOLUMES       SIZE                CREATED ago         STATUS                       NAMES
5f15ff79bc44        errbit/errbit:latest    "bundle exec puma ..."   0                   0B                  3 weeks ago ago     Up 3 weeks (healthy)         errbit_errbit_1
9c876e5f91f4        redash/redash:latest    "/app/bin/docker-e..."   0                   16.5kB              11 months ago ago   Up 20 hours                  redash_worker_1
4b08babe3be6        redash/nginx:latest     "nginx -g 'daemon ..."   0                   38.8MB              11 months ago ago   Up 6 weeks                   redash_nginx_1
862cb38007a3        redash/redash:latest    "/app/bin/docker-e..."   0                   1.16GB              11 months ago ago   Up 7 days                    redash_server_1
098126220a5b        mongo:3.2               "docker-entrypoint..."   2                   0B                  14 months ago ago   Up 3 weeks                   errbit_mongo_1
f6e965d00219        postgres:9.5.6-alpine   "docker-entrypoint..."   0                   28.5kB              17 months ago ago   Up 6 weeks                   redash_postgres_1
03a8de294c69        redis:3.0-alpine        "docker-entrypoint..."   1                   0B                  17 months ago ago   Up 6 weeks                   redash_redis_1
d68b144fc7f3        postgres:9.5.6          "docker-entrypoint..."   0                   1.17GB              17 months ago ago   Exited (137) 17 months ago   bkdb

Local Volumes space usage:

VOLUME NAME                                                        LINKS               SIZE
b5976d2e3d871820bd35e87d20ac174e08f927d569ed04727d8802fb0034b253   1                   74.76MB
09557be5cec0ec1e30f88e5d1ba65361255eb57dae1ce20f4dfc71c695f6e271   1                   477.3MB
f56dd56299fbc947791fa9c1c9ce3445815db04e9e91a039c76910659de6ef37   1                   0B

Terraform: module化する話

モノはこんな

$ cd terra-modulized-es
$ tree .
.
├── modules
│   └── elasticsearch
│       └── aws_es_node.tf
└── services
    └── elasticsearch
        ├── production
        │   ├── main.tf
        └── staging
            └── main.tf

6 directories, 4 files

ここに変数の中身を書く

$cat terra-modulized-es/services/elasticsearch/production/main.tf
module "production-es-cluster" {
  region          = "ap-northeast-1"
  source          = "../../../modules/elasticsearch"
  lb_name         = "production-es-alb"
  internal_option = "false"
  lb_type         = "application"
  es_alb_sg       = "sg-xxxxxxxxxxxxxxxxx"
  es_alb_subnet   = ["subnet-xxxxxxxx", "subnet-xxxxxxxx"]
  env             = "production"
}

こっちは変数の定義とリソースのオプションを書くだけ

$cat terra-modulized-es/modules/elasticsearch/aws_es_node.tf
provider "aws" {
  region = "${var.region}"
}

variable "region" {}
variable "lb_name" {}
variable "internal_option" {}
variable "lb_type" {}
variable "es_alb_sg" {}

variable "es_alb_subnet" {
  type = "list"
}

variable "env" {}

resource "aws_lb" "es-alb" {
  name                       = "${var.lb_name}"
  internal                   = "${var.internal_option}"
  load_balancer_type         = "${var.lb_type}"
  security_groups            = ["${var.es_alb_sg}"]
  subnets                    = ["${var.es_alb_subnet}"]
  enable_deletion_protection = false

  tags = {
    Environment = "${var.env}"
  }
}

できた。

$ cd terra-modulized-es/services/elasticsearch/production
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  + module.production-es-cluster.aws_lb.es-alb
〜略〜
module.production-es-cluster.aws_lb.es-alb: Still creating... (2m10s elapsed)
module.production-es-cluster.aws_lb.es-alb: Creation complete after 2m13s (ID: arn:aws:elasticloadbalancing:ap-northea...app/production-es-alb/xxxxxxxx)

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

variableも外だしした方がいいな。

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

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