二日間通し券はないYAPC::Asia Hachioji 2016 mid in Shinagawaで話します!
タイトルは注意喚起を込めています!
2016/7/2(土),3(日)に開催されるYAPC::Asia Hachioji 2016 mid in Shinagawaで話すことができることなりましたー!
タイトルに入れたようにこのイベントでは
- 二日間通し券はありません
それぞれの日でなんらかの登録が必須です。
すでに一般枠は定員オーバー抽選必須となっているので、どうしても参加したいかたはその他の枠をうまく利用するしかないでしょう!
本題
7/2(土)の最後の時間帯で話します。
事例があるのかないのかよくわからない Vault ですが実際に MySQL アカウント管理のために導入してみたお話しです。興味あるかたは是非お越しくださいませ〜。
Vault の説明と事例の説明という感じの予定です。できれば、他の方がどのように使われているかも知りたいので、質問タイムや懇親会などでお話しできると嬉しいです!
あ、懇親会は懇親会で申し込み必須です。
私は、今回スタッフとしても参加させていただおり、受付担当予定です。ですので、皆様まずは当日受付でお会いしましょう。
繰り返しますが、
- 二日間通し券はありません
各日それぞれ登録し、もちろん受付も各日で行ってください。
また、
- 入館証は当日限りで、再発行はありません
絶対になくさないで!お願い!
ということで、当日皆様とお会いできることと、有意義なイベントになることを楽しみにしております!
TLS1.2が使えない環境のためのProxy (squid)設定
TL;DR
接続先がTLS1.1、TLS1.2 以降しか接続を許可しなくなるけど、環境そのもののアップデートができなくて、Proxy でとりあえず逃げたいという方向けです。
Squid を使った設定例を書いてます。(参考情報 - Intercept HTTPS CONNECT messages with SSL-Bump)
目次
PCI DSSというクレジット業界におけるグローバルセキュリティ基準があるらしく(詳しくないです)、これのv3.2が2016/04/28が公開されました。
それによると、PCI DSSを取得している業者は ことになるようです。 参考記事 実際PayPal は 2017/06 には TLS1.2 のみの接続しかできなくなるようです。 まぁ普通はOpenSSLの1.0/1.1系の最新バージョンを使っていればなんの問題もないです。 しかし、世の中には様々な そこでProxyで頑張ってみる( というイメージです。 Squid 3.5 を使います。 /etc/yum.repos.d/squid.conf を下記のように用意して epelも有効にしたうえで yum コマンドでインストール クライアントから見るとTLSでのやりとりはProxyとなるので、Proxyに証明書が必要となります。
これを準備します。 /etc/squid/squid.conf を以下のように記述。 visible_hostname は適当。 lan のアドレス帯は自分の環境にあわせて修正ですね。 sslproxy_options ですが、TLS1.1 も制限したいなら NO_TLSv1_1 を加えます。(参考 - squid : sslproxy_options configuration directive) CentOS5 から TLS1.2 のみの環境に接続してみると(下記のコマンドの接続先は実在するものではないです) となるが、proxy (ここでは 192.168.2.241 とします)を経由すると のように接続ができます。 Webサーバ側のログに接続に使われたSSL/TLSのバージョンを出力するようにしてあれば のように TLSv1.2 で繋がっていることが確認できます。 clientがTLS1.1 TLS1.2 に対応できていなくても、Proxy 側でサーバとのTLSの接続をさせることで、なんとか接続する方法を書きました。 まぁ、普通はちゃんとclientの環境をバージョンアップしているのでこんなことはしなくてよいでしょう。背景
闇のような理由でSSL3ぐらいまでしかサポートしていない環境で運用している人もいるでしょう。臭いものに蓋をする)にはどうすればいいのかを調べてみました。今回試す構成
client(CentOS5 + curl) <--> Proxy (CentOS7 + squid 3.5) <--> Web
Squid
3.5インストール
[squid]
name=Squid repo for CentOS Linux - $basearch
#IL mirror
baseurl=http://www1.ngtech.co.il/repo/centos/$releasever/$basearch/
failovermethod=priority
enabled=1
gpgcheck=0
yum install perl-Crypt-OpenSSL-X509 squid squid-helpers
自己署名証明書作成
cd /etc/squid
mkdir ssl_cert
chown squid:squid ssl_cert
chmod 700 ssl_cert
cd ssl_cert
openssl req -new -newkey rsa:2048 -sha256 -days 365 -nodes -x509 -keyout myCA.pem -out myCA.pem
squid.conf
visible_hostname my.example.com
acl CONNECT method CONNECT
acl lan src 192.168.2.0/255.255.254.0
http_access allow localhost
http_access allow lan
http_access deny all
http_port 3128 ssl-bump \
cert=/etc/squid/ssl_cert/myCA.pem \
generate-host-certificates=on dynamic_cert_mem_cache_size=4MB
acl step1 at_step SslBump1
ssl_bump peek step1
ssl_bump bump all
sslproxy_options NO_SSLv2,NO_SSLv3,NO_TLSv1,SINGLE_DH_USE
forwarded_for off
request_header_access Referer deny all
request_header_access X-Forwarded-For deny all
request_header_access Via deny all
request_header_access Cache-Control deny all
SSL certificates cache directory
/usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db
chown squid:squid -R /var/lib/ssl_db
起動
systemctl start squid
結果
$ curl https://hogehoge.xxxx.xxxx/
curl: (35) Unknown SSL protocol error in connection to hogehoge.xxxx.xxxx:443
$ curl -k --proxy 192.168.2.241:3128 https://hogehoge.xxxx.xxxx/
<!DOCTYPE html>
<html lang="en">
<head>
以下略
xxx.xxx.xxx.xxx - - [03/Jun/2016:21:36:26 +0900] "GET / HTTP/1.1" TLSv1.2/ECDHE-RSA-AES128-GCM-SHA256 200 45838 "-" "curl/7.15.5 (i686-redhat-linux-gnu) libcurl/7.15.5 OpenSSL/0.9.8b zlib/1.2.3 libidn/0.6.5" "-"
まとめ
臭いものに蓋をすると一生そこは闇になります。
BigQueryのテーブルを一定期間経過後削除する defaultTableExpirationMs
Google BigQuery 便利ですね。
テーブルを日毎に分割してデータを貯めていっているのですが、ある程度経過したらまぁ消してもよいかなと思うデータもあります。
そんなときに、GCSやS3のObject Lifecycle Management的なものがあると、自前でcronまわして削除するという手間とか何らかのリソースが不要になって嬉しいなということで、調べてやってみた話です。
答えはちゃんと公式ドキュメントに書いてあって、 defaultTableExpirationMs というプロパティを設定すれば良いようです。
GitHub - GoogleCloudPlatform/gcloud-ruby: Google Cloud Client Library for Ruby 使って設定するコードは以下のような感じです。
require "gcloud" gcloud = Gcloud.new "project-id", "/path/to/keyfile.json" bigquery = gcloud.bigquery dataset = bigquery.dataset "mydataset" dataset.default_expiration = 3600000
ドキュメントの通り、単位はmsecで、設定以降に作られたテーブルは、その作成した時間から上記設定時間経過後に自動的に削除されます。作成済みのテーブルには反映されませんし、作成済みのテーブル個別に対して削除期限を変更する設定はないようです(これこれで欲しいのですが)。また、1時間より短い設定はできません。
あと注意として、Datasetに対してオーナーの権限(Is owner)を持ったキー(上記のコードでいうkeyfile.json)でないと設定できませんでした。編集権限(Can edit)では設定できませんでした。
現状ではUIからは1日で削除するか否かの設定はできますが、細かい指定をするには上記のようにAPIを使って設定するしかなさそうです。
が、これでテーブルの管理の一手間が減って大変助かりますね。
エンジニアサポートクロス2016にゴールドスポンサー( Hamee )として参加してきた
2/5に横浜大桟橋で開催されたエンジニアサポートクロス2016にゴールドスポンサーのHamee
の一員として参加してきました。
ISUCON5で惨敗し、その悔しさのエネルギーがあるときに、CROSS2016スポンサー募集を発見して、そのエネルギーで会社も説得し、なんとか会社として初のエンジニア系イベントのスポンサーというところにこぎつけました。
最初はシルバーくらいのつもりだったのが、結局はゴールドスポンサーでエントリー。
ゴールドなのでランチセッションもできるということで、ブースの準備はあるは、ランチの手配、セッションスピーカーの手配など、初めてづくしで、みんなでアイデア出して協力してと大変だったけどよい経験でした。もっともほとんどのことは仲間がうまくやってくれて私は大したことせず状態でしたが。仲間に感謝ですね。
ともあれ、当日はがらぽんでMacBook Airがあたるという、太っ腹!?企画でそれなりにブースも盛況になるし、twitterも賑わってくれたました。
MacBook Airはなんとしても当てて欲しかったので、結構最後の方まで出なかったのはハラハラでした。当たりでてよかったー。
知り合いが当てた!#cross2016 #Hamee pic.twitter.com/33f1p2Sbgr
— ひらひら (@hirahira_mb_) February 5, 2016
ランチセッションのまとめは、こちら。まとめ、ありがとうございます!
とにかく、スポンサーやってみて良かったです。
いろんな方と出会いがありましたし、今まで参加するだけだったのと違って数倍楽しめました。
また、来年もなんとか会社を丸め込んで説得してスポンサーで参加したいですね。
最後に、当日一緒にHameeスタッフとして参加した皆様に感謝します。
そして、エンジニアサポートクロス2016のイベントスタッフの皆様、いろいろ手配・ご協力いただきありがとうございました。
もちろん、ブースに来てくれた参加者の皆様、本当にありがとうございました!!
ランチは小田原のはなまるキッチンさんにご用意いただきました。
マジでおいしいので、小田原きたときにはちょっと歩くけど、超オススメです。
続:Consul 0.6でユーザのいるshardを探す(Prepared Queryを使う)
この記事は HashiCorp Advent Calendar 2015 - Qiita の23日目です。(1時間ほど早めに公開したのでブログの日付は22ですが)
前回の記事 Consul 0.6でユーザのいるshardを探す(Prepared Queryを使う) - kikumotoのメモ帳 の続編です。
id:fujiwara さんの
Consul 0.6でユーザのいるshardを探す(Prepared Queryを使う) - kikumotoのメモ帳b.hatena.ne.jp というコメントを受けて、Prepared Queryを100万件突っ込んでみた結果をまとめます。
- [consul]
数百万のPQがconsulに登録されても大丈夫なものだろうか
2015/12/21 07:25
結果
先に結果を。
100万件PQを突っ込みましたが、DNSの応答は10件だけ登録のときも、100万件登録後も、ほぼ2msecとなり特に性能面での変化は見られませんでした。
ただ、PQの登録については若干劣化(最初は0.9msくらいあったのが、1.5msくらいになった)するようです。ただし、環境が安定しているかどうかは確証がもてないので、参考程度に。
あと、
というコメントもいただき、突っ込んだデータを削除しました。
確かに、Disk使用量が減ることはなかったです。
一方で、メモリの方は解放されているようです(Consul0.6のため?0.5では未検証)。
環境
項目 | 内容 |
---|---|
Consul version | 0.6 |
Consul server | 5ノード |
Consul client | 4ノード |
Consul データパス | /dev/shm/consul_data(tmpfs) |
メモリ(全ノード共通) | 16GB |
CPU | Xeon(R) CPU E5-2407(4コア) |
OS | CentOS5,6,7混在 |
という感じで、特にデータは tmpfs 上において試しました。(これは各ノードのDisk性能が一律ではないため、今回の評価用にこの設定にしてあります。)
データの登録
データの登録は下記のようなrubyコードで行いました。Keep-Aliveしながら、一件ごとの登録にかかった時間を記録しています。
#!/usr/bin/env ruby require 'net/https' require 'uri' require 'benchmark' base_uri = "http://localhost:8500/v1/query" uri = URI.parse(base_uri) c = Net::HTTP.new(uri.host, uri.port) req = Net::HTTP::Post.new(uri.path) c.start do |x| 11.upto(1000000) { |i| id = sprintf("%07d", i) req.body = <<-EOS {"Name":"mdb-#{id}","Service":{"Service":"db01","Tags":["master"]},"DNS":{"TTL":"30s"}} EOS res = nil time = Benchmark.realtime do res = x.request(req) end puts "#{id}, #{time}, #{res.code}, #{res.body}" } end
登録は、leaderノード上で実行しました。
登録前後、削除後の状況
登録前は厳密には、10件だけPQを登録した状態です。
DNS応答(ms) | データサイズ(byte) | メモリ空容量(byte) | 1件登録時間(ms) | |
---|---|---|---|---|
登録前 | 2 | 262144 | 6523371520 | 0.9 〜 1.0(10件登録した時) |
登録後 | 2 | 134217728 | 5202753454 | 1.3 〜 1.6(100万件付近) |
削除後 | - | 134217728 | 6361238449 | - |
◼︎ 測定方法について
- DNSはdigの結果に表示される
Query time
を取得(CacheにのっていないURLをqueryしてます)。 - データサイズは
/dev/shm/consul_data/raft/raft.db
のサイズ。ls より。 - メモリ空容量は、freeコマンでのfeeの値。
- 1件登録時間は、登録スクリプトの出力より、目でみておおよその値を抽出。
メモリの状況は下記グラフも載せておきます。下がり始めたところが、100万件データを入れているところ。回復しているところが削除しているタイミングなので、メモリは回復する感じです。
まとめ
- 100万件PQ入れてもDNS引きに関して性能面での劣化はない。
- データ登録については性能劣化がある。
- データ削除しても、Disk容量は減らない。
- データ削除するとメモリは解放される。
実際は各自の用法・設定に合わせて確認してもらうのが一番なので、以上の結果は参考程度にどうぞ。
また、利用用途としても多分ソシャゲのような数百万ユーザが対象なものについて、この方法を採るのはちょっと微妙かなという印象です。DNS引きに影響はないにしても、登録や削除が頻繁なものにはちょっとという気がします。(障害時のデータ復元も大変そう)
自分の想定環境では多くて10万ユーザ、多分1万ユーザくらいの登録で、変動も頻繁でなく、PQのデータはすべてDBから復元可能なので、DNS引きだけでshardを解決できるという利点をとって採用方向で、今後本番環境内でConsulの動作試験していくかなぁという感じです。
何がご要望がいただければ、お正月に試すかもしれません。(ただ寝てるかもしれません)
Consul 0.6でユーザのいるshardを探す(Prepared Queryを使う)
この記事は HashiCorp Advent Calendar 2015 - Qiita の第21日目です。(大人な事情により Hamee Advent Calendar 2015 - Qiita の第20日目でもあります。なので微妙な時間に公開)
概略
ユーザIDをベースにDBを分割(sharding)しているのですが、プログラムからユーザのいるshardを探すのにConsulを使えないかなぁと思って試している話。
Consul0.6のPrepared Queryを使って解決してみました。
目次
ユーザIDをベースにDBを分割(sharding)していると、プログラムからユーザのいるshardを探す必要があります。 これをどこかのメタDBサーバにするってのも良いんだけど、Consul使ってDNSで引っ張ってこれると使う側にとって扱いやすいかなと思って調べてます。 ・Node設定 各DBではconsulのServiceが下記JSONの定義のように登録されています。 なので以下のような感じでDNSでひける状態です。
ちなみに試している環境にはdnsmasqを入れています。 Consul0.6で導入されたPrepared Query(以下PQ)を使う方法です。 PQに下記のような情報を登録します。(user1.jsonとします) これを以下のように登録します。 IDが発行されるので、これは後で必要になります。もしくは /v1/query にGETでリクエストすれば一覧が取れるので、そこから必要ものを探せばOKです。 このようにすると、以下のようにDNSでひけて、ユーザが収容されているmaster DBのIPが取得できます。 ・slave昇格 db01-aが死んでdb01-bがmasterになるときは、db01-bで のようにmasterのタグをもたせて これで、同じようにDNSをひくと、昇格したノードのIPが取得できます。 なお、db01-aがmasterのタグを持って起動しないようにする必要はあります。今回は、マシンブート時にconsulを自動起動させないようにして逃げてます。 ・shard移動 user1のいるshardがdb02になれば、 というJSONを用意して、このPQのIDを指定してPUTします。 これで、同じようにDNSをひくと、今度はdb02のmasterのIPが取得できます。 Consul0.6より前だとPQがないので、外部サービス(ノード)を登録することで同じようにことできると思います。 この場合、外部サービスとして以下のようなJSONを登録します。 こうすると、以下のようにDNSがひけます。 外部サービス(ノード)なので、CNAMEで解決されて、その後Aレコードを得るような形となります。 shardの移動は、Nodeの定義を更新することで対応することとなります。 Consul0.6より前ではこの方法かなぁとは思うのですが、Consul0.6だとPQによりCNAMEを介さずにひけるので方法1を採用予定です。 ・タグだけで のようにタグだけで解決することも可能は可能かと。 ただ、shard移動するときとか、userの追加・削除時には必要なタグをして指定して更新するのでちょっと大変そう。 ・サービスだけで みたいなサービスをユーザ数分だけ登録することでもできそう。 この場合、slave昇格でユーザ数分だけServiceを更新・登録とかしないといけなのでこれも大変そう。 ユーザIDをベースにDBを分割(sharding)しているような場合に、それをDNSでひけるようにするには、Consul0.6のPrepared Queryを使うとなんとかなりそうでした。 ちなみに、PQを1万ほど突っ込んでみた範囲では、DNSをひくことにパフォーマンス的な影響は特に見られませんでした。 Consulでやる場合のもっと良い方法とか、そもそもConsul使うべきじゃないとかありましたら教えてください。背景
前提
{
"Service": {
"name": "db01",
"tags": [ "master" ]
}
}
# dig master.db01.service.consul.
; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.37.rc1.el6_7.4 <<>> master.db01.service.consul.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53317
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;master.db01.service.consul. IN A
;; ANSWER SECTION:
master.db01.service.consul. 30 IN A 192.168.0.11
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Dec 18 14:11:33 2015
;; MSG SIZE rcvd: 94
方法1(今回採用予定)
{
"Name": "master-db-user1",
"Service": {
"Service": "db01",
"Tags": ["master"]
},
"DNS": {
"TTL": "30s"
}
}
$ curl -X POST http://localhost:8500/v1/query --data-binary @user1.json
{"ID":"66804426-8e5f-427b-caa7-d896c9328910"}
$ dig master-db-user1.query.consul.
; <<>> DiG 9.3.6-P1-RedHat-9.3.6-25.P1.el5_11.2 <<>> master-db-user1.query.consul.
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 14375
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;master-db-user1.query.consul. IN A
;; ANSWER SECTION:
master-db-user1.query.consul. 30 IN A 192.168.0.11
;; Query time: 1 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Dec 18 14:44:21 2015
;; MSG SIZE rcvd: 94
{
"Service": {
"name": "db01",
"tags": [ "master" ]
}
}
consul reload
すればよいです。$ dig master-db-user1.query.consul. +short
192.168.0.12
{
"Name": "master-db-user1",
"Service": {
"Service": "db02",
"Tags": ["master"]
},
"DNS": {
"TTL": "30s"
}
}
$ curl -X PUT http://localhost:8500/v1/query/66804426-8e5f-427b-caa7-d896c9328910 --data-binary @user1.json
$ dig master-db-user1.query.consul. +short
192.168.0.21
方法2
{
"Node": "master-db-user1",
"Address": "master.db01.service.consul"
}
$ curl -X PUT http://localhost:8500/v1/catalog/register --data-binary @user1-node.json
$ dig master-db-user1.node.consul.
; <<>> DiG 9.3.6-P1-RedHat-9.3.6-25.P1.el5_11.2 <<>> master-db-user1.node.consul.
;; global options: printcmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29792
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;master-db-user1.node.consul. IN A
;; ANSWER SECTION:
master-db-user1.node.consul. 30 IN CNAME master.db01.service.consul.
master.db01.service.consul. 30 IN A 192.168.0.11
;; Query time: 5 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Dec 18 15:20:49 2015
;; MSG SIZE rcvd: 166
その他の方法
{
"Service": {
"name": "db01",
"tags": [ "master", "user1", "user2", ・・・ ]
}
}
{
"Service": {
"name": "user1",
"tags": [ "master"]
}
}
まとめ
fluentdのプルリク#696へのフィードバックを求めています
下記は、https://github.com/fluent/fluentd/pull/775 で2016/01/18にマージされたました!
Fluentd Advent Calendar 2015 - Qiita の10日目がまだ空いていたので、入れさせてもらいました!
今、in_tailに関して下記PRを出させてもらっています。
fluentd v0.12.18 が出ましたが、これはまだ取り込まれていません(想定内)。
な状況です。
in_tailのmultilineモードでは、Fluentdのin_tailプラグインで複数行のログをよむ方法 - Boost Your Programming! で説明されているように
つまり、メッセージがログに出力されてもすぐにそのログがFluentdのメッセージとして送信されるわけではなく、次のログが出てくるまで遅延することになります。
という問題があります。
頻繁にログが流れるような状況であると問題にはならないのですが、ログをfluentdでとりあえず集めているとそんなに頻繁に出力されるないようなログも対象としいたりして、その際にmultilineで取り込んでいるとこの仕様では困ることがあります。
そこで、上記PRを出している感じです。
とりあえず、同じことができるものを in_tail_multiex.rb · GitHub に起きました。
これを /etc/td-agent/plugin 配下に置いて conf に
<source> type tail_multiex path /path/to/logfile tag my.tag pos_file /var/log/td-agent/my.log.pos format multiline format_firstline /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d / format1 /^(?<time>\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d) (?<message>.*)$/ multiline_flush_interval 1s </source>
のようにmultiline_flush_interval
を指定してもらえればよいです。この指定した期間、ログに出力がないと、fluentdのメッセージとして送信されます。
問題や、コメントなどありましたら、上記PRなり、そもそもの issue
などにご意見をいただければ幸いです。
実際問題としてはとりあえず、gistにあげたような独自プラグインで当面のニーズは満たしていますが、本体に取り込まれるとより嬉しいかな、ということで。