AWS [Retirement Notification] 対応

AWS [Retirement Notification] 対応

概要

とある日、AWS よりこんなメール通知が来ました。

要約すると
ホストしている基盤のハードウェアで回復不可能な障害が検知されたので
指定期限までに対応しないとインスタンスが停止する、とのこと。

今回こちらの対応をまとめました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Dear Amazon EC2 Customer,

We have important news about your account (AWS Account ID: xxxxxxxxxxxx). EC2 has detected degradation of the underlying hardware hosting your Amazon EC2 instance (instance-ID: i-xxxxxxxx) in the ap-northeast-1 region. Due to this degradation, your instance could already be unreachable. After 2017-04-25 04:00 UTC your instance, which has an EBS volume as the root device, will be stopped.

You can see more information on your instances that are scheduled for retirement in the AWS Management Console (https://console.aws.amazon.com/ec2/v2/home?region=ap-northeast-1#Events)

* How does this affect you?
Your instance's root device is an EBS volume and the instance will be stopped after the specified retirement date. You can start it again at any time. Note that if you have EC2 instance store volumes attached to the instance, any data on these volumes will be lost when the instance is stopped or terminated as these volumes are physically attached to the host computer

* What do you need to do?
You may still be able to access the instance. We recommend that you replace the instance by creating an AMI of your instance and launch a new instance from the AMI. For more information please see Amazon Machine Images (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html) in the EC2 User Guide. In case of difficulties stopping your EBS-backed instance, please see the Instance FAQ (http://aws.amazon.com/instance-help/#ebs-stuck-stopping).

* Why retirement?
AWS may schedule instances for retirement in cases where there is an unrecoverable issue with the underlying hardware. For more information about scheduled retirement events please see the EC2 user guide (http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-retirement.html). To avoid single points of failure within critical applications, please refer to our architecture center for more information on implementing fault-tolerant architectures: http://aws.amazon.com/architecture

If you have any questions or concerns, you can contact the AWS Support Team on the community forums and via AWS Premium Support at: http://aws.amazon.com/support

Sincerely,
Amazon Web Services
  • AWS Console イベントを見ると一覧で表示されている。
  • AWS Console 詳細を見ると Notice が出ている。

ToDO

ボリュームタイプによって異なります。

  • EBS ボリューム

    • インスタンスの停止後、起動 (Reboot は ×)
  • インスタンスストアボリューム

    • AMI からインスタンス再作成、データ移行

今回は EBS ボリューム対応について記載してます。

対応

対象インスタンスが多かったのでローカル PC (macOS) から awscli でインスタンス停止 → 起動するシェル作成しました。
本番環境で利用されるインスタンスも含まれていた為、1 件ずつ実行することとしました。

事前準備

  • awscli, jq インストール
1
$ brew install awscli jq
  • 各アカウント毎のアクセスキー、シークレットキー等設定
1
2
$ aws configure --profile <profile>
$ grep 'profile' ~/.aws/config

インスタンスの停止・再起動シェル

以下のように実行すると
インスタンスが起動(running)していれば
停止後、再び起動し、ステータスチェックをするようにしました。

1
$ sh stop_and_start_ec2_instance.sh "<profile>" "<instance id>"

イベント情報取得シェル

.aws/config で設定されている profile を全てチェックし
未対応インスタンスのみ表示する様修正しました。

結果確認

大体 1 インスタンス 5 分程度で完了。
問題なく停止起動でき、対象イベントが一覧から消えたことを確認しました ♪

所感

メンテ対象インスタンスの Region が northeast に集中していたのが気になる点でした。
このインスタンス何に使ってるんだっけ?とならない様に、インスタンスや private key の命名ルール必須と感じました。

以上です。

Docker コマンド早見表

Docker コマンド早見表

バージョン

1
2
3
docker --version

Docker version 17.04.0-ce, build 4845c56

コンテナ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker ps                     # running コンテナ一覧
docker ps -a # 全コンテナ一覧表示
docker start <CONTAINER ID> # コンテナ起動
docker restart <CONTAINER ID> # コンテナ再起動
docker stop <CONTAINER ID> # コンテナ終了
docker kill <CONTAINER ID> # コンテナ強制終了
docker attach <CONTAINER ID> # コンテナへアタッチ
docker top <CONTAINER ID> # コンテナプロセスを表示
docker logs -f <CONTAINER ID> # コンテナログ表示
docker inspect <CONTAINER ID> # コンテナ情報表示
docker rm <CONTAINER ID> # コンテナID指定でコンテナ削除
dockre rm <CONTAINER NAME...> # コンテナ名(複数)指定でコンテナ削除
docker container prune # 停止コンテナを削除

dockr run -it -h <host name> <IMAGE>[:TAG] <command> # イメージよりコンテナ起動 command 実施

イメージ

1
2
3
4
docker pull <IMAGE NAME>[:tag]     # イメージダウンロード
docker images ls # イメージ一覧
docker inspect <IMAGE ID> # イメージ情報表示
docker rmi <IMAGE ID> # イメージ削除

イメージ作成

1
2
docker build -t NAME[:TAG]
docker commit -m "<comment here>" <CONTAINER ID> <IMAGE NAME>[:TAG]

Docker Compose

1
2
3
4
5
docker-compose up -d    # デタッチモードでイメージよりコンテナ起動
docker-compose ps # コンテナ一覧表示
docker-compose stop # docker compose 管理下全てのコンテナ停止
docker-compose start # docker compose 管理下全てのコンテナ起動
docker-compose rm # docker compose 管理下全ての停止コンテナ削除
Vagrant (Ubuntu) に Docker, Docker Compose インストール

Vagrant (Ubuntu) に Docker, Docker Compose インストール

概要

開発環境構築用に作成した、
Vagrant (Ubuntu) に Docker と Docker Compose をインストールする手順をまとめました。

Vagrantfile 作成

かなりシンプルにしてます。

  • Vagrantfile
1
2
3
4
5
6
7
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.network "private_network", ip: "192.168.35.101"
end

vagrant provision で docker compose をインストールすることも可能ですが
vagrant ならではの provision だと他環境で利用できない為、OS 上でインストールする方針です。

VM 起動

1
2
3
4
5
6
7
8
9
MacOS%$ vagrant up
...
しばし待つ
...

MacOS%$ vagrant ssh

// ssh ログイン成功
vagrant%$

Vagrant Ubuntu 環境情報確認

1
2
3
4
5
6
7
vagrant%$ lsb_release -a

No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 14.04.5 LTS
Release: 14.04
Codename: trusty

カーネルバージョン確認

1
2
vagrant%$ uname -r
3.13.0-116-generic

カーネルバージョンが 3.10 より低いとバグを引き起こす危険性があるので NG。
別のカーネルバージョンの高い box を使用しましょう。

古いバージョンをアンインストール

1
vagrant%$ sudo apt-get remove docker docker-engine

extra パッケージインストール

Docker に aufs ストレージを使用許可する為です。

1
2
3
4
5
vagrant%$ sudo apt-get update
vagrant%$ sudo apt-get -y install \
wget \
linux-image-extra-$(uname -r) \
linux-image-extra-virtual

Docker インストール

1
2
3
4
5
6
7
8
9
// Docker インストール
vagrant%$ wget -qO- https://get.docker.com/ | sh

// Docker バージョン確認
vagrant%$ docker --version
Docker version 17.04.0-ce, build 4845c56

// vagrant ユーザを docker グループに追加 (一旦ログアウトしログインし直すと有効になることを確認できます)
vagrant%$ sudo usermod -aG docker vagrant

Docker Compose インストール

1
2
3
4
5
6
7
8
9
10
11
vagrant%$ curl -L "https://github.com/docker/compose/releases/download/1.12.0/docker-compose-$(uname -s)-$(uname -m)" >  ~/docker-compose

// 実行権限付与
vagrant%$ chmod +x ~/docker-compose

// 実行パス移動
vagrant%$ sudo mv docker-compose /usr/bin/

// Docker Compose バージョン確認
vagrant%$ docker-compose --version
docker-compose version 1.12.0, build b31ff33

一度ログアウトし再度ログイン

1
2
3
vagrant%$ exit
MacOS%$ vagrant ssh
vagrant%$

メモリとスワップ利用量の調整

Docker を使用していない時にメモリのオーバーヘッドとパフォーマンス劣化を低減させる様、
GRUB (GRand Unified Bootloader: グラブ or ジーラブ) に設定する必要があります。

  • grub 設定
1
2
3
4
vagrant%$ sudo vi /etc/default/grub

# GRUB_CMDLINE_LINUX=""
GRUB_CMDLINE_LINUX="cgroup_enable=memory swapaccount=1"
  • GRUB (GRand Unified Bootloader: グラブ or ジーラブ) 更新
1
2
3
4
vagrant%$ sudo update-grub

// 念の為、再起動
vagrant%$ sudo reboot

以上で準備完了です ♪

早速試してみる

簡単なチュートリアルとして nginx コンテナを立ててみます。

1
2
3
4
5
6
7
8
9
10
vagrant%$ docker run --rm -p 80:80 nginx:mainline-alpine

Unable to find image 'nginx:mainline-alpine' locally
mainline-alpine: Pulling from library/nginx
709515475419: Already exists
4b21d71b440a: Pull complete
c92260fe6357: Pull complete
ed383a1b82df: Pull complete
Digest: sha256:5aadb68304a38a8e2719605e4e180413f390cd6647602bee9bdedd59753c3590
Status: Downloaded newer image for nginx:mainline-alpine

ブラウザアクセス

ローカルの Mac からブラウザでアクセス

http://192.168.35.101

※192.168.35.101 … Vagrant で指定した private ip

問題なく Welcome ページが表示されました。

先程のログに以下のようにアクセスログが出力されるのがわかります。

1
192.168.35.1 - - [13/Apr/2017:10:45:46 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36" "-"

MacOS → Vagrant → Docker
とアクセスできるようになりました ♪

追記

今回作成した Box を Vagrant Cloud に置きました。

https://atlas.hashicorp.com/kenzo0107/boxes/ubuntu14.04.5LTS-docker-dockercompose/

こちら設定を元にこれから様々な環境構築を記載していきたいと思います ♪

参照

Docker Compose チュートリアル

Docker Compose チュートリアル

前回 Vagrant (Ubuntu)で Docker, Docker Compose 環境構築しました。

上記環境を元に Docker Compose チュートリアルを実行しました。

完全な備忘録です。

プロジェクトディレクトリ作成

1
vagrant%$ mkdir composetest && cd composetest

app.py 作成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def hello():
count = redis.incr('hits')
#return 'Hello World! I have been seen {} times.\n'.format(count)
return 'Hello from Docker! I have been seen {} times.\n'.format(count)

if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)

requirements.txt 作成

pip でインストールするモジュールを列挙します。

1
2
flask
redis

Dockerfile 作成

1
2
3
4
5
FROM python:3.4-alpine
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

docker-compose.yml 作成

1
2
3
4
5
6
7
8
9
10
11
version: '2'
services:
web:
build: .
ports:
- '5000:5000'
volumes:
- .:/code

redis:
image: 'redis:alpine'

Docker Compose でイメージビルド、コンテナ起動

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
vagrant%$ docker-compose up

Creating composetest_web_1
Creating composetest_redis_1
Attaching to composetest_redis_1, composetest_web_1
redis_1 | 1:C 13 Apr 14:25:38.483 # Warning: no config file specified, using the default config. Inorder to specify a config file use redis-server /path/to/redis.conf
redis_1 | _._
redis_1 | _.-``__ ''-._
redis_1 | _.-`` `. `_. ''-._ Redis 3.2.8 (00000000/0) 64 bit
redis_1 | .-`` .-```. ```\/ _.,_ ''-._
redis_1 | ( ' , .-` | `, ) Running in standalone mode
redis_1 | |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379
redis_1 | | `-._ `._ / _.-' | PID: 1
redis_1 | `-._ `-._ `-./ _.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' | http://redis.io
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | |`-._`-._ `-.__.-' _.-'_.-'|
redis_1 | | `-._`-._ _.-'_.-' |
redis_1 | `-._ `-._`-.__.-'_.-' _.-'
redis_1 | `-._ `-.__.-' _.-'
redis_1 | `-._ _.-'
redis_1 | `-.__.-'
redis_1 |
redis_1 | 1:M 13 Apr 14:25:38.486 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1 | 1:M 13 Apr 14:25:38.486 # Server started, Redis version 3.2.8
redis_1 | 1:M 13 Apr 14:25:38.486 # WARNING overcommit_memory is set to 0! Background save may failunder low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf andthen reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1 | 1:M 13 Apr 14:25:38.486 * The server is now ready to accept connections on port 6379
web_1 | * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1 | * Restarting with stat
web_1 | * Debugger is active!
web_1 | * Debugger PIN: 135-466-976
web_1 | 192.168.35.1 - - [13/Apr/2017 14:25:53] "GET / HTTP/1.1" 200 -
web_1 | 192.168.35.1 - - [13/Apr/2017 14:25:53] "GET /favicon.ico HTTP/1.1" 404 -

ブラウザにアクセスしてみる。

表示されました!

リロードする度に以下数字部分がインクリメントされるのが確認できます。

1
Hello from Docker! I have been seen 1 times.

便利 ♪

Terraform でキーペア登録し起動した EC2 に SSH接続

Terraform でキーペア登録し起動した EC2 に SSH接続

今回やること

  • Mac ローカルで公開鍵、秘密鍵を生成
  • Terraform で EC2 起動、セキュリティグループで SSH (ポート 22)許可、key-pair 登録

Terraform の Hello World 的なチュートリアルと思っていただけたら幸いです。

環境

  • Mac OS 10.12.3 (Sierra)
  • Terraform 0.9.1

公開鍵、秘密鍵生成

RSA フォーマットで鍵を生成します。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ssh-keygen -t rsa

Enter file in which to save the key (/Users/kenzo_tanaka/.ssh/id_rsa): /Users/kenzo_tanaka/.ssh/terraform-test
Enter passphrase (empty for no passphrase): (空のままEnter)
Enter same passphrase again: (空のままEnter)
...
...

// 生成されたか確認
$ ls ~/.ssh/terraform-test*

/Users/kenzo_tanaka/.ssh/terraform-test # 秘密鍵
/Users/kenzo_tanaka/.ssh/terraform-test.pub # 公開鍵

公開鍵を起動した EC2 インスタンスに登録し
秘密鍵でアクセスします。

以下のように利用する予定です。

1
$ ssh -i ~/.ssh/terraform-test <ec2 user>@<ec2 public ip>

Terraform 設定ファイル

  • Point !

    • resource "aws_key_pair" で使用する公開鍵設定をしています。
    • resource "aws_security_group" で SSH(ポート 22)を開いてます。
    • resource "aws_instance" で使用しているセキュリティグループの指定は vpc_security_group_ids を利用
      • セキュリティグループの条件追加・削除する場合にインスタンスを一度削除し作り直すことをしたくない場合に vpc_security_group_ids を利用すると良いです。
  • main.tf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
provider "aws" {
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
region = "${var.region}"
}

resource "aws_instance" "example" {
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.nano"
key_name = "${aws_key_pair.auth.id}"
vpc_security_group_ids = ["${aws_security_group.default.id}"]
}

resource "aws_key_pair" "auth" {
key_name = "${var.key_name}"
public_key = "${file(var.public_key_path)}"
}

resource "aws_security_group" "default" {
name = "terraform_security_group"
description = "Used in the terraform"

# SSH access from anywhere
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
}
  • variables.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
variable "access_key" {}
variable "secret_key" {}
variable "region" {
default = "ap-northeast-1"
}

variable "amis" {
type = "map"
default = {
us-east-1 = "ami-13be557e"
us-west-2 = "ami-21f78e11"
ap-northeast-1 = "ami-1bfdb67c"
}
}

variable "key_name" {
description = "Desired name of AWS key pair"
}

variable "public_key_path" {
description = <<DESCRIPTION
Path to the SSH public key to be used for authentication.
Ensure this keypair is added to your local SSH agent so provisioners can
connect.

Example: ~/.ssh/terraform.pub
DESCRIPTION
}
  • terraform.tfvars
1
2
3
4
5
access_key = "A******************Q"
secret_key = "q**************************************Z"

key_name = "terraform-test"
public_key_path = "~/.ssh/terraform-test.pub"

いざ実行

  • 実行計画確認
1
$ terraform plan
  • 実行
1
$ terraform apply

確認

  • AWS コンソール上で起動確認

    • キーペアに terraform-test が指定されています。
    • vpc, subnet も自動的にアタッチされてます。
  • キーペア
    一応キーペアを見てみると登録されているのがわかります。
  • セキュリティグループ確認
  • SSH ログイン確認
1
$ ssh -i ~/.ssh/terraform-test ubuntu@ec2-54-65-244-25.ap-northeast-1.compute.amazonaws.com

無事 SSH ログインできました!

所感

terraform を見ながら各パラメータの利用意図を確認しながら
設定してみましたが
パラメータの説明自体はざっくりで利用方法まではわからないです。

Teffaform のチュートリアルに始まり
その他 Stack Overflow
適宜パターンを蓄積していく学習が程よいと思います。

参考

Terraform で AWS インフラストラクチャ!

Terraform で AWS インフラストラクチャ!

Terraform とは

  • インフラ構成や設定をコードにより実行計画を確認しながら自動化できるツール
  • AWS, Google Cloud 等多数のクラウドサービスで利用可能
  • HashiCorp 社製

今回やること

  • インスタンス起動
  • Elastic IP 付きインスタンス起動
  • インスタンス破棄

非常にミニマムなインフラ構築をしてみます。
※個人のアカウントでも無料枠を使えば数十円しか掛からなかったです。

環境

  • Mac OS Sierra X 10.12.3 16D32
  • Terraform 0.9.1

terraform インストール

1
$ brew install terraform

バージョン確認

1
2
3
$ terraform version

Terraform v0.9.1

では、早速使ってみます。

EC2 instance (t2.micro) 起動

  • main.tf 作成
1
2
3
4
5
6
7
8
9
10
provider "aws" {
access_key = "A******************Q"
secret_key = "q**************************************Z"
region = "ap-northeast-1"
}

resource "aws_instance" "example" {
ami = "ami-71d79f16"
instance_type = "t2.micro"
}
  • 実行計画確認
1
$ terraform plan
  • 実行
1
$ terraform apply

Amazon Console からインスタンスが起動されたことが確認できます。

変数を別ファイルで管理

上記 main.tf を github 等で管理するとなると
access_key, secret_key が露見されてしまいます。

その為、以下の様に別ファイルで管理することが望ましいです。

  • main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
variable "access_key" {}
variable "secret_key" {}
variable "region" {
default = "ap-northeast-1"
}

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

resource "aws_instance" "example" {
ami = "ami-71d79f16"
instance_type = "t2.micro"
}
  • terraform.tfvars
    • terraform 実行時に自動で読み込まれるファイル
1
2
access_key = "A******************Q"
secret_key = "q**************************************Z"
  • 実行計画確認
1
2
3
4
5
$ terraform plan

...

Plan: 1 to add, 0 to change, 0 to destroy.

正しく実行できることが確認できました。

terraform.tfvars ファイルは .gitignore に登録しておくなど
絶対に公開されない様な設定が望ましいと思います。

EC2 instance (t2.micro) AMI 変更

  • main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
variable "access_key" {}
variable "secret_key" {}
variable "region" {
default = "ap-northeast-1"
}

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

resource "aws_instance" "example" {
ami = "ami-047aed04"
instance_type = "t2.micro"
}
  • 実行計画

変更される内容が表示されます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ terraform plan

...

-/+ aws_instance.example
ami: "ami-71d79f16" => "ami-047aed04" (forces new resource)
associate_public_ip_address: "true" => "<computed>"
availability_zone: "ap-northeast-1a" => "<computed>"
ebs_block_device.#: "0" => "<computed>"
ephemeral_block_device.#: "0" => "<computed>"
instance_state: "running" => "<computed>"
instance_type: "t2.micro" => "t2.micro"
ipv6_addresses.#: "0" => "<computed>"
key_name: "" => "<computed>"
network_interface_id: "eni-f4a214bb" => "<computed>"
placement_group: "" => "<computed>"
private_dns: "ip-172-31-31-239.ap-northeast-1.compute.internal" => "<c
omputed>"
private_ip: "172.31.31.239" => "<computed>"
public_dns: "ec2-52-199-88-146.ap-northeast-1.compute.amazonaws.com"
=> "<computed>"
public_ip: "52.199.88.146" => "<computed>"
root_block_device.#: "1" => "<computed>"
security_groups.#: "0" => "<computed>"
source_dest_check: "true" => "true"
subnet_id: "subnet-7a79cc0d" => "<computed>"
tenancy: "default" => "<computed>"
vpc_security_group_ids.#: "1" => "<computed>"


Plan: 1 to add, 0 to change, 1 to destroy.

最初に作成したインスタンスは破棄され、新たにインスタンスを作成していることがわかります。

terraform で新規作成・変更ができました。

次は破棄してみましょう。

EC2 instance (t2.micro) 破棄

  • 実行計画確認

破棄対象のリソースが表示されます。

1
2
3
4
5
$ terraform plan -destroy

...

- aws_instance.example
  • 実行
1
2
3
4
5
6
7
8
9
10
$ terraform destroy

Do you really want to destroy?
Terraform will delete all your managed infrastructure.
There is no undo. Only 'yes' will be accepted to confirm.

Enter a value: yes (← yes 入力)
...

Destroy complete! Resources: 1 destroyed.

Amazon コンソールで破棄されたことを確認できます。

インスタンス起動し Elastic IP (固定 IP) 設定

  • main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
variable "access_key" {}
variable "secret_key" {}
variable "region" {
default = "ap-northeast-1"
}

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

resource "aws_instance" "example" {
ami = "ami-047aed04"
instance_type = "t2.micro"
}

resource "aws_eip" "ip" {
instance = "${aws_instance.example.id}"
}
  • 実行計画確認
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
$ terraform plan

...

+ aws_eip.ip
allocation_id: "<computed>"
association_id: "<computed>"
domain: "<computed>"
instance: "${aws_instance.example.id}"
network_interface: "<computed>"
private_ip: "<computed>"
public_ip: "<computed>"
vpc: "<computed>"

+ aws_instance.example
ami: "ami-047aed04"
associate_public_ip_address: "<computed>"
availability_zone: "<computed>"
ebs_block_device.#: "<computed>"
ephemeral_block_device.#: "<computed>"
instance_state: "<computed>"
instance_type: "t2.micro"
ipv6_addresses.#: "<computed>"
key_name: "<computed>"
network_interface_id: "<computed>"
placement_group: "<computed>"
private_dns: "<computed>"
private_ip: "<computed>"
public_dns: "<computed>"
public_ip: "<computed>"
root_block_device.#: "<computed>"
security_groups.#: "<computed>"
source_dest_check: "true"
subnet_id: "<computed>"
tenancy: "<computed>"
vpc_security_group_ids.#: "<computed>"


Plan: 2 to add, 0 to change, 0 to destroy.
  • 実行
1
$ terraform apply

Elastic IP が設定されたインスタンスが起動していることが確認できます。
※ただ、起動しただけで接続できないことがわかります(>_<) 次回実施します

[f:id:kenzo0107:20170323230208p:plain]

  • 実行計画確認

破棄される Elastic IP, インスタンスが確認できます。

1
2
3
4
5
6
7
$ terraform plan -destroy

...

- aws_eip.ip

- aws_instance.example
  • 実行
1
2
3
4
5
$ terraform destroy

...

Destroy complete! Resources: 2 destroyed.

全インスタンスが破棄されていることが確認できました。

その他便利な設定

Map 設定

  • region 毎に AMI を選択し terraform apply 時に変数指定し選択可能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...

variable "amis" {
type = "map"
default = {
us-east-1 = "ami-13be557e"
us-east-2 = "ami-71d79f16"
us-west-1 = "ami-00175967"
us-west-2 = "ami-06b94666"
ap-northeast-1 = "ami-047aed04"
}
}

...

resource "aws_instance" "example" {
ami = "${lookup(var.amis, var.region)}"
instance_type = "t2.micro"
}

ex) region us-west-2 を選択

1
$ terraform apply -var region=us-west-2

出力設定

生成された Elastic IP の値が知りたいときなど便利です。

  • main.tf
1
2
3
4
5
6
7
resource "aws_eip" "ip" {
instance = "${aws_instance.example.id}"
}

output "ip" {
value = "${aws_eip.ip.public_ip}"
}

出力値が確認できます。

1
2
3
4
5
6
7
$ terraform apply

...

Outputs:

ip = 52.197.157.206
  • terraform output

より明示的にパラメータを絞って表示できます。

1
2
3
$ terraform output ip

52.197.157.206
  • show
1
2
3
4
5
6
7
$ terraform show

...

Outputs:

ip = 52.197.157.206

構成のグラフ化

1
$ terraform graph | dot -Tpng > graph.png
  • graph.png
  • dot コマンドがない場合は graphviz インストール
1
$ brew install graphviz

総評

簡単でしょ?と言われているようなツールでした ♪

引き続きプロビジョニングや AWS の各種設定をしていきたいと思います。

次回 EC2 インスタンスを起動し、ローカル環境で作った鍵をキーペア登録し SSH ログインを実施します。

node_exporter シェルでクエリ自作

node_exporter シェルでクエリ自作

概要

node_expoter のオプション --collector.textfile.directory で指定したディレクトリに *.prom という拡張子を配置することで
そこに記述したメトリクス情報を prometheus server が読み取ってくれます。

この *.prom ファイルを一定時間毎に更新すればメトリクスが自作できる、というものです。

手順

  • node_exporter 自体のインストール・セットアップは以下ご参照ください。

上記手順では以下に node_exporter を配置しています。
環境によって適宜書き換えてください。

1
/usr/local/node_exporter/node_exporter

text_collector ディレクトリ作成

1
2
$ cd /usr/local/node_exporter
$ mkdir text_collector

shell 作成

今回は httpd の process count のメトリクス追加することとします。

  • /usr/local/node_exporter/text_collector/httpd.sh 作成

cron 設定

1
2
# node_exporter httpd 5分毎更新
*/5 * * * * /usr/local/node_exporter/text_collector/httpd.sh

httpd.prom 作成確認

  • /usr/local/node_exporter/text_collector/httpd.prom
1
node_httpd_count 24

上記の node_httpd_count がメトリクス名になります。

node_expoter 再起動

以下のようにディレクトリ指定します。

1
node_expoter --collector.textfile.directory /usr/local/node_exporter/text_collector

作成したメトリクスを指定し確認する。

無事できました!

これを利用してるとシェル芸で色々事足りることもあります ♪

一助になれば何よりです。

標準的な Golang インストール方法

標準的な Golang インストール方法

概要

Golang オフィシャルサイトに書かれているそのままです。

他 Golang 関連記事説明の為に、また、備忘録として記述します。

環境

  • CentOS Linux release 7.3.1611 (Core)

手順

Golang Official - Downloads から環境に合わせ
最新バージョンをインストールすることをお勧めします。

  • ソースからビルド
1
2
3
$ cd /usr/local/src
$ sudo wget https://storage.googleapis.com/golang/go1.7.5.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xzf go1.7.5.linux-amd64.tar.gz
  • PATH 設定
1
2
3
4
5
6
7
8
$ sudo cat << 'EOF' | sudo tee /etc/profile.d/golang.sh
export GOPATH=$HOME/go
export PATH=$PATH:/usr/local/go/bin
EOF

$ sudo cp /etc/profile.d/golang.sh /etc/profile.d/golang.csh

$ source /etc/profile
  • 確認
1
2
3
$ go version

go version go1.7.5 linux/amd64

以上で Golang のインストール完了です。

node_expoter error occured ! hwmon collector failed

node_expoter error occured ! hwmon collector failed

概要

Amazon Linux に node_exporter をインストールし起動した所以下のエラーが発生し、起動停止してしまいました。

1
ERRO[0007] ERROR: hwmon collector failed after 0.000011s: open /proc/class/hwmon: no such file or directory  source="node_exporter.go:92"

hwmon とは?

Hard Ware MONitoring. Linux カーネルのセンサーチップから Hard Ware の温度やファン回転数や電圧を取得できる。

環境情報は以下の通りです。

  • Amazon Linux AMI release 2016.09
  • node_exporter version 0.14.0-rc.1 (branch: master, revision:5a07f4173d97fa0dd307db5bd3c2e6da26a4b16e)

上記エラーですが issue として上がっていました。
そして解決されてました!

タイミングが悪かったのかマージされる前の release を取得していた為
このエラーに遭遇していました。

最新のソースは master ブランチしてビルドするのが良さそうです。

以下に Amazon Linux で実施したインストール手順をまとめました。

手順

Golang インストール

以下 Golang オフィシャルサイトにある標準的なインストール方法です。参考にしてください。

node_exporter をソースからインストールしビルド

1
2
3
4
5
6
7
8
9
$ mkdir -p $GOPATH/src/github.com/prometheus
$ cd $GOPATH/src/github.com/prometheus
$ git clone https://github.com/prometheus/node_exporter
$ cd node_exporter
$ make build

// version 確認
$ ./node_exporter --version
node_exporter, version 0.14.0-rc.1 (branch: master, revision: 428bc92b1c9b38f6de96bceb67bc5d9b3bdcf6e7)

ついでに起動スクリプト

  • 事前準備
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// pid ファイル置き場 作成
$ sudo mkdir -p /var/run/prometheus

// log ファイル置き場 作成
$ sudo mkdir -p /var/log/prometheus

// daemonize インストール
$ cd /usr/local/src
$ sudo git clone https://github.com/bmc/daemonize
$ cd daemonize
$ sudo ./configure
$ sudo make
$ sudo make install

// PATHが通ってなかったらPATHに乗せる
$ sudo cp daemonize /bin/

$ which daemonize
/bin/daemonize
  • 起動スクリプト作成
1
2
3
4
$ cd /etc/init.d
$ sudo git clone https://gist.github.com/kenzo0107/eebb6c1c06ba04b7073c171580cec445
$ sudo cp eebb6c1c06ba04b7073c171580cec445/node_exporter.init ./node_exporter
$ sudo chmod 0755 node_exporter
  • 起動
1
$ sudo /etc/init.d/node_exporter start

無事エラーなく起動するようになりました ♪

Alertmanager 構築手順

Alertmanager 構築手順

概要

前回 Node Exporter 構築しました。

今回は監視実施サーバで Alertmanager 構築を実施します。

今回やること 3 行まとめ

  • Alertmanager インストール & 起動スクリプト作成
  • Prometheus 通知条件設定
  • Alertmanager で Slack 通知

Alertmanager の役割

アラートのレベルによって通知先をどの程度の頻度で送信するかを管理します。
あくまで、通知先の管理をします。

実際のアラート条件の設定は Prometheus Server でします。

環境

  • CentOS Linux release 7.3.1611 (Core)

Alertmanager インストール

  • パッケージインストール
1
2
3
4
5
$ cd /usr/local/src
$ sudo wget https://github.com/prometheus/alertmanager/releases/download/v0.5.1/alertmanager-0.5.1.linux-amd64.tar.gz
$ sudo tar -C /usr/local -xvf alertmanager-0.5.1.linux-amd64.tar.gz
$ cd /usr/local
$ sudo mv alertmanager-0.5.1.linux-amd64 alertmanager
  • シンボリックリンク作成
1
2
3
4
5
6
7
8
$ sudo ln -s /usr/local/alertmanager/alertmanager /bin/alertmanager

$ alertmanager --version

alertmanager, version 0.5.1 (branch: master, revision: 0ea1cac51e6a620ec09d053f0484b97932b5c902)
build user: root@fb407787b8bf
build date: 20161125-08:14:40
go version: go1.7.3

Alert 通知先設定

以下 Slack へ通知設定です。

1
2
3
$ cd /usr/local/alertmanager
$ git clone https://gist.github.com/kenzo0107/71574c2d4d70ba7a9efaa88b4ff1be1b
$ mv 71574c2d4d70ba7a9efaa88b4ff1be1b/alertmanager.yml .
  • alertmanager.yml

slack 通知箇所を適宜変更して下さい。

Alertmanager 起動

とりあえず起動するならこれだけ

1
$ sudo alertmanager -config.file alertmanager.yml

http://alertmanager_server:9093/#/alerts にアクセスすると以下のような画面が表示されます。

Prometheus 同様、Alertmanager も起動スクリプトを作成しそこで起動管理をします。

起動スクリプト作成

  • オプションファイル作成
1
2
3
$ cat << 'EOF' > /usr/local/alertmanager/option
OPTIONS="-config.file /usr/local/alertmanager/alertmanager.yml"
EOF
  • Alertmanager 起動スクリプト
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ sudo cat << 'EOF' | sudo tee /usr/lib/systemd/system/alertmanager.service
[Unit]
Description=Prometheus alertmanager Service
After=syslog.target prometheus.alertmanager.service

[Service]
Type=simple
EnvironmentFile=-/usr/local/alertmanager/option
ExecStart=/bin/alertmanager $OPTIONS
PrivateTmp=false

[Install]
WantedBy=multi-user.target
EOF
  • 起動設定
1
2
3
4
$ sudo systemctl daemon-reload
$ sudo systemctl enable alertmanager.service
$ sudo systemctl start alertmanager.service
$ sudo systemctl status alertmanager.service -l

アラート通知条件設定

アラート通知条件は Prometheus Server 側で設定します。

Prometheus Official - ALERTING RULES

サンプルとして以下設定します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ cd /usr/local/prometheus-server
$ cat << 'EOF' > alerts.rules

# インスタンスに 5分以上(FOR) アクセスできない場合(IF up == 0)
# severity = "critical" とラベル付けし通知
ALERT InstanceDown
IF up == 0
FOR 5m
LABELS { severity = "critical" }
ANNOTATIONS {
summary = "Instance {{ $labels.instance }} down",
description = "{{ $labels.instance }} of job {{ $labels.job }} has been down for more than 5 minutes.",
}

// Prometheus 設定ファイルチェック
$ promtool check-config prometheus.yml

Checking prometheus.yml
SUCCESS: 1 rule files found

Checking alerts.rules
SUCCESS: 1 rules found

Prometheus Server で Alertmanager URL 設定

Prometheus の起動オプションで Alertmanager URL 設定します。

1
-alertmanager.url=http://localhost:9093
1
2
3
4
5
6
7
$ cd /usr/local/prometheus-server
$ cat << 'EOF' > option
OPTIONS="-config.file=/usr/local/prometheus-server/prometheus.yml -web.console.libraries=/usr/local/prometheus-server/console_libraries -web.console.templates=/usr/local/prometheus-server/consoles -alertmanager.url=http://localhost:9093"
EOF

// Prometheus 再起動
$ sudo systemctl restart prometheus.service

注意

今回 Alertmanager は Prometheus Server と同サーバ上に設定しているので

1
http://localhost:9093

となっていますが、ドメインが異なる場合は適宜設定してください。

Prometheus Alerts ページアクセス

設定した通知条件が表示されています。

通知試験

監視対象サーバの node_exporter を停止してみます。

1
$ sudo systemctl stop node_exporter

すると…

Slack に通知が届きました!

http://alertmanager_server:9093/#/alerts にアクセスすると通知内容一覧が表示されます。

以上で簡単ながら
Prometheus からリモートサーバを監視しアラート通知するところまでを
まとめました。

  1. Prometheus でサーバ監視
  2. Node Exporter 構築手順 + Prometheus から AWS オートスケール監視
  3. Alertmanager 構築手順

補足

フロントエンド

Grafana 3.x 以降でデフォルトプラグインで Prometheus をサポートしていたりと
Prometheus のフロントは Grafana が導入しやすく相性が良かったです。

メトリクスを自作したり、Prometheus 独自のクエリを駆使して
様々なメトリクス監視が実現できます。

My alerts.rules

Learning

改めて自身で構築してみて
Line Casual Talks #1, #2 を見直すと非常に理解が深まると思います。

一助になれば何よりです。

以上です。
ご静聴ありがとうございました。