続 カッコの付け方

AWSを始めとしたクラウドコンピューティング全般と、唯一神emacsにおける()の付け方についてだらだら書きます

Crate.IO クラウドネイティブな新しいデータベースエンジン

Crate.IOという新しいDBエンジンが 2014 TCのアワードをとっていたらしい。それからもう1年近く立っていますが、正直なところ、流行っているのか定かではないです。が、誰もやらないことのほうが面白いのでやります。

Crate.IOとは?

Crate でググると、木の箱の絵が出てきたり、Rustのパッケージマネジャ?とかぶるので、Crate.IOとします。正直、Crateはかなりググりにくい言葉です。ざっとまとめとくと

  • マルチマスタ型
  • ハナからクラウド前提
  • RDBで全部やるのじゃなくて、NoSQLでやろう、それもNoSQLの中でも用途ごとに分割しよう」という最近の風潮を全否定 全部 Crate.IOでやれ!
  • クライアントライブラリはもうほとんどの言語で用意済み
  • サーバ側はゼロコンフィグでいける(ようにしたい)

なかなか魅力的な おしながき でしょう?流行るかどうかはわからないですが。

アプリ開発者視点

Use Cases

インフラ的にいくら面白くとも、アプリ開発上意味がなければわざわざ採用する価値がありません。ましてや新しいDBエンジンです。全体的な印象としては、開発者に優しいと思います。
なんといっても
SQLが通る!

Crate SQL — Crate documentation

やっぱりSQLは強し! 上記マニュアル流し読み。

DDL

普通のRDBDDLとほぼ変わりませんが、シャーディング・ルーティングを意識した構文があります。

DDL デフォルトでシャーディング5本

Crate supports sharding natively, it even uses 5 shards by default if not further defined.

らしいです。5本以外だとDDLで指定すればOK。

Routing デフォルトはPrimary Key

If primary key constraints are defined, the routing column definition can be omitted as primary key columns are always used for routing by default.

Routingというと聞き慣れませんが、所謂シャードキーと捉えれば良さそう。Primary Key無しで、特定のカラムをシャードキー(clusterd by) に指定する。

Replication デフォルトで1レプリカ

Defining the number of replicas is done using the number_of_replicas property.

何箇所にレプリケーションするかを、DDLで指定しちゃいます!マニュアルによると最大4つ。ここまでやれば盤石でしょう。
しかもですよ!

Note The number of replicas can be changed at any time.

なんだと!

DDLまとめ

他にも Full Text や Partitioned Tableなど、ジジイがニヤつく機能やら、聞き慣れない Analyzer という物があったり、マニュアル読むだけでお腹いっぱい。
私が抜粋した分だけでまとめますと。

  • シャーディング・ルーティング・レプリケーション等、本来はウラ(インフラ側)で吸収していた部分が、思いっきりオモテ(=DDL)に出てきた

最初から、いかにスケールさせるかを想定して作られているので、これらの機能をDDLで指定します。ひとことで言うと、 なんかMongoDBっぽい ですが、MongoDBよりももう一歩踏み込んでいる感じはします。インフラ(サーバ)側を知るとそれは明確になります。

Query

https://crate.io/docs/reference/sql/queries.html#object-arrays

基本的なSQLは通りそうですが、その中でも気になったのが、Arrayに対するQueryです。いずれ試してみる。

Types

Object型など、ある程度予想がつくものもありますが、ユースケースにも上げられているジオ系のTypeと関数があります。複雑なことは出来ないですが、lat-longから距離を測ったりとかはできるようです。もっと複雑な機能は自分で拡張しろやってことでしょう。

https://crate.io/docs/reference/sql/data_types.html#geo-point

https://crate.io/docs/reference/sql/scalar.html#geo-functions

Blob

https://crate.io/docs/reference/blob.html

blobテーブルはDDLで定義して、Upload & Download は HTTP経由ですね。ここのDDLも勿論 シャード、レプリケーション数が指定できるようです。

各種言語の対応状況

安心してください、ほぼ全部です。

https://crate.io/docs/getting-started/clients/

万が一見つからなかったとしても。HTTPのRESTを叩くだけっぽいので、多分移植は楽勝。

アプリ側のまとめ

実のところ、インフラ側の方が楽勝ヒャッハーなんで、そこを書こうと思ってましたが力尽きました、次回書きます。
アプリ側も改めて見ると結構いいですね~

  • SQLが使えるよ!
  • シャーディング・ルーティング・レプリケーション、これらすべてDDLで指定する
  • Blobも使えるよ!、Upload/DownloadはHTTP
  • 認証機構は今のところ無い(マニュアル読んだ分だと)

今後Crate.IOの主戦場では、おそらく認証機構は必要となりそう。認証を入れた上で、どれぐらいのスピードが確保できるか。
最近の動向として、ESとの連携(データのマイグレーション?)が話題になっているようです。ココらへんも後ほど書くつもり。

知らん間にGoogle Cloud loggingでログ監視ができるようになっている件

GCPあるある
久しぶりにDevelopers Consoleにログインして新機能実装に気づく。

一応RSSとか購読してるんですが、ほんとにこのパターン多い。今回はCloud Logging (& Cloud Monitoring)です。以前にLog監視できたらいいなーとか、Pub/Sub + GAE でログ監視ができる!と言ってたのですが、ノンプログラミングでできるようになりました。

仕組み

Cloud Logging も Cloud Monitoring も本ブログで触れています。Cloud Logging は AWSCloud Watch Logs に似た仕組みですが、Cloud Logging自体にはLog監視機能がありませんでした。今回の機能追加でかなりの部分が競合するシステムとなりました。
今回のログ監視の仕組みもほぼ、AWSCloud Watch Logs と同じです。Logs-Based Metrics という名前そのまんまの機能を使って、Logをメトリックスとして Cloud Monitoring に見てもらいます。(グラフを書いたり、アラートを飛ばしたり)
今回はカスタムログ(自前のログ)を用いないので、ちょっと違いますが、だいたいこんな感じ。

Google fluent on GCE -> Cloud Logging -> Logs-based Metrics -> Cloud Monitoring -> アラート発報

実装

簡単です!今回はログの流し込みはやらないで、Activity log という、GCEのAPIコールのログを使います。

Cloud Logging側

f:id:iga-ninja:20151025091144p:plain

f:id:iga-ninja:20151025091323p:plain

f:id:iga-ninja:20151025091333p:plain

f:id:iga-ninja:20151025091340p:plain

Cloud Monitorninng側

f:id:iga-ninja:20151025091425p:plain

f:id:iga-ninja:20151025091441p:plain

参考

Logs-based Metrics - Cloud Logging — Google Cloud Platform

unicast対応でよみがえる keepalived on VPC-EC2

AWSを始め、ほとんどのパブリッククラウドはmulticastが出来なくて不便。と言われてきましたが、だったらunicastでやってしまえば良い!という考え方が 2013年頃すでにありました。なぜmulticastをやりたいの?と言うと そうだね!、LVS + keepalived だね! (あとはゴシッププロトコル) これまた2年前に EC2 + LVM (DSR) を実践してみたという素敵な解説があり、パッチを当てればいける ということは知ってたけど、月日がながれて 今日keepalivedの総本山を見てみたら

http://www.keepalived.org/changelog.html
Release 1.2.8 ぐらいからunicast対応してますね。というか、今更開発が活発になってきたのか?これは。というわけで、最新版の 1.2.19を使ってみます。

予備知識

EC2でmulticast でググると日本語を含めて結構な情報が得られます。混乱しないよう先に言うと、keepalivedのVRRPだけ に限ると、パケットキャプチャやらtcやらで自前実装して、事前準備するということは不要です。keepalivedがVRRPをunicastで実現してくれます 上記でもちらっと匂わせていた話ですが、

www.slideshare.net

は、汎用的な話です。つまり素直にmulticast/broadcastをエミュレーションしようということです。

www.slideshare.net

は、keepalived固有の話です。ていうか手順。keepalived側ですでにVRRP via unicastを実現しているので、パケットを覗いてMACアドレス分コピーして再送とかを自前で実装する必要はないです。

構成

LVS * 2 で VRRP冗長
Web * 2
動作確認用 Client
というこれまたパクリ構成です。

  • LVSの2つはお互いにVRRPで生きていることを広告します(正確にはVRRPで投げるのはMasterのみ、死亡を確認するとBackupが昇格)。重要な要素はVIP(フローティングIP)の存在です。このVIPを2台のうちどちらが持つかを決定します。
  • さらにこのVIPは EIP/ENIとは違います。この方法はEIP/ENIのインスタンスへの付替えは発生しません。大事なことなので2度言いますEIP/ENIの付替えは行いません。 しかし、ルートテーブルのみ書換は行います。詳細は後述。
  • VIPという(VPCから見ると)異物で一旦リクエストを受けるので、Src/Destのチェック無効化LVS側にも必要です。
  • Webサーバの死活監視もLVS(keepalived)で行います。

Webサーバ側は、DSRに備えて Src/Dest のチェック無効化VIP宛のパケットを、自分宛てとみなして受け取る設定が必要です。これも後述。

keepalivedの実装

上記より、インストールさえ済めば、keepalived.confの設定のみで、VRRPの部分は終わりです。そのたDSRを実現する部分やらは Sugawara氏のスライド丸パクリです。

インストール

RPMを作りました、AmazonLinux用のみです。気が向いたらCentOS用も作ります。
http://bit.ly/1OZfBtE
でもSRPMがあれば簡単なので、自力でなんとかなると思います。keepalivedぐらいでしたら、素直にソースビルドでもよいかと。

keepalived.conf

Sugawara氏のスライドと違うところは

vrrp_unicast_bind => unicast_src_ip
vrrp_unicast_peer => unicast_peer { xxx } 配列になった!

ぐらいです。

!Configuration File for keepalived

global_defs {
  router_id LVS_DEVEL
}

vrrp_instance VI_1 {
  state BACKUP # or MASTER
  interface eth0
  virtual_router_id 51
  priority 100 # MASTERは 101
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass 1111
  }
  virtual_ipaddress {
    192.168.20.11
  }
  unicast_src_ip 172.31.18.163
  unicast_peer {
    172.31.18.164
  }
  notify_master "/etc/keepalived/notify_master.sh"
}

virtual_server_group VSG_1 {
 192.168.20.11 80
}

virtual_server group VSG_1 {
  delay_loop 6
  lb_algo rr
  lb_kind DR
  protocol TCP

  real_server 172.31.8.1 80 {
    weight 1
    HTTP_GET {
      url {
        path /
      }
    }
  }
  ...
}

切替時に走る スクリプト notify_master.sh EC2-Roleでやったので、credentialのベタ書きはやめました。ここはおこのみで。

#!/bin/bash

VIP=192.168.20.11
ROUTE_TABLE_ID=rtb-[your routetable's id]
INSTANCE_ID=`curl -s 169.254.169.254/latest/meta-data/instance-id`

#export AWS_ACCESS_KEY_ID=...
#export AWS_SECRET_ACCESS_KEY=...
#export AWS_DEFAULT_REGION=ap-northeast-1

aws --region ap-northeast-1 ec2 delete-route --destination-cidr-block $VIP/32 --route-table-id $ROUTE_TABLE_ID
aws --region ap-northeast-1 ec2 create-route --destination-cidr-block $VIP/32 --route-table-id $ROUTE_TABLE_ID --instance-id $INSTANCE_ID

VRRP動作確認

tcpdum -n vrrp を叩いて、multicast用IPアドレスが出ず、上記で指定したローカルIPアドレスが出ていればOK。他にも
ip a を叩いて VIPをeth0が持っていないことを確認します。2台ともVIPを持っていたら、スプリットブレイン状態です。多分設定ファイルかSG設定が間違っています

VIPの切り替わりとRouteTable

結構複雑な話が混ざっているので、1つずつひも解きます。

  • VIPのこだわり
    VIPは必ずVPCのCIDRから外れたものを指定します。後で意味が分かります。 具体的にはクラスAを割り当てていれば 172.16.xxx.xxx とか 192.168.xxx.xxx クラスの違うローカルIPを当てるのが良いです。
  • RouteTableが必要な理由
    VIPの面倒はVRRPが見てくれるなら、RouteTableなんか要らないんじゃないか?それにVIPもVPC(Subnet)内の空いてるIPさせば良いんじゃね?と思いますが、それは出来ないです。
    VPC内はそもそもブロードキャストが通りません、よって、MACアドレスの割り出しのためにARPを打っているわけではないのです。これにより、このVIPがわかっていてもそこに至る経路が分かりません。それをRouteTableで何とかします。
  • RouteTableのルール
    RouteTableで宛先を指定できるならば、VPCのCIDR内のIPでも良いんじゃね?と思いますが、これはやりたくても出来ません。実際にやればわかりますが、エラーが出ます。よって、VPCのCIDR外の適当なIPアドレスをVIPとして、これをRouteTableの経路とします。
  • notify_master.shスクリプトがやること
    VIPの割当はkeepalivedが勝手にやりますので、経路の変更のみです。ルートテーブルで、VIPへ向き先をMasterとなった自分(インスタンスID > ENI)に向けます。

バックエンドのWebサーバ側の設定

DSRで動かすことを意識した設定が必要です。
- Src/Destのチェックを無効にする
- iptables で VIP宛のパケットを自分宛てにする
点を注意

iptables

iptables -t nat -A PREROUTEING -d 192.168.20.11 -j REDIRECT

動作と解説

上手く動いていると、Clientマシンから curl 192.168.20.11 が正常に動作するはずです。この構成でできることを後述します。

どこでAZをまたいでも問題ない

  • Client - LVS(Master)間のAZ跨ぎ
    VIPへのアクセス経路はRouteTableに制御されています。よって、NATインスタンスと同じような感覚で使えます。
  • LVS間のAZ跨ぎ
    結局ただのunicastでVRRPを投げるので、AZを跨いでも全く問題ありません。keepalivedVRRPについては万事OK。
  • バックエンドサーバ - LVSのAZ跨ぎ
    問題ないのはわかると思いますが、Client(A) - LVS(C) - Server(A) と最悪の場合でも、DSRでいけるので、コネクション確立後は Client - Server の AZ-A内で通信ができるはずです。

まとめ

  • keepalivedの開発がなんか活性化してて、VRRP via unicastに対応。これにより keepalived = multicast必須でなくなった
  • VIPの付替えはkeepalivedがやってくれるけど、RouteTableの書き換えはAWS CLIでやる必要あり。EIP/ENI付替えよりはスマートだと思う。
  • AZ跨ぎも問題ない。

multicastについて

結局multicast関係無くなってしまいましたが、色々ためしてみました。
まだ途中ではありますが、パケットをキャプチャし、MACアドレス分コピー送信という方法はあまり上手くいっていないです。(私のテストが間違っているだけかもしれませんが)
別解として、GREトンネルを張る方法も下記にドキュメントがあります。いずれ試してみようと思っています。

Overlay Multicast in Amazon Virtual Private Cloud : Articles & Tutorials : Amazon Web Services

VPC Flowlogが見づらいので、htmlでViewer作ってみた

VPC flowlogという機能が最近リリースされました。SGを通過した・蹴られたのログが取れるというものです。これ自体はとてもありがたいのですが、ログの閲覧はCloudWathLogsからとなり、コレがイケてない。だから何とかしたという話

どんなふうにイケてないのか

CloudWatchLogs上の見え方ですが、こんなかんじです。 f:id:iga-ninja:20150816210033p:plain

フィルタで頑張ることも出来なくはないのです。たとえば80ポートへのアクセスで絞るなら[スペース]80[スペース]とかでフィルタかければなんとかいけます。ただ、Unixタイムスタンプはキツイよねー

で作りました

gist.github.com

f:id:iga-ninja:20150816210256p:plain

f:id:iga-ninja:20150816210238p:plain

機能解説

ローカル実行可能 Credential別サーバに投げるとかない

ローカルにおいたhtmlファイルを、ブラウザで叩いてOK。Web Storageとかも使ってない(使えてない)

ローカルファイルとしてJSONダウンロード可能

CreateDownloadLink を押してから 右のリンクをクリック。事前にデータロードした状態でないと動かない。おまけで付けた機能

各columnで絞り込み

80とかにマッチさせたければ、Regex on で ^80$とかしないとダメ。あんまりイケてない。

問題点

そんなに作りこんでいない。でかいデータをガツンとやるなら、素直にローカルにダウンロードするツール使った方がいい。

何度か実行すると Call Stackが足らんとか言われる

いつか直す。

4,5 万行ぐらいでまともに動かない

Dynatableの方がいいのかも?StartDateで絞れるようにはした。

各種部品(ライブラリ)

AWS SDK

S3は少々CORSとかで癖があるけど、それ以外は特に問題ない。必要な機能だけの最小版も作れるみたい。

Build your own AWS SDK for JavaScript

これいいね!

datatables

テーブルをいい感じに捌くやつ。調べつつ使ったけど、あんまり使いやすくない。

moment.js

jsの面倒くさいところに、日付の変換とかがありますが、こいつはいい感じに捌いてくれます。

bootstrap-datetimepicker

昔からよくあるやつだけど、こいつのお陰でmoment.jsに触れた。

File API

とりあえず使ってみたかっただけ。

感想

やっぱjs難しいな-と思った。Bootstrap以外のものを使ってみよかとおもったけど、やめた。ともかく非同期地獄をコントロールできるようにならねばな、Promiseとか。

ipv6とAWS 繋がるから、運用まで

世の中の全てのデバイスがipv6グローバルIPアドレスを持つ時代が来る。そんな時代が来ると考えていた頃が私にもありました。

f:id:iga-ninja:20150815105712p:plain

2015年になった今も、残念ながらipv4が主流のままです。また、足らないグローバルIPやら、本当はグローバルIP同士でやるべき通信をipv4で何とかしようとする技術は沢山あります、が
小手先の技術ではなく、本当に膨大なグローバルIPを割り当てる方法および実装は、ipv6以外に2015年時点では存在せず
djbが書いた大昔の予言どおりの現在であったとしても、v4との互換性がないのがアレだといわれても、2015年の今日、でデバイスレベルで実装があるのはipv6だけです。良い、悪いは置いといて、ipv6以外の代替案が無く、結果的にダメな点が多いと言われるipv6に変わるテクノロジーを作り、協議/策定することが15年たっても誰一人出来なかったというのが、今です。おかげでipv4で何とかする技術は発展したと言えますが。。

壮大な話になってしまいました。
歴史に関してはググればいくらでもでてくるので、興味があれば調べてください。また私個人はdjbの予言は的確であったと思うし、当時の私には大変分かりやすかった。djbと翻訳者ともに尊敬、感謝しています。
http://www.unixuser.org/~euske/doc/ipv6ex/

モチベーション

djbの言葉を借りますが、ipv4 -> ipv6 マイグレーションには相当な覚悟 という名のモチベーションが必要です。

2012年のipv6 dayを経て、
「やっぱりipv6はまだ人類には早すぎた」
と私は思いました。それ以前にも、大手のISPは、なんだかよくわからないサービスをipv6限定にして展開し、何とかipv6キラーコンテンツをつくろうとしていましたが、まあ、結果失敗してます(現状をみれば一目瞭然) しかし最近になって、少しずつモチベーションが高まりつつ有ります。1つは Docomo / AU におけるスマートフォンipv6 IPアドレスを本当にしゃべる時代が来たという点です。しかもその端末が何と私の手元にあるのです! Next5です!
http://trendy.nikkeibp.co.jp/article/pickup/20131209/1053986/?P=3

それともう一つ、最近、iOS9 からのアプリ審査には、ipv6対応にしておけ、ニュアンスとしては、ipv4縛りをするな!という方針が組まれるようです。
http://www.internetsociety.org/deploy360/blog/2015/06/apple-will-require-ipv6-support-for-all-ios-9-apps/

急にipv6対応とはご無体な話ですが、実際に「はい、明日からipv6でないアプリはNGね」って話ではなく、「インフラ側がipv6になっても動くようにしとけ」ということだと思います(そうじゃないと困る)。ちなみにiPhoneDocomo & AUはすでに ipv4 & ipv6両方いける、softbankipv6非対応のはず、2015/08/14現在。

AWSにおけるipv6

単刀直入にいうと、ipv6非対応です。
EC2-Classic & ELBでは可能だったらしいのですが、私はClassicを触ったことがないので分かりません。現在、新規アカウントでClassicは出来ないので、実質非対応です。また、この点については、Asure, GCP(GCE), も同様です。ぱっと思い当たるので対応しているのは softlayerです、あくまで2015/08/14時点の話。

ELBはipv4/6 dualstack?

EC2-Classicであればdualstack.<elbのエンドポイント> で、 AレコードもAAAAレコードも戻ってくるので、ipv6による接続が可能でした。しかし、EC2-VPC(今のEC2)では、どうやらこれは出来ないようです。

Internet-Facing Load Balancers - Elastic Load Balancing

実際に試してみました。EC2-VPCでELBを立てても、dualstak.ipv6. も作成されます、DNS上は。実際にipv6でアクセスした場合、Connection Refused となります。この原因は私の推測ですが
EC2-VPCでも ELB自体にipv6アドレスは付く、しかしSecurity Group や Network ACL で ipv6のアドレスは指定出来ない(::/0とか無理)。よって、通信出来ない。
SGは明示的に許可されていないアドレスからのアクセスは蹴りますが、Refuseではなく、無視するので、外しているかもしれません。

Security Group と Network ACL ipv6対応状況

現状のEC2は全てVPC内に構築するため、Network ACL および Security Group側で v6 IPアドレスを制御出来ないというのが現状です。よって、グローバルであれ、ローカルであれ、仮にEC2に直接 v6のIPアドレスがふれたとしても、別マシンと一切通信出来ないということです。
しかしIPプロトコル番号41 = ipv6 には対応しています。ということは、アレですな、4to6とかのトンネルです。

ipv6 tunnel brockerを使う

グローバルで参照可能なipv6アドレスを実現するには、ipv6 tunnel brockerのちからを借ります。Hurricane Elasticというところがやっています。

www.slideshare.net

HEで実装

Hurricane Electric Free IPv6 Tunnel Broker

アカウント作成などが必要なので、サクっと作ってっください。具体的な設定方法の大まかな部分は、ググれば出てくるので、特記事項のみ書きます。

トンネルの作成

IPv4 Endpoint(Your side) は、AWSの場合はEIPとなります。トンネルを作る前に、疎通確認をHE側から行うようなので、pingが通るようにSGをいじっておきます。 f:id:iga-ninja:20150815111205p:plain

f:id:iga-ninja:20150815111327p:plain
各種OS向けの設定方法も生成してくれます。何と親切!しかし、下記に注意
1. IPプロトコル番号 41 を通過できるようにしておく。これは HEのサーバIP(v4) と EIP(v4)の話
2. localに指定するIPアドレスは、AWSの場合、EC2(ENI)のローカルIPアドレス

動作確認はpin6とかで

$ ping6 ipv6.google.com
PING ipv6.google.com(nrt13s38-in-x0e.1e100.net) 56 data bytes
64 bytes from nrt13s38-in-x0e.1e100.net: icmp_seq=1 ttl=59 time=3.85 ms
64 bytes from nrt13s38-in-x0e.1e100.net: icmp_seq=2 ttl=59 time=3.89 ms
64 bytes from nrt13s38-in-x0e.1e100.net: icmp_seq=3 ttl=59 time=4.16 ms
64 bytes from nrt13s38-in-x0e.1e100.net: icmp_seq=4 ttl=59 time=4.01 ms

Nexus5からhttpを叩いてみる

一応DNSにAAAAレコードを追加して試したが、直打ちでも多分いける。Apacheアクセスログはこんな感じ

2001:240:2401:dumm:dumm:dumm:dumm:dumm - - [15/Aug/2015:01:15:06 +0000] "GET / HTTP/1.1" 200 27 "-" "Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48I) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.133 Mobile Safari/537.36"

uとかmとかないからダミー。もちろん本物のIPv6アドレスが取れます。ただ、端末から確認できるv6アドレスとは異なる。今のところNexus側には/64で割り当てられるらしいので、wifiルータとしてIPv6を他の機器に付けられたらとか思うけど、今のところそんな機能は無いらしい。

ipv6のフィルタリング

SGはipv4しか捌けないので、source IPとかで絞るなら、EC2上のip6tablesにお願いするしか無いので試してみた。
http://wiki.princo.org/?ipv6%A4%C7%A5%D5%A5%A3%A5%EB%A5%BF%A5%EA%A5%F3%A5%B0(netfilter%2Fip6tables) を参考にしました。

# ip6tables -A INPUT -p tcp -s <NexusのIP 上から64>::/64 --dport 22 -j ACCEPT
# ip6tables -A INPUT -p tcp --dport 22 -j DROP

上手く動いているようです。ただし、v4/v6両方でアクセス可能としていたら、v6だと思ってたらv4でアクセスしてたことがあったので注意。

まとめ

  1. 2015/08 時点で ipv6 をネイティブ対応出来ているのはsoftlayerのみ
  2. ELBはipv6IPアドレスを持つようだが、EC2-VPCでは疎通出来ない
  3. 外部からipv6アクセス可能にするには、ipv6 tunnel brokerでなんとかできる
  4. トンネルの中の通信をSGで制御出来ないので、ip6tablesなど、EC2内部で何とかする

自分が生きている間にipv6を触ることなんてないと思っていたけど、こんなに簡単に触れるなら、一発あるかも?モバイルやIoTなど、大量のグローバルIPアドレスはやっぱりあった方がいい、と言うのはわかっているけど、そこへ至る動機がなかった、けど、今はある。ただ、softlayer以外のクラウドコンピュティングがネイティブに対応するのはきっとまだまだ先。

最近のDNS事情まとめ

私が一旦インフラを離れる10年前、もうすでに「BINDはヤバイんじゃないか? 」と言われてましたが、(自前運用では)未だにBINDは主流な気がする。Route53を始め、いまやどこのクラウドでも権威サーバはあるので、わざわざDNSをたてる意味はもうないですが。今のDNSを適当にまとめる

権威サーバ・キャッシュサーバ

一緒にするな!は10年前からすでに言われていた。BINDはごっちゃになるのと(無論、きちんと設定すれば分離可能)、セキュリティー問題が当時から多く、djb の tinydns & dnscache という(今となっては)検索しづらい名前のソフトウェアを使っていた。ココらへんの詳しい話はdjbの資料を読まなくても、世の中の常識になった感がある。

ざっとまとめ

あとは、このスライドで。

www.slideshare.net

キャッシュならunbound、結構最新版出てる。 DNSラウンドロビンもreadyになってる。 install は epelで

www.unbound.net

権威は NSD、これも最新版で標準入力からゾーン追加できる?みたい

www.nlnetlabs.nl

権威サーバをクラウド(当時はそんな言葉なかった)でサーバレス、しかもAPIでレコード追加できて、しかもしかも超安い。Route53とか使わずに権威サーバを立てる意味はほとんど無いと思う。とくに外向け。

AWS ELB + SSL Termination下でEC-CUBEを正しく動かす

EC-CUBEAWS上で運用するとき、良くある構成

f:id:iga-ninja:20150726081412p:plain

今回の構成は SSL Termination を行い、ELB -> EC2(Webサーバ)間ではHTTPS(443)通信を行いません。この場合、EC2側は常にHTTP(80)で通信を受けるので、ユーザーのELBに対するアクセスがHTTPなのかHTTPSなのか普通の方法では判断出来ません。

X-Forwarded-[xxx]ヘッダ

ELBを通過するときに、X-Forwarded-Port/Proto等のヘッダが付きます。これを判別することにより見分けることが出来ます。 http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/x-forwarded-headers.html

EC-CUBE内部におけるHTTPS判定

EC-CUBEに対してGREPかけると

./data/module/Net/URL.php:            $this->protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
./data/module/Net/URL.php:            case 'https':   return 443;
./data/class/util/SC_Utils.php:        if (SC_Utils_Ex::sfIsHTTPS()) {
./data/class/util/SC_Utils.php:            $proto = "https://";
./data/class/util/SC_Utils.php:            $domain  = SC_Utils_Ex::sfIsHTTPS() ? HTTPS_URL : HTTP_URL;
./data/class/util/SC_Utils.php:     * HTTPSかどうかを判定
./data/class/util/SC_Utils.php:    function sfIsHTTPS () {
./data/class/util/SC_Utils.php:        // HTTPS時には$_SERVER['HTTPS']には空でない値が入る
./data/class/util/SC_Utils.php:        // $_SERVER['HTTPS'] != 'off' はIIS用
./data/class/util/SC_Utils.php:        //if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
./data/class/util/SC_Utils.php:        #if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
./data/class/util/SC_Utils.php:        if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
./data/class/util/SC_Utils.php:        } else if(ereg("^https://", $istr)) {
./data/class/util/SC_Utils.php:            $head = "https://";

このように方方で$_SERVER['HTTP']で判定しています。これらをすべて $_SERVER['HTTP_X_FORWARDED_PROTO']に変換していくのは至難の業です。
じゃあどうするか。無い変数はつけてしまえばいいです。

mod_setenvif

apacheモジュールで setEnvIfというのがあります。これを使って$_SERVER変数を無理やり追加します。

SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on

リダイレクトで片っ端からSSLにする

SetEnvIf X-Forwarded-Proto ^https$ HTTPS=on

RewriteEngine on
RewriteCond %{HTTP:X-Forwarded-Proto} ^http$
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

せっかく HTTPS変数にするんだから、そいつを使えばいいと考えるなら、RewriteCondで HTTP:HTTPSを指定すること。

もう一つの解法、ソースをちょっといじって解消する

https://forge.typo3.org/issues/29693

f ($_SERVER['X-Forwarded-Proto'] == 'https') {
    $_SERVER['HTTPS'] = 'on';
}

phpの初手でこいつをかませばいい。

まとめ

  • EC-CUBEHTTPS判定は、サーバ変数 $_SERVER['HTTPS']
  • HTTPS -> X-Forwarded-Protoに判定をまるっと変えるようなconfigはない
  • SetEnvIfで HTTPSサーバ変数を付与するのが楽

X-Forwarded-Protoでリダイレクトだけかけても、商品をカートに入れるときにエラーが出ます。これの対処方法がわからない場合、参考に。 ちなみに、EC-CUBEはセッションをDBに保存するらしいので、(デフォルト) StickySessionは必須ではないはず。