作成日: 2023-4-25
更新日: 2023-9-28
まずはkubernetesってどんなものかを説明します。
その後、kubernetesでのコンテナ生成がどんなものかを説明します。
最後にコンテナ技術で使われるLinuxの技術や関係性について言及します。
結構ロングな内容です。
コンテナ化されたアプリケーションをデプロイ、スケーリング等管理したりするためのシステムです
AWSならEKS、GCPならGKEでkubernetes環境を構築することができます。
オンプレミスやハイブリッドな環境でもkubernetesを運用することができます。
マニフェストと呼ばれるファイルを使って宣言的にkubernetesの環境を設定することができます。
kubernetesはデプロイするとクラスターが展開されます。
クラスターはコンテナアプリケーションを実行する環境を提供します。
クラスターでは、ワーカーノード(node)とコントロールプレーンが稼働しています。
ワーカノード(node)では、コンテナアプリケーションがpodと呼ばれる環境内で稼働しています。
コントロールプレーンでは、クラスターに関する全体的な決定やワーカーノード(node)、podの管理を行なっています。
ここからはコンテナが生成されるまでのコントロールプレーンとワーカノードの役割等をそれぞれのコンポーネントごとに解説します。
kubernetesはkubernetes APIを使って使って操作します。
kubernetes APIはHTTP APIとして公開されています。
kubectlと呼ばれるコマンドラインインターフェースで操作することが一般的ですが、RESTコールで操作することもできます。
管理者はkubectlコマンドを使ってマニフェストの適用、podの立ち上げ等を行います。
コントロールプレーンは以下のように挙動します。
マニフェストの宣言
kubectl applyコマンドを使ってクラスターにマニフェストを宣言します。
マニフェストはクラスター内の理想の状態を記載したファイルです。
kubernetesはマニフェスト通りの状態を常に維持してくれます。
kube-api-server
コマンドの受付や全体への指示ははコントロールプレーンのkube-api-serverで受け付けます。
コンテナ作成の過程では、nodeで稼働しているkube-letに対してpod作成の指示を出します。
etcd
マニフェストはetcd(エトセディー)に格納されます。
etcdでは、受け付けたマニフェストとクラスター内の状態に差異がないか確認してくれます。
差異があった場合、それを検知し、kube-api-serverに対して変更を指示します。
kube-sheduler
kube-shedulerでは、etcdでの変更検知をkube-api-server経由で検知しています。
kube-shedulerはpodをどのnodeで稼働させるか決めてくれます。
通常のwebサービスであれば、複数nodeが稼働しています。
kube-shedulerはそれぞれのnodeの負担が均一になるようpodの稼働先を決めてくれます。
kubelet
kubeletはnodeで動作するコンポーネントです。
コントロールプレーンから指示を受け取り、node上のpodを管理します。
kubeletはkube-api-server経由でetcdの変更を検知し、podの作成を指示されます。
その指示はkubeletからコンテナランタイムに伝達されます。
コンテナランタイム
コンテナランタイムは高レベルランタイムであるCRIランタイムと低レベルランタイムであるOCIランタイムで構成されています。
CRIランタイム
CRIランタイムは
を行います。
OCIランタイム
OCIランタイムは、ホストと隔離された実行環境をコンテナとして作成する役割があります。
前置きが長くなりましたが、kubernetesの環境で最終的にコンテナのを作っているのは、OCIランタイムであることが分かりました。
ここからはOCIランタイムがどのようにコンテナを作っているかを解説します。
OCIランタイムが作り出すコンテナは、Linuxのnamespaceとcgroupの機能を使っています。
Linuxのnamespace機能は、namespaceで区切ったプロセスのみ操作できるリソースを持っているように見せる機能です。
namespaceにはいくつかの機能があり、それらをの機能を組み合わせてコンテナを作り出しています。
PID namespace
コンテナは独立した一つの実行環境として作成されるので、コンテナ内ではホストOSとは違うプロセスが動いているように見せる必要があります。
コンテナ内のプロセスとホストOSのプロセスを隔離する機能をPID namespaceが担っています。
Mount namespace
マウントとはディレクトリ構造を追加することです。
コンテナにマウントした部分は、ホストOSからは隔離されており、ホストOSからコンテナ内のマウントした部分を確認することはできない。
Network namespace
Network namespaceは、利用可能なネットワークをホストから隔離することができます。
CRIランタイムのCNIプラグインは、Network namespaceで区切られたプロセスに対して、仮想的なNICを付与しています。
これによりコンテナ間での通信を可能にしています。
cgroupはプロセスが利用できるリソースに制限を設定することができます。
ちょっとnamespaceとごっちゃになるかもしれないので、namespaceの機能を振り返っておきます。
namespaceは、namespaceで区切ったプロセスのみ操作できるリソースを持っているように見せる機能です。
コンテナはあくまでホストOS上で動くプロセスに過ぎないです。
なのでcgroupの機能を使って、コンテナから使用できるCPUの制限、メモリ使用量の制限を行なっています。
kubernetesでコンテナがどう作られてきたかを解説してきました。
コンテナランタイムがLinuxの機能を使ってコンテナを作っていることは理解できたかと思います。
kubernetesではLinuxの理解が必要だと言われています。
個人的な結論としては、原因の切り分けができるようにだと思っています。
kubernetesはプラガブルな構成が可能なので、コンテナランタイムをその他のランタイムに交換することもできます。
なのでもっと突っ込んだ結論としては、
かなと思います。
Kubernetesを理解する上でのLinuxへの理解はあくまで全体のうちの一部でしかないのかなと思いました。