AWS ELB

4ヶ月ぶりにダーツ部が活動しました。
ぜんっぜんダメでした。
3時間投げても、4ヶ月前の投げ方がわかりませんでした。
1年ぐらい前に三ヶ月間ほど週二で通って身につけてフォームもブランク空くと分からなくなるもんです。
ブログはそうならないように頑張ります。

さて、本題。
前回はAMIを利用してEC2インスタンスを複製し、
同一構成のEC2インスタンスを2つのAZに分けて配置しました。

ただし、これだけでは2つのWebサーバがあるだけで、
負荷分散も冗長化も構成されていません。
入口となるグローバルIPアドレスDNSがバラバラだからです。

一般的な負荷分散方式としてDNSラウンドロビンを使ったDNSによる負荷分散、
ロードバランサーを入口に置くことで振り分けてもらうことによる負荷分散があります。
前者は負荷分散としては意味がありますが、冗長化の観点では役に立たないため、あまり採用されません。

ロードバランサーの過負荷となる場合にロードバランサー複数並べてDNSラウンドロビンして負荷分散することは可能です。
ただし、この場合も各ロードバランサー冗長化しないと、意味を成し得ません。
またGSLBのようにDNSによって死活監視を行うことでDNSレコードをダイナミックに切り替えるシステムを使うことでロードバランサーの負荷も、そもそもロードバランサーを置く必要がなくなる仕組みもあります。
AWSのRoute53を使えば簡単に組むことができます。

、、、今調べたらELBは負荷に応じてスケーリングするようです。
AWSさん、さすがです。

今回はELBを起動して、
2つのWebサーバを負荷分散、冗長化できる構成を組みます。

EC2でWebAP構築
 ↓
RDSでWebAP-DB構築
 ↓
AMIでEC2のイメージ化、複製
 ↓

ELBで冗長化 (今回はここ)

 ↓
ElastiCacheでセッション管理
 ↓
S3にアクセスログ保存
 ↓
(できれば)SQSでWebAP連携

ELB (Elastic Load Balancing)

ELBはロードバランサーです。
通信を振り分けてくれることにより負荷分散してくれたり、
負荷分散対象を監視し、ダウンした対象を切り離すことで冗長化構成としてくれます。

ELB作成

  1. EC2画面へ遷移
    AWSのメニューからEC2を選択します。
    ELBはEC2画面より作成します。

    AWSのポータルが日本語対応しました。
    アマゾンジャパンの方、本当にありがとうございます。

  2. ELB作成
    左のメニューからロードバランサーを選択します。
    ロードバランサーの作成」ボタンを押下します。

  3. ロードバランサーの定義
    基本情報を入力します。
    ロードバランサー
      : 名前です。DNS名にも利用されます。
      今回はlbとします。
    内部向け LB の作成
      : 作成する対象のVPCを指定します。
    内部向けロードバランサーの作成
      : インターネットに開放せず、内部からのアクセスのみの場合、
      こちらをチェックしてください。
    ロードバランサープロトコル/ロードバランサーのポート
      : アクセス元が指定するプロトコル/ポート番号です。
      今回は80番ポート(http)を利用します。
    インスタンスプロトコル/インスタンスのポート
      : ロードバランサーインスタンスにアクセスするプロトコル/ポート番号です。
      今回は80番ポート(http)を利用します。
    サブネットの選択
      : バランシン対象が存在するサブネットを選択します。
      今回は2つのazにあるpublic networkを選択します。
      EC2インスタンスに設定したサブネットです。

  4. セキュリティグループの割り当て
    80番ポートが空いていればいいのでEC2インスタンスに割り当てたセキュリティグループを選択します。

  5. セキュリティ設定の構成
    httpだと注意されます。。

  6. ヘルスチェックの設定
    ELBがEC2インスタンスを監視する方式を指定します。

    pingプロトコル
      : HTTP、HTTPSSSLTCPから選択します。
      今回はHTTPを利用します。
    pingポート
      : そのポート番号です。
      今回は80番ポートを利用します。
    pingパス
      : ヘルスチェック先パスを指定します。デフォルト値は「/index.html」です。
      SSLTCPの場合、指定不要です。
    応答タイムアウト(秒)
      : ヘルスチェックの応答待ち時間を指定します。デフォルト値は「5」です。
      ここで指定した時間以内に応答がない場合、NGと判断します。
    ヘルスチェック間隔(秒)
      : ヘルスチェックを行う間隔を指定します。デフォルト値は「30」です。
    非正常のしきい値
      : EC2インスタンスがダウンしたと判断するヘルスチェックNG連続回数を指定します。
      デフォルト値は「2」です。
    正常のしきい値
      : EC2インスタンスがアップしたと判断するヘルスチェックOK連続回数を指定します。
      デフォルト値は「10」です。

    デフォルト設定の場合、30秒ごとに監視対象サーバに向けて、
    http://<対象サーバ>/index.html
    のリクエストを発行し、5秒間応答がない、を2連続検知すると、
    監視対象サーバがダウンしたと判断します。

  7. EC2 インスタンスの追加
    振り分け対象のサーバを指定します。
    今回は作成したWebサーバ2台を選択します。

    クロスゾーン負荷分散の有効化
      : LBが存在するEC2インスタンスにしか振り分けない場合、こちらのチェックを外してください。
    Connection Drainingの有効化
      : LBがEC2インスタンスを強制的に切り離す時間を設定します。
      ファイルダウンロード等長時間のリクエスト処理があった場合、
      切り離してもここで指定した秒数は待つ、という設定です。
      メンテナンス等で片系切り離して設定変更などする時に大変有用な機能です。

  8. タグの追加
  9. 確認
    LBが作成されます。

  10. 作成状況確認
    一覧画面へ遷移します。

    作成されたELBを選択して、概要タブを選択します。

    ステータスが「2 個のうち 2 個のインスタンスが実行中です」となっていれば準備完了です。
    DNS名はメモってください。

    インスタンスタブを選択します。

    インスタンスの各ステータスが「InService」となっていることも確認します。

  11. 動作確認
    それでは接続しましょう。
    その前に、、、
    接続先がわかるように各Webサーバのindex.htmlをホスト名等分かり易いように編集してください。

    $ curl http://lb-*********.ap-northeast-1.elb.amazonaws.com/index.html
    ip-192-168-100-35

    Web#2(複製先)へアクセスされました。
    それではもう一回。

    $ curl http://lb-*********.ap-northeast-1.elb.amazonaws.com/index.html
    ip-192-168-0-54

    Web#1(複製元)へアクセスされました。
    はい、ちゃんとバランシングされていますね。

    次に片系を落としてみて切り離されることを確認しましょう。

    今回はWeb#2を落とします。

    [root@ip-192-168-100-35 ~]# /etc/init.d/httpd stop
    Stopping httpd:                                            [  OK  ]

    15秒ぐらいでWeb#2のステータスがOutOfServiceとなりました。
    それでは接続

    $ curl http://lb-*********.ap-northeast-1.elb.amazonaws.com/index.html
    ip-192-168-0-54

    Web#1にアクセスされました。
    10回ほどアクセスしても全てWeb#1へアクセスされました。

    Web#2を起動します。

    [root@ip-192-168-100-35 ~]# /etc/init.d/httpd start
    Starting httpd: httpd: apr_sockaddr_info_get() failed for ip-192-168-100-35
    httpd: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1 for ServerName
                                                               [  OK  ]
    >||
    
    10分ほどでWeb#2のステータスはInServiceとなりました。
    
    >||
    $ curl http://lb-*********.ap-northeast-1.elb.amazonaws.com/index.html
    ip-192-168-0-54
    $ curl http://lb-*********.ap-northeast-1.elb.amazonaws.com/index.html
    ip-192-168-100-35

    またWeb#2へ振り分けられるようになりました。
    以前、ELBは切り離されたインスタンスはアップしても自動復旧しない(ELBに組み込まれない)という情報を得たのですが、改善したようです。

いかがでしたでしょうか?

AWSを使えば負荷分散、冗長構成のWebAPシステムを簡単に構成することが出来ます。
メンテナンスも考慮されたシステムとなっており、インフラ担当の悩みをどんどんAWSが吸収してくれます。
インフラ担当の運用・保守をAWSに任せることができるので、
その分、楽しい楽しい開発業務に専念することができます。

次回はElastic Cacheを利用してステートレスのWebAP構成を作りましょう。

「Amazon Web Services徹底活用ガイド」を読みました

Amazon Web Services 徹底活用ガイド (日経BPムック)

Amazon Web Services 徹底活用ガイド (日経BPムック)

AWSのノウハウ、Tipsを学びたく読んでみました。

AWSを触ったことがない人にはオススメの一冊だと思います。

AWSの機能紹介はいらなかった。
もっと多くの事例紹介が欲しかったです。

とにかく感じたことはオンプレから移行するなら方式設計、運用設計は大きく見直す必要がある。
郷に入っては郷に従え!に尽きます。

脱vSphereClient (Apple信者向け)

最近、自宅マシンにESXiをインストールしました。

プライベートの端末がOSXということもあり、vSphereClientの利用がサポートされません(*)。
VirtualBox上のWindowsマシンにインストールして操作する、という利用方法もありますが、
vSphereClientを利用するのに、VirtualBoxを起動して、Windowsを起動して、vSphereClientを起動。
んで、GUI操作ぽちぽち。

めんどい!

実はある程度のことはESXiにSSH接続してコマンドラインで出来るんです!

今回はVM作成を実施してみます。

ESXiのインストールやストレージ、ネットワークは準備済みとします。

ほとんどはvim-cmdコマンドを利用します。

vim-cmd

サブコマンドを実施し、色々なことを実現できます。

[root@localhost:~] vim-cmd
Commands available under /:
hbrsvc/       internalsvc/  solo/         vmsvc/
hostsvc/      proxysvc/     vimsvc/       help

[root@localhost:~] vim-cmd hostsvc
Commands available under hostsvc/:
advopt/                   enable_ssh                refresh_firewall
autostartmanager/         firewall_disable_ruleset  refresh_services
datastore/                firewall_enable_ruleset   reset_service
datastorebrowser/         get_service_status        runtimeinfo
firmware/                 hostconfig                set_hostid
net/                      hosthardware              standby_mode_enter
rsrc/                     hostsummary               standby_mode_exit
storage/                  login                     start_esx_shell
summary/                  logout                    start_service
vmotion/                  maintenance_mode_enter    start_ssh
connect                   maintenance_mode_exit     stop_esx_shell
cpuinfo                   pci_add                   stop_service
disable_esx_shell         pci_remove                stop_ssh
disable_ssh               queryconnectioninfo       task_list
enable_esx_shell          querydisabledmethods      updateSSLThumbprintsInfo

例えば、
vim-cmd hostsvc/enable_sshを実行すると、ESXiホストでssh接続が有効となります。
vim-cmd maintenance_mode_enterを実行すると、ESXiホストをメンテナンスモードにします。
とかです。

それではいってみよう。
今回はCentos6のVMを作成します。

  1. VM作成
  2. ブランクVMを作成します。

    [root@localhost:~] vim-cmd vmsvc/createdummyvm centos6-1 /vmfs/volumes/local_ssd
    4

    戻り値はVMのIDです。

    [root@localhost:~] ls -l /vmfs/volumes/local_ssd/centos6-1_3/
    total 1024
    -rw-------    1 root     root       1048576 May 10 10:42 centos6-1_3-flat.vmdk
    -rw-------    1 root     root           465 May 10 10:42 centos6-1_3.vmdk
    -rw-r--r--    1 root     root             0 May 10 10:42 centos6-1_3.vmsd
    -rwxr-xr-x    1 root     root           977 May 10 10:42 centos6-1_3.vmx
    [root@localhost:~] cat /vmfs/volumes/local_ssd/centos6-1_3/centos6-1_3.vmx
    .encoding = "UTF-8"
    config.version = "8"
    virtualHW.version = "11"
    nvram = "centos6-1_3.nvram"
    pciBridge0.present = "TRUE"
    virtualHW.version = "11"
    nvram = "centos6-1_3.nvram"
    pciBridge0.present = "TRUE"
    svga.present = "TRUE"
    pciBridge4.present = "TRUE"
    pciBridge4.virtualDev = "pcieRootPort"
    pciBridge4.functions = "8"
    pciBridge5.present = "TRUE"
    pciBridge5.virtualDev = "pcieRootPort"
    pciBridge5.functions = "8"
    pciBridge6.present = "TRUE"
    pciBridge6.virtualDev = "pcieRootPort"
    pciBridge6.functions = "8"
    pciBridge7.present = "TRUE"
    pciBridge7.virtualDev = "pcieRootPort"
    pciBridge7.functions = "8"
    vmci0.present = "TRUE"
    hpet0.present = "TRUE"
    floppy0.present = "FALSE"
    scsi0.virtualDev = "lsilogic"
    scsi0.present = "TRUE"
    scsi0:0.deviceType = "scsi-hardDisk"
    scsi0:0.fileName = "centos6-1_3.vmdk"
    scsi0:0.present = "TRUE"
    displayName = "centos6-1"
    guestOS = "other"
    uuid.bios = "56 4d fd a6 54 0c 8e 22-a5 d9 9a 10 df 9d be ae"
    uuid.location = "56 4d fd a6 54 0c 8e 22-a5 d9 9a 10 df 9d be ae"
    vc.uuid = "52 79 a6 30 04 b7 91 37-35 5d ad 4c 42 08 59 a4"

    vmxファイル、vmdkファイル等おなじみのファイルが作成されています。
    勝手に付加された「_3」はどこから来たのでしょう。

  3. ISOファイルアップロード
  4. scpコマンドでCentOS6のisoファイルをdatastoreにアップロードします。

  5. VMリソース設定
  6. 最低限必要な箇所のみ設定します。

    まずは以下を設定。

    • CPU数 -> 2core
    • メモリ値 -> 2GB
    • ネットワーク -> 1つ
    • CDROMデバイス
    • ゲストOS種別
    • VNC
    [root@localhost:~] vi /vmfs/volumes/local_ssd/centos6-1_3/centos6-1_3.vmx
    
    以下、編集
    guestOS = "other"
     ↓
    guestOS = "rhel6-64"
    
    以下、追記
    numvcpus = "2"
    memSize = "2048"
    ide1:0.startConnected = "TRUE"
    ide1:0.deviceType = "cdrom-image"
    ide1:0.fileName = "/vmfs/volumes/local_ssd/CentOS-6.6-x86_64-minimal.iso"
    ide1:0.present = "TRUE"
    ethernet0.virtualDev = "vmxnet3"
    ethernet0.networkName = "VM Network"
    ethernet0.addressType = "generated"
    ethernet0.present = "TRUE"
    RemoteDisplay.vnc.enabled="true"
    RemoteDisplay.vnc.port="5901"
    RemoteDisplay.vnc.password="password"
    RemoteDisplay.vnc.keyMap="jp"

    ide1:0.fileNameはアップロードしたisoファイルのパス指定
    ethernet0.networkNameはポートグループ名
    RemoteDisplay.vnc.portはVNC接続するポート番号
    後述しますがVNC接続する用のポートをESXiで開放する必要があります。
    RemoteDisplay.vnc.passwordはVNC接続時のパスワード


    次はディスクサイズを設定。

    • ディスクサイズ -> 16GB
    [root@localhost:~] vmkfstools -c 10g -d thin /vmfs/volumes/local_ssd/centos6-1_3/centos6-1_3-1.vmdk
    [root@localhost:~] vi /vmfs/volumes/local_ssd/centos6-1_3/centos6-1_3.vmx
    
    以下、編集
    scsi0:0.fileName = "centos6-1_3.vmdk"
     ↓
    scsi0:0.fileName = "centos6-1_3-1.vmdk"
    
    [root@localhost:~] vmkfstools -U /vmfs/volumes/local_ssd/centos6-1_3/centos6-1_3.vmdk

    元のvmdkファイルは削除して構いません。

  7. VNC接続設定
  8. ESXiでVNC接続できるようにポートを開放します。

    セキュリティプロファイル定義
    [root@localhost:~] cp /etc/vmware/firewall/service.xml /etc/vmware/firewall/service.xml.bak
    [root@localhost:~] chmod u+w /etc/vmware/firewall/service.xml
    [root@localhost:~] chmod +t /etc/vmware/firewall/service.xml
    以下を<ConfigRoot>タグ内に追記
      <service id='0140'>
        <id>vnc</id>
        <rule id='0000'>
          <direction>inbound</direction>
          <protocol>tcp</protocol>
          <port type='dst'>5901</port>
        </rule>
       <enabled>false</enabled>
       <required>false</required>
      </service>
    [root@localhost:~] chmod 444 /etc/vmware/firewall/service.xml
    ポート開放
    [root@localhost:~] esxcli network firewall refresh
    [root@localhost:~] esxcli network firewall ruleset list
    vnc                    false
    [root@localhost:~] esxcli network firewall ruleset set -r vnc -e true
    [root@localhost:~] esxcli network firewall ruleset set -r vnc -a true
    Already allowed all ip

  9. VM起動
  10. [root@localhost:~] vim-cmd vmsvc/power.on 3
    Powering on VM:

  11. コンソール接続
  12. OSXの場合、デフォルトでVNCクライアントが備わっています。
    Finderのメニューから[移動] - [サーバへ接続]を選択
    f:id:sfujimoto:20150510215217p:plain

    vnc://:<設定したポート番号>
    f:id:sfujimoto:20150510215013p:plain

    vmxファイルに設定したパスワードを入力
    f:id:sfujimoto:20150510220408p:plain

    コンソールの画面が表示されます。
    f:id:sfujimoto:20150510215356p:plain

このようにコマンドとVNC接続により、VMを構築できました。
細やかな設定は難しいところもありますが、
多くの機能を扱うことができます。

私は省エネのため、利用しない時はESXiを落としています。
そのため、VMを全てシャットダウンして、シャットダウンが完了したらESXiをシャットダウンするスクリプトと、
ESXiを起動したらtxtファイルに登録したVMを自動で起動するスクリプトを作成しています。
またESXiはpythonを標準搭載しているのでpythonistaには助かります。

(*) Wineでほとんどの機能を利用可。

AWS AMI

最近、MAC用のSSHクライアントを探しています。
iTerm2でやっていますが、
WindowsSSHクライアントはログの設定保存でホスト名でログファイルを作成できますが、
iTerm2は元々SSHクライアントツールじゃないところもあり、
ログは都度Startさせなきゃ開始してくれないし、
ファイル名も都度指定しなきゃいけないし、で正直めんどい。

はい、本題です。
前回はRDSを使ってWeb-AP-DB構成を作りました。
本日はWebAPサーバ(EC2インスタンス)をAMIのImage化し、
異なるEC2インスタンスとして生成します。

EC2でWebAP構築
 ↓
RDSでWebAP-DB構築
 ↓

AMIでEC2のイメージ化、複製(今回はここ)

 ↓
ELBで冗長化
 ↓
ElastiCacheでセッション管理
 ↓
S3にアクセスログ保存
 ↓
(できれば)SQSでWebAP連携

AMI (Amazon Machine Image)

AMIはテンプレートです。
EBSディスクのコピーです。
AMIは単体では何もできず、
AMIからEC2インスタンスを作成して複製したり、
AMIを他リージョンにコピーしてDR構成を取ることが可能です。

AMIは不変なデータであるため、
バックアップとしても利用可能です。

それでは作成します。

  1. EC2画面へ遷移
    AWSのメニューからEC2を選択

  2. AMI作成
    対象となるEC2インスタンスを選択して、
    [Actions] -> [Image] -> [Create Image]を選択します。

  3. 設定値入力
    Image name -> イメージ名
    Image description -> 説明

    [Create Image]ボタンを押せば、作成が開始されます。

    AMI一覧ページを表示するとpenddingステータスのAMIを確認することができます。

次は作成したAMIからEC2インスタンスを作成します。

  1. AMI画面へ遷移
    AWSのメニューからEC2を選択
    左のメニューからAMIsを選択

  2. EC2インスタンス作成
    作成したAMIを選択して、
    [Actions] -> [Launch]を選択します。
    それ以降はEC2インスタンス作成と同じです。

    EC2インスタンス一覧を確認すると、
    作成したAMIのIDと同じAMI IDのEC2インスタンスが作成されていることを確認できます。

それでは確認です。

# curl http://<EC2 Instance Public DNS>/django/list/
Hello, fuji

アクセスできました。
今回はボリューム少な目でしたね。。

次回はELBを作成してアクセスが分散されることを確認します。

AWS RDS

早いもので更新が2週間空いてしまった。

AWSスクリプトを書くことが楽しくなっちゃってアウトプットをサボりました。
botoというPython製のAWSライブラリがあって、
これがまた利用者に優しくAPIリファレンスさえ読めば、
PythonAWSも理解が乏しい私が簡単にAWSの環境構築スクリプトを組めちゃいました。

さて、本題。
前回はEC2インスタンスを作成して、Webサーバを立ち上げました。

今回はRDSインスタンスを立ち上げて、Webサーバと連携します。

EC2でWebAP構築
 ↓

RDSでWebAP-DB構築 (今回はここ)

 ↓
AMIでEC2のイメージ化、複製
 ↓
ELBで冗長化
 ↓
ElastiCacheでセッション管理
 ↓
S3にアクセスログ保存
 ↓
(できれば)SQSでWebAP連携

では早速RDSを作成しましょう。
(キャプチャは後日こっそりつけときます)

あれ?
2週間の間にEC2インスタンスのOSがRHEL7になってる。。。

  1. RDS画面へ遷移
     AWSのメニューからRDSを選択

  2. RDS作成開始
     [Get Started Now]ボタンやら[Launch DB Instance]ボタンやらをクリック

  3. DBエンジン選択
     DBエンジンは4種類が選べます。(ブログ執筆現在:2015/04/18)
     Auroraはまだ東京リージョンでは登場していません。

     今回はMySQLを利用します。


  4. MultiAZ
     MultiAZかどうかを選択します。
     MultiAZはDBの配置方式として複数のAZに配置するかどうかです。
     MultiAZを選択すると、稼働率99.95%以上を保証されます。
     99.95%を下回る場合、AWSから返金があります。
     ※注意:MultiAZは無償枠外です!
      私のような無償プレイヤーは要注意です。
      でも、本番運用するような場合は必須だと思う。


  5. 基本設定

     t1.micro以外は無償枠外

      • ストレージタイプ

     SSD、高性能SSD、HDDから選択可

      DNS等に利用され、データベースでは持たないっぽ

      • DBユーザ名
      • パスワード


  6. 詳細設定

    • ネットワーク設定
      • VPC
      • SubnetGroup

      VPCのSubnetとは別で、複数のSubnetをまとめたもの

      • Availability Zone
      • SecurityGroup

      EC2作成時とは別でDBポート番号のみを許可した紐づけるのが望ましい

    • DB詳細設定
      • DB名

      作成する空のデータベース

      • ポート番号

      最初からデフォルト値が入っている

     以上の設定で作成されます。


  7. 作成中
     けっこう時間かかります。。。


  8. APサーバ作成
     DB作成中にDBを利用可能なAPサーバを構築しましょう。
     APサーバはDjangoでちょちょいと。。。


     ん?


     あれ?こうかな。


     ダメだな。


     あー、これか。


     はぁ。。。


     あーーーー
     ですよねー
     だいたいこういう時ってSELINUXですよねー


     ちょちょいと、3時間(内、SELINUXに2時間半)で出来ました。
     さて、そろそろRDS立ち上がったかな。

     簡単にやったことを備忘録

    # yum install -y gcc python-devel mysql mysql-devel
    # pip install django mysql-python
    # django-admin startproject project
    # cd project
    # vi project/settings.py
    databaseの設定追記
    # ./manage.py startapp app
    # vi project/settings.py
    appを追加
    # vi app/models.py
    Userクラス追加
    # ./manage.py makemigrations
    # ./manage.py makemigrate
    # vi app/views.py
    list関数定義
    UserテーブルからSelectしたデータにHelloを付けて返す
    # vi project/urls.py
    list/とapp.views.listを紐付け
    # vi /etc/httpd/conf.module.d/10-wsgi.conf
    魔法の言葉を追加
    # systemctl 
    
    # setenforce 0
    こ、こいつまで遠かった。。。


  9. DB接続確認
     試験用にDBを設定します。

    # mysql -h <RDS Public DNS> -u <username> -p
    Password: 
    
    > show databases;
    +--------------------+
    | Database           |
    +--------------------+
    | information_schema |
    | innodb             |
    | mysql              |
    | newdb              |
    | performance_schema |
    +--------------------+

    newdbがRDS作成時に指定したDB名です。

    > use newdb;
    Database changed
    
    > show tables;
    +----------------------------+
    | Tables_in_newdb            |
    +----------------------------+
    | app_user                   |
    | auth_group                 |
    | auth_group_permissions     |
    | auth_permission            |
    | auth_user                  |
    | auth_user_groups           |
    | auth_user_user_permissions |
    | django_admin_log           |
    | django_content_type        |
    | django_migrations          |
    | django_session             |
    +----------------------------+
    
    > desc app_user;
    +-------------+-------------+------+-----+---------+----------------+
    | Field       | Type        | Null | Key | Default | Extra          |
    +-------------+-------------+------+-----+---------+----------------+
    | id          | int(11)     | NO   | PRI | NULL    | auto_increment |
    | name        | varchar(32) | NO   |     | NULL    |                |
    | create_date | date        | NO   |     | NULL    |                |
    +-------------+-------------+------+-----+---------+----------------+
    

    Djangoが勝手に色々作ってます。
    app_userテーブルにデータを登録して取得します。

    > insert into app_user values(1, 'fuji', '2015-04-18');
    Query OK, 1 row affected (0.00 sec)
    
    > select * from app_user;
    +----+------+-------------+
    | id | name | create_date |
    +----+------+-------------+
    |  1 | fuji | 2015-04-18  |
    +----+------+-------------+
    1 row in set (0.00 sec)

    おk


  10. 接続確認
    早速繋いでみましょう。

    # curl http://<EC2 Instance Public DNS>/django/list/
    Hello, fuji

    おー、うまくいきました。

    今回は
    クライアント -> Internet -> Web -> AP -> RDS
    というあるある構成をAWS上に作ることができました。

    次回は今回作ったAPサーバをAMIにイメージ化して複製します。

AWS EC2

AWSの記事を書き直します。
前回はごちゃごちゃしてて分かりづらかった。
やっぱり一つ一つ書いていきます。

どうせならより多くの機能を試してみたい。

EC2でWebAP構築

 ↓
RDSでWebAP-DB構築
 ↓
AMIでEC2のイメージ化、複製
 ↓
ELBで冗長化
 ↓
ElastiCacheでセッション管理
 ↓
S3にアクセスログ保存
 ↓
(できれば)SQSでWebAP連携

以上を目標とする。

EC2 (Elastic Compute Cloud)

仮想マシン
AMIというテンプレートから作成可能。
AMIは標準でたくさんのものが用意されている。
無料枠ではAmazonLinux、RHELCentOSUbuntu、SuseLinux

それでは早速作ってみよう。

前提
  • AWSアカウント登録済み
手順

  1. EC2画面
    f:id:sfujimoto:20150331000606p:plain

    AWSのメニュー一覧です。
    画面下部が切れているが、ほんとたくさんある。
    各メニューには更にオプションがたくさんある。
    把握しきれまてん。

    EC2を選択する。

  2. EC2作成
    f:id:sfujimoto:20150331000610j:plain

    Launch Instanceを選択する。

  3. AMI選択
    f:id:sfujimoto:20150331000614j:plain

    私はCentOS派だ。
    左メニューからAWS Marketplaceを選択。
    CentOS 7を選択。

  4. インスタンスタイプ選択
    f:id:sfujimoto:20150331000616j:plain

    CPU、MEM、ディスク、ネットワークの性能を選択できる。
    t2.microを選択。
    これ唯一の無料枠インスタンスタイプです。

  5. インスタンス設定
    f:id:sfujimoto:20150331000619j:plain

    なんか色々設定できる。

  6. ディスク設定
    f:id:sfujimoto:20150331000622j:plain

    サイズを選択できる。
    Storageタイプを選択できる

  7. タグ設定
    f:id:sfujimoto:20150331000625j:plain

    です。

  8. セキュリティグループ設定
    f:id:sfujimoto:20150331000628j:plain

    ファイアウォールに位置します。
    Source IP、Dest Portでフィルタリング可能。
    EC2インスタンスはリモートコンソール機能はないため、
    Linux系OSはSSHアクセスするためのポートを開放する必要がある。
    今回はWebアクセスもするのでHTTPも開放する。

  9. 確認・作成
    f:id:sfujimoto:20150331000631j:plain

    Launchを選択。

  10. キーペア作成・選択
    作成していない場合、キーペアを作成します。

    Instanceの作成が始まります。

    f:id:sfujimoto:20150331000634j:plain

    View Instanceを選択

  11. 起動
    作成が完了すると自動で起動してきます。
  12. 接続
    キーペア作成時にダウンロードした証明書ファイルを使用して、
    SSH接続でログインする。
    AMIにCentOSを選択した場合、centosユーザでログインできます。
    AMIにAmazonLinux、RHELを選択した場合、ec2-userユーザでログインできます。
  13. apache起動

    # systemctl enabled httpd
    # systemctl start httpd
    # ps -ef |grep httpd


  14. webアクセス
    WebブラウザからEC2のPublic DNSへアクセス
    http:///

    Apacheのサンプルページが表示されれば、アクセス成功!


いかがでしょうか?
今回はEC2インスタンス作成、接続をしました。
こんなに簡単にVMを手に入れることができました。
英語ですが項目が分かり易いですし、
ググれば誰かしら説明してくれている方がいるので敷居は低いです。

次回はRDSを作って、繋いでを実施します。

それにしても、キャプチャ貼りだすと、一気にめんどくさくなる。。

Webアプリケーション on EC2 and RDS

AWSを使ってみた
無償枠でより多くの機能を使ってみたい

とりあえずは基本のEC2とRDSを連携させたWebアプリケーションを構築してみる。
WEB/AP - DBの構成

機能

  • ログイン
    • データベースに登録されたID/PASSと一致した場合、アカウント一覧画面を表示する
    • データベースに登録されたID/PASSと一致しない場合、ログイン画面を再表示して、エラーメッセージを表示する
  • アカウント一覧表示
    • データベースに登録されたIDを一覧で表示する
    • 有効フラグが立っていないIDは表示しない
  • アカウント追加
    • 入力された情報でデータベースへレコードを追加する

構成

  • Web/APサーバ

 EC2
 OS : CentOS7
 AP : Django

  • DBサーバ

 RDS
 DB : MySQL

前提

  • AWS契約済み
  • KeyPair作成済み、ローカルに証明書ファイルがあること

手順

  1. EC2インスタンス作成
     AMIはCentOS7を利用

  2. RDSインスタンス作成
     MySQLを選択
     EC2インスタンスと同じVPC、同じSubnetを選択
     EC2インスタンスと同じSecurityGroupを選択
     DB nameはtestsitedb

  3. SecurityGroup
     Sourceに選択したセキュリティグループ
     ポートにRDSのポート番号を入力(今回はMySQLのデフォル3306)

  4. OSログイン
     EC2はコンソール接続はない。
     個人的には衝撃の事実
     OSのNW系障害が発生したらどうするんだろ。。

    # ssh -i <証明書> centos@<PublicIP>
    $ sudo su -


  5. MySQLクライアントインストール
     パッケージインストール

    # yum install mysql mysql-dev gcc python-devel
    Loaded plugins: fastestmirror
    
    ・・・(略)・・・
    
    Installed:
      mariadb.x86_64 1:5.5.41-2.el7_0
    
    Dependency Installed:
      perl.x86_64 4:5.16.3-283.el7             perl-Carp.noarch 0:1.26-244.el7            perl-Encode.x86_64 0:2.51-7.el7
      perl-Exporter.noarch 0:5.68-3.el7        perl-File-Path.noarch 0:2.09-2.el7         perl-File-Temp.noarch 0:0.23.01-3.el7
      perl-Filter.x86_64 0:1.49-3.el7          perl-Getopt-Long.noarch 0:2.40-2.el7       perl-HTTP-Tiny.noarch 0:0.033-3.el7
      perl-PathTools.x86_64 0:3.40-5.el7       perl-Pod-Escapes.noarch 1:1.04-283.el7     perl-Pod-Perldoc.noarch 0:3.20-4.el7
      perl-Pod-Simple.noarch 1:3.28-4.el7      perl-Pod-Usage.noarch 0:1.63-3.el7         perl-Scalar-List-Utils.x86_64 0:1.27-248.el7
      perl-Socket.x86_64 0:2.010-3.el7         perl-Storable.x86_64 0:2.45-3.el7          perl-Text-ParseWords.noarch 0:3.29-4.el7
      perl-Time-Local.noarch 0:1.2300-2.el7    perl-constant.noarch 0:1.27-2.el7          perl-libs.x86_64 4:5.16.3-283.el7
      perl-macros.x86_64 4:5.16.3-283.el7      perl-parent.noarch 1:0.225-244.el7         perl-podlators.noarch 0:2.5.1-3.el7
      perl-threads.x86_64 0:1.87-4.el7         perl-threads-shared.x86_64 0:1.43-6.el7
    
    Dependency Updated:
      mariadb-libs.x86_64 1:5.5.41-2.el7_0
    
    Complete!


  6. 接続試験

    # mysql -h <RDS Endpoint> -u <db user> -p
    Enter password:
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 154
    Server version: 5.6.22-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2014, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


  7. djangoインストール

    # easy_install pip
    Searching for pip
    Reading https://pypi.python.org/simple/pip/
    Best match: pip 6.0.8
    Downloading https://pypi.python.org/packages/source/p/pip/pip-6.0.8.tar.gz#md5=2332e6f97e75ded3bddde0ced01dbda3
    Processing pip-6.0.8.tar.gz
    Writing /tmp/easy_install-hvl4ts/pip-6.0.8/setup.cfg
    Running pip-6.0.8/setup.py -q bdist_egg --dist-dir /tmp/easy_install-hvl4ts/pip-6.0.8/egg-dist-tmp-UeBzQD
    warning: no previously-included files found matching '.coveragerc'
    warning: no previously-included files found matching '.mailmap'
    warning: no previously-included files found matching '.travis.yml'
    warning: no previously-included files found matching 'pip/_vendor/Makefile'
    warning: no previously-included files found matching 'tox.ini'
    warning: no previously-included files found matching 'dev-requirements.txt'
    no previously-included directories found matching '.travis'
    no previously-included directories found matching 'docs/_build'
    no previously-included directories found matching 'contrib'
    no previously-included directories found matching 'tasks'
    no previously-included directories found matching 'tests'
    Adding pip 6.0.8 to easy-install.pth file
    Installing pip script to /usr/bin
    Installing pip2.7 script to /usr/bin
    Installing pip2 script to /usr/bin
    
    Installed /usr/lib/python2.7/site-packages/pip-6.0.8-py2.7.egg
    Processing dependencies for pip
    Finished processing dependencies for pip
    
    # pip list
    backports.ssl-match-hostname (3.4.0.2)
    boto (2.25.0)
    chardet (2.0.1)
    Cheetah (2.4.4)
    cloud-init (0.7.5)
    configobj (4.7.2)
    decorator (3.4.0)
    iniparse (0.4)
    IPy (0.75)
    jsonpatch (1.2)
    jsonpointer (1.0)
    kitchen (1.1.1)
    Markdown (2.4.1)
    Pillow (2.0.0)
    pip (6.0.8)
    policycoreutils-default-encoding (0.1)
    prettytable (0.7.2)
    pycurl (7.19.0)
    Pygments (1.4)
    pygobject (3.8.2)
    pygpgme (0.3)
    pyliblzma (0.5.3)
    pyudev (0.15)
    pyxattr (0.5.1)
    PyYAML (3.10)
    requests (1.1.0)
    seobject (0.1)
    sepolicy (1.1)
    setuptools (0.9.8)
    six (1.3.0)
    urlgrabber (3.10)
    urllib3 (1.5)
    yum-metadata-parser (1.1.4)
    [root@ip-172-31-8-41 ~]# pip install django mysql-python
    Collecting django
      Downloading Django-1.7.7-py2.py3-none-any.whl (7.4MB)
        100% |################################| 7.4MB 74kB/s
    Installing collected packages: django
    
    Successfully installed django-1.7.7


  8. 動作確認

    # django-admin startproject testweb
    # cd testweb/
    # ./manage.py runserver 0.0.0.0:8888
    Performing system checks...
    
    System check identified no issues (0 silenced).
    
    You have unapplied migrations; your app may not work properly until they are applied.
    Run 'python manage.py migrate' to apply them.
    
    March 28, 2015 - 16:39:27
    Django version 1.7.7, using settings 'testweb.settings'
    Starting development server at http://0.0.0.0:8888/
    Quit the server with CONTROL-C.

    Webブラウザ起動してページへアクセス・・・繋がらない

    あ、SecurityGroupで8888ポート開放していない
    EC2のSecurityGroupに戻ってMyIPから8888へのアクセス開放

    もう一回アクセス・・・繋がった


  9. DB設定
     DjangoはデフォルトDB設定がsqlite3を利用する
     DBをRDSのDB情報に設定変更する

    # vi testweb/settings.py
    以下を変更
    ---
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        }
    }
    ---
     ↓
    ---
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'HOST': <RDS Endpoint>,
            'PORT': '3306',
            'NAME': 'testsitedb',
            'USER': 'test',
            'PASSWORD': <password>,
        }
    }
    ---
    # # ./manage.py runserver
    Traceback (most recent call last):
      File "./manage.py", line 10, in <module>
        execute_from_command_line(sys.argv)
      File "/usr/lib/python2.7/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line
        utility.execute()
      File "/usr/lib/python2.7/site-packages/django/core/management/__init__.py", line 354, in execute
        django.setup()
      File "/usr/lib/python2.7/site-packages/django/__init__.py", line 21, in setup
        apps.populate(settings.INSTALLED_APPS)
      File "/usr/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
        app_config.import_models(all_models)
      File "/usr/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
        self.models_module = import_module(models_module_name)
      File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
      File "/usr/lib/python2.7/site-packages/django/contrib/auth/models.py", line 40, in <module>
        class Permission(models.Model):
      File "/usr/lib/python2.7/site-packages/django/db/models/base.py", line 122, in __new__
        new_class.add_to_class('_meta', Options(meta, **kwargs))
      File "/usr/lib/python2.7/site-packages/django/db/models/base.py", line 297, in add_to_class
        value.contribute_to_class(cls, name)
      File "/usr/lib/python2.7/site-packages/django/db/models/options.py", line 166, in contribute_to_class
        self.db_table = truncate_name(self.db_table, connection.ops.max_name_length())
      File "/usr/lib/python2.7/site-packages/django/db/__init__.py", line 40, in __getattr__
        return getattr(connections[DEFAULT_DB_ALIAS], item)
      File "/usr/lib/python2.7/site-packages/django/db/utils.py", line 242, in __getitem__
        backend = load_backend(db['ENGINE'])
      File "/usr/lib/python2.7/site-packages/django/db/utils.py", line 108, in load_backend
        return import_module('%s.base' % backend_name)
      File "/usr/lib64/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
      File "/usr/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 18, in <module>
        raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)
    django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: No module named MySQLdb

    MySQLdbモジュールがないらしい
    というか色々ないらしい。

    # yum install mysql-devel gcc python-devel
    # pip install mysql-python
    # ./manage.py migrate
    Operations to perform:
      Apply all migrations: admin, contenttypes, auth, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying sessions.0001_initial... OK

    なんか色々作られた。

    # mysql -h <RDS Endpoint> -u test -p
    Enter password:
    Welcome to the MariaDB monitor.  Commands end with ; or \g.
    Your MySQL connection id is 167
    Server version: 5.6.22-log MySQL Community Server (GPL)
    
    Copyright (c) 2000, 2014, Oracle, MariaDB Corporation Ab and others.
    
    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
    
    MySQL [(none)]> use testsitedb
    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 [testsitedb]> show tables
        -> ;
    +----------------------------+
    | Tables_in_testsitedb       |
    +----------------------------+
    | auth_group                 |
    | auth_group_permissions     |
    | auth_permission            |
    | auth_user                  |
    | auth_user_groups           |
    | auth_user_user_permissions |
    | django_admin_log           |
    | django_content_type        |
    | django_migrations          |
    | django_session             |
    +----------------------------+
    10 rows in set (0.00 sec)

    データベースにテーブルが作成されていた。


今日はここまで。。
全然出来なかった。

EC2とRDSが連携出来たので目的は達成かな。