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のこと

この投稿は、チュートリアルを終えて実務に入る前の人に知っておいて欲しいことをまとめています。
チュートリアルは終えている前提なので、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のこと

続きを読む

TerraformとAWSに同時入門する

GMOペパボ、ムームードメインのエンジニア@litencattです。

昨日は@dp42による、“Hello, World.”の次としてのチャットボットでした。

今日は、入社以来専らWeb開発がメインでやってきたけど、最近興味のあるAWSやTerraformによるインフラ構築について読んだ本をベースにやってみたことについて書いていきます。

やること

Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版のインフラ環境や手順を参考に、AWS環境構築をTerraformを用いて行います。

なお今回はApacheなどEC2インスタンスに対する各種インストールは直接インスタンス内に入ってコマンド実行しています。

ゴール

AWS上に以下の環境構築を行ないます

  • EC2インスタンス x 2台

    • Webサーバ

      • インターネットゲートウェイを持つ
      • Apache(httpd)上でWordPressが動作している
    • DBサーバ
      • NATゲートウェイを通してインターネットに接続する
      • MySQLが起動している

具体的には以下のAWSリソースを扱います。

  • EC2
  • VPC
  • サブネット
  • ルートテーブル
  • インターネットゲートウェイ
  • セキュリティグループ
  • Elastic IP
  • NATゲートウェイ

今回参考にした本について

ネットワークにつての基礎的な用語について詳しい説明があったり、AWSで構築していく環境についての図がとてもわかりやすいのでこのあたり初めてな人にはおすすめな本だと思いました!

Terraformとは

  • AWSなど様々なサービスProviderに対して、サーバの構築・変更・管理を行うためのツール
  • HashiCorpのプロダクト
  • Enterprise版もあるみたい

ペパボではプライベートクラウドとしてOpenStackを自社運用しています。
TerraformはOpenStackにも対応しており、最近は各サービスのインフラ管理がTerraformで行われるようになってきています。

今回はこのTerraformをAWSに対して使っていきます。
https://www.terraform.io/docs/providers/aws/index.html

今回のコードのレポジトリ

https://github.com/litencatt/terraform-aws-templates

準備

Terraformのインストール(Mac)

$ brew install terraform

使用バージョン

2017/12/3の執筆時点での最新リリースバージョンをつかいます

$ terraform version
Terraform v0.11.1
+ provider.aws v1.5.0

https://github.com/hashicorp/terraform/blob/master/CHANGELOG.md#0111-november-30-2017

主にVim向け

HCL扱う場合は入れとくと便利そうです
https://github.com/hashivim/vim-hashicorp-tools

AWSの準備

terraform.tfvarsの設定

今回はAWSのアクセスキーなどの秘匿情報をterraform.tfvarsに持つようにしています。
ここに作成したアクセスキーとシークレットアクセスキーを設定してください。
リージョンなども変更したい場合は必要に応じて変更してください。

terraform.tfvars
access_key = "AWS_ACCESS_KEY"
secret_key = "AWS_SECRET_KEY"
region     = "ap-northeast-1"
key_name   = "KEY_PAIR_NAME"

:warning:実際のアクセスキーなどが書かれたterraform.tfvarsはレポジトリには登録しないよう注意ください

EC2インスタンスへのログイン時に必要な鍵ファイルについて

今回はAWSのダッシュボード上のキーペアで鍵を作成し、それをEC2インスタンス作成時に使用するように指定しています。そのため、key_nameには作成したキーペア名を設定してください。

VPC作成

まずはVPCを作成します
https://github.com/litencatt/terraform-aws-templates/pull/1

main.tf
+variable "access_key" {}
+variable "secret_key" {}
+variable "region" {}
+
+provider "aws" {
+  access_key = "${var.access_key}"
+  secret_key = "${var.secret_key}"
+  region     = "${var.region}"
+}
+
+resource "aws_vpc" "vpc-1" {
+  cidr_block = "10.0.0.0/16"
+  tags {
+    Name = "vpc-1"
+  }
+}

main.tfファイル作成後$ terraform initを実行し、AWSのpluginを取得します。

その後、$ terraform applyを実行して成功するとVPCが作成され、AWSのVPCダッシュボードのVPCページでも確認することが出来ます。
image

ちなみにv0.11.0より$ terraform applyした場合は下記のようにyesを入力しないとapplyが実行されないように変更されています。

$ terraform apply

(省略)

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

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value:

initせずにplanなどを実行した場合のエラー

$ terraform initを先に実行してください

$ terraform plan
Plugin reinitialization required. Please run "terraform init".
Reason: Could not satisfy plugin requirements.
...(略

以降の作業

すべて記事内に書くと結構なボリュームになりそうなので、以降の作業内容については各PRを参照ください。
PRを作成して手順や差分をわかりやすくし、必要に応じて説明を入れています:nerd:

WordPressページの表示確認

NATゲートウェイの作成のPR内の作業までをすべて完了後、
WebサーバのURLに対してブラウザよりアクセスするとWordPressのスタートページの表示を確認することが出来ます。
image

:warning:この記事で作成したインスタンスは既にdestroy済みなのでPR上のURLにはアクセスできませんのでご注意ください

TerraformでAWSの環境構築してみて

今後のやっていき

最後に

今回、WordPress環境をAWS上にTerraformを主に使って構築してみましたが、
こんなWordPress環境だけでなく、Node.jsやRails環境などがなんと約10秒で出来上がってしまうというロリポップ!マネージドクラウドのβ版が現在無料公開中ですので、そちらも是非宜しくお願いします:smile:
https://mc.lolipop.jp/

参考にさせて頂いたサイト

など多数

続きを読む

AWS、KUSANAGIを利用したワードプレス構築依頼 [CMS構築・WordPress制作・導入の仕事]

日本最大級のクラウドソーシング「ランサーズ」なら、AWS、KUSANAGIを利用したワードプレス構築依頼の仕事を依頼できます。質の高いCMS構築・WordPress制作・導入のプロが多数登録しており、納期・価格・細かいニーズにも対応可能。会員登録・発注手数料は無料です! 続きを読む

アドレス変更したらWordPressの対応

EC2再起動したら、wordpressにアクセスできなかった。

原因:WordPressではサイトURLをDBに保存し、このURLが変更になってしまった場合、このDBの値を変更しないことです。

案1:DBの値修正(非推奨)
原因:wp_posts テーブル中にも 旧IPアドレスが含まれたリンクが残っている。

select * from wp_options where option_name = ‘siteurl’;
select * from wp_options where option_name = ‘home’;

UPDATE wp_options SET option_value=’http://xxx.xxx.xxx.xxx/wordpress‘ where option_name = ‘siteurl’;
UPDATE wp_options SET option_value=’http://xxx.xxx.xxx.xxx/wordpress‘ where option_name = ‘home’;

1.jpg

案2:wp-cli利用して、すべての旧urlも書き換えます。

参照文章:
https://www.agilegroup.co.jp/technote/wordpress-site-change.html

続きを読む

Lambdaの「invalid ELF header」エラーを解消する – EC2からlambda-uploaderを使用してLambdaにデプロイする方法

今回のお題

PythonでSSH経由のMySQLアクセスをして、WordPressの投稿情報を取得する
こちらを元に作成したLambda関数をデプロイし、
AWSのLambdaからLambdaを呼んで、Slackにメッセージを送信する
このような形で、RequestとResponseでデータをやりとりするように改造して見ました。
しかし、その際に下記の2点が課題になりました。

  1. サイズが大きいとソースが見れない・・・
    スクリーンショット 2017-11-22 0.02.33.png
    このように表示され、ソースが見れなくなります(解決策はないようです)
  2. 実行した際にELFエラーになる
    スクリーンショット 2017-11-22 0.03.40.png
    このようなエラーが表示されます。今回はこれを解消するための手順を備忘録として記載します。

原因

使用している「sshtunnel」のパッケージが原因でした。
どうやらpipでインストールする際に、バイナリファイルを生成しておりますが、私の開発環境がMacOSのため、Amazon Linux環境でのバイナリ形式と異なり正常に読み取れないようです。
パッケージをデプロイし実行した結果、エラーにinvalid ELF headerと出力される場合は、Amazon linux上でデプロイパッケージを作成する必要があるようです。

解消法(2017/11/27時点)

  1. ユーザに必要なアクセス権限を付与する
  2. IAMからアクセスキーと、シークレットアクセスキーを取得する。
  3. EC2を作成し、Amazon Linuxのインスタンスを立ち上げる。
  4. lambda-uploaderを入れる
  5. Lambdaにアップロード

となります。方法はいくつかあると思いますが、シンプルそうなので、EC2で環境を整えて、lambda-uploderを使用してLambdaにデプロイします。
MaxOS内にvirtualenvを導入し、python-lambda-localを入れて見ましたがダメでした・・・
やはりバイナリファイルを生成する場合のOSを同一にしなければいけないようです。。。

ユーザロールを設定する

実行するユーザのロールに必要なポリシーをアタッチします。
ちゃんと調べたわけでなくすみませんが、自分は下記でいけました。
1. AmazonEC2FullAccess
2. AWSLambdaFullAccess
3. IAMFullAccess
4. AmazonVPCFullAccess

ポリシーをアタッチする

IAM>ユーザで、対象のユーザを選択します。
アクセス権限の追加ボタンを押下します。
スクリーンショット 2017-11-27 22.38.30.png

既存のポリシーを直接アタッチを選択
スクリーンショット 2017-11-27 22.39.01.png

必要なポリシーを選択し、次のステップ:確認ボタンを押下します。
スクリーンショット 2017-11-27 22.25.24.png
スクリーンショット 2017-11-27 22.26.34.png
スクリーンショット 2017-11-27 22.27.14.png
スクリーンショット 2017-11-27 22.28.49.png

内容に問題がなければ、アクセス権限の追加を行う。
スクリーンショット 2017-11-27 22.28.58.png

アクセスキーを取得する

デプロイする実行するユーザのアクセスキーIDとシークレットアクセスキーが必要になるので、下記の画面から確認しメモをしておきます。
IAM>ユーザ>概要の認証情報をクリックします。
スクリーンショット 2017-11-26 19.30.41.png

アクセスキーの作成を押下する
スクリーンショット 2017-11-26 19.31.43.png

アクセスキーが作成されるので、内容をメモを取ります。
スクリーンショット 2017-11-26 19.32.18.png

アクセスキーとシークレットキーをメモします。CSV保存だけして、あとで削除するもの有りです。

EC2を作成する。

無料枠でEC2を作成します。作成する際のOSはAmazon Linuxを設定してください
デフォルトで、Python2.7系が入っているようなので今回はそちらを使用します。
Python3系で環境を作りたい場合は、下記のAWSのドキュメントを参考にコマンド入力していきます。
AWSのドキュメント
作成したら、ssh経由で接続し、以下のコマンドを入れていきます。

lambda-uploaderを導入する

lambdaへのアップロードを行ってくれるパッケージです。こちらを導入し、デプロイを行いたいと思います。

lambda-uploaderを入れるコマンド

$ pip install lambda-uploader

アクセスキーを設定する

aws configureを入力し、AWSの設定を行います。

$ aws configure
$ AWS Access Key ID:"取得したアクセスキーを入力しエンター"
$ AWS Secret Access Key:"取得したシークレットキーを入力しエンター"
$ Default region name: ap-northeast-1(東京の場合)
$ Default output format [None]: (何も入力せずにエンター)

lambda-uploaderを使用するためのファイルを作成する。

下記の4つが必要のようで、全て同一ディレクトリに配置します。
1. requirements.txt
2. lambda.json
3. XXXXX.py(実行する処理を記載したPythonファイル)
4. event.json(必要なら)

1は、使用するパッケージの内容を羅列したもの。
2は、lambdaにデプロイする際の情報の定義
3は、登録するpythonのソース
4は、イベント定義です。
今回は特にイベントを設定しないので、1〜3を順番に設定していきます。

下記では、必要なものだけを抜粋してますが定義ファイルなどはgitを参照願います。
https://github.com/rackerlabs/lambda-uploader

1. インストールするパッケージの定義を行う

適当な作業ディレクトリを作成し移動します。
下記のコマンドを叩いて、ファイルを作成し中身をpipでインストールするパッケージを定義します。

$ mkdir ~/python-deploy
$ cd ~/python-deploy
$ touch requirements.txt
$ echo PyMySQL >> requirements.txt
$ echo sshtunnel >> requirements.txt
$ cat requirements.txt
PyMySQL
sshtunnel

今回はSSHTunnelとMySQLが必要なので、この2つを定義しました。
他にもrequestsなど、必要に応じて記載します。

2. Lambdaアップロード用の定義ファイルを作成する。

デプロイ時の設定が必要ですが、その際にロールを設定する場面が出てきます。
適用するロールを開き、arnの内容を確認しておきます。
あとでLambdaの画面から変更できるので、デフォルトで用意されている「lambda-basic-exetcution」をとりあえず設定します。

先ほどと同階層のディレクトリに、lambda.jsonを作成し、中身を記載します。

$ touch lambda.json
$ vi lambda.json

記載内容はこのような形になります。

lambda.json
{
  "name": "lambdaに設定する名前",
  "description": "lambdaの説明",
  "runtime": "使用するランタイム",
  "region": "リージョン(東京ならap-northeast-1)",
  "handler": "Pythonのファイル名.実行関数名(lambda.handlerみたいに記載)",
  "role": "arn:aws:iam::アカウントID:role/ロール名",
  "timeout": タイムアウト値(数値:300が最大値),
  "memory": 使用メモリ(数値)
}

仮で書くと下記のような形になると思います。

lambda.json
{
  "name": "lambda-upload-test",
  "description": "lambda uploaderからのデプロイテスト",
  "runtime": "python2.7",
  "region": "ap-northeast-1",
  "handler": "ssh.ssh_test",
  "role": "arn:aws:iam::000000000000:role/lambda-basic-exetcution",
  "timeout": 300,
  "memory": 128
}

3. 実行ファイルを定義

lambda.jsonに記載したファイル名を記載しますので、下記のようなファイルができると思います。
SSH接続してMySQL接続は、下記を参照。
PythonでSSH経由のMySQLアクセスをして、WordPressの投稿情報を取得する
LambdaのRequestとResponseの利用方法は、下記を参照。
AWSのLambdaからLambdaを呼んで、Slackにメッセージを送信する

ssh.py
# -*- coding: utf-8 -*-
from sshtunnel import SSHTunnelForwarder
# モジュール読み込み
import pymysql.cursors

def ssh_test(event, date):
    is_write = is_wordpress_write(event["id"], event["date"])
    return {"ret": is_write}

def is_wordpress_write(id, date):
    # SSH関連の設定
    with SSHTunnelForwarder(
    ("SSH接続先ホスト名", SSH接続ポート),
    ssh_host_key="SSHホストキー(使用しないならNone)",
    ssh_pkey="SSHファイルの鍵のパス",
    ssh_username="接続ユーザ名(使用しないならNone)",
    ssh_password="接続パスワード or 鍵ファイルのパスフレーズ(使用しないならNone)",
    remote_bind_address=("127.0.0.1(ローカルホストとしてMySQLに接続するので)", MySQLのポート)
    ) as ssh:
        # MySQLに接続する
        conn = pymysql.connect(host='127.0.0.1(localhostなので)',
                                    user='ユーザ名',
                                    password='パスワード',
                                    db='DB名',
                                    charset='utf8',
                                    cursorclass=pymysql.cursors.DictCursor)
        # select
        # SQLを実行する
        cursor = conn.cursor()
        # select
        # SQLを実行する
        with connection.cursor() as cursor:
            sql = "select count(id) as count " 
                    " from " 
                    " wp_posts " 
                    " where " 
                    " post_author = %s " 
                    " and " 
                    " post_date > %s " 
                    " and " 
                    " post_status = 'publish' " 
                    " and " 
                    " post_type = 'post' "
            cursor.execute(sql, (id, date))

            # Select結果を取り出す
            rets = cursor.fetchall()
            is_write = False
            for r in rets:
                if r["count"] >= 1:
                    is_write = True
            # cursorクローズ
            cursor.close
        # MySQLから切断する
        connection.close()
    return is_write

接続情報は、直書きしたくないので、KMSを利用して暗号化したテキストを定数に置いたり、
環境変数に定義したりしてください。使用する際に複合化します。
あとはRequestで検索条件をもらい、Responseで結果を返すものにしました。
Lambdaの環境変数をKMSで暗号化して、Pythonで複合化する

デプロイを実行する。

上記で作成したファイルを格納したディレクトリに移動し、コマンドを実行します。

$ cd ~/python-deploy
$ lambda-uploader
λ Building Package
λ Uploading Package
λ Fin

と表示されれば無事にアップロード完了です。
もしエラーが起きる場合は、定義ミスか、ファイルサイズの容量(最大10MB)、asw configureの設定や、実行ユーザの権限のどれかだと思います。

Lambdaを確認する

一覧に追加されています。
名前や説明も設定どおりです。
スクリーンショット 2017-11-27 22.50.04.png

ハンドラも大丈夫そうです。
スクリーンショット 2017-11-27 22.50.46.png

テスト実行する

スクリーンショット 2017-11-27 22.51.49.png
結果も無事に取得できました。

以上

続きを読む

AWS linux PHP apache mysql wordpress 環境構築

Step1
EC2インスタンス作成

1.png

Step2
TaraTerm使って、linuxサーバ接続する

2.jpg

Step3
yum 更新
$ sudo yum -y update

4.jpg
5.jpg

Step4
Apache2.4インストール

//バージョン確認
$ sudo yum list available | grep httpd

8.jpg

//httpd24インストールする
$ sudo yum -y install httpd24

6.jpg
7.jpg

//結果確認
$ sudo yum list installed | grep httpd24

9.jpg

Step5
PHP7.0インストールする

//バージョン確認
$ sudo yum list available | grep php70
//インストールする
$ sudo yum -y install php70 php70-mbstring php70-pdo
//結果確認
$ sudo yum list installed | grep php70

10.jpg
11.jpg
12.jpg

Step6
mysqlインストールする

//mysql バージョン確認
//mysql インストールする
//結果確認
$ sudo yum list available | grep mysql57
$ sudo yum install mysql57
$ sudo yum list installed | grep mysql

20.jpg21.jpg
22.jpg

Step7
apache配置

etc/httpd/con/httpd.confを編集し、以下の2行を追加
(編集する前はhttpd.confバックアップする)
AddType application/x-httpd-php .html .htm .php .phtml
AddType application/x-httpd-php-source .html .htm .phps

・httpd.confバックアップする
$ sudo cp httpd.conf httpd.conf.bak

23.jpg

・httpd.conf編集する
$ vim httpd.conf

24.jpg

・AddTypeのところで下記二行追加
AddType application/x-httpd-php .html .htm .php .phtml
AddType application/x-httpd-php-source .html .htm .phps

25.jpg

・httpd restart
$ sudo service httpd restart

26.jpg

・確認する
var/www/htmlの下でindex.php を作成、下記のコードを追加
<?php
phpinfo();
?>
ブローザにIP入力、下記の画面出ます

28.jpg

Step8
mysql配置

・mysql起動する時、エラー発生しました。
改正:$ sudo yum install mysql57-server

29.jpg

・mysql 起動する
$ sudo service mysqld start

30.jpg

・mysql 登録する

31.jpg

・ユーザ追加
ユーザ名:mysql
パスワード:mysql
mysql> CREATE USER ‘mysql’@’localhost’ IDENTIFIED BY ‘mysql’;

32.jpg
33.jpg

Step9
wordpess配置

・下記のurlから日本語wordpessダウンロードする
https://ja.wordpress.org/install/

var/www/html下に
$ sudo wget https://ja.wordpress.org/wordpress-4.8.3-ja.zip

36.jpg

・解凍する

37.jpg

38.jpg

・エラー発生した
39.jpg

・原因:PHPにmysqlサポート追加されない。

・改正:
$ sudo yum -y install php70-mysqlnd
/etc/php.ini に extension=msql.so 追加

40.jpg
41.jpg

・設定画面が出ます
43.jpg

Step10
wordpess設定

・rootユーザにdatabaseを追加
mysql> create database wordpress;

・rootユーザパスワード修正
$ sudo service mysqld stop

$ sudo mysqld_safe –skip-grant-tables

mysql>update mysql.user set authentication_string=password(‘root’) where user=’root’;

45.jpg

・wordpessに情報記入
46.jpg

47.jpg

wp-config.php作成
$ cd var/www/html/wordpress

48.jpg

・情報記入
49.jpg
50.jpg
51.jpg

ここまで、以上になります。

追記:
FTP使いたくない場合下記参照

・wp-config.php に書きます
define(‘FS_METHOD’, ‘direct’);
・wordpressフォルダすべてのファイル書き可能に変更
sudo chmod 777 * -R

続きを読む

LambdaでPythonを使用してSlack通知を作る(技術調査中)

最終目的

現在勤めている会社では、週に1回社員が持ち回りでブログを書いています。
その当番を手動でSlackで通知してましたが、
良い加減自動化したかったので若手を巻き込んでシステム化してみようと思い至りました。
どうせなら使ったことのないものを使ってみようと考え、AWSのLambdaやPythonを使用します。
教育用件備忘録としてQiitaを使用します(これも初めての試みw)

PythonやAWSで必要なもの調べて試してみる

  1. AWSでPythonを使用したLambdaを作ってみる
  2. LambdaからWebHookを使用してSlackにメッセージを送信してみる
  3. Python2.7でPyMySQLを使用してSQLを実行する
  4. PythonでSSH経由のMySQLアクセスをして、WordPressの投稿情報を取得する
  5. Lambdaの環境変数をKMSで暗号化して、Pythonで複合化する
  6. CloudWatchで定期的にLambdaを実行して、Slackにメッセージを送信する
  7. AWSのLambdaのタイムゾーンをUTCからJST(東京)に変更

上記で調べたものを利用して、定期的なSlack通知をしてみる

調査中
少しずつ記載していきます。

続きを読む