Amazon Aurora(MySQL互換) Auto Scalingで追加されたレプリカ(Reader)インスタンスのバッファキャッシュはどうなる?

…と来れば、やっぱりAuto Scalingで追加されたレプリカ(Reader)インスタンスのバッファキャッシュ(バッファプール・バッファプールキャッシュ)が起動時にウォームアップされるのか、についても知りたいところ(?)。

というわけで、いい加減しつこいですが、検証…というには雑なので、確認をしてみました。

1. Amazon Aurora(MySQL互換) Auto Scalingの設定

いつもの通り、すでにクラスメソッドさんのDevelopers.IOに記事があります。

ありがたやありがたや。

というわけで、私の記事では部分的にスクリーンショットを載せておきます。

※以前、以下の記事を書くときに使ったスナップショットからインスタンスを復元して使いました。

クラスター画面から、Auto Scaling ポリシーを追加しようとすると、
aws_as1.png

新コンソールへのお誘いがあり、
aws_as2.png

先へ進むと見慣れない画面が。
aws_as3.png

Auto Scalingを設定するには、新コンソールでもクラスター画面から。
簡単にスケールするよう、「平均アクティブ接続数」を選択して「3」アクティブ接続を指定します。
aws_as4.png

とりあえずAuto Scalingで作成されたレプリカで確認できればいいので、上限は少な目で。
aws_as5.png

書き忘れましたが、Auto Scaling ポリシーを新規追加する前に、最低1つのレプリカ(Reader)インスタンスを作成しておきます(そうしないと怒られます)。

これで、Auto Scalingの準備ができました。

2. Auto Scalingでレプリカが自動追加されるよう負荷を掛ける

引き続き、クライアントから複数セッションで接続します(とりあえず4つぐらい)。

まずは接続。

クライアント接続
$ mysql -u mkadmin -h test-cluster.cluster-ro-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

(ここで3つ追加接続)

mysql> SHOW PROCESSLIST;
+----+----------+--------------------+------+---------+------+----------------------+------------------+
| Id | User     | Host               | db   | Command | Time | State                | Info             |
+----+----------+--------------------+------+---------+------+----------------------+------------------+
|  2 | rdsadmin | localhost          | NULL | Sleep   |    2 | delayed send ok done | NULL             |
|  3 | rdsadmin | localhost          | NULL | Sleep   |    2 | cleaned up           | NULL             |
|  4 | rdsadmin | localhost          | NULL | Sleep   |   13 | cleaned up           | NULL             |
|  5 | rdsadmin | localhost          | NULL | Sleep   |  568 | delayed send ok done | NULL             |
|  6 | mkadmin  | 172.31.21.22:43318 | NULL | Query   |    0 | init                 | SHOW PROCESSLIST |
|  7 | mkadmin  | 172.31.21.22:43320 | NULL | Sleep   |   99 | cleaned up           | NULL             |
|  8 | mkadmin  | 172.31.21.22:43322 | NULL | Sleep   |   79 | cleaned up           | NULL             |
|  9 | mkadmin  | 172.31.21.22:43324 | NULL | Sleep   |    9 | cleaned up           | NULL             |
+----+----------+--------------------+------+---------+------+----------------------+------------------+
8 rows in set (0.00 sec)

各セッションで、SQLを実行していきます。

SQL(SELECT)実行
mysql> USE akptest2;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> SELECT s.member_id memb, SUM(s.total_value) tval FROM dept d, member m, sales s WHERE d.dept_id = m.dept_id AND m.member_id = s.member_id AND d.dept_name = '部門015' GROUP BY memb HAVING tval > (SELECT SUM(s2.total_value) * 0.0007 FROM dept d2, member m2, sales s2 WHERE d2.dept_id = m2.dept_id AND m2.member_id = s2.member_id AND d2.dept_name = '部門015') ORDER BY tval DESC;
+-------+---------+
| memb  | tval    |
+-------+---------+
| 28942 | 1530300 |
| 47554 | 1485800 |
(中略)
| 29294 | 1176700 |
| 70092 | 1176300 |
+-------+---------+
41 rows in set (24.33 sec)

(別セッションで)

mysql> SELECT s.member_id memb, SUM(s.total_value) tval FROM dept d, member m, sales s WHERE d.dept_id = m.dept_id AND m.member_id = s.member_id AND d.dept_name = '部門015' GROUP BY memb HAVING tval > (SELECT SUM(s2.total_value) * 0.0007 FROM dept d2, member m2, sales s2 WHERE d2.dept_id = m2.dept_id AND m2.member_id = s2.member_id AND d2.dept_name = '部門002') ORDER BY tval DESC;
(中略)
60 rows in set (0.19 sec)

すると、めでたく(?)レプリカインスタンスが自動的に追加されました!(手動で作成するのと同様、ちょっと時間が掛かりましたが。)
aws_as6.png

※1個目のレプリカインスタンスはAZ-cに作成しましたが、こちらはAZ-aに追加されました。

3. いよいよ確認

そこで、このインスタンスに直接指定で接続してみます。

自動追加されたレプリカインスタンスに接続
$ mysql -u mkadmin -h application-autoscaling-d43255f2-e133-4c84-85a1-45478224fdd2.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> USE akptest2;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show variables like 'aurora_server_id';
+------------------+--------------------------------------------------------------+
| Variable_name    | Value                                                        |
+------------------+--------------------------------------------------------------+
| aurora_server_id | application-autoscaling-d43255f2-e133-4c84-85a1-45478224fdd2 |
+------------------+--------------------------------------------------------------+
1 row in set (0.01 sec)

さあ、いよいよ、バッファキャッシュがどうなっているか、確認です!
最初に発行したものと同じSQLを発行してみます。
バッファキャッシュに載っていれば、1秒未満で実行できるはずですが…。

追加インスタンスで確認
mysql> SELECT s.member_id memb, SUM(s.total_value) tval FROM dept d, member m, sales s WHERE d.dept_id = m.dept_id AND m.member_id = s.member_id AND d.dept_name = '部門015' GROUP BY memb HAVING tval > (SELECT SUM(s2.total_value) * 0.0007 FROM dept d2, member m2, sales s2 WHERE d2.dept_id = m2.dept_id AND m2.member_id = s2.member_id AND d2.dept_name = '部門015') ORDER BY tval DESC;
+-------+---------+
| memb  | tval    |
+-------+---------+
| 28942 | 1530300 |
| 47554 | 1485800 |
(中略)
| 29294 | 1176700 |
| 70092 | 1176300 |
+-------+---------+
41 rows in set (24.71 sec)

残念!!
…まあ、予想通りですね。

接続を切ってしばらく待つと、自動追加されたインスタンスは削除されます。
aws_as7.png

※私が試したときには、設定した時間よりはるかに長い時間が経過してから削除が始まりました。安全を見ているのでしょうか?

さて、プロキシが間に入り、コンテナ(多分)でDBノードが構成されるAmazon Aurora Serverlessでは、どうなるんでしょうか?


続きを読む

Amazon RDSにSSHトンネルでIntelliJ IDEAから接続した時のメモ

RDSのパブリックアクセスを「いいえ」にしている状況で、IntelliJ IDEAから接続したい。という状況での設定メモ。
RDSにかぎらず、踏み台サーバ使うときは同様の設定方法でいけるはず。

RDSにアクセス可能なEC2インスタンス1台にElastic IPでIPが振られている状態で、
sshクライアントからアクセス可能な状態を想定しています。

データ・ソースおよびドライバー

一般

ここはローカルのDBなど直接アクセスできるDBに接続するときと同じ設定です。

20171211_1.png

ホスト: AWSコンソールのRDSの[エンドポイント]
データベース: AWSコンソールの[DB名]
ユーザー: AWSコンソールの[ユーザ名]
パスワード: インスタンス生成時に入力したパスワード

SSH/SSL

SSHトンネルの設定をします。

20171211_2.png

プロキシー・ホスト: インスタンスに設定したElastic IP
ポート: 22 (sshdの設定を変更していればその値)
プロキシー・ユーザー: ubuntu (ubuntuでインスタンス生成したとき、AMIはec2-user)
認証タイプ: Key pair
プライベート・キー・ファイル: キーペアで設定した秘密鍵を設定

こんな感じで出来ました。

mysqlコマンドで接続したときは

$ ssh -N -L 3307:appname.aaaaaaa.ap-northeast-1.rds.amazonaws.com:3306 -i ~/.ssh/id_rsa -p 22 ubuntu@host

とした後に、

$ mysql -u username -p -h 127.0.0.1 --port=3307

で接続できました。

続きを読む

postgresql – unable to connect to AWS VPC RDS instance (mysql or postgres)

postgresql – unable to connect to AWS VPC RDS instance (mysql or postgres) – Stack Overflow. Additional information for people who might run into similar issues trying to connect to RDS or R… 続きを表示. Additional information for people who might run into similar issues trying to connect to RDS or … 続きを読む

AnsibleでAWS環境(RDS)を自動構築する

はじめに

AWSの無料枠範囲で遊んでいます。

無料枠を超えないようにするため、作っては削除。作っては削除。をコンソールでやるのがめんどくさくなりました。

そのため、AnsibleでAWSの環境構築を自動構築できるようにしよう!ということで、
Ansible Playbookのサンプルを作成してます。

この記事で作成したplaybookはgithubで公開しています。

https://github.com/rednes/ansible-aws-sample
(AWS02フォルダ)

AWSの何を作るか

以下の内容をAnsibleで自動構築できるようにします。

  • VPCの作成
  • Internet Gatewayの作成
  • サブネットの作成
  • ルートテーブルの作成
  • セキュリティグループの作成
  • EC2インスタンスの作成
  • サブネットグループの作成
  • RDSの作成
  • EC2インスタンスにWordPress環境の構築

前提

  • ansible, botoをインストールすること
  • AWSのサーバー構築に使用するIAMユーザが作成されていること
  • AWSマネジメントコンソールでキーペア登録していること

AWS構成図

今回Ansibleで構築するAWSの構成図はこんな感じです。

AWS構成図

ディレクトリ構成

├── ansible.cfg
├── group_vars
│   └── all.yml
├── host_vars
│   └── localhost.yml
├── hosts
│   ├── ec2.ini
│   └── ec2.py
├── roles
│   ├── ec2
│   │   └── tasks
│   │       ├── ec2.yml
│   │       ├── main.yml
│   │       ├── security_group.yml
│   │       └── vpc.yml
│   ├── rds
│   │   └── tasks
│   │       ├── main.yml
│   │       └── rds.yml
│   ├── wordpress
│   │   ├── defaults
│   │   │   └── main.yml
│   │   └── tasks
│   │       └── main.yml
│   └── yum
│       ├── defaults
│       │   └── main.yml
│       └── tasks
│           └── main.yml
└── site.yml

Playbookの解説

AnsibleでAWS環境(RDS以外)を構築する内容については、過去の記事を参考にしてください。
今回はRDSの構築についてだけ説明します。

RDSの環境はrdsのroleで作成しています。

roles/rds/tasks/main.yml
---
- include_tasks: rds.yml

main.ymlでは単純にrds.ymlをインクルードしているだけです。
rds.ymlでRDSインスタンスを作成しています。

サブネットとセキュリティグループはec2のroleであわせて作成しています。

1. 異なるAZでサブネットを二つ作成

ec2_vpc_subnetモジュールでサブネットを構築します。
サブネットではVPC, Availability Zone, CIDRを指定します。

RDSでは単独のAZでしか使用しない場合でも、複数のAZにまたがったサブネットグループを作成する必要があるため、
今回は使用していませんがわざわざ使用しないAZにサブネットを作成しています。

サブネットグループ作成時に使用するサブネットを識別するため、タグに「route: private」を設定しています。

roles/ec2/tasks/vpc.ymlの一部
- name: subnet作成
  ec2_vpc_subnet:
    region: "{{ aws.common.region }}"
    state: present
    vpc_id: "{{ vpc_net.vpc.id }}"
    az: "{{ aws.common.region }}{{ item.value.zone }}"
    cidr: "{{ item.value.cidr }}"
    map_public: "{{ item.value.map_public|default(True) }}"
    tags: "{{ item.value.tags }}"
  with_dict: "{{ aws.vpc.subnet }}"
  register: vpc_subnet
host_vars/localhost.ymlの一部
aws:
  common:
    region: ap-northeast-1
  vpc:
    subnet:
      subnet1:
        tags:
          Name: public-a
          route: public
        cidr: 10.0.1.0/24
        zone: a
      subnet2:
        tags:
          Name: private-a
          route: private
        cidr: 10.0.2.0/24
        map_public: False
        zone: a
      subnet3:
        tags:
          Name: private-c
          route: private
        cidr: 10.0.3.0/24
        map_public: False
        zone: c

2. セキュリティグループを作成

ec2_groupモジュールでセキュリティグループを構築します。
セキュリティグループでは主にVPCとインバウンドルールを指定します。

AnsibleDBという名称のセキュリティグループを作成して、
EC2からのみ接続できるように設定しています。

roles/ec2/tasks/security_group.ymlの一部
- name: security group作成
  ec2_group:
    name: "{{ item.value.name }}"
    description: "{{ item.value.description }}"
    tags:
      Name: "{{ item.value.name }}"
      vpc_id: "{{ vpc_net_fact.vpcs[0].id }}"
    region: "{{ aws.common.region }}"
    purge_rules: "{{ item.value.purge_rules|default(False) }}"
    rules: "{{ item.value.rules }}"
  with_dict: "{{ aws.vpc.security_group }}"
  register: security_group
host_vars/localhost.ymlの一部
aws:
  common:
    region: ap-northeast-1
  vpc:
    security_group:
      security_group1:
        name: AnsibleWeb
        description: EC2 group
        rules:
          - proto: tcp
            ports:
              - 22
            cidr_ip: 0.0.0.0/0
          - proto: tcp
            ports:
              - 80
              - 443
            cidr_ip: 0.0.0.0/0
      security_group2:
        name: AnsibleDB
        description: EC2 group
        rules:
          - proto: tcp
            ports:
              - 3306
            cidr_ip: 10.0.1.0/24

3. サブネットグループを作成

rds_subnet_groupモジュールでサブネットグループを構築します。
サブネットグループでは主にsubnet idを指定します。

ec2_vpc_subnet_factsモジュールでタグが「route: private」である全てのサブネットを取得して、
一つのサブネットグループを作成しています。

roles/rds/tasks/rds.ymlの一部
- name: subnet取得
  ec2_vpc_subnet_facts:
    region: "{{ aws.common.region }}"
    filters:
      "tag:route": private
  register: ec2_subnet_facts
  check_mode: no

- name: rds-subnet-group作成
  rds_subnet_group:
    name: "{{ aws.vpc.rds.subnet_group.name }}"
    region: "{{ aws.common.region }}"
    state: present
    description: "{{ aws.vpc.rds.subnet_group.description }}"
    subnets: "{{ ec2_subnet_facts.subnets | map(attribute='id') | list }}"
  register: rds_subnet_group
host_vars/localhost.ymlの一部
aws:
  common:
    region: ap-northeast-1
  vpc:
    rds:
      subnet_group:
        name: wp-dbsubnet
        description: WordPress DB Subnet

4. RDSを作成

rdsモジュールでRDSインスタンスを構築します。
セキュリティグループはec2_group_factsモジュールを利用して、
名称からIDを引っ張ってきて定義しています。

roles/rds/tasks/rds.ymlの一部
- name: RDS作成
  rds:
    command: create
    instance_name: "{{ aws.vpc.rds.db_name }}"
    username: "{{ aws.vpc.rds.db_user }}"
    password: "{{ aws.vpc.rds.db_password }}"
    db_name: wordpress
    region: "{{ aws.common.region }}"
    subnet: "{{ aws.vpc.rds.subnet_group.name }}"
    vpc_security_groups: "{{ ec2_group_facts.security_groups[0].group_id }}"
    db_engine: "{{ aws.vpc.rds.db_engine }}"
    engine_version: "{{ aws.vpc.rds.engine_version }}"
    license_model: "{{ aws.vpc.rds.license_model }}"
    instance_type: "{{ aws.vpc.rds.instance }}"
    size: "{{ aws.vpc.rds.size }}"
    tags:
      Name: "{{ aws.vpc.rds.db_name }}"
  register: rds
host_vars/localhost.ymlの一部
aws:
  common:
    region: ap-northeast-1
  vpc:
    rds:
      db_name: wordpressdb
      db_user: root
      db_password: password
      db_engine: MySQL
      engine_version: 5.6.37
      license_model: general-public-license
      instance: db.t2.micro
      size: 20

注意点

RDSのエンドポイントがRDSを作成するまでわからないため、まず最初にRDSインスタンスまで作成した後に
RDSのエンドポイントをgroup_vars/all.ymlに追記する必要があります。

group_vars/all.ymlの一部
---
my_vars:
  rds:
    endpoint: XXXX # RDSで作成したDBのエンドポイントを入力

RDS作成が完了したら以下の様にawscli等を使用してエンドポイントを取得し、
上述のall.ymlにエンドポイントを記載するとEC2からRDSのmysqlに接続してWordPress環境を構築できます。

$ aws rds describe-db-instances --query="DBInstances[].Endpoint"

続きを読む

AWS の RDS で外部アクセスを可能にする

1) Details で「パブリックアクセス可能」が 「はい」になっていることを確認する
mysql_01.png

2) セキュリティグループ のインバウンドで、ポート 3306 を、0.0.0.0/0 にする
mysql_02.png

3) 接続の確認
エンドポインント、ユーザー、パスワードは変更して下さい。

mysql -hiot-test.aaaa1q8npue.ap-northeast-1.rds.amazonaws.com -uuseraa -ppassword

mysql_03.png

続きを読む

中途入社のAWSエンジニアが、稼働中サービスの運用状況をキャッチアップするために意識すること

Classiアドベントカレンダー11日目です。
今回は、AWSエンジニアが稼働中のAWSの管理アカウントを渡されて、ビクビクしながらキャッチアップを行っていったときのメモになります。

1.TL;DR

AWSアカウントのログイン前に準備できることもあるし、AWSアカウントにログインしてわかることもあるし、サーバーにログインしてわかることもある。それぞれのレイヤーでどういったことを確認するかを意識しながらキャッチアップを進めていきましょう。

2.AWSアカウントログイン前の事前準備

pre_aws.png

サービスが稼働しているのであれば、AWSアカウントにログインせずとも、たくさんの情報をキャッチアップすることができます。1日目から何らかの大きなアウトプットを出さないと解雇するような会社は、(おそらく)存在しない筈です。まずは落ち着きましょう^^;

2-1.ドキュメント読み込み

サービスのインフラにAWSが使われることが多くなったからといって、入社前に経験したAWS運用フローがそのまま活かせる訳ではありません。まずは、前任者や運用中のドキュメント管理ツールの中から、今までどのような運用を行っていたかを確認します。
ドキュメントを見たときに意識する観点としては、

  • フロー型:時間による鮮度の劣化があるドキュメント
  • ストック型:システム仕様など、メンテナンスが求められるドキュメント

どちらの情報であるかを意識して読むことが重要です。
フロー型の情報は、障害などで一時的な対応用にメモっていることもあり、運用の中で解決済みのことがあります。そのため、ストック型のドキュメントを中心に見ることが素早いキャッチアップになると思います。
とはいえ、ドキュメントの全てがメンテナンスされている会社というのは稀だと思いますので、各種ドキュメントを見ながら、仮説程度に自分なりのシステム構成図などを書いてみましょう。
要件定義書や各種構成図の変更履歴、課題管理表、リスクコントロール表といったドキュメント類があるのであれば、目を通しておきましょう。

2-2.運用フローを観察する

サービス側のドキュメントについては、まだ文書化されてることが多いですが、運用系ツールに関しては、ドキュメント化されていないことがあります。今の開発スタイルであれば、何らかのチャットツール(Slack,ChatWork,HipChat)上で、

  • デプロイ
  • 各種の通知
  • 運用Bot

の運用といったことが行われていると思います。また、チャットだけでなく、メールでの運用フローも存在しているかもしれません。
こうした運用系ツールの存在は、今後自分がリファクタするときに、「必須要件ではないが、重宝している」ということで、「リファクタ後にも、あの機能を実装して欲しい」といった声が社内から上がると思います。
そのため、このような運用フローがどこで実装されているかを見極めることが重要になってきます。

2-3.インフラ部分のコード読み

「俺はフルスタックエンジニアだ!」という強い意思がある方は、この時点で稼働中のアプリ側のコードまで読み込んでいただければよいですが、まずは入社前に期待されたであろう、インフラまわりのコード化部分を把握しておきましょう。どのみち、いずれはメンテナンスを任されたり、質問されることが増えてきますので、自分のメンテナンスする部分を優先的に確認しておきましょう。
実サーバーの運用はAWSに任せているので、ここで意識しておくことは、

  • Infrastructure Orchestration Tools:Terraform, CloudFormationなど
  • Server Configuration Tools:Chef,Ansible,Itamaeなど

あたりのコードがgithubなどに保存されているからといって、メンテナンスされていない可能性もあります。
コードの設計方針などを確認するのは当然必要なのですが、コードの変更履歴が年単位で放置されていないかどうかも見ておきましょう。特に、AWS関連のコードについては、担当する人がアプリ側よりも少ないので、構築当初のコードのままなのか、運用されているコードなのかはPRなどで確認しておいた方がよいです。

3.AWSのアカウント内を調査する

aws_kansatsu.png

実際にAWSアカウントにログインしたり、APIで各種設定を確認していきます。Web系サービスであれば、TCP/IPモデルやC/Sモデルを意識しながら、下層レイヤー回りから調査していき、ネットワークがどうせ設定されているかを確認していきます。
おそらく、ここで多くの疑問(場合によっては、絶望)が生まれる段階です。「あれ?ドキュメントにこう記述されているけど、設定上は違うような…」という沼にハマることがあるでしょう。負けないでください、一人で抱え込まずに闇を共有できる仲間を見つけましょう。

3-1.外部システム連携の確認

関連するAWSサービス

VPC関連のサービスを中心に、自AWSアカウント以外の連携がないかの確認を行います。

関連しやすいAWSサービス例)

  • DirectConnect
  • NAT Gateway
  • Peering Connection
  • Customer Gateways
  • Virtual Private Gateways
  • VPN Connections
  • NetWorkACL
  • SecurityGroup
  • EIP

などに、何らかのインスタンスが稼働していて、productionやhonbanなどの文言がついたものがあれば、それはドキュメント上には存在しないが、サービス上何らかの理由で稼働しているものである可能性があります。
自社のサービスがAWSアカウント内だけで完結しているのであればよいのですが、誤ってここのインスタンスなどを削除すると、場合によってはシステム復旧できないぐらいの痛手になるので、慎重に確認していきましょう。
特に、SecurityGroupは、最近でこそInboundルールにDescriptionをつけられるようになりましたが、数年運用されているシステムには、何で利用しているIPアドレスなのかがわからないことがあるので、設定確認中に不明なIPアドレスを見つけたら社内で有識者に聞いてみましょう。

3-2.システム導線の確認

関連するAWSサービス

インスタンス障害があるとユーザー影響がありそうな、システム導線を追っていきます。

関連しやすいAWSサービス例)

  • ELB(CLB,ALB,NLB)
  • CloudFront
  • EC2
  • ElasticCache(redis,memcached)
  • RDS(Aurora,MySQL,PostgreSQL,SQLServer)
  • ElasticSearch
  • DynamoDB
  • S3

各種のインスタンスサイズが適切かを確認するのはもちろんですが、DB関連についてはバックアップ関連の設定がちゃんと行われているかどうかも確認しておきましょう。バックアップウィンドウの世代数やメンテナンスウィンドウの時間が営業時間内になっているとかは、結構ありがちな設定漏れケースになります。パラメータストアの設定については、本番で稼働している設定が正義なので、設計と違う場合は、社内で経緯を追ってみましょう。

3-3.運用導線の確認

関連するAWSサービス

直接のユーザー影響はないものの、バッチ系およびログインやログ連携など、システム運用で必要な運用導線を追っていきます。

関連しやすいAWSサービス例)

  • EC2
  • Lambda
  • ElasticSearch(& kibana)
  • IAM
  • CloudTrail
  • AWS Config
  • CloudWatch Logs
  • S3
  • Glacier

24224というポート開放を見れば、そのシステムはfluentd関連のフローがあるのはほぼ確定なので、ログの発生から可視化ツールおよびバックアップのフローまで追っていきましょう。また、バッチ系のEC2に関しては、最近のAWSだと、FargateやECS、Lambdaなどで定期バッチを行うことも可能なので、単一障害点をなくすことができないか、今後の計画のために、バッチ系が整理されているドキュメントなどを探してみましょう。

4.サーバー内の設定を確認する

server_chosa.png

最近だと、Server Configuration Toolsが大分普及していたり、コンテナ系の運用が発達してきているので、このあたりのキャッチアップ期間が少なくなるのかなと思います。とはいえ、SSH接続を頻繁に行うサーバーや起動時間が長いサーバーだと、コードの設定と異なる部分が出てきていることがあるかもしれません。
OSの設定やミドルウェアのバージョンなど、SSH接続すると確認した方がよいところは多々ありますが、Server Configuration Toolsの設定と異なっていたり、運用中のアラート設定などで差異がでやすそうな部分を以下に記載します。

4-1.各種メトリクス確認

メモリやプロセスの状況は、通常CloudWatchだけではわからないので、MackerelやZABBIXなどの監視ツールエージェントを入れているのであれば、各サーバーのメトリクスを確認しておきましょう。

4-2.稼働プロセスの確認

pstreeなどで、稼働しているプロセスを確認します。SSH接続が禁止されているのであれば、AWSのSSMエージェントなりで確認できないかを検討してみましょう。設計上のソフトウェアスタックに存在しないプロセスが常駐している場合は、何のエージェントが動いているかを追っておきましょう。

4-3.不要なファイルが出力されていないかの確認

ログレベルがデバッグのままだったり、ログファイルのローテートがなされていない場合があり、アラートは上がっていないけど、サーバー内のリソースを侵食しているときがあります。また、生成されるログファイルが小さすぎると、ディスクに余裕がありそうに見えても、inodeが先に枯渇するときもあります。lsofdf -iなどを可視化するなどして、サーバー内のディスク状況を確認しておきましょう。

4-4.同期処理と非同期処理のプロセス確認

同期処理のプロセスは意識しやすいので、監視対象に入っている可能性が高いです。ただ、非同期系プロセス(Rubyだとsidekiq,Pythonだとcelery,PHPだとphp-resqueなど)が監視対象に入っていないこともあるので、どのサーバーで非同期処理が行われているかを把握しておきましょう。

5.まとめ

AWSや他のパブリッククラウドが全盛になった今でも、3層アーキテクチャのシステム構成やOSI7階層などのレイヤーを意識しながらキャッチアップを行うと、システムを俯瞰しながらキャッチアップを進めることができるのではないかなと思います。とはいえ、前任者がコード化しきれなかった部分もある筈なので、そこは社内で過去経緯を知っている人に笑顔で質問をしてみましょう。技術が発達しても、人に蓄積されるノウハウはまだまだ多いので…
AWSエンジニアが転職する際などのご参考になれば。

続きを読む

[初心者向け] 実務開始の前に知っておきたいAWSのこと

この投稿は、チュートリアルを終えて実務に入る前の人に知っておいて欲しいことをまとめています。
チュートリアルは終えている前提なので、AWSのサービスに関する説明は省略しています。
ベンチャー企業の複数あるうちの1サービスくらいの規模感のアプリケーションを構築すること(移行ではない)を前提としています。
社内メンバー宛なので偏りがあるかもしれないですが、みなさまの役にも経てば幸いです。

設計に役立つツール

AWSを実務で利用する際は、構成図を書くかと思います。その際に利用できるのが Cloudcraft です。
構成図とともに料金もざっくりわかります。
cloudcraft例.png

もっと詳細に料金を出す必要があるならば、AWSが提供している料金計算ツールを使うと良いかもしれません。
SIMPLE MONTHLY CALCULATOR

また、サーバーレス構成を検討している方は、re:Invent2017で発表された「AWS Serverless Application Repository」を利用すると構成案が公開されていますので、参考になると思います(2017年12/11時点ではまだpreview版)

リザーブドインスタンス

リザーブドインスタンスはEC2やRDSのようなサービスで、前払いをすると料金を節約)できる制度です。 (参考: AWSリザーブドインスタンスについて)
インスタンスタイプや期間によりますが、「半年以上使うことが決まってるなら、1年分はリザーブドインスタンス買っちゃった方がお得」ということも少なくありません
ただし、リザーブドインスタンスはリージョン(もしくはアバイラビリティーゾーン)ごとで、インスタンスタイプも指定するので、インスタンスを立て直したり、何も知らずにインスタンスタイプを変更してしまうと「リザーブドインスタンスを買っているのに使えてない」状態になりえます。
リザーブドインスタンスは売買もできますし、t2.small2つをt2.medium1つに変更などもできるので、一度買ったらできるだけ今の構成を追随するようにしましょう。

IAM

IAMはAWS内の権限をつかさどるサービスです。各種サービスへの参照・書き込み・実行などを細かく設定できます。
権限を操作できてしまうので、一度作るとなかなか変更するのが怖いところです。
ここでのtipsはポリシーはできるだけ細かく設定することです。めんどくさいですが、サービスAのs3参照ポリシーとサービスBのs3参照ポリシーは分けた方が良いと思います。たとえ1つしかサービスをローンチしてなくても、サービスAに限定するようなポリシーを設定しておきましょう。
最小単位であるポリシーが細かければその組み合わせで柔軟に設定が可能です。

awsを操作するためのツール

  • aws-cli … コマンドラインからawsを操作できる
  • ansibleのec2.py … ansibleでipを指定するのではなく、ec2についているタグ名で絞ってec2をプロビジョニングするためのツール(というかpython script)

最後に

クラウドになるとlinuxではないもの(IAMやセキュリティグループなど)の設定をたくさんしなければならず、(aws-cliもありますが)guiでの設定も増えてしまいます。
面倒な部分はありますが、慣れてしまえば早いですし、コスパもよいのでどんどん利用していきたいですね
では、よいaws lifeを

[初心者向け] 実務開始の前に知っておきたいシリーズ

[初心者向け] 実務開始の前に知っておきたいSpreadSheetのこと
[初心者向け] 実務開始の前に知っておきたいAnsibleのこと
[初心者向け] 実務開始の前に知っておきたいGoogleAnalyticsのこと
[初心者向け] 実務開始の前に知っておきたいWordPressのこと
[初心者向け] 実務開始の前に知っておきたいRailsのこと

続きを読む

[AWS Cloud9]EC2自動停止を検知して別の処理を始める

はじめに

AWS Cloud9はIDEのブラウザを閉じたとき、自動でEC2インスタンスが停止する機能があります。
何分後に、自動停止するかは、設定から変更が可能です。
1.PNG

AWS Cloud9を1週間使うと、EC2インスタンスが自動停止するのが「便利 → 当たり前」という感覚になりました。そして、思いました。自動停止を検知してもっと楽できないかと。

やりたいこと

AWS Cloud9の機能で

  • 検知した情報をトリガーに別の処理を動作させてみる。
  • 今回は、サンプルに以下を動作確認
    • 自動停止のお知らせメール (実装したら、イチイチお知らせが来てウザくなった)
    • RDSの自動停止 (IDEとセットで使ってたので、止め忘れがなくなり非常に便利になった)

自動停止したことを検知

CloudWatchのルールを作成。

  • イベントパターンを選択
  • サービス名:EC2
  • イベントタイプ:EC2 Instance Status-change Notification
  • 特定の状態:インスタンスの停止を設定
  • Specific instance Id(s):AWS Cloud9のインスタンスIDを設定
    2.PNG
{
  "source": [
    "aws.ec2"
  ],
  "detail-type": [
    "EC2 Instance State-change Notification"
  ],
  "detail": {
    "state": [
      "running",
      "stopped"
    ],
    "instance-id": [
      "AWS Cloud9のインスタンスID"
    ]
  }
}

検知した情報をトリガーに別の処理を動作

ターゲットに今回は2つ(SNS(メール送信)とLambda(rds停止)を設定しました。)
SNSは使い道を思いつかなかったのでEメールを設定したのみ。jsonがそのままメールに飛んでくる。

3.PNG

LambdaはついでにIDE起動したときの動作も記述。

  • IDE起動→EC2開始→RDS開始
  • IDE終了→30分後EC2停止→RDS停止
IAMロール
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "logs:CreateLogGroup",
                "logs:CreateLogStream",
                "logs:PutLogEvents",
                "rds:StartDBInstance",
                "rds:StopDBInstance"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
lambda_function.py
import boto3

def lambda_handler(event, context):
    dbinstance = 'RDSインスタンス名'
    rds = boto3.client('rds')
    instanceState = event['detail']['state']
    if instanceState == 'stopped':
        result = rds.stop_db_instance(DBInstanceIdentifier = dbinstance)
    else:
        result = rds.start_db_instance(DBInstanceIdentifier = dbinstance)
    print(result)    
  • 開始状態のRDS

4.PNG

  • EC2が停止するイベントが発生

5.PNG

  • RDSが自動で停止
    6.PNG

まとめ

  • CloudWatchを使うことでIDEの終了後、EC2自動停止を検知できました。
  • 後続処理を自動化できることが分かったので、一日の作業終了をブラウザを閉じるだけに出来そうです。

関連

続きを読む

AWS Lambda in VPC

この記事はDMM.com #2 Advent Calendar 2017 – Qiitaの9日目です。

カレンダーはこちら
DMM.com #1 Advent Calendar 2017 – Qiita
DMM.com #2 Advent Calendar 2017 – Qiita

はじめに

こんにちは、@funa1gと申します。
社内で共通で利用されるAPIなどの開発をやっています。
技術選定のために、AWSについても色々と試しています。
今回は、その中でAWS LambdaとVPCをつないだ、アンチパターンについてです。

全体の構成

API Gateway + LambdaでAPIを作成する時、RDSにアクセスしたい場合があります。
しかもRDSとなるとやっぱりVPC内に置きたいです。
この組み合わせがアンチパターンなのは、すでに色々検証記事が出ていますが、
多少遅くても動くなら許せるかなと思って、検証してみました。

全体の構成です
AWS Networking (1).png

動作テスト

雑に動けばいいので、こんなエンドポイントにしました
レスポンスはDB内のデータです

METHOD: GET
URL: /LambdaTest
Response

[
  {
    "id": 1,
    "name": "test1"
  },
  {
    "id": 2,
    "name": "test2"
  }
]

Lambda側のコードも、DBにアクセスして、JSONを返すだけです

const { Client } = require('pg');

exports.handler = (event, context, callback) => {
    // 接続先のPostgresサーバ情報
    const client = new Client()

    client.connect()
    client.query("SELECT * FROM test", (err, res) => {
        if (err) throw err
        client.end()
        callback(null, res.rows)
    })
};

負荷テストにはGatlingを使いました。
利用したコードは以下です。

constantTest.scala
  setUp(
    scn.inject(
      // 50人のアクセスを40秒間継続
      constantUsersPerSec(50) during(40 seconds)
    )
  ).protocols(httpConfig)

これでテストの準備は整いました。
あとは実行結果を待つだけです。

テスト結果

上記の設定でテストした結果が以下になります。

---- Global Information --------------------------------------------------------
> request count                                       2000 (OK=1839   KO=161   )
> min response time                                      0 (OK=144    KO=0     )
> max response time                                  57613 (OK=57613  KO=0     )
> mean response time                                   471 (OK=512    KO=0     )
> std deviation                                       2902 (OK=3023   KO=0     )
> response time 50th percentile                        259 (OK=262    KO=0     )
> response time 75th percentile                        279 (OK=281    KO=0     )
> response time 95th percentile                        454 (OK=479    KO=0     )
> response time 99th percentile                       1304 (OK=1410   KO=0     )
> mean requests/sec                                     20 (OK=18.39  KO=1.61  )
---- Response Time Distribution ------------------------------------------------
> t < 800 ms                                          1802 ( 90%)
> 800 ms < t < 1200 ms                                   1 (  0%)
> t > 1200 ms                                           36 (  2%)
> failed                                               161 (  8%)
---- Errors --------------------------------------------------------------------
> j.u.c.TimeoutException: Request timeout to not-connected after    161 (100.0%)
 60000 ms
================================================================================

いくつか問題がありますね。

  • かなり遅いレスポンスが一部発生している
  • タイムアウトが発生している

何度か試しましたが、1700前後のシナリオを実行したところで、処理ができなくなっていました。
実行側の問題なのか、AWS側の問題なのかまで確認できず。
そこの検証を続けていたんですが、わからないまま、日付が変わりそうなので(12/9 22:00)、一旦の結果を放流です。
寂しい結果になりましたが、検証だとこういうこともありますね。
引き続き調査は続けて、わかったら追記したいと思います。

二ヶ月ほど前に試した際には、300ユーザーのアクセスを60秒間ほどやることで、API GatewayとVPC間のENIを限界(300)まで到達させることができたのですが、そこまでたどり着きませんでした。
http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/vpc.html
実際にそうなると、この記事の一番下のような現象が発生します。
ENIがこれ以上作成できないため、Lambdaの起動ができず、その分が全て失敗します。
しかも、CloudWatchにログが出ないので、かなり厳しいです。
やはりアンチパターンはアンチパターンですね。

最後に

さて、AWS側からアンチパターンということになっているのは、それなりの理由があることがわかりました。
今後もこの方法は取れないかというと、まだわからないかと思っています。

先日のre:InventでAPI Gateway VPC integrationが発表されました。
これはAPI GatewayからVPCのリソースにアクセスする手段を提供したものです。
アーキテクチャの問題上、Lambdaには明示的なエンドポイントがあるわけではないので、現状はアクセスできません。
しかし、VPCへのアクセス手段が用意されたということで、展開に希望が持てないかなと考えています。
今後の発表が楽しみなところです。

続きを読む

AWS Vulnerability / Penetration Testing Request Form(日本語訳)

AWSの環境に対して脆弱性診断を実施する際には、事前に「侵入テスト申請」が必要となります。
この申請フォームの内容が、2017年9月頃のアップデートの影響で大幅に変更されたのですが、日本語訳がなかったので翻訳してみました(2017年12月9日時点の情報です)。

AWSの脆弱性/侵入テストリクエストフォーム

AWS クラウド内の任意のリソースに起因する脆弱性および侵入テストの実施を許可するには、次の情報が必要です。要求側当事者は、セキュリティ評価ツールとサービスの使用に関する利用規約とAWS の方針に同意する必要があります。情報の受領と確認の後、テストプランを承認する承認メールが下記のアドレスに送信されます。テストは、要求側当事者がその承認を受け取るまで許可されません。アスタリスク(*)は、必要な情報を示します。

連絡先

このフォームにログインする際に使用した AWS アカウント所有者のメールアドレスと関連する名前を入力してください。このフォームにログインする際に使用されたアカウントの AWS アカウント ID 番号が、送信時に送信されます。別のアカウントのテストをリクエストしたい場合は、ログアウトして、テストするアカウントで再度ログインしてください。

顧客情報

  • あなたの名前(*)
  • 会社名(*)
  • 電子メールアドレス
  • 追加のメールアドレス
  • 追加のメールアドレス
  • 追加のメールアドレス
  • あなたは AWS と NDA (秘密保持契約)を締結していますか?

ターゲットデータ

  • AWS ターゲット

    • EC2 Resources
    • Cloudfront Distribution
    • API Gateway
    • Lambda
    • RDS Resources
    • ELB Name
  • 非 AWS ターゲット
    • IP アドレス

DNSZoneウォーキング

  • ネームサーバのドメイン名とIPアドレス
  • ターゲットにはアクティビティが通知されていますか?
  • スキャンされた TLD(トップレベルドメイン)

ソースデータ

  • IP アドレス
  • 上記の IP アドレスはあなたのオフィスのものですか?
  • 誰が IP アドレスを所有していますか?
  • テストチームの電話連絡先
  • テスト会社は AWS と NDA (秘密保持契約)を締結していますか?

テストの詳細

  • 予想される帯域幅のピーク(Gbps)(*)
  • 予想される1秒あたりのピーク要求数(RPS)(*)
  • DNSゾーンウォーキングで予想されるピーク秒数(OPS)
  • 開始日時(YYYY-MM-DDHHMM)(*)
  • 終了日時(YYYY-MM-DDHHMM)(*)
  • 追加のテストの詳細とこのテストが必要な理由
  • このテストの成功を確実にするために、どのような基準を監視しますか?
  • あなたが問題を発見した場合、すぐにトラフィックを停止する方法がありますか?
  • 2つの緊急連絡先(電子メールと電話)を提供してください(*)

利用規約

侵入テスト(以下「テスト」)

(a)AWS の脆弱性/侵入テストリクエストフォームに指定されている送信元および宛先のIPアドレス、ネットワーク帯域幅、インスタンスレベルのリソース(CPU、メモリ、入出力など)、および上記で提供された電子メールアドレスに送信される承認メール。
(b)t2.nano、m1.small または t1.micro インスタンスは含まれません(AWS の Web サイト http://aws.amazon.com に記載されています)。
(c)AWS と当社(http://aws.amazon.com/agreement /で利用可能)(以下「本契約」)との間の Amazon Web Services 顧客契約の条件に従います。
(d)セキュリティ評価ツールおよびサービスの使用に関する AWS の方針(下記を含む)を遵守します。

なお、 AWS が情報を検証し、認証番号を含む要求側の当事者に認証メールを送信するまで、テストは承認されません。承認には最大 48 時間かかることがあります。

AWS の直接的な結果である脆弱性やその他の問題の発見は、テストが完了してから 24 時間以内にaws-security@amazon.comに伝達されなければなりません。テストの結果は、本契約第 9 条に基づく AWS 機密情報とみなされます。

  • 利用規約に同意しますか?(*)

セキュリティ評価ツールおよびサービスの使用に関するAWSの方針

セキュリティ評価ツールおよびサービスの使用に関する AWS の方針は、 AWS 資産のセキュリティ評価を実行する際に大幅な柔軟性を提供し、他の AWS 顧客を保護し、 AWS 全体のサービス品質を保証します。

AWS は、 AWS 資産のセキュリティ評価を行うために選択できる公的、私的、商用、および/またはオープンソースのさまざまなツールとサービスがあることを理解しています。

「セキュリティ評価」という用語は、 AWS 資産間のセキュリティ管理の有効性または存在を判断する目的で従事するすべての活動を指します。(例えば、 AWS 資産間、 AWS 資産間、または仮想化内でローカルに実行される、ポートスキャン、脆弱性スキャン/チェック、侵入テスト、開発、 Web アプリケーションスキャン、注入、偽造、 資産そのもの。)

AWS 資産のセキュリティ評価を行うためのツールやサービスの選択に制限はありません。 ただし、サービス拒否( DoS )攻撃や、 AWS の資産、お客様または他のものに対するそのようなもののシミュレーションを実行する方法で、ツールまたはサービスを利用することは禁止されています。 禁止されている活動には、以下が含まれますが、これに限定されません。

  • プロトコルフラッディング(例えば、 SYN フラッディング、 ICMP フラッディング、 UDP フラッディング)
  • リソースリクエストフラッディング(例えば、 HTTP リクエストフラッディング、ログインリクエストフラッディング、 API リクエストフラッディング)

DoS に脆弱であることが知られているバージョンのリストと比較する目的で、バナーをつかむなど、 AWS 資産のリモートクエリを単独で実行してソフトウェア名とバージョンを判断するセキュリティツールは、このポリシーに違反していません。

さらに、セキュリティ評価の一環として、リモートまたはローカルの搾取のために必要に応じて、 AWS 資産の実行中のプロセスを一時的にクラッシュするセキュリティツールまたはサービスは、このポリシーに違反していません。 ただし、このツールは、前述のように、プロトコルのフラッディングやリソース要求のフラッディングに関与しない場合があります。

DoS 状態を作成、決定、または実際にまたはシミュレートされた他の方法で DoS 状態を示すセキュリティツールまたはサービスは、明示的に禁止されています。

一部のツールまたはサービスには、実際に DoS 機能が含まれています。不注意に使用された場合、またはツールまたはサービスの明示的なテスト/チェックまたは機能として、静かに/本質的に使用されます。このような DoS 機能を持つセキュリティツールまたはサービスは、その DoS 機能を無効にするか、無効にするか、そうでなければ HARMLESS を表示する明示的な能力を備えていなければなりません。さもなければ、そのツールまたはサービスは、セキュリティ評価のどの側面にも採用することはできません。

セキュリティ評価を実施するために使用されるツールとサービスが適切に構成され、 DoS 攻撃やそのようなシミュレーションを実行しない方法で正常に動作することを保証することは、 AWS のお客様の唯一の責任です。使用するツールまたはサービスが、 AWS 資産のセキュリティ評価に先立って、 DoS 攻撃またはそのシミュレーションを実行しないことを独立して検証するのは、 AWS のお客様の唯一の責任です。この AWS の顧客責任には、契約している第三者がこのポリシーに違反しない方法でセキュリティ評価を実施することが含まれます。

さらに、侵入テスト活動によって引き起こされた AWS または他の AWS 顧客に対する損害賠償責任はお客様にあります。

  • セキュリティ評価ツールとサービスの利用に関する AWS の方針に同意しますか?(*)

参考

続きを読む