KubeCon + CloudNativeCon China 2019 現地レポート 2日目

こんにちは、Necoプロジェクトのsatです。

本記事はKubeCon + CloudNativeCon China 2019(以下本イベントと記載)の最終日であるday2の参加レポートです。

day0とday1の記事はこちらです。

blog.cybozu.io

blog.cybozu.io

筆者はday2ではどちらかというとKubernetesそのものよりも、その土台となるソフトウェアを扱うセッションに参加することが多かったです。本記事では筆者が参加した2つのセッションで触れられたソフトウェアそのもの、および、それらがKubernetesにどのようにかかわっているかという観点で紹介します。

Secure Container with SGX: Protecting Secret in Cloud Environment - Isaku Yamahata, Intel & Xiaoning Li, Alibaba

これはアプリケーション*1のセキュリティ機能を高めるためのGraphene-SGX(以下本ソフト)というソフトウェア、およびそれをGo言語で作られたアプリケーションに適用できるように拡張した取り組みについての話でした。もともとは本節のタイトルにあるようにIsaku YamahataさんとLiさんの2人による発表の予定でしたが、Xiaoning Liさんが都合により参加できなくなったため、Yamahataさん一人による発表となりました。

まずは本ソフトのもとになったGrapheneというソフトの説明からはじまりました。本ソフトは一言でいうと、C言語で書かれた既存のソフトウェアを、リコンパイルすることなくセキュリティを向上させられるライブラリです。ソフトウェアはOSカーネルに処理を依頼するためのシステムコールを発行するときにCPUの特殊な命令を使います。C言語で書かれたソフトウェアにおいて、システムコールは通常libcと呼ばれるライブラリが持つシステムコールのラッパー関数を介して呼ばれます。本ソフトはこのラッパー関数を、システムコールを直接呼び出すだけではなくセキュリティをより高めるための処理を追加した関数で置き換えるというライブラリです。アプリケーションの実行時にリンクされるlibcをGrapheneで置き換えるため、アプリケーションの変更は不要、というわけです*2

続いてGprahine-SGXについての紹介がありました。Software Guard Extention(SGX)とは、簡単に説明するとアプリケーションを実行する基盤となるカーネルや仮想マシンに脆弱性があったとしてもアプリケーションのデータを盗み見られないようにするための、IntelのCPUに搭載されている機能です。SGXを使うには通常アプリケーションのソースコードを書き換える必要があるため、現在世の中に普及しているとはいいがたい状況でした。本イベントのday1においてもLinuxの主要開発者であるGreg KHさんが「SGXは誰も使っていない」と言ったことについてYamahataさんが本セッション中に嘆いていました。

この状況を打破するきっかけになりうるのがGraphene-SGXです。本ソフトはSGXを使えるようにGrapheneを拡張したものです。アプリケーションをGraphene-SGXを介して実行することによって、もともとGrapheneが持っている機能に加えてSGXによってもアプリケーションのセキュリティ機能を高められる、かつ、アプリケーションの実行ファイルを変更する必要もない、というわけです。

最後にYamahataさんによる本ソフトの機能拡張について紹介がありました。GrapheneおよびGraphene-SGXには一つ弱点があります。それはlibcを使わないアプリケーションには使えないということです。その代表的なものが現在DockerやKubernetesなどの有名どこを含めてたくさんのソフトウェアで使われているGo言語で書かれたプログラムです。この課題を解決するために彼はGo言語の実行ファイルを実行時に書き換えてGraphene-SGXの機能を呼び出すようにするという方法を使いました。C言語で書かれたプログラムとGo言語で書かれたプログラムは構造が大きくことなるために大変な苦労をされたようですが、ひとまず簡単なアプリケーションが動く状態にはこぎつけたようです。

Yamahataさんが拡張した機能は現在のところ本家Gprahine-SGXとは別のプロジェクトですが、現在本家へのマージを試みているところだそうです。あるOSSをforkして新しい機能を追加したら積極的に本家に還元するというOSSのエコシステムにおける非常によい流れだと思いました。

本ソフトがKubernetesとどのように関係するかというと、Pod内で動かすアプリケーションを本ソフトを介して実行することによって、アプリケーションの実行ファイルを変更せずに他のプログラムからのデータの盗み見を回避できるようになるということです。将来的にはKubenetesそのもの、およびKubernetes上で動作するアプリケーションにおいてよく使われる機能になるかもしれません。

余談ですが、筆者とYamahataさんはお互いにLinuxカーネルの開発に携わっていた頃から数えて10年来の知り合いです。お互いに連絡を取り合わずに現地で偶然再会したので非常に驚きました。現在何をしているかなどについて話に花を咲かせたのに加えて、day0の記事を書いたmitzさんとの新たなつながりができるなど、充実した時間を過ごしました。このように旧交をあたためたり新しいつながりができたりするのもこの手のイベントの魅力です。

New Cgroup Subsystem for Buffer Write io and Network RX Control in Kernel - Dongdong Chen, Tencent

これはLinuxカーネルのリソース制御機能であるcgroupsというカーネルの機能のうち、ストレージI/OおよびネットワークI/Oの帯域を制御する機能について紹介するセッションでした。

まずcgroupsについて簡単に説明しておきます。これはCPUやメモリ、ストレージI/O、ネットワークI/Oなどのリソースをプロセスやそのグループ(以下プロセス群と記載)ごとに利用制限をかけるためのカーネルの機能です。たとえばメモリのリソースを管理するmemory cgroupという機能は、プロセス群が使用できるメモリ量に制限をかけられます。たとえばユーザAとユーザBが同じ料金を払って使用しているシステムにおいて、ユーザAのアプリケーションがメモリをほとんど使っているためにユーザBのアプリケーションが起動できなくなる、といった事態がmemory cgroupによって避けられます。cgroupsはとくに仮想マシンやKubernetesなどのコンテナ実行環境において広く使われています。Kubernetesにおいては以下のようにcgroupsを活用してコンテナのリソース制御をしています。

Managing Compute Resources for Containers - Kubernetes

1つ目に紹介されたのはプロセス群ごとにストレージI/Oの帯域を制限する機能です。たとえばプロセス群Aは100MB/s、プロセス群Bは50MB/sにするといった使い方をします。この機能の主な目的は特定のプロセス群が大量のストレージI/Oを発行することによって他のプロセス群のI/Oがなかなか終わらないという事態を避けるためのものです。従来はこの機能は通常のページキャッシュ*3を使わないdirect I/Oと呼ばれる特殊なI/Oに対してしか効果がなく、使いづらいものでした。Chenさんが紹介したのはページキャッシュを使う通常のI/Oにおいてもこの帯域制御ができるという機能です。彼は実際に機能が動作している様子をグラフを使って説明するとともに、この機能がどのように実装されているかについて説明してくれました。実装についての説明が非常に興味深かったことに加えて、機能の有効性についてわかりやすく視覚的に理解できたので非常に有益でした。

2つ目に紹介されたのはプロセス群ごとにネットワークI/Oの帯域を制限する機能です。彼はネットワークのリソース制御のうち、受信量の制御について説明してくれました。これは特定のプロセス群のネットワークを介したデータ受信量を、たとえばプロセス群Aは100MB、プロセス群Bは50MB/sのように制限する機能です。この機能のおかげで特定プロセス群がネットワークI/Oの帯域を占有することによって他のプロセス群のネットワークI/Oが阻害されるのを防げます。こちらについても実装と動作例について図を使った紹介がありました。

普段Kubernetesを使っていてcgroupsを直接意識することは少ないとは思います。しかし、いざKubernetesのリソース制御機能にまつわるトラブルが発生したときにはcgroupsについての知識が無いと何が起こっているか見当がつかないために調査が非常に難航します。Kubernetesを使ったシステムをただ動かすのではなく長期間運用していくためにはcgroupsは知っておいて損はない機能です。

おわりに

最後に本イベントの全体としての感想を述べておきます。まず、今回はOpen Source Summitと共催になったことによって、アプリケーションからlinuxカーネルまでの幅広い知識を一気に得られる良いイベントになったのではないかと思います。というのも、KubeConではKubernetesそのものについての知識は得られるのですが、Kubernetesが内部的に使っているLinuxカーネルの機能についてはOpen Source Summitに参加するなどの方法で別途得なければいけなかったからです。Necoプロジェクトにおいてはソフトウェアスタックをカーネルの領域まで下りて調査することも珍しくないので、今回の共催は大いに助かりました。

続いて規模について。年に三回開催されるうち、本イベントは開催期間が一日短く、かつ、規模も半分程度です。これについては大きければよいというものではなくて、本イベントくらいの規模が適切だと思いました。なぜかというと最近参加したKubeCon North AmericaやKubeCon Europeは参加人数が一万人に近づいたりと盛り上がってはいるのですが、セッションが最高20並列で進んだり、部屋間の移動で大渋滞が起きたりと一か所で開催するのに無理があると筆者は考えています。

最後に会場の雰囲気について。わたしがこれまで参加してきた大規模な国際なイベントはすべて日本、北米、ないしヨーロッパで開催されていたものであり、そこではすべてのプレゼンおよびそれに使う資料は英語で統一されていました。しかし本イベントはそれとはまったく異なり、中国語で発表されるセッション、およびプレゼン資料が中国語というものがかなりありました。では中国語を介さないわたしのような人にはまったくわからないかというと、全セッションにおいて中→英、英→中の同時通訳があるためにある程度理解できるというようになっていました。「国際」といってもいろいろなやりかたがあるのだなと感心しました*4

来年も本イベントへの参加が叶えば、また読者のみなさまにこのような形で情報を共有できればと思います。ここまで読んでいただき、ありがとうございました。

*1:正確には任意のプログラムが対象ですが、ここではアプリケーションと記載します

*2:このようなソフトウェアに興味のあるかたは"Library OS"というキーワードで検索してみてください

*3:アプリケーションがデータを読み書きするときに毎回ストレージデバイスにI/Oを発行するのではなくデータをメモリ上にキャッシュすることによってアプリケーションから見たI/Oの高速化を図るカーネルの機能

*4:day0では中国語のスライドで中国語の発表をして同時通訳なしというセッションがいくつかあったのでほとんど何もわからずにかなりつらかったですが…