抽象化の話

クラウドだのなんだのと昨今なんやかやいろいろやってるとよく言われるのが「抽象化しました」とかそういう言葉。

で、これってまあ僕らわかるでしょ?みたいな勢いで使っていますが、具体と抽象って概念の話だから本来はちゃんとコンセンサス取らねーといけないんだろうなぁとかおもいつつ。

さてさて。我々インフラの人々の抽象化、は例えばDockerコンテナとか仮想基盤、というものがそれを実現しています。アプリの方々における抽象化、というとフレームワークが担う部分になりますかね。

言っちゃえばこの辺はオブジェクト指向とかその辺とも絡むんですが。

さて、この抽象化、という概念、我々のNICが抽象化された仮想NICでつけ放題だぜひゃっほー!とかいうだけじゃなく、抽象化されたものをさらに抽象化し、それをさらに抽象化でラップする、みたいな芸当によって世界の物理領域というのは人の目から徹底的に隠ぺいされて行っています。

要するに抽象化ってある意味ではブラックボックス化なんですよ。

EC2起動して、EBSをアタッチして、というこれも、実機のレイヤから見れば仮想マシンとしての抽象化が行われ、ストレージも仮想ストレージデバイスとして抽象化されている。だってどこにも接続ケーブルとかの話は出てこないですよね。ちゃんと接続プロトコルあるんですよ? あるけど意識しないですよね。実機だったらSCSIケーブルとSATAケーブルじゃ全然違うし、HDDやSSDだって接続方式ごとに異なる製品ですよ。

何のためにやってんのか、と言ったらそりゃあ実機なんてメーカー違いどころか下手すればCPUのロットナンバーによってすら違いが生じる場合があるわけで、それを均質的に一律にしようと思ったら抽象化するでしょ。具体まで下りて行って実機毎にチューニングしてくださいとか言われたらいやでしょ、皆さん。私だっていやだwwwww

でも、EC2もOSいじったりしないといけないんですよね。くそ面倒ですね。それにnginxとphp-fpmいれてアプリ屋さんのアカウント発行してlaravel入れてもらって、プロジェクト立てて、みたいなことを開発系環境と環境合わせつつやって。

とかも面倒ですね。面倒ですよ。じゃあまるっと実行環境ごと抽象化しちゃえ。というのがDockerのコンテナですね。実行環境だけパージしてもしょうがないから、動作するのに必要なネットワークだとかストレージも抽象領域に接続しないといけないから、それらも仮想NICとかの上にさらに抽象化が乗っかります。これがいわゆるDockerネットワークだとかコンテナストレージとかの話。内部的にはもっと細かく抽象化が働いていますが。

これでサーバは「OS+Docker」と「コンテナ」というレイヤで分離し、抽象化されています。

OS+Dockerをさらに抽象度を上げると、Lambdaの実行環境とか、Fargateとかになります。コンテナは現状ここからさらに抽象度を上げるとただの製品になっちゃうんだけど、EKSのHelmとかのコンテナパッケージ管理ですかね。

さらにその先はロールによる抽象化、というものが現れてきます。そもそもnginxだのapacheだのとなんで気にかけなきゃいけないのか、まるっとまとめてWebサーバという概念だけでリリースできてしまえればもっといいですね。まあこの辺はまだまだ途上ですが。
※そもそもApache/nginxくらいは選びたい、というニーズのほうが強い。でもポンチ絵にいちいち書いたりしないのは抽象化してるから。

粒度がもうちょっと大きくてもいいなら、この辺はプロプライエタリ環境としてアプライアンスにパッケージングすることで隠蔽する、という手になってきます。ただ、これを抽象化と呼ぶか、というと抽象化とは呼ばないかと…。パッケージング、ではありますし、アプリケーションの実行に関する何もかもすべて、みたいな抽象化ではあるんですが、なんでなんでしょうね。自由度の低さかな?

抽象化はそれによって制約を受けますし、自由度は下がっていくものですが、あくまで部品、というイメージが強いです。まあ私の感覚ではありますが。厳密な話をし始めたらいろいろ間違っているのかもしれません。

何が言いたいのか、というと、そもそも抽象を掘り下げたってその先にはまた抽象があるかもしれない、という話ですね。具体に落とし込め、とかはよく言うセリフですが、クラウドなんかにおける具体って別に具体本体じゃなくて「もう一段低いレイヤーで示せ」という意味でしかありません。

だってそこだって仮想マシンとかの抽象体でしかないわけです。というかOSだって抽象化されたインターフェースです。

ここでいう具体、とは実態を示していなくて、何かを抽象化させた場合の「何か」を指しているだけです。

実体 > 抽象化1 > 抽象化2 > 抽象化3

で抽象化3に対する具体、は普通は抽象化2を指しています。抽象化2のレイヤーで具体を示せ、と言われたら抽象化1を示すことになる、ということですね。

いわゆるレイヤーの考え方でラップされているわけです。

というわけで、抽象化、というのは世の中にとてもありふれていて、特殊なものでもなんでもありません。なので我々も気軽にもっと抽象度あげてよ、とか気軽に言います。これは、視点がピンポイントフォーカスされすぎてるとかの時によく言いますねぇ。要するに、ある抽象化レイヤで話しているのに、その下層の具体レイヤに意識が向いてしまっている状態です。

例えば、CDNおいてLoadBalancerおいてEC2二台でバランスして、という構造を考えていた時に、EC2にはApache入れるのか、nginx入れるのか、gitは要るか、phpなのかRubyなのかって言い出したら、会話レイヤが違ってしまっている、ということです。

今の抽象レイヤにその要素は存在しないんですよ。ところが人間って面白いもので、「自分のわかるところ」にリーチしてしまいやすく、上記の例だとEC2の中身はよくわかるんだけどCDNが何するのかよくわかってなかったら、この設計検討の時点でEC2の中に入っていってしまうんですね。

そんなもんよりもドメイン何にするー?とかTLSどこまでかけるー?とかCDNってほんまにいるかな?とか、そんなもんのほうがこのレイヤでは議論されるべきこと、ということです。

だから、この段階でEC2にApacheいれてー。いやいやnginxでしょ。とか言い始めたら抽象度あげてください、という話になっちゃうわけですね。これ、意外とちゃんと意識していないと人間簡単によりわかりやすい具体の話始めてしまいます。

例えば私だって、上記の内容書きつつLoadBalancerのとこで「スティッキー要る?」とか書きかけましたが、これ実はレイヤ一つ下です。もっとも、この抽象レイヤに影響強そうな個所なので、このレイヤで議論してもいいかな、とは思いますが、厳密なことを言えば下層の具体レイヤにあたります。

で、世の中のクライアントの要求やサービサーのサービス内容ってこの超抽象レイヤで語られるんですよ。

例えばほら。「弊社ソフトウェアによって不正なアクセスをブロック!」とか「うちのサイトを置くなんかいい感じのサーバ作って。セキュリティばっちりのやつ」とか。

ほーら具体なんか一ミリもないですよね。で、これをもとにサービス選ぶって普通に難易度高い。通常はもっと具体レイヤに下りていって、「実際にできること・できないこと」「使用にあたってかかる制約」「実際の画面の操作感」とかを見るんですね。

なので、アプリもそうですけどインフラ屋も基本的にはこの超抽象レイヤをゆっくり下層レイヤに落とし込んでいく、という行為をします。

これが「具体化」という言葉の実態、ということですね。

書いてみればすごく当たり前のことばかりなんですが、ごくまれに時折、なんかきょとん、とした顔されるんですよねー…不思議。