続 カッコの付け方

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

2018年なぜ私達はコンテナ/Dockerを使うのか

2017年にもうコンテナの未来・一つのカタチはもう確定したと言え、今更感があるものの、改めてDockerとコンテナについて。 今更こんなことを書くのは、情報が溢れてくる今こそ、正しく理解し、正しい順序で学習することが重要だと切に思うから。

https://www.docker.com/sites/default/files/vertical.png

内容についてのお断り

  • How Toはかきません
  • あくまでも2018年時点の私見
  • 目新しい情報はない、2016年頃に書けたレベル

Dockerをこう使えとか、こうするのがいいとかの話ではなく、コンテナとDockerに関して大きな視点で現時点で私の考えを書きます。また、私自身はかなりのコンテナ推進派です。 Dockerをよくわかっている人には意味のない記事となります。

コンテナ(Docker)のメリット

何故コンテナがいいのか、コンテナをある程度の学習コストを払ってでもやる理由

コンテナとDocker

コンテナ技術はDockerが生まれる前から存在する技術ですが、今のコンテナブームは確実にDockerによるもの です。Dockerそのものについては後述します。 この記事のコンテナという表記はほとんどDocker(によるコンテナ)と読み替えて差し障りありません。

Docker Image

Dockerの最大の利点は ポータブルなDocker Imageが使えるということです。
本当にこの1点に尽きます。
Docker Image は言い換えるとベンダーロックインの無い AMI (OSイメージ)といえます。

なぜ、Docker Imageが便利なのか

ローカル開発環境の統一

恐らく最初のDockerの使われ方がこれだと思います。複数人でアプリケーションを開発する場合、開発者のマシンの数だけ開発環境を立てる必要があります(VDIでというのは無視)。まあ、大変ですよね、何人かにもよりますが、phpでもrubyでも、composerなりgemなり使えば参照ライブラリは合わせられますが、phprubyのバージョンまで合わせたり、もっと大きく考えればローカル環境がWindowsLinuxでも異なりますね。

これが dockerのサービス/デーモンさえ動いていれば、1つの共通 Docker Imageを挿すだけで全く同じ環境が、開発者全員に行き渡ります。開発環境を構築するのが趣味の人もいると思いますが、突き詰めると全員が同じバージョンで開発するのは非常に厳しい事がわかります。普段気にしないですが OS + ランタイム(phpとかruby) + ライブラリ すべて一緒ではじめて完全に同じ開発環境といえるのです。

本番環境 CI/CDでも使える

コンテナ(Docker)オーケストレーションツールが出揃った昨今では、こちらのほうが目立っている感じがします。開発で使ったImageをそのまま本番へ、更にはCI(テスト)もやってしまおうとする考え方です。もちろん開発と本番で環境差異(エンドポイントなど)を吸収する仕組みは必要ですが、開発で動いたものがまるっきりそのまま本番、しかもCIもその開発で使っていたImageなので、如何に安定性・リスク回避からも有利であることがわかると思います。

OSSの playgroundとして

Docker以前は、Vagrantとかでやっていた、とりあえずローカルで試してみようは、全てコンテナでみんなハッピーです。実際にそこらじゅうのOSSがDockerイメージで提供されています。

https://hub.docker.com/r/graphiteapp/graphite-statsd/

https://hub.docker.com/_/redmine/

https://hub.docker.com/r/ceph/demo/

特に単コンテナで完結しないものも、docker-compose でお手軽に一瞬で作れます。

https://docs.docker.com/compose/wordpress/#define-the-project

では、なぜVagrantではだめなのか?ですが、2つ理由があります

  • Vagrantをはじめとして、他プロビジョニングツールについて知っていなければ動かせない
    ここはDockerの功罪とも言えますが、VagrantにくらべてDockerはツールの使い方を覚えなくても、そのOSSのReadme.mdに書いている Dockerコマンドを一発叩けばいとも簡単に構築完了です。Vagrantは少なくともrubyの知識などが少しは無いとこんなにすんなり動かせません。Docker run 一発の楽さになれると Vagrantを今更やろうとは思えない。特に複数マシンでクラスタを組む(=複数コンテナでクラスタ構成)場合はdocker-composeの安心感には到底かなわない。
  • Boxファイル (OSイメージ) が大きい
    この点もDockerと大きく違う点です。詳しくは後述しますがDockerが流行る理由は、Docker Imageデータストレージの扱いが極めて賢いからです。対してBoxファイルはかなりサイズが大きく、Docker Imageのように賢いストレージエンジンではないです。

インフラ屋のテスト

これは実際に私が使っています。単純に AmazonLinuxやubuntuなどでのサーバ構築手順などを探るために、素のDocker Imageでサクッと起動させてテストします。当たり前ですが、Docker Imageのキャッシュがあれば一瞬で起動します、Vagrantなんてトロくてもう使ってないです。AWSでEC2を建てることすらウザいです。新しいOSのイメージを探す必要すらないのです。普段使いという点では、インフラ屋が受ける恩恵のほうが大きいと感じています。

コンテナにまつわる誤解

すごく残念なことですが、巷には間違ったコンテナにまつわる must/should が蔓延しています。

オーケストレーションツールが主体という考え方

人として、エンジニアとして、本番環境での実践を考えることは間違ってはいませんが、コンテナをやると聞いて、オーケストレーションから入るというのはどうも気に食わないです。
もっと自由に考えて、気軽に使うべきだと思います。そもそもオーケストレーションツールが存在しない時代を経験している人にとって、オーケストレーションほしいから使う ツールであって、オーケストレーションが無いとコンテナは使えないというような must/should としてオーケストレーションを捉えるのは間違いです。

コンテナの用途はそんな矮小化したものではないです。もっと広い用途に使えるもので、どこぞの権威が言っているからオーケストレーションわなきゃ ではなく、 どうしたいかは自分で決めて、そして自分で選ぶべきです。

Dockerfileが必須 / IaC必須

必須ではない。Dockerfileが便利であること、IaCもできることには誤りではないですが、Dockerfileは所詮 Docker Imageを作る道具に過ぎないです。使わなければならないではなく、使いたいから使うのです。 実際、run /bin/bash で直接 apt install でパッケージを入れてもからの docker commit でもいいですし、Dockerfileをつかってもいい、Dockerfileが非力なら、Packerから作ってもいいです。

https://blog.james-carr.org/build-docker-images-with-packer-and-ansible-3f40b734ef4f

こうしなければならないなんて、なにもない。あなたが思うように、使いたいものを選んで使えばよいのです。

マイクロサービス化が必須

マイクロサービス化と相性が良いのは間違いないですが、必須ではないです。マイクロサービスではなとも、コンテナは有利です。1コンテナ1プロセスとかいう標語も、場合によっては無視してもいいと思います。supervisordでプロセス束ねが正解の場合もあります。コンテナに置けるベストプラクティス1なんてものは存在しない、自分たちの欲しいものを自分たちで実装すればいいだけです。コンテナにはそれを受け入れる器の大きさがあります。

永続データは入れちゃだめ

この考えは概ねあっていますが、ほとんどの人が誤解しているはず。k8sやECSなどのオーケストレーションではコンテナは使い捨てですが、素のDockerではコンテナは使い捨てではありません。正確には使い捨てもできるし、stop状態としてデータを維持することもできます。これもコンテナの使い方を矮小化しないで欲しいのであえて書きました。オーケストレーションが必要ない小規模な単発コンテナなら、本番環境だろうが、Docker run で良いです。

この点は今現時点でもDockerの課題と言えるので、逆に時代を切り開く度量のある、反骨精神溢れる若人にとってはとてもおもしろいテーマと言えます。実際にこのテーマに挑戦している先駆者もすでにいます。

https://github.com/vitessio/vitess

常識を疑え

コンテナで何が変わるか

デプロイ高速化

オーケストレーションの利用は事実上、前提になりますが、多台数マシンへのアプリケーションのデプロイについて、コンテナによるデプロイは圧倒的に早くて確実です。デプロイ方法も今は選択肢がたくさんあり、デプロイと一口に言ってもやることは様々ですが、コンテナによるデプロイは単純明快で圧倒的なスピードです。新しいコンテナを立ち上げて古いコンテナを消す。 たったそれだけです。
docker pull がどれほど早いのかは体験すればすぐに分かるはずです。しかも、pull して run するだけで新しいバージョンのデプロイ終わりです。古いバージョンの殺しなどはオーケストレーションが大体やってくれます。

IaCの最適化と役割ベースのサーバ管理の終焉

世の中の大体のサーバーは、役割ごとに1台ずつサーバを分離していると思います。 e.g. webサーバ、applicationサーバ、DBサーバなど
設計が必要ではあるもののコンテナ、現実解として、オーケストレーションは必須になりますが、この考え方を崩すことができます。
サーバはもはや只の箱で、それをどう使うかは走らせるコンテナでフレキシブルに変える考え方です。 e.g. 3台でECSクラスタ構成、昼間は web:4,batch:1 夜は web:1,batch:8 このコンテナが動く
サーバをどう使うか、どの役割をもたせるかを、今まではサーバを分離して考えていたのが、それをすべて無しにして、機能を、使いたいときに使いたいだけ使うという考え方に変えることができます。
今までインフラ屋が「このサーバはWebです、このサーバはAppです」などと管理のしやすさだけで決めていた(大半の場合それは無駄の温床)がアプリ屋の主権に戻ると言っても差し支えないです。(もちろん、主権には責任が伴う)

もう一つ、IaC (Infrastracture as Code) にも良い影響があります。コンテナ時代になり、構成管理は楽になった、というよりほとんど不要になったと言えます。
具体的に chef なり ansibleなりで構成管理をしたときに、面倒なのは、すでに動いているサーバに対して「あとからこの機能足して!」です。例えばすでに ruby2.0 系が入っているのに 2.3系でないと動かないアプリだった場合、rbenv入れますか?それともサーバー新設しますか?(動いている本番に手を入れたくない心理が強く働くので、ほとんどこちらになるはず)になると思いますが、コンテナであればrubyのバージョンまで含めて1つのコンテナなので、他のコンテナに入っている rubyのことなんて全く関係ありません。また、1台のサーバーに機能を足せば足すほど構成管理の辻褄わせなど、本来は楽するための構成管理がイライラの元になることも私は経験しています。コンテナは単純明快 別機能がほしければ、別コンテナでやればいい

もっと簡単にAutoScaling

これもオーケストレーション、ECS前提ですが、EC2+CodeDeploy+AutoscalingによるAS対応に比べて、ECS (fargate前提)によるAutoScalingは遥かに簡単で実装がたやすいです。Autoscalingの実装は簡単そうに見えて難しいです。具体的にはスケールアウト時の最新版デプロイを確実にする方法と、スケールイン時の後始末(ログをS3に投げるなど)です。ECSはこの問題に対するユーザー実装を大幅に減らしてくれます。

サーバーレスとコンテナ

そもそも異質なものなので、比較自体がナンセンスですが、私が考える用法用量について

そもそもサーバーレスって何?

ここで言っている サーバーレス については、勝手意味を狭めて定義します。
サーバーレス = AWS Lambdaのようなリソース(CPU/RAM)の完全時間課金
と限定します。PaaSもサーバーレスの一部とも考えられますが、違うものとして、バッサリ切ります。

サーバーレスは直接コストが安い

サーバーレスの最大のメリットは (ほとんどの場合において)直接コストが安いという点です。
文字通りサーバーレスとはサーバーを建てないことです。対して従来型の一般的なWebサーバの場合、使っていようがいまいが、(クエストがあろうが、なかろうが)Listenしていなきゃいけないので、サーバは動いてないといけないです。Lambdaはサーバーを動かしっぱなしにしないで、API-GWでリクエストを受けて、必要なときだけ処理が走るので、ひっきりなしにリクエストが発生するWebサイト出ない限り、ほとんどの場合はサーバー有りの従来型に比べてコストは圧倒的に安いです。もちろんLambdaはWeb以外にも使えます。

サーバー構築は不要だが、ビジネスロジックに集中できるは嘘

これはほとんどのPaaSも同じですが、よく言われる「サーバーのお守りをしなくていいので、ビジネスロジックに集中できる」は半分あたりで半分外れです。
確かにサーバーレスの文字通り、サーバーの構築とお守りは不要です。スケールアウトも自動でしますが、逆にいうと、やりたくても自分ではできないとさえ言えます。
じゃあビジネスロジックだけに集中できるかと言ったら、そんなこと無いです。
サーバーのお守りは意識しなくていいですが、PaaSなりサーバーレスなりが強要してくるレギュレーション

にあなたの実装方法をあわせなければならないです。それでビジネスロジックだけに集中とはとても言えない、少なくとも従来型ではできていたことができないので、サーバーレスにしてみんなハッピーというような単純な話ではないです。

用途の狭さ

レギュレーションもそうですが、明らかにマイクロサービスを前提としたものです。時代の流れとして、マイクロサービス化そのものは正しいと思いますが、逆にそこでしか使えない。対してコンテナはサーバーレスどころか、モロにサーバー有りですが(Fargateとかは無視)、マイクロサービスだけに用途がとどまりません、GPUだって使える。

サーバーレスについてまとめ

  1. サーバーレス自体には、等しくみんなをハッピーにする力は無い = 用途が限られる
  2. サーバーというものは意識しなくていいが、レギュレーションへ合わせ込みが必要 = マイクロサービス化ほぼ必須
  3. しかしそれらを受け入れたとしても、圧倒的にサービス利用料が安い

暴論ですが 安いは正義

API-GW + Lambda のサーバーレスアーキテクチャと言われるものは、GAE(google)がもう10年以上前に通過した道です、技術的には。
http://write.kogus.org/articles/Y2Rtpp

GAEが流行らなくて、対するLambdaがわーわー言われている理由は100ms単位の完全従量課金にしたという1点です。

あともう一つ

  • コンテナとサーバーレスは競合関係に無いので、いいとこ取りすればいい

Dockerについて

Dockerについてです、コンテナという意味よりも狭い道具としての意味で書いています。

Dockerの2つの機能

1つはランタイムとして、つまりはDVDプレイヤーのような再生装置としての機能、ここについては特に触れません。 もう1つはDocker Imageの管理機能、たとえるとDVDそのものを作ったり、管理したりする機能について書きます。

dockerは、gitの OSイメージ版

git と dockerはコマンドとしてそっくりです。

こう考えるとdockerコマンドの本質がよく理解できます。

  • docker build = Dockerfileの中身をもって、コンテナを作成し、stopして docker commitする
  • docker commit = stop状態のコンテナから docker imageを作成する
  • docker push = 指定したローカルにある docker imageを docker-hub や ECRに pushする
  • docker pull = docker-hub や ECRにある docker imageをローカルにコピーする

docker imageソースコード に読み替えると、ほぼ gitと同じ、というか明らかに gitを意識した作りです。 ここで重要なのは、docker imageは差分(レイヤー)で管理され、差分でダウンロード可能である点です。実にエコです。

http://enakai00.hatenablog.com/entry/20140802/1406958412

Docker hub & github

同じく Docker hub も github をもろに意識したものです。何度も言いますが、 Docker hub は Dockerfile の差分を保持しているものではなく、 docker imageの差分を保持しています。大事なのは docker image です。 Dockerfileは docker imageをつくるためのただのヘルパーです。

上記にも触れましたが、OSSお試し環境として docker image の提供は極めて有益で、使い方ビデオを youtoube に上げるぐらいなら、 docker image を Docker hub に pushしたほうがより利用者にわかりやすいです。ものにもよりますが、今後のOSSの提供者としては、githubでソース公開 & バクトラッキングは当然、 dockerhubで機能・追加機能の紹介とやるのが良いでしょう2

Git & GitHub がやったことをOSイメージ = 本当の意味でのランタイムで実現したのがDockerです。このDocker Imageの取り回しのしやすさが起爆剤となり

  • CI/CD
  • IaC
  • 高速デプロイ
  • 開発・本番の共通化
  • ローカル開発

という数えきれないメリットを生み出した。

コンテナ化のデメリット

正直言って無いです。
あるにはありますが、メリットに対してデメリットが薄過ぎる。
マイクロサービス化の弊害は無視します、前述の通り コンテナ化 ≠ マイクロサービス化 なんで。

パフォーマンス劣化

パフォーマンスは軽微とはいうものの、当然劣化します。 ただし、私の世の中に対する感覚から言えば、ここで言われるパフォーマンス劣化は語ることすらナンセンスです。

何故か?
現状を見れば答えはあります。まだオンプレとかいう言葉がなかった頃、仮想環境(VMWareなど)で動かすほうがマイノリティーだった頃があります(この自体は体験している)。クラウドコンピューティングなんて影もカタチもなかった。
それから仮想環境が動かすのが当たり前になった。 理由はパフォーマンスの劣化よりも得るもののほうが大きかったから。
クラウドコンピューティングが出始めたころも、「こんなもの、開発でしか使えねー」と言われていたらしい。一見仮想環境よりも更にコスト効率悪いしね。
だけど、そんな上っ面のコストよりも深層で得られる見えづらいコストに対するメリットがあまりにデカかった。高いけど売れる という本当の価値。
コンテナ(Dockerと言い換えられる)も全く同じ、「開発はいいんだけどねー」だった、始まった頃は。だけど今はどう?

もちろんすべてのコンピューティング分野において、パフォーマンス劣化を受け入れられるわけはないのは知っているけど、ほぼ無視できるレベル。
むしろ仮想化のコストはバカ高だけど、コンテナならイケるというパターンも(正直レアだと思うけど)考えられる。

学習コスト

Dockerは低いと思います。問題はオーケストレーションかなと。予備知識なしだと複雑すぎるので、苦戦するところもあると思う。
まずはローカル環境のDockerを弄り倒すことから、それだけでも十分利を得られるはずです。

まとめ

  1. Docker Image が起爆剤となり、現存するいろんな問題を解決していった (= Docker Image をまず知る)
  2. Dockerだから〇〇しなければいけない制約は何一つない (= やりたいからやる、やりたい方法を選ぶ)
  3. Dockerが開発環境だけなんてもったいない!

最後に
オーケストレーションは置いといて、今現在、Dockerを使わない手はない。


  1. 私はベストプラクティスという言葉は大嫌い、なんか偉そうに感じませんか?「何がベストかは俺が決めるんや、アホ扱いするな!」といつも思う

  2. 私の提言みたいに書きましたが、すでに世の中がそうなってます。

わかったつもりのCloudWatch

CloudWatchのプリセット(ビルトイン)メトリックスに関する記事です。カスタムメトリックスには殆ど触れません。

世の中には2つのタイプの製品があると思います。

  • 説明書を読まなくても使える
  • 説明書を読まないとハナから使えない

AWS CloudWatchは 明らかに前者ですが、この手のプロダクトはテキトーに触りだけ覚えてわかったつもりになるケースが極めて多いです。このエントリで わかったつもり から ちゃんと理解した の橋渡しをします。

重要なポイントの先出し

  • メトリックが定時観測型なのか、随時記録型なのか見極める
  • メトリックスの 1サンプルの値 は必ず1なのか確認する
  • EC2のMC(マネージメントコンソール)の特徴と落とし穴

定時観測型? 随時記録型?

両方共私の造語です。

定時観測型とは、RDS Auroraの qps 等を指します。
このタイプの特徴は、統計の種類 Average, Max, Min が必ず全て同じ値 になります。くわしくは後述

随時記録型とは、ELBの Request数、レイテンシ、各HTTPコードなどのメトリックスです。これはすごく雑に書くと、何時いつの値がNだった というデータを1個1個格納しています。周期的に格納しているのではなく、実際にその現象が発生した都度となります。特徴は、統計の種類 Average, Max, Min が異なる値となりうる です。

定時観測型の説明

特定の周期で、その時の値をCloudWatchのストレージが記録しています。
単純な話ですね、直感的にわかると思います。つまり、1分間隔であれば

  • 10:00 に 10.0
  • 10:01 に 15.0
  • 10:02 に 9.0

のように記録しています。よって、集計間隔を1分, 統計方法SampleCount とすれば、常に1です。 1分ごとに1個データが入っている という意味です。
上記を踏まえると

集計間隔を1分, 統計方法 Average, Max, Min とした場合、全て同じ値になります。だって1分毎に1個しかデータが入っていないから。 また、パーセンタイルも Sumも意味ないですね。だって1分毎に1個しかデータが入っていないから

勿論、データの間隔よりも大きな集計間隔を取った場合は異なります。データは1分間隔で入っている、5分間隔での集計なら、各々の集計間隔に5個データがあるからです。

随時記録型の説明

上記で大事なことなので2回言いました的に だって1分毎に1個しかデータが入っていないから と書いたのは随時記録型は 1分毎に1個以上のデータが入っている との対比のため。

取り敢えず ELB の Latecyを挙げます。Latencyはこんな感じでデータが入ります

  • 10:00:01 に 10
  • 10:00:02 に 12
  • 10:00:09 に 9
  • 10:00:23 に 4
  • 10:00:31 に 11
  • 10:00:42 に 3
  • 10:01:06 に 5

上記のように間隔はバラバラで、その現象が発生した時間 = リクエストが発生した(レスポンスを返した?)タイミング で随時・都度書かれます。つまり 10:00:00 - 10:00:59.xxx の間に 100個リクエストがあれば、100個データを持っていることになります。これ、インフラ屋ならわかると思いますが、ゲージ型と較べて全然データ量が違いますよね。これがタダって凄い太っ腹ですよね!
1分毎に1個以上のデータが入っている だから Average,Max,Min も異なってくるし、パーセンタイルも意味ある。

定時型・随時型の見分け方

長いので 定時型 随時型 と書き分けます。 正確な見分け方は、統計としてSampleCountを使うと一発でわかります。もうわかると思いますが、定時型なら集計間隔を何に変更しようとも常に一定です。(Demenstionで複数のリソースが混ざる場合は?とか意地悪なことは言わないで)

そもそも AWSのプリセット?ビルトイン? つまりカスタムじゃないメトリックスはほぼ全て定時型です
例外はELB(ALB/NLB含)ぐらいです。

ELBのメトリックス

ELBの随時型メトリックスを個別に掘り下げます。

Latency

前述しているので、軽く追加情報。
Latencyは、各リクエストに掛かった時間を値として書いています。 (敢えて を強調します、伏線です。) ですので、Max,Min,Average およびパーセンタイルは基本全部違いがあります。勿論Sumも

では、SampleCount ですが、これが 別メトリックスのRequest数:Sum とは一致します。AWS的には個別メトリックスとしていますが、実は1メトリックスで賄えるのです。

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

線が丸かぶりしているので1本に見えますが、一致しています。

ではRequest数:Sumはなんでリクエスト数を表しているのでしょうか?LatencyでSumをやると、これまでの知識でわかると思いますが、その単位時間に発生したリクエストレスポンスの合計値となります。当たり前ですがとんでもなくデカイ値になります。では Requests:Sum はなんでバカでかい値にならないのでしょう?

単純な話です。伏線回収 = 1サンプルの値 が常に1だからです。

  • 10:00:01 に 1
  • 10:00:02 に 1
  • 10:00:09 に 1
  • 10:00:23 に 1
  • 10:00:31 に 1
  • 10:00:42 に 1
  • 10:01:06 に 1

とデータが格納されている場合、当然1分等の集計間隔で Sumすれば、その時間のリクエスト合計になります。ま、SampleCountを使ってもおなじですが。

2xx,4xx,5xx 系のカウント数

これらは常に1サンプルの値が1 です。なので Max,Min,Average は常に1です、パーセンタイルも意味ありません。 よって使える統計は Sum か SampleCount だけです。

HealtyHostsCount

これは結構特殊ですので、先に答えを書きます。

  • 定点型
  • データのサンプル数 = ELBを配置するAZの数 (正確にはELBのノードが増えた場合はその台数?)
  • 1サンプルの値 は healtyなホストの数 だが、それは最低でもAZ毎に出している。

前提知識を先に記載。
ELBはマネージメントコンソール上は1台ですが、実際は複数台で動いています。複数AZに配置する場合、最低でもそのAZに1台となります。暖気申請や、自動スケールアウトによりELB自身もスケールアウト・インします。つまりELBを構成する台数は常に一定ではない。

まず定点型 これについては素直に理解出来るはず。
データのサンプル数 = ELBを配置するAZの数 は直前に書いた前提知識の通りです。おそらくELBを構成する実ノード(私達は見れない、AWSが管轄しているリソース)の数になります。
最後に 1サンプルの値 は healtyなホストの数ですが、試すのが早いです。AZ2つで、EC2を2台ぶら下げて、Sumを出して下さい、ちゃんと healtyなら 4となるはずです。

今EC2が2台ぶら下がっていて * AZが2つ(=ELBを構成するノードが2つ) = 4

この点、もうちょっと掘り下げます。ELBと言えど、実体は恐らくただのEC2です。上記のケースで 例として A,B という2台のELBノードがあった場合

Aは 2台 healty Bは 0台 healty

と返す場合もありえます。つまりELB自身の片方であるBに障害があった場合の話です。この場合 Sumすると2となります。
殆どの場合、Average,Max,Min は一定になりますが、ELB側で障害があった場合、これらの値が一定でなくなります。監視屋としてどの値を使うかは検討した方がよいです。
妥当なのは Average、 Minだとつまり悪いとこ取りするので、さっきのA,Bの話だと0となります。これをもってNGとしてもAは生きているのでELB全体としては全滅ではないので厳しすぎとも言えます。逆にMaxだといいとこ取りなので、A,Bともに0になって始めて0になります。緩すぎな感じもします。

ManagementCosole @EC2 と @Cloudwatch の違い

メトリックスを見る時にEC2からみたほうが纏まっていてわかりやすいですが、EC2側で確認するのと、CloudWatchで直接確認するのと随分異なることがあります。

  • このメトリックスはSumがいいだとか、Averageがいいとか、予め空気読んでくれている
  • IOPSとかは予め計算してくれている(そのせいでCloudWatchの値と合わない)

1つ目の空気読んでくれている点ですが、たしかに便利は便利ですが、私はこれが学習を妨げる原因の1つになってしまったように思います。なんでこのメトリックスはAverageが全部1になるの? とか気づきを奪っているようにも感じます。
2つ目も詳しく書きますが、@EC2 と @CloudWatchは同じ物が出ているという間違った頭があると危険です。データーソースは同じですが、見せ方が違う。EC2側は一手間勝手に掛けてくれている

EBS Volume Write&Read Ops and Bytes

EC2側はいい感じに計算済みの値が入っています。試しに SampleCountに変えるとおかしな値が出ます。

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

CloudWatch側は生の値です。

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

言いたいことは、EC2とCloudWatchで値違うので、ちゃんとCloudWatchで調べなおしてね。

まとめ

  • メトリックが定時観測型なのか、随時記録型なのか分かっていると、統計のどれを使えば良いのか自ずとわかる
  • 1サンプルの値 は必ず確認すること。1の場合 随時記録型 で ずっと値が一定なものに監視を掛けたりしかねない
  • EC2のマネジメント ≠ CloudWatchの正規の値

監視屋として、どの統計を使っていいかわからないければ、 ELB Cloudwatchのようにググって

http://docs.aws.amazon.com/elasticloadbalancing/latest/classic/elb-cloudwatch-metrics.html

にある推奨を使えば大抵OK

Google Cloud Storage (gcs) IAM対応でACL設定がより簡単に

Google版 S3である Google Cloud Storage (gcs) ですが、もう随分前になるもののIAM対応となり、アクセス・ユーザー管理が非常に楽になりました。
ここでのIAMは勿論 GCPのIAMです。名前は同じですが、AWS の IAMとは、全く異なるものです。 今のところgcsのIAMはAWSに比べて機能面で大きく劣ります。

2019追加機能について下記エントリを作成しました。もっと楽になっているので合わせて参照してください。

iga-ninja.hatenablog.com

f:id:iga-ninja:20171023195140p:plain f:id:iga-ninja:20171023195105p:plain

IAMと、今までのACL

元々GCPにはIAMは存在せず、GCSはそれ単体で独自のACLを持っていました。今回の変更でこのACLレガシーACL と呼ばれるようになりました。レガシーと後述します。
対して今後はIAMによるGCSのアクセス制限・許可を使うようになります。
では、レガシーは今後どうなるのかですが、恐らく無くなることはないと思います。が、Developsers Console(ブラウザから)のレガシーACL設定は、もうできなくなりました。

IAMで出来るようになること

まず最初に、非常に語弊があるIAMという名称。先にAWS識者に言うことは S3に対するIAMと違って、リソース縛り(/pub/* は全員許可 /user1* は IAM user user1だけが通るとか、が一切できません。
制御出来るのは バケット単位のみです。 Prefix/Key単位では制御不能です。Denyのルールとかも書けません。

で、何が出来るようになったかと言うと バケット単位で IAM権限として付与した場合は、レガシーACLに頼らず(レガシーよりも強く) そのバケットの全てのオブジェクトに対して制御が可能です。

は?何いってんの?そんなの当たり前じゃねーか?

AWS識者は即反応しそうですが、この当たり前が、ほんのすこし前まで当たり前ではなかった。この記事は主にそれを書きます。

レガシーACL

S3のバケットACLやオブジェクトACLと同じで、バケット・オブジェクト1個1個単位でACLを設定します。このACLには、プロジェクトメンバだけではなく、Web公開する場合は allUsers に対する権限も含まれます。
大変なのは1個1個に指定しなければならないことです。極端な話、静的サイトをホスティングする場合、全部で100ファイルから成る場合は、その100個1つ1つに allUsers の閲覧権限が必要です。
...
そんなのやってられないですよね!そこで Default ACL と言うものをバケット単位で指定します。

Default ACL ?

バケット単位で指定する、DefaultでオブジェクトにつけるACLです。

例をあげるともしも、Default ACLを指定していなかったら。 バケットACLがあれば、ファイルのアップロードは可能です。つまり、XさんがAバケットに書き込み権限が付与されていると gs://a/hoge/fuga.txt など、好きな場所にファイル(オブジェクト)を upload可能です。 しかし、 gs://a/hoge/fuga.txt というファイル(オブジェクト)自体には ACLが何も付きません。勿論ACLの後付は可能です、が ACLが何も付いていないオブジェクトは、例え作成者であるXであっても`削除や移動や編集(上書きUpload)が一切できないオブジェクトになります。 対して、 Default ACL に AllUser に対して ReadOnly を指定していた場合。上記と同じ手順で、gs://a/hoge/fuga.txt がWeb公開された状態に自動でなります。

つまりは、オブジェクトをUploadする時に、ACLを何も指定しなかったら Default ACLの内容で、オブジェクトACLが付くということです。

バケット・オブジェクト ACLの問題点

一見問題なさそうに見える Default ACLですが、実に大きな問題を持っています。それは

バケットACLに新たにユーザーを追加した場合でも、既存オブジェクトのACLは変わらない、という点です。 つまりこういうことです。

  1. X さんが gs://hoge/a.txt を upload この時、 Default ACL は Xの編集権限のみ
  2. upload により a.txt に Xの編集権限が付く(仮に)
  3. Y さんがプロジェクトに参加、 gs://home にレガシーACLとしてユーザーを追加した Default ACL にも Yの編集権限を追加
  4. Y さんが gs://hoge/b.txt を upload これは問題ない
  5. Y さんが gs://hoge/a.txt を削除 or 上書き これができない、 だって a.txt は Yがいない時に生成されたので、 オブジェクトACLにXの編集権限しかないから

これに対する対処方は2つ

  1. 既存のオブジェクトのACLを全部変更する 具体的にはYの編集権限もオブジェクト全部につける
  2. そもそもユーザー個単位で権限を付与しない Google Group (G SuiteでなくてもOK)単位で許可をする

1) は根性です。全てのファイルのACL書き換えですので、それなりに時間もかかるリスキーな作業です。
2) はGroupという管理単位を1つかまして、ユーザー追加・削除の影響を最小限にする方法です。Google Gruop単位でACL設定した場合、もしもメンバを追加したいとなっても、GCS側はとくに変更無しで、Google Groupに該当するユーザーを追加 or 削除すればよいのです

Web公開とallUsers

注意
2019年にこの点に対する更新エントリを書いています。ぜひ参照してください。

2019年版 Google Cloud Storage (gcs) のアクセスコントロールがより簡単に - 続 カッコの付け方

GCSのオブジェクトをWeb公開する場合、AWSのような便利なバケットポリシーは存在せず、オブジェクトACL単位で管轄します。この、公開する時につかうユーザー(= 無認証ユーザーのアクセス)を allUsers という名前で指定します。回りくどく書きましたが、

Web公開したい なら allUsersでRead権限付ける しかもファイル一個一個に
だけどそんな面倒なことやってられないので、 Default ACLallUsers 足しとけ

となります。

レガシー or IAM

レガシーとIAMを比較して、じゃあこれからどうすればいいの?をまとめます

ユーザー・グループには IAMで権限付与

Object ACLの問題が発生しないため、レガシーを捨ててIAMにすることを強くおすすめします。 デメリットは私は思いつきません。

allUsers には レガシーで

ここは私の感覚をもろに出しているので、そうじゃないと思う人もいるかもしれません。

結論から言うと、 allUsers としてIAMで読み取り専用で権限付与は可能です。 が、1つ大きく問題があります。 詳しくは書きませんが、GCSはブラウザ上でバケット内のオブジェクトの一覧を確認できるGCPのツールがあります。AWSでいうマネージメントコンソールからのS3一覧画面のようなものですが、GCSはGCPの認証とは別にGCS単体での管理画面を持ちます。この画面が、何とallUsersとしてIAMでバケット許可していると、だれでも見えてしまいます。 つまりどう言うことかというと、所謂Apacheとかが自動生成する そのディレクトリに含まれるファイル一覧無認証で閲覧可能 になります。

結局Webで全部公開するなら、見れてもいいじゃないか?

という考えも有ると思いますが、「公開してはダメなものも意図せず置いちゃった。。」というのが二昔前の情報漏えいの基本だったと記憶しています。なので、私はIAMとして allUsers を読み込み専用とするのはかなり危険だと思います。このバケットには絶対に公開してOKのものしか置かない・置けないという仕掛けが無い限りは。

おまけ Default ACLの設定

今のDevelopers Console上から、 Default ACLを設定することはできません。gsutil のみとなります。 gsutil で Default ACLを設定する手順をざっくり書きます。

gsutil defacl get gs://[バケット名] > default.json

vim default.json 
# 編集する 下記を追記
  {
    "entity": "allUsers",
    "role": "READER"
  }

gsutil defacl set default.json gs://[バケット名]

まとめ

  • 今後はGCSのアクセス管理は基本IAMでいい
  • allUsers を IAMで ReadOnlyとするのは結構危険

Default ACLをブラウザ上から設定できないのは不便だなとおもう。

AWS NLB 初心者向け説明 (特にHealthCheck)

続々とELBに機能が追加されていますが、今更ですがNLBについて書きます。 今更NLBの記事を書くことに意味があるのか?と自問しましたが、一応 (初心者向け) と (HealthCheck) という切り口で、なるべく優しく書こうと思います。

NLBについて

先に言っておきたいこととして、NLBははっきり言って玄人好みで初見殺しです。いや、死ぬことは無いかも、そもそも思った通りに動かせない。

先にこの記事よりも遥かにレベルの高いものをエントリしておきます。下記を理解出来るレベルであればこのエントリは用済みです。

kanny.hateblo.jp

dev.classmethod.jp

dev.classmethod.jp

HealthCheckについて

早速本題です。 HealthCheck と ELB(TargetGroup)はセットで切り離せない存在ですが、NLBにSecurityGroupを当てることができません。

今までなら、ELBに X というSGを付けたら、バックエンドのサーバには X からのインバウンド 例えば TCP:80 とかを許可していました。SG設定できないなら、どうすんの? 答えは NLBの属するSubnetのIPレンジに対して許可するとなります。しかも上記の記事をちゃんと読んだ人ならわかるはずですが、NLBはバックエンドとの通信でAZを跨ぎません。よって、NLBが属するAZと同じAZにあるバックエンドに対して、設定すれば良いとなります。ここはAccess.logを見ても確認できます。

NLBの解説

なるべく簡単に

所謂リバースプロキシ型ではない

ALB, ELB (Classic ELB) は所謂リバースプロキシで、ロードバランサで一旦全てのリクエストを受けきって、ロードバランサのSourceIPでバックエンドにリクエストを飛ばします。当然レスポンスが戻って来るので、それを受け止めてリクエスタ(エンドユーザーのブラウザ等)に返します。雑に書くと、結構忙しい。だから暖気とか必要。 もっというと 複雑なこともできる となります。複雑なこととは SSL Terminate, Stickey Sessionなどです。

対して NLB はリバースプロキシではないです。厳密にはDSRとも違う?らしいですが、ロードバランサが一旦リクエストを受ける... の動きがなく、いきなりバックエンドのインスタンスにリクエストが来ます(来たように見えますが正しい)そして、ロードバランサを介さずレスポンスが戻ります。これまた雑に書くと、結構ヒマ、だけど複雑なことは無理

GCEの場合

敢えてGCEと比較します。 GCEが最初にだした、ネットワークロードバランサ(元々は単にローバランサ)はDSR方式です。ウチのLBは暖気要らずやで!どやぁ と言っていたのはこのためです。 これは私の感覚ですが何度も出している言葉ですが、 Google は IP, AWS は DNS という冗長のための仕組みの思想があるように思います。最初にDSRを作ったのもこの設計思想が強く反映されているように思います。しかしDSR型は機能が盛れない、SSL Terminateとかです。そこで HTTP(S) ロードバランサというリバースプロキシ型 + 地域分散型のLBを出しました。

話をHealthCheckに戻します。 GCEはHealthCheck、どうやってるのか? 答えは LB自身がヘルスチェックをせずに特定のIPアドレスからヘルスチェックが飛んでくる、です。この特定のIPとは、プロジェクト(AWSで言うところのアカウント)が異なっても同じです。なので、ヘルスチェックだけを通す・殺すは一応可能です。

NLBのHealthCheckは誰がやんの?

誰がHealthCheckするのかは、他のLBと変わらずNLB自身がやります。 で、SGが指定できない。なので、今のところバックエンド側のinbound SG ルールを絞りたいとなったら、(個人的にはこれはやだなというのも含みますが)

  • VPC の CIDRで妥協 (AWSドキュメントでおすすめとか言ってる)
  • Subnet の CIDRで行く (AZ跨がない考慮を入れる・入れないで2段階)
  • NLBだけを特定のSubnetに押し込めてそのCIDR (Subnetだらけになる、ただでさえ嫌いなのに)
  • 固定かどうか分からないが、アクセスログに出てくるIPだけ許可する。(変わらない保証はない)

今のところ、これぐらいです。

おまけ1. 従来のPrivate Subnetにバックエンドを引っ込めるは出来るのか?

結論から言うとできます。 この構成は CLB,ALBともよくやっていると思います。バックエンドにグローバルIPアドレスを持たせない。DSRは自力でクライアントにデータを届けなくてはならないので一見無理そうですが、できます、できました。 必要なものは

  • NLB は当然 Public Subnetにおく
  • バックエンドは Private Subnet & グローバルIP無し(あっても意味ない)
  • バックエンドが立つ Subnet は NAT-GatewayとかでOutboundが出来る
  • バックエンドにSG inbound TCP:80 0.0.0.0/0 とかを付ける

グローバルIPが無いインスタンスinbound TCP:80 0.0.0.0/0 を付けるんです!気になるのは、NAT経由で戻る点ですが、帯域的にもまあ問題ないかと。そもそもこの構成で本当に行くなら、全AZにNAT-GW必須と言えると思います。理由は?冒頭のエントリ見直してみてください。

おまけ2. ECSと組み合わせ可能?

可能です。ただし、普通にPublic Subnetにおいてしまうと、ポート全開で丸裸にせざるを得ないので、Privateに引っ込めるのはかなりいい手だと思います。NLBもターゲットグループを参照するので、普通にECSと連携できます、Drainingはできませんが、そもそもDSR方式(じゃないけど)なら原理的にはそんなもん必要ないです。

まとめ

  • healthcheck は VPC か Subnet のCIDRぐらいしか無い
  • NLB + Privateに引っ込んだバックエンドの構成は可能
  • ECS + NLB も一応イケる Privateに引っ込めるのがおすすめ

healthcheck はそのうち綺麗な方法がでるかも。一応、healthcheckにしか使わないよ!とUIで言って予防線張っても、ユーザーは NLBのSGに 0.0.0.0/0 とか絶対付けちゃうだろうし、NLBでIP制限出来るとか考えちゃうだろうから、NLBはSG無しとしたのは良い手だと思う。ただ、仕組み的にはhealthcheckだけSGは付けられるはず、だってhealthcheckするのは結局NLBだしローカルIPあるってことは、ENIがあるってこと、SGはインスタンスに付くのではなく、ENIに付くものなので仕組み上は絶対出来るはず。

結局あんまり初心者むけではなくなったような。。。

CloudWatchLogs データを入れてからのおたのしみ(概要編)

リリースから随分日が経っていますが、改めてCloudWatchLogsの良さを書きます。今回はLogs Agentや取り込みの話しは触れません。Logsに取り込んだは良いけど、どうしよう にフォーカスします。

その前にCWLogsの概要

長いのでCWLogsと略記。 CWLogsは文字通り、システムログやアプリケーションログ、Windowsはイベントログも含むを、CloudWatchLogs(AWS側の基版と言い換え可能)に投げます。CloudWatchはカスタムメトリックスといって、ユーザーが任意のメトリックスを送信することが出来ますが、CWLogsはそれのLog版となります。Logですので、メトリックス値(数値)ではなく、ログそのもの=文字列です。

ログをCWLogsに投げる処理は、CWL-Agent等を使います。前述の通りCWLogsに投げるまでの話しはこの記事では触れません。

CWLogsの代替

ここまでの 「Logを何処か一箇所に投げる」という機能だけみれば、fluentdや、同じくAWSkinesis、kafkaなどでも実現出来ます。逆に言うと、「Logを何処か一箇所にに投げる」という目的だけで使ってしまうと、ある程度の量を越えると割高で、kinesisの方がお得です。

これより、CWLogsの利点です。

用語説明

その前に用語説明を

ロググループ 後述のログストリームを束ねるものです。一般的にログの種類でロググループを分けます。
e.g. /var/log/messages や /var/log/http/access_log 毎に1ロググループ

ログストリーム 必ずどこかのロググループに所属します。一般的にはホスト毎に1ストリームとします。そうしない設計も可能ですが、その場合ログの中にホスト名を書くなど考慮が必要です。(どのホストのログか見かけが付けられないので)

The Log group has some Log streams .
A Log stream belong to one Log group.

CWLogsの利点

  1. マネジメントコンソールからログの検索
  2. メトリックスフィルタにより、ログをメトリックス(数値)化、そこからClowdWatch アラート発報
  3. ロググループをサブスクライブして、Lambdaでリアルタイム処理

マネジメントコンソールからログの検索

ロググループ単位で検索可能です。つまり複数のホストのログをまとめて、時間と検索文字列を指定して探すことができます。触ればわかる機能ですので、詳しく説明しませんが。これはこれで便利だと思います。

メトリックスフィルタについて

CWLogsがリリースされたすぐに使えた機能です。先の説明どうりですが、Log中の特定の値を含んだものをカウントし、Logを数値化します。 これを ClowdWatchで閾値を指定、アラーム発報とします。メトリックスフィルタは、ロググループ単位で指定します。

メトリックスフィルタの特徴

Pros
- 1つのロググループに対して、複数のメトリックスフィルタを指定可能
- フィルタルールは結構柔軟。複合条件に似たような記載も可能(後述)
- 検出・通知までプログラミングは一切不要

Cons
- ログ -> 数値化し、その数値に対してアラート発報をするだけなので、ログのアラート発報の原因となったレコード自体 はわからない

簡単に指定出来る点は有利ですが、ログそのものはアラートに含まれないという欠点があります。
つまり、
アラート飛んできたら、どのログ(種類)でアラートを検出したかや、発生の時間帯はわかるが、
どのノードで発生した?/一部なの?全体なの?
ログの中身は?
と言った利用者が本当に欲しいものはそのアラートだけでは得らず、わざわざマネージメントコンソールにログインしてログ検索する必要があります。
それでも最低限の監視、何かが起こっているの検知にはなると思います。

ロググループのサブスクライブの特徴

CWLogs出たてのころはlambdaは存在しなかったため、この機能は後発で実装されました。この機能もロググループ単位で指定出来ます。

Pros
- 生のログを処理出来るので、ログの内容をアラートに込めることが出来る
- フィルタルールだけでなく、lambdaで処理できるので、自由自在

Cons
- lambda必須 = プログラミング必須
- 1つのロググループに対して、1つののサブスクライバしか指定できない

メトリックスフィルタで出来ないことは実現できるのが強力です。が、ロググループ1つに付き1つのサブスクライバとなるので、この点は注意です。

1つの記事にまとめるつもりでしたが、結構な長編になってしまいました。 次回はメトリックスフィルタ編、次にサブスクライブ編と続けます。

AWS EBS SSD (gp2 general purpose) バーストクレジット計算式

「EBS (gp2) のクレジットの回復レートってどんなの?」の質問に即答できなかったので、書いておきます。 結論、数式としては

クレジット 0 -> Fullまでの時間 = 5,400,000(IO) ÷ ベースラインIOPS

となります。

概要と用語

簡潔に

  • EBSは 3000 IOPSまでのバーストクレジットがある
  • 1GBあたり 3 IOPSのベースラインIOPS ただし、 33.333GB ?(つまり 100IOPS以下)の場合でも最低100IOPS
  • バーストの継続時間は、 3000IOPS と、ベースラインのIOPSの差に反比例する 言い換えると ベースラインが 3000IOPSに近ければ長く、遠ければそれだけ短い
  • 1TB超の場合はベースラインが 3000IOPSとなるので、そもそもバーストしない

上記は理解できていると思います。 用語も改めて

  • ベースラインIOPS = バーストなしで利用可能なIOPS上限
  • バーストクレジット = ベースラインを越えるIOPSを利用した時に消費され、ベースライン以下のIOPSしか消費していなければ貯まる

公式ドキュメント

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSVolumeTypes.html

http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/images/gp2-burst-bucket.png

解説もなにもありません、この絵の通りです。 EBSはOS起動時にIOPSが派手に発生することを見込んで、CPUクレジットとは異なり、いきなり 5,400,000 クレジットから始まります。このクレジットを消費することによって、バーストします。

Volume size (GiB) Baseline performance (IOPS) Maximum burst duration @ 3,000 IOPS (seconds) Seconds to fill empty credit balance
1 100 1862 54,000
100 300 2,000 18,000
214 (Min. size for max. throughput) 642 2,290 8,412
250 750 2,400 7,200
500 1,500 3,600 3,600
750 2,250 7,200 2,400
1,000 3,000 N/A* N/A*
3,334 (Min. size for max. IOPS) 10,000 N/A* N/A*
16,384 (16 TiB, max. volume size) 10,000 N/A* N/A*

上記抜粋表のの 1GB を見て下さい 単純な算数ですが 54,000 * 1000 = 5,400,000 となります。 100GBの場合、1GBの3倍のベースラインですので、54,000 / 3 = 18,000 となっています。

数学的な説明

5,400,000 という数字ですが、単位として示すなら 5,400,000 IO (英語的にはIOsが正しいですが、紛らわしいので IOとします) と読み替えられます。算数の 速さ・時間・距離(地方によっては、は・じ・き と言うらしい)の関係のように、単位変換を式で表すと

まずIOPSは文字通り1秒あたりのIO数ですので IOPS = IO / 1sec とします。そのあと、
Sec = 5,400,000 IO ÷ BaseLine IO / 1 sec 変換して
Sec = 5,400,000 IO × 1 sec / BaseLine IO

5,400,000 の IO と 掛け算の分母である BaseLine の IOが相殺されて
Sec = 5,400,000 / BaseLine
となります。

AmazonLinux や CentOS6 で upstart root以外で実行

もうオワコンである upstart で結構苦戦しました。やりたい事は単純に root以外のユーザーで実行したいということだけ

upstart ?

sysVと systemd の間にあったデーモン管理Tool(というか機構?)です。こいつは sysV とは違って systemdと共存出来ないので、オワコンです。が、残念なことにAmazonLinuxはこれに依存しているサービスが沢山あります。 AmazonLinuxのイケてないところは後述します。

やりたい事

root以外でデーモン起動

setuid / setgid があるじゃん!

残念ながら、 Cent6(RHEL6)をベースにしている AmazonLinuxは古すぎてsetuid/setgid に対応していません。その気になれば差し替えも出来るでしょうが、upstart のような根幹に関わる部分を差し替えるのは難しいはずです。少なくとも再起動は伴うと思いますので、やりません

方法

ubuntu - Running upstart jobs as unprivileged users - Super User

色々ありますが、単に su/sudo でやる方法でも、私の目的のスクリプト(中でデーモンプロセスが動く)は上手く動かなかった。挙動としてはsu コマンドの部分のみプロセスを見ているような動き。 コマンドその物に chmod コマンドで setuidもありですが、今回はシェルスクリプトなので不可能。シェルスクリプトで setuidが使えない理由はセキュリティー上の問題です。結構重要なことですが、詳しくはググって下さい。

結論 setuidgid コマンドを使う

daemon-tools の一部である setuidgid コマンドを使います。古いツールですが、パッチさえ当てればビルド出来ます。

ビルド

kaztr.hatenadiary.com

抜粋

wget http://cr.yp.to/daemontools/daemontools-0.76.tar.gz
tar zxvf daemontools-0.76.tar.gz
admin/daemontools-0.76
wget http://qmail.org/moni.csi.hu/pub/glibc-2.3.1/daemontools-0.76.errno.patch
patch -p1 < daemontools-0.76.errno.patch 
package/compile

使う

upstart のサービス毎の設定ファイルにて

exec setuidgid <ユーザ名> xxxx

AmazonLinuxのイケてないところ

他所のディストリビューションが 全て systemd に行ったのに、未だに sysV upstartなのは、centos6 をベースにしたから。 AmazonLinuxはkernelだけは上げていますが、grub, init系など は centos6 の古典時代のまま。 さらに悪い事に、ECS Agent 等は upstart で動かしているなど、この古い基版の上にAWS謹製のものを作っています。 思うに、今更 死んだ upstart に触りくないし、触ってほしくない。

なんでスパッと切り替えられないかの最大の要因は たぶんAmazonLinuxはローリング・リリースしているから。つまり yum updateだけでメジャーバージョンアップ完了。当然カーネルは無理だが、その他のものはこれで問題ない。しかし、 grub, init系を弄るとなると、結構怖い変更かつ、OS再起動は必須になるはず。だからやらなかったのだとおもうし出来る気がしない。

なので、次のバージョンから 最低でもベースを Cent7 か何かに切り替えた AmazonLinuxと、今のAmazonLinuxの2本立てとなるのが嬉しい。でもなんとなくそうしない気がする、2本立てのリソース裂きを嫌って。

まとめ

upstart root以外ユーザーなら setuidgidが良さげ、

AmazonLinuxへ一言 さっさと systemd化してくれ。。