いますぐ使う CloudFront

CloudFrontとは

台数不明で性能不明ですが、グローバルに配置された、キャッシュサーバー。

効果

CloudFrontをリバースプロキシキャッシュとして立ててみました。お問い合わせページなど動的ページを除いて、ほぼ全部のリクエストをCloudFrontが捌いてくれてます。

d0ff6181-11f1-d277-eee8-2d5999566133.jpg

※効果には個人差がございます

課金ポイント

  • 料金 – Amazon CloudFront | AWS

    • データ転送料金
    • キャッシュクリア料金
      • 1ファイル1回クリアが、月間1000回までは無料。以降は0.005 USD

        • リリースとかでこまめに大量のファイルをクリアすると、金かかる
        • キャッシュ有効期限は24時間。24時間ほっとけるならキャッシュクリア料金かからない

用語整理

  • ひとつのCloudFrontは「ディストリビューション」。

    • EC2やRDSが「インスタンス」と呼んだように。
  • キャッシュルールは「ビヘイビア」
  • キャッシュ元データを配信するサーバーを「オリジン」
    • ELB、EC2、S3、その他のサーバー
  • キャッシュクリアは「インバリデート」
    • 「無効化リクエスト」と書いてある文書もある

CloudFront の設置場所

CloudFront無しの構成

EC2のローカルディスクにすべてがあります。静的コンテンツ、動的ページ、すべてのアクセスを、EC2が捌く必要があります。ApacheとかNginxでキャッシュを効かせると、負荷は軽くなるかも。みたいな涙ぐましいノウハウがあったのです。

f65e1219-60fe-d83f-c483-73b133b04544.jpg

横に置く

昔のCloudFrontは、GETとHEADしか受け付けなかったため、JS/CSS/画像/添付ファイルなどを配信するS3を別立てにして、その手前にCloudFrontを置いていました。HTMLの実装では、cssとかjs、画像のタグに書くのリンクを xxxxxxxx.cloudfront.com にしておくことで、こうできます。図ではS3に置くことにしていますが、リリースでのCSSやJSの同期とか、何かと状況が複雑になりがちです。

40904824-cf46-b636-e04c-ee2462471b96.jpg

前に置く

CloudFrontの2013年10月のアップデート から、すべてのHTTPメソッドを受けてくれるため、ウェブアプリサーバーの手前に置くことができます。この場合は、静的コンテンツはCloudFrontのキャッシュでリクエストを捌き、動的ページはCloudFrontはスルーさせて、EC2で処理させます。

626b87d4-abd6-5ba8-6835-b3319f2722c0.jpg

今からやるなら「前に置く」構成

CloudFront無しの構成に導入するなら、断然「前に置く」構成です。

ウェブアプリのソース改修不要で、CloudFrontを適切に設定して配置するだけでOKなので、面倒がないです。

ただし、特定のページだけIP制限してたりすると、ApacheやNginxの設定を変更する必要があります。

とりあえずCloudFrontを立てる

必須項目だけ埋めて、あとで直せばOKです。

  • AWSコンソールにはいる
  • CloudFrontのページに行く
  • Create Distribution
    • Webを選ぶ(RTMPは動画配信とかに使う用)

      • Origin Settings

        • Origin Domain Name

          • ELBエンドポイントURL、BeanstalkエンドポイントURL、S3エンドポイントURL、EC2 DNS名など
          • IPアドレスでなければOK
      • Default Cache Behavior Settings
        • あとで変えるので放置
      • Distribution Settings
        • Alternate Domain Names(CNAMEs)

          • このディストリビューションに当てる予定のドメイン名。
          • 「前に置く」構成なら、これまでELBに当てていたドメイン名を指定。
          • 「横に置く」構成なら、空欄でOK
      • 他はあとで変えればOKなので放置
      • Create Distributionボタン押す
  • ディストリビューションは全世界に分散して立つのと、微妙にダサい仕様のため、しばらく時間がかかります

ビヘイビアの掟

  • ビヘイビアリストの上から順に評価されます。
  • Default (*)は、
    • 一番下から動かせません。
    • 削除できません。
    • どのビヘイビアにも当たらなかった場合のため存在します。
  • パスパターンにマッチしたら、そのビヘイビアだけに従って、キャッシュを見たり、オリジンにスルーしたりする
    • なので、ビヘイビアの上下の並び順は重要

ビヘイビアの設定方針

下記のどちらか。後からでも変更はできますが、どっちで行くかを考えるために、先に切り分けておくと良いです。

  • Default (*)を「キャッシュする」で書く。他のパスパターンは「キャッシュしない」で書く。
  • Default (*)を「キャッシュしない」で書く。他のパスパターンは「キャッシュする」で書く。

キャッシュしないページの設定

  • Path Pattern

    • 仮に http://hoge.example.com/contact/piyo.jpg みたいなとき

      • /contact/piyo.jpg
      • /contact/*.jpg
      • *.jpb
    • みたいに、そのキャッシュルールを適用するパスパターンを指定します。
  • Allowed HTTP Methods
    • 全部入りのを指定
  • Forward Headers
    • 「all」を指定
  • Object Caching
    • Customize
    • TTL(min, max, default)
      • ぜんぶゼロを指定
  • Forward Cookies
    • 「all」を指定
  • Query String Forwarding and Caching
    • 「forward all, cache based on all」を指定

キャッシュするページの設定

  • Path Pattern

    • 仮に http://hoge.example.com/contact/piyo.jpg みたいなとき

      • /contact/piyo.jpg
      • /contact/*.jpg
      • *.jpb
    • みたいに、そのキャッシュルールを適用するパスパターンを指定します。
  • Allowed HTTP Methods
    • GET,HEAD を指定
  • Forward Headers
    • 「Host」は必須。他にも必要なものがあれば追加。
  • Object Caching
    • Use Origin Cache Headers
    • Customizeにして、TTLを入れてもOK
  • Forward Cookies
  • Query String Forwarding and Caching
    • 「forward all, cache based on all」を指定

DNS設定

ビヘイビアふくめて、ディストリビューションの設定が完成したら、DNSの設定を書き換えます。

ディストリビューションには、「d1lxxxxxxxxx.cloudfront.net」のような、一意なドメイン名が発行されます。

Alternate Domain Names (CNAMEs)に入れたドメイン名のCNAMEとして、ディストリビューションのドメイン名を向けた、DNS CNAMEレコードを作成します。

動作確認

サイトにアクセスして、期待したとおりにビヘイビアが設定できているか、確認しましょう。

ChromeのデベロッパーツールのNetworkタブで、個々のファイルのレスポンスヘッダーに下記のようなのがあれば、CloudFrontを経由しています。

Via:1.1 41f313008af830d498dcb13814523bd7.cloudfront.net (CloudFront)
X-Amz-Cf-Id:xcP_6KiTFG_guNA9dRA-KOW6pg740-3mP1SvSrt2NqKGndWGPJKVuA==
X-Cache:Hit from cloudfront

X-Cacheに、キャッシュヒットしたかしてないかが記載されます。HitとMiss、ほかにもいくつかありますが、、、

  • X-Cache:Hit from cloudfront

    • CloudFrontにあるキャッシュが返っています
  • X-Cache:Miss from cloudfront
    • CloudFrontにキャッシュがなく、オリジンから返っています

HitとMissが想定と異なる場合は、ビヘイビアの調整が必要です。がんばりましょう。

その他、TIPS

制限、仕様

導入前に、CloudFrontというプロダクトの制限と仕様が、プロダクトの制限と仕様にマッチするのか、検討が必要です。

参考文書

続きを読む

AWS環境構築でやったこと

自分用のメモですが、よければ参考にしてください。

AWS

 言わずもがな、Amazon Web Services のことです

準備

EC2コンテナ作成

参考:http://qiita.com/tmknom/items/303db2d1d928db720888

ほとんどこの通り!ありがとうございます!

SSHアクセス

  • 固定IPの設定

    • Network & Security -> Elastic IPs
    • Allocate New address
    • Actions -> Associate address
    • Instanceと紐付ければOK
  • SSHアクセス

    • pem取得

      • Network & Security -> Key Pairs
      • Create Key Pair
      • 証明書ダウンロード
    • SSHアクセス
    ssh -i xxx.pem ec2-user@ec2-XX-YY-WW-ZZ.us-west-2.compute.amazonaws.com
    

アクセスできたらもうあなたはAWSマスター

構築後

  • セキュリティアップデート
    yum -y update

* 自動更新設定
http://qiita.com/yangci/items/2ccac2b598900eb5928d
  • ツールのインストール
    yum -y install oh-my-zsh
    yum -y install emacs

    #etc...

続きを読む

aws周りのメモ2

postgresqlを使う

RDSへpostgresqlをいれて立ち上げ

認証と接続

import-key-pair — AWS CLI 1.11.87 Command Reference
http://docs.aws.amazon.com/cli/latest/reference/ec2/import-key-pair.html

cd $HOGE
openssl genrsa -out my-key.pem 2048
openssl rsa -in my-key.pem -pubout > my-key.pub
# IAMのコンパネで*.pubを入力
# 多分、権限があれば以下でもいける
# aws iam upload-ssh-public-key

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

便利

無料枠

無料のクラウドサービス | AWS 無料利用枠
https://aws.amazon.com/jp/free/

AMI

AWS Marketplace: Search Results
https://aws.amazon.com/marketplace/search/results?x=14&y=18&searchTerms=&page=1&ref_=nav_search_box

CFテンプレート

サンプルコード & テンプレート – AWS CloudFormation | AWS
https://aws.amazon.com/jp/cloudformation/aws-cloudformation-templates/

ec2 ami tool & ec2 api tool

Mac で Amazon EC2 API Toolsを設定する – サーバーワークスエンジニアブログ
http://blog.serverworks.co.jp/tech/2013/01/31/mac-amazon-ec2-api-tools-setup/

ec2 api toolは若干心配。

VPCを使う

接続の際に、sshを経由したい。sslでもいいけどなんかsshがいいなと。
パスワードよりkeyのほうがセキュアだからかな。

0から始めるAWS入門①:VPC編 – Qiita
http://qiita.com/hiroshik1985/items/9de2dd02c9c2f6911f3b

導入

Amazon VPC とは? – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Introduction.html

公式のいろいろ

料金 – Amazon VPC | AWS
https://aws.amazon.com/jp/vpc/pricing/

基本は無料だけどNATとVPNは別課金。

【AWS 再入門】VPC 環境に踏み台サーバーを構築して SSH 接続してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-bastion-host-vpc/#i-3

ec2(Bastion)を配置する必要がありそう。

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

VPC に推奨されるネットワーク ACL ルール – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/VPC_Appendix_NACLs.html

vpcでのネットワークのポリシーの例

Default VPC

AWSのDefault VPCを削除して困った話 – MikeTOKYO Developers
http://blog.miketokyo.com/post/49939300091/aws-default-vpc

デフォルトvpcは削除したらダメか。使い分けがわからん。

Amazon EC2 と Amazon Virtual Private Cloud – Amazon Elastic Compute Cloud
http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/using-vpc.html

基本の機能はデフォルトとそうじゃないvpcは同じだけど、
デフォルトvpcがないとちゃんと機能しない。
デフォルトの属性によって、指定がないとipを紐付けたりする。

VPCネットワーク設計

これだけ押さえておけば大丈夫!Webサービス向けVPCネットワークの設計指針 | eureka tech blog
https://developers.eure.jp/tech/vpc_networking/

ネットワークは一度稼働させると移行が大変なので、初期設計が非常に重要になります。

わかりやすい。図が特に。

  • Bastion
  • NAT
  • Security Group

ENI

インフラエンジニアに贈るAmazon VPC入門 | シリーズ | Developers.IO
http://dev.classmethod.jp/series/vpcfor-infra-engineer/

サブネットで指定したIPアドレスのうち、先頭4つと末尾の1つはVPCで予約されるため使用できません。

VPCでは常にDHCP有効とするのがポイントです。

また、DHCPサービスで伝えられる情報(DHCPオプション)は、変更することもできます。

仮想マシンにひもづくENIにより、DHCPサーバーから毎回同じMACアドレス、IPアドレスが付与されます。これは、仮想マシンの状態に依存しないため、仮想マシンを再起動しようと、一旦シャットダウンしてしばらくしてから起動した場合でも必ず同じアドレスが付与されます。

ENI(Elastic Network Interface)か。。なるほど。でも、使うことはなさそうだな。

NAT

IPマスカレードが使えないVPC
NATは、Static(静的・サーバー用途)とElastic(仮想・クライアント用途)がある。
個人的には、このNATインスタンスの実装は、あまり好きではありません。動きがややこしいですし、ユーザーが自分でNATインスタンスの管理をしなければならないのも煩雑な印象を受けます。VPCのネットワークサービスの一つとして提供される機能であれば、ユーザーからはなるべく抽象化され仮想マシンとして意識されないようにするべきと考えます。
ただ、ユーザーから仮想マシンとして見える分、機能・実装が具体的に把握できる点やカスタマイズ性が高い点は良いとも思っています。

NAT インスタンスと NAT ゲートウェイの比較 – Amazon Virtual Private Cloud
http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-nat-comparison.html

なるほど。。

Bastion

AWSで最低限セキュアな構成を組む – Qiita
http://qiita.com/ausuited/items/09b626fa5264f0c650fd

パブリックSubnetにEC2インスタンス(踏み台サーバーとして)
NATインスタンスを作成した要領で、パブリックSubnetにEC2インスタンスを作成する。Security groupは新規に作成してSSHをAnywhereに。Key pairは厳重に管理。尚、踏み台サーバーは、使用する時以外はStoppedにしておく事で、さらにセキュアな状態とする。このデザインパターンをOn Demand Bastionパターンと呼ぶらしい。

詳しい。「On Demand Bastionパターン」か。なるほど。

vpcへの踏み台サーバー
ポートフォワーディング、トンネルなどと同じ意味。

Network ACL

インスタンス単位じゃなくサブネット単位でより制限してセキュアにしたい場合に使うのかな。

安全なVPC設計 — Commerce Hack
http://tech.degica.com/ja/2016/01/07/designing-vpc-and-subnets/


結局どうするのか、、ひとまずNATはつかわずに、Bistionをつくってみる感じかな。

アベイラビリティーゾーン

リージョンごとでの、障害などで全部やられないように物理的にセグメントされた範囲の単位かな。
RDSではセグメントグループに2つ以上のゾーンを含める。でも、一つしか使わなくていい。ということか。s

RDSのVPC間の移動

サブネットグループの関連付けを変えればいいらしい。間違って設定したので移動した。

【小ネタ】知っていましたか?RDSを別のVPCに移動できることを | Developers.IO
http://dev.classmethod.jp/cloud/aws/rds_can_move_to_another_vpc/

Bastion作成作業をしてみる

主に下記を参考。

【AWS 再入門】EC2 + RDS によるミニマム構成なサーバー環境を構築してみよう – NET BIZ DIV. TECH BLOG
https://tech.recruit-mp.co.jp/infrastructure/retry-aws-minimum-vpc-server-environment/

  • サブネットってなんだっけとか復習。
  • ストレージはどうするのか。
    • とりあえずssdにしたけどマグネティックでよかったかなあ。

      • ssd:$0.12 : 1 か月にプロビジョニングされたストレージ 1 GB あたり
      • マグネティック: 0.05 USD/GB-月
  • public IPは設定必要だよね
  • market placeからamiを取得した方がいいの?
    • とりあえず公式のウィザードを使ったけど。
  • 認証にIAMが追加されていたので使ってみた
    • これとは別にキーペアは必要ってことかな。
  • CFnテンプレート(CloudFormationテンプレート)というのがあるらしい。。
    • これでつくりなおそうかな。。
  • サブネットとかいろいろネットワーク系の設定
    • なんだかんだいっていろいろあった
  • セキュリティグループ
    • エイリアスみたいなセキュリティグループにできたらいいのに。タグや名前で明示化かな。
    • bastionは22をあけて、rdsは5432をbastionからのみあける
  • ログイン
  • DNS
    • あれ、パブリックDNSがうまく割り振ってないな。。
      AWSでPublic DNS(パブリックDNS)が割り当てられない時の解決法 – Qiita
      http://qiita.com/sunadoridotnet/items/4ea689ce9f206e78a523
    • RDSのDNS
      • nslookupしたら内部ipがかえってくるのね。接続できないけどなんか気持ち悪いな。これかな。。
        外部からdnsを引けることを気にしている人は見かけなくて便利だからって話なのかね。
        【AWS】VPC内でPrivate DNSによる名前解決 – Qiita
        http://qiita.com/y_takeshita/items/2eb5e6abb5eb5516d1de

やってるうちはいいけど、しばらくやらないと設定の方法とか忘れそう。。こういうのは学習コストだけじゃないな。

PlantUMLで図にしておく

Kobito.hQIwJs.png

VPC内のRDSへLambdaから接続。。

しまった!アンチパターンだそうだ。。

Lambda+RDSはアンチパターン – Qiita
http://qiita.com/teradonburi/items/86400ea82a65699672ad

Lambda + RDS benchmark – Qiita
http://qiita.com/taruhachi/items/3f95ae3e84f56edb3787

新し目の記事でIAM認証でクリアできそうな。。

【全世界待望】Public AccessのRDSへIAM認証(+ SSL)で安全にLambda Pythonから接続する – サーバーワークスエンジニアブログ
https://blog.serverworks.co.jp/tech/2017/04/27/rds-iam-auth-lambda-python/


セキュアに接続するのと速度のトレードオフになっていたのが
IAM認証のおかげで両方可能になったということっぽい。
でも、ネットのスループット、コネクション数(料金・負荷)、など、、ほかにも気にすることが出て来そうで若干不安。
非同期でよければキューイングして一回投げっぱなしすればどうだろう。
もしくは、似てるけど、Lambdaから一回値を返してもらってからRDSへ投げ直す。
これでいっかなあ。。Lambdaの意味がなくなる?うーん。

今後

  • 疑問としてrdsなど内部向けのdnsを外から見れなくできないものか。
  • というか、rdsのエンドポイントって再起動したら変わったりしないかね。ipは固定されるのか。
    • たぶん、サブネット内でdhcpになるのでipは変動するけどエンドポイントは固定。。じゃないかしら。

posgresqlをつかうための情報

Amazon RDS 上の PostgreSQL – Amazon Relational Database Service
http://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_PostgreSQL.html#PostgreSQL.Concepts.General.SSL

続きを読む

[AWS] 積年の夢の終焉…?:リージョン間VPN接続 (powered by VyOS 1.1.7)

プロローグ

[AWS] 積年の夢の実現:リージョン間VPN接続 (powered by SoftEther)
[AWS] 積年の夢の続き:リージョン間VPN接続 (powered by Windows Server 2012 R2)
と歩を進めてきた、三部作(勝手に後付け♪)のファイナルw VyOS編。

  • VyOSがSoftEther/Windowsより優れているのは、VPN Connection接続(下記【a】)もPeer-to-Peer接続(下記【b】)もMobileアプリからのL2TP/IPSec接続(下記【c】)も可能なこと(と思っている)。
    ⇒SoftEtherは【a】不可、Windowsはそりゃ頑張ればナンでもできるでしょうが。。
    OVERVIEW_20170516.jpg

  • 。。。と思っていたところ、VPN ConnectionでVyOS(Vyatta)用のconfigをDLできなくなった???一昔前はできたはず…(・・;)
    ⇒なんと、RegionによってVPNCがサポートしているルータが異なることを発見!!(VyOS(Vyatta)は、N.Virginiaにはあるが、N.Californiaにはない、といった具合)

  • 半面、VyOSのDisadvantageは、学習コストが(少なくともCCNAしか持っていないヲレには)高い、という点か。
    ※SoftEtherもWindowsも、自動化とか欲張らなければ、GUIでも設定可能

    • といいつつ、VyOSもLinuxベース(vbash?)なので、そこまではぢめまして感はなく。
    • 「configure~commit/save」は、Cisco IOSの「configure terminal」と似ていると感じたよ。
    • その後、VyOSも、接続するまでなら、そんなに敷居が高くない(低くはない)ことを識る(いわゆる「知らないから怖い」&「食わず嫌い」)

⇒いや、やはりVyOSの敷居は高かった。。。CentOS等と似て非なり。Cisco IOSと非なりて似る。

構成オプション、どん!

VyOSは、様々なインストール方法・様々なVPN接続方法がある(♬そしてワタシはツブされる…(@_@))

  • VyOSインストール方法
     【1】 AWSのAMIを利用してEC2インスタンスとして作成
     【2】 オンプレミスにVirtualBox上に仮想マシンとして作成
     【3】 VirtualBox上のDockerホストにてDockerコンテナとして作成【Dockerでルータをコンテナ化してみた】
     【4】 あらゆるDockerホストにてDockerコンテナとして動作
        ⇒ そしてマルチクラウドへ。。。(【VyOSを使ってSoftLayerとAWSをIPSecVPN接続】

  • VPN接続方法
     【a】 AWSのCustomer Gateway(CGW)/VPC Connection(VPNC)/Virtual Private Gateway(VGW)を利用 [//]
     【b】 VyOS同士の直接接続(Site-to-Site接続)[]
     【c】 Windows10やAndroidから接続(Point-to-Site接続) [/]

【1】AMIを利用してEC2インスタンスとして作成

  • VyOS AMIのビルトインユーザは、「ec2-user」でなく「vyos」
  • rootユーザにパスワードを設定。。。passwdコマンドではできない。。。!?【保留中】
  • ログインユーザ作成【保留中】
$ configure
# set system login user 《管理者ユーザ》 authentication plaintext-password 《管理者ユーザのパスワード》
# commit
# save
# exit
  • 「vyos」の公開鍵を、《管理者ユーザ》にコピー【保留中】
$ sudo cp /home/vyos/.ssh/authorized_keys /home/《管理者ユーザ名》/.ssh/
  • ビルトインユーザ「vyos」削除 ※「vyos」以外のユーザでログインし直した上で
    【保留中】VyOSサーバを再起動したら、作成した管理者ユーザでSSHログインできなくなった (・・;)
$ configure
# delete system login user vyos
# commit
# save
# exit
  • 2枚目のENI(Private側)にプライベートIPアドレスをアサイン

※EC2を作成するCloudFormationにおいて、Public側ENIをIndex0、Private側ENIをIndex1と指定済み
OR
※ENI 1枚挿しのEC2インスタンスを起動した後で、2枚目ENIを手動でAttach済み

$ configure
# set interfaces ethernet eth1 address '10.100.12.100/24'
# commit
# save
# exit
$ sudo ifconfig
《eth1にプライベートIPアドレス「10.100.12.100」が割り当たっていることを確認》 

※ifconfigやroute等のNW系コマンドはrootでのみ実行可能

【1】を使ってAWS上で【a】でツナぐずら

(韓国(KR)のVyOSサーバと、USのVGWをVPN Connectionで接続)

  • 【US】VyOSサーバ持つEIPを使って、CSGを作成

    • BGPのAS番号を「65000」と指定
  • 【US】VPCとVPNCを作成

    • VPCのRouteTableにおいて「Propagated=yes」
      ⇒KRへのルーティング情報が、VGW経由で、US側のRouteTableに動的に追加されるようになる!
  • 【US】VPNCから「VyOS用config」をDL・・・少なくとも「N.Virginia」なら可能

  • 【KR】「VyOS用config」の一部を手動で書き換え:

    • local-address

      • VyOSサーバのパブリック側プライベートIPアドレス(10.100.11.100)に書き換え
        NAT-Tを利用するため、EIPではなくてプライベートIPアドレスと理解)
    • BGPのアドバタイズ情報
      • 10.100.11.0/24, 10.100.12.0/24
      • このBGPアドバタイズが中々できずにハマる。。。「10.100.12.0/24」をVyOSが認識していないためと推理(後述)
  • 【KR】「VyOS用config」を投入!!

    • AWSからDLしたスクリプトを一部書き換え後に愚直に実行すると、BGPアドバタイズの行で「Already exists」のエラーが発生★ そりゃそうなので無視~
  • 【KR】BGPアドバタイズ情報の追加

$ configure
# set protocols static route 10.100.12.0/24 next-hop 10.100.12.1
# set protocols bgp 65000 network 10.100.12.0/24
# commit
# save
# exit

【とっても素敵な参考情報】BGPアドバタイズするネットワーク設定の追加

  • 【US】ルーティング情報の確認

    • VGWのTunnel(2本)がUpしていることを確認
    • KR側のVPCサブネットに関するルーティング情報が、BGPによって動的にUS側RouteTableに反映されていることを確認する。
  • 【KR】疎通確認
    ①KR側のVyOSサーバからUS側にPingを送って確認

vyos@VyOS-AMI:~$ ping 172.16.12.200 interface 10.100.11.100
PING 172.16.12.200 (172.16.12.200) from 10.100.11.100 : 56(84) bytes of data.
64 bytes from 172.16.12.200: icmp_req=1 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=2 ttl=254 time=196 ms
64 bytes from 172.16.12.200: icmp_req=3 ttl=254 time=196 ms
・・・

VyOS上の送信IF(Public側)を明示的に指定する必要がある模様

②KR側のプライベートEC2からUS側にPingを送って確認

ping 172.16.12.200
  • 【US】疎通確認

    • US側からKR側にPingを送って確認

【閑話休題】BGPアドバタイズでハマった考察

疎通できた後で振り返ってみれば単純なことだが、めっちゃハマったのは、BGPによる動的ルーティング情報交換

  1. VyOS EC2の2枚目のENIの(プライベート)IPアドレスが、いつの間にか外れていた…
    ⇒最初ifconfigで設定していたから、再起動中に消失?VyOS設定「set interfaces ethernet eth1 address~」なら永続的?

  2. VyOSサーバに対して、KR側プライベートサブネットへのStatic Routeが必要だった。
    ⇒これは…自力では思いつかない…
    【再掲】BGPアドバタイズするネットワーク設定の追加

  3. BGPのルーティング情報伝達(コンバージェンス?)に、設定投入~環境反映の間のタイムラグがある?
    ⇒KR側のVyOSへのBGP設定投入後、US側のVGWからRouteTableへの伝達に少し時間がかかることを知らず、設定ミスだと思いこんでいた…

【2】オンプレミスのVirtualBox上に仮想マシンとして作成

VyOSは、一般的にはISOファイルで提供されているのか(AWSならAMIで提供)。
ISOファイルをDLし、VirtualBoxの起動時の「Optical Device」として指定してあげると、VyOSのインストールプロセス開始☆
格闘中…)

【1】と【2】を【b】でツナぐもな

(オンプレミスのVirtualBox仮想マシンと、VyOS-EC2を、VyOS機能で直接通信)

【1】と【3】を【c】でツナぐだなも

(Windows10/Android端末と、VyOS-EC2を、IPSec/L2TPで通信)

エピローグ

AWSリージョン間接続について、SoftEther/Windows/VyOSをひととおりやってみた。
まだまだ試したいこと・課題はあるけど、ひとまずおなかいっぱい。

続きを読む

〇FLAGの中の人に憧れてMastodon×AWSでモンストドン作ってみた

Mastodon立ち上げたらいい会社に入れると聞いて、邪な気持ちで。。。いや、Mastodonとモンストって相性よさそうだなぁと思いたち、少し乗り遅れた感をかもしだしながら、フルにAWSを使って規模拡大しても大丈夫な構成で作ってみた。

モンストドン (https://monstdn.com)

構成

monstdn.png

最小構成のざっくり料金($1=113円、1ヶ月30日計算)

サービス 単価 月額料金
ALB 1台 × $0.0243/1H + データ転送的なの  約2000円 + α
EC2 2台(t2.nano) × $0.008/1H + データ転送的なの 約1300円 + α
RDS 1台(db.t2.micro シングルAZ) $0.028/1H + データ転送的なの 約2300円 + α
ElasticCache 1台(cache.t2.micro) $0.026/1H + データ転送的なの 約2100円 + α
S3Bucket $0.025/GB + リクエスト数的なの + α
SES $0.10/1,000通あたり + データ転送的なの + α
合計     ( 約7700円 + α なので ) ざっくり1万ぐらい

※無料枠があるので1年目はもう少しやすくできそう

やったこと

  • AWSのアカウント作成
  • IAMの作成とアカウントの初期設定(二段階認証とか、パスワードポリシーとか)
  • Route53でドメインを買う
  • SESでメール設定と制限解除申請
  • ACMの取得(無料でHTTPS通信)
  • S3バケット作成(画像とかのアップロードファイルの配信用)
  • VPCとセキュリティグループの作成
  • SES、S3へアクセスする為のIAMユーザの作成
  • ElasticCacheでRedisの作成
  • RDSでPostgreSQLの作成
  • EC2でCentOSを使ってMastodonの構築(下に詳細)とイメージ(AMI)の作成
  • AutoScallingの設定
  • ALB(ApplicationLoadBalancer)の作成(ACMをつける)
  • Route53でHostZoneのレコード設定

CentOSでのMastdon構築(20170517現在)

sudo su -
yum -y update
yum -y install vim

localectl set-locale LANG=ja_JP.utf8
localectl set-keymap jp106
localectl status

timedatectl set-timezone Asia/Tokyo
timedatectl status

dd if=/dev/zero of=/mnt/swapfile bs=1M count=2560
mkswap /mnt/swapfile
swapon /mnt/swapfile
chmod 0644 /mnt/swapfile
echo "/mnt/swapfile                             swap                    swap    defaults                0 0" >> /etc/fstab
free

vim /etc/sysconfig/selinux
 SELINUX=enforcing
 ↓
 SELINUX=disabled

systemctl disable postfix
systemctl disable auditd.service

yum -y install libxml2-devel ImageMagick libxslt-devel git curl nodejs file
yum -y install epel-release
rpm --import http://li.nux.ro/download/nux/RPM-GPG-KEY-nux.ro
rpm -Uvh http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
yum -y install ffmpeg ffmpeg-devel

yum -y group install "Development tools"
curl -sL https://rpm.nodesource.com/setup_4.x | sudo bash -

yum -y install nodejs
npm -g install yarn

yum -y install postgresql postgresql-contrib postgresql-devel
yum install -y openssl-devel readline-devel

useradd mastodon
passwd mastodon
su - mastodon
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
cd ~/.rbenv && src/configure && make -C src && cd ~
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile && source ~/.bash_profile
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.4.1 && rbenv global $_ && rbenv rehash

# 確認
ruby -v

cd ~
git clone https://github.com/tootsuite/mastodon.git live
cd live
git checkout $(git tag | tail -n 1)

gem install bundler
bundle install --deployment --without development test
yarn install --pure-lockfile

cp .env.production.sample .env.production
sed -i "/^PAPERCLIP_SECRET=$/ s/$/`rake secret`/" .env.production
sed -i "/^SECRET_KEY_BASE=$/ s/$/`rake secret`/" .env.production
sed -i "/^OTP_SECRET=$/ s/$/`rake secret`/" .env.production

vim .env.production
#Redis,Postgresql,言語,SMTP,S3の設定

RAILS_ENV=production bundle exec rails db:setup
RAILS_ENV=production bundle exec rails assets:precompile

exit

cat << "_EOF_" > /etc/systemd/system/mastodon-web.service
[Unit]
Description=mastodon-web
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="PORT=3000"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_


cat << "_EOF_" > /etc/systemd/system/mastodon-sidekiq.service
[Unit]
Description=mastodon-sidekiq
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="RAILS_ENV=production"
Environment="DB_POOL=5"
ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

cat << "_EOF_" > /etc/systemd/system/mastodon-streaming.service
[Unit]
Description=mastodon-streaming
After=network.target

[Service]
Type=simple
User=mastodon
WorkingDirectory=/home/mastodon/live
Environment="NODE_ENV=production"
Environment="PORT=4000"
ExecStart=/usr/bin/npm run start
TimeoutSec=15
Restart=always

[Install]
WantedBy=multi-user.target
_EOF_

systemctl enable mastodon-{web,sidekiq,streaming}
systemctl start mastodon-{web,sidekiq,streaming}

cat << "_EOF_" | crontab -
RAILS_ENV=production
@daily cd /home/mastodon/live && /home/mastodon/.rbenv/shims/bundle exec rake mastodon:daily > /dev/null
_EOF_

yum -y install nginx

cat << "_EOF_" > /etc/nginx/conf.d/mastodon.conf
map $http_upgrade $connection_upgrade {
  default upgrade;
  ''      close;
}

server {
  listen 80;
  listen [::]:80;
  server_name {domainName};

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}
_EOF_

systemctl enable nginx
systemctl start nginx

# ユーザ登録後 admin設定
RAILS_ENV=production bundle exec rails mastodon:make_admin USERNAME={UserName}

メモ

EC2のDiskはSSDで(swapで使う)
ロードバランサーはApplicationの方じゃないとwebSocketがうまくいかない
コミュニティベースのシステムだからCloudFrontはあまり必要性感じなかったので使わなかった
(日本向けだしS3のバケット東京リージョンにあるし、S3もかなり性能いいし)
もしCloudFrontを使うなら、websocketできないからS3の前に置く感じ
今回CloudFrontの利点があるとすれば”ドメイン”が自分の使えることぐらいかな
CentOSじゃなくてAmazonLinux使いたかったけど、ffmpeg入れるのにやたら時間かかったからやめた。一応動いたけど(純正AWSが。。。)
DockerはDeployまで楽そうだけど、効率よくなさそうだったのでやめた
AWSでDocker使うならECSでやってみたいけど、Mastodonはすんなりできるのかなー
セキュリティ的にはロードバランサーからの80番ポートしか受け付けないように制御してるから大丈夫かな。
sshでのログインは同じVPC内に踏み台サーバ立ててと。

最後に

ここまで読んで頂きありがとうございます。
技術的なことを投稿するのはこれが初めてですが、だれかのお役にたてれたら嬉しいです。
普段はPHPとAWS少しいじる程度なのでいい勉強になりました。
ほとんど公開されている文献をもとにプラモデル感覚で作りましたので、ご指摘等あればコメント頂ければと思います。
個人でのサイト運用となりますので、落ちたらごめんなさい。

続きを読む

VPCのネットワークまわりをもう一度

VPCまわりって、ややこしいよね


  • VPC
  • サブネット
  • IGW・VGW
  • NATインスタンス・ゲートウェイ
  • セキュリティグループ
  • ネットワークACL
  • VPCピア接続

😂


今日はこのへん話します

  • VPC
  • サブネット
  • IGW
  • NATインスタンス

ひとつずつ、思い出してみよう
(知らない人はこれを機にそんなもんがあるのかと思ってみよう)


VPC(Virtual Private Cloud)


VPCとは

利用者ごとのプライベートなネットワーク空間のこと

クラスA〜Cのプライベートネットワークのいずれかの値を使用します


Q. aとbどちらが正しいでしょう

a. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげる
b. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげない


答え

a. VPCはリージョン内でAZ(アベイラビリティゾーン)をまたげる


AWS Design Simple AZ:Untitled - Cacoo 2017-05-17 11-07-07.png


サブネット


サブネットとは

大きなネットワークの中の小さなネットワーク

役割に応じてWeb用、DB用と作られる。これによって、インターネットからのアクセス制限をかけられたりする


Q. aとbどちらが正しいでしょう

a. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげる
b. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげない


答え

b. サブネットはリージョン内でAZ(アベイラビリティゾーン)をまたげない


AWS Design Simple subnet:Untitled - Cacoo 2017-05-17 11-12-13.png


IGW(Internet Gate way)


IGWとは

VPCと外部ネットワークの間で通信を行うための出入り口。こいつをVPCにアタッチしてインターをネットする


サブネットでネット制限

  • インターネットとのアクセスを許可するサブネット: パブリックサブネット
  • インターネットとのアクセスを許可しないサブネット: プライベートサブネット

ルートテーブルの設定によってパブリック/プライベートが決まる。
ルートテーブルでIGWをターゲットに設定するとパブリックになる。


AWS Design Simple:Untitled - Cacoo 2017-05-17 11-15-36.png


でもこのままだとプライベートサブネット孤立問題が起こる

  • パッチなどをダウンロードしたいときインターネットにアクセスできない
  • DynamoDBなど他のリージョンサービスにアクセスできない

そこで

NAT(Network Address Translation)

が登場します


NATを使うことで、インターネットからのアクセスを受け付けないまま、インターネットやDynamoDBなどのリージョンサービスにアクセス可能に


nat-gateway-diagram.png


ルーターとは

サブネットを相互接続し、インターネットゲートウェイ、仮想プライベートゲートウェイ、NAT ゲートウェイ、およびサブネットの間でトラフィックを正しい宛先に送る機能。


ありがとうございました

続きを読む

boto3でec2をdescribeして値を取り出す

どうもLambda(Python)初心者の若松です。

唐突ですが、みなさんはLambda使っていますか?

サーバが無くてもコードが動く。
魅力的ですよねぇ。

やっぱり時代はServerlessだと。
インフラでも言語の一つくらい使えるようになれと。

そんな流れに逆らわないゆとり世代ど真ん中の私は、とうとうLambdaに踏み込んだわけです。

前置きが長くなりましたが、インフラ屋が四苦八苦しながら戯言言ってんなぁぐらいの気持ちで生暖かく見ていただければと思います。

やりたいこと

特定のIPを持っているインスタンスのインスタンスIDを取得したい。

環境

AWS Lambda
Python 3.6

第一形態

コード

とりあえずインスタンス情報を全部取り出してみようかと思い、以下のコードを書きました。

import boto3

def lambda_handler(event, context):

    ec2 = boto3.client('ec2')

    responce = ec2.describe_instances()

    return responce

結果

returnで以下のエラーが返って失敗

{
  "errorMessage": "An error occurred during JSON serialization of response",
  "errorType": "datetime.datetime(2017, 5, 11, 5, 15, 59, tzinfo=tzlocal()) is not JSON serializable"
}

結果そのままではJSONとして扱えないみたいです。

調査

boto3のリファレンスを呼んでみると、どうやら describe_instances の返り値は dict(辞書)型 というもののようです。
とりあえずprintで出力したほうがよさげなので、コードを変更することにしました。

第二形態

コード

とりあえず出力をプリント文に変更

import boto3

def lambda_handler(event, context):

    ec2 = boto3.client('ec2')

    responce = ec2.describe_instances()

    print(responce)

    return

結果

ログに以下が出力されました。
AWSCLIの結果でよく見るあれですね。

{
    "Reservations": [
        {
            "OwnerId": "xxxxxxxxxxxx", 
            "ReservationId": "r-xxxxxxxxxxxxxxxxx", 
            "Groups": [], 
            "Instances": [
                {
                    "Monitoring": {
                        "State": "disabled"
                    }, 
                    "PublicDnsName": "ec2-xxx-xxx-xxx-xxx.ap-northeast-1.compute.amazonaws.com", 
                    "Platform": "xxxxxxx", 
                    "State": {
                        "Code": 80, 
                        "Name": "stopped"
                    }, 
                    "EbsOptimized": false, 
                    "LaunchTime": "xxxx-xx-xxxxx:xx:xx.xxxx", 
                    "PublicIpAddress": "xxx.xxx.xxx.xxx", 
                    "PrivateIpAddress": "xxx.xxx.xxx.xxx", 
                    "ProductCodes": [], 
                    "VpcId": "vpc-xxxxxxx", 
                    "StateTransitionReason": "", 
                    "InstanceId": "i-xxxxxxxxxxxxxxxxx", 
                    "EnaSupport": true, 
                    "ImageId": "ami-xxxxxxxx", 
以下略

調査

次はIPで絞りたいと思います。
AWSCLIでいうところの--filterはboto3にもあるらしいのでそれを使うことにしました。

第三形態

コード

特定のIPを持っているインスタンスに絞るため、Filtersを追加

import boto3

def lambda_handler(event, context):

    ec2 = boto3.client('ec2')

    responce = ec2.describe_instances(
        Filters=[{'Name':'network-interface.addresses.private-ip-address','Values':["xxx.xxx.xxx.xxx"]}]
    )

    print(responce)

    return

結果

指定したIPアドレスを持つインスタンスに絞れた。

調査

次は返り値をインスタンスIDに絞ります。
イメージとしてはAWSCLIでいうところの--queryだが、boto3にはないようです。
ここでJSONに変換するだのなんだのと、ネットの情報に踊らされてかなり苦戦しました。
結果的には、dict型はオブジェクトの後に [“hoge”][“fuga”] と書くことで値を取り出せるらしいことがわかりました。

最終形態

コード

import boto3

def lambda_handler(event, context):

    ec2 = boto3.client('ec2')

    responce = ec2.describe_instances(
        Filters=[{'Name':'network-interface.addresses.private-ip-address','Values':["xxx.xxx.xxx.xxx"]}]
    )["Reservations"][0]["Instances"][0]["InstanceId"]

    print(responce)

    return

結果

めでたくインスタンスIDの取得に成功しました。
リストある際には[0]と明示的に0を書く必要があるというところに気をつけたいところです。
※AWSCLIの--queryでは[]と省略して書けるため

まとめ

いかがでしたでしょうか。
やってる内容は非常に初歩的な内容ですが、いくつかハマった箇所があったので備忘録的にまとめました。

意外と簡単に動かせるので、是非Tryしてみてください。
Lambda怖くない。

続きを読む