こんにちは。クラウドエース編集部です。

Kubernetesという名前は聞いたことあるけど、実際何のために使うのか、何がすごいのかを知らないという人は多いのではないでしょうか。本記事では、Kubernetesがどのようなサービスなのか、Google Cloud 上で Kubernetesを使うと何がすごいのかについて解説していきます。
Kubernetes未経験の方にもわかりやすく解説するので、最後まで読んでみてください!

Kubernetesとは

https://kubernetes.io/ja/docs/concepts/overview/what-is-kubernetes/

Kubernetesは複数のコンテナを簡単にデプロイ・管理できるサービスです。そもそもKubertenesという名前はギリシャ語で「操舵手」を意味します。コンテナ船を操縦・管理する人のようなイメージですね。

実際にコンテナ上にアプリケーションを構築する際は、複数のコンテナを組み合わせて一つのサービスを構築します。コンテナのデファクトスタンダードはDockerだと言われており、Dockerだけの機能では複数のコンテナを組み合わせて管理することはとても大変です。

複数のコンテナの管理で必要な観点には以下のようなものが挙げられます。

  • コンテナのスケジューリング
  • ホストの管理
  • ロードバランシング
  • オートスケーリング
  • コンテナ間のネットワーク制御など

Kubernetesを使用すれば、これらのことが簡単に管理できるようになるわけですね。

コンテナとは

https://docs.docker.com/get-started/overview/

ここまでの説明で、「コンテナ」という単語を当たり前のように使ってきましたが、コンテナについて知らない人もいると思うので簡単に解説します。

コンテナとは、ホストOS上に独立した領域を確保し、その中でアプリケーションを動作させる仮想化技術です。簡単に言い換えると、一台の物理サーバーの中に軽量な別のサーバーを立ち上げるようなイメージです。このような技術は仮想化技術と呼ばれ、ハイパーバイザーなども仮想化技術として有名です。ただハイパーバイザーはカーネル自体も仮想化するのに比べて、コンテナはホストのカーネルを使用するので、ハイパーバイザーより軽量に動作します。

ここでコンテナができる前にどのような問題があったのかを紹介します。コンテナができる前は、複数のアプリケーションを動作させようとすると、以下のような問題が起こっていました。

  • 依存関係(ライブラリ、ミドルウェアなど)が衝突して、動作しなくなる
  • 1つのアプリケーションがリソースを消費しすぎることで他のアプリケーションのリソースが足りなくなる。
  • デプロイに時間がかかる
  • 動作する環境ごとで、設定や構成を変える必要がある

こういった問題を解決するためにコンテナが使用されるようになりました。コンテナ上でアプリケーションを動作させると、以下のように問題が解決します。

  • 依存関係(ライブラリや設定ファイルなど)をコンテナの中に集約できる
  • CPUやメモリなどのリソースをコンテナ単位で管理することができる
  • 高速にデプロイできる
  • どんな環境でも同じように動作させることができる

マイクロサービスやアジャイル開発といったデプロイを小さく分けて、細かくデプロイを積み重ねる運用が重視されてきている今、コンテナは必須の技術と言っても過言ではないかもしれませんね。

ここまでの内容をまとめると、コンテナはアプリケーションを独立した環境で、軽量に動作させるための仮想化技術のことで、Kubernetesは複数のコンテナの管理を自動化・簡略化してくれるツールのことでした。

ここまでの説明で、コンテナとKubernetesについてなんとなく理解できたと思うので、ここからはKubernetesは何がすごいのかについてもう少し細かく紹介します!

※ ここから Podという単語が出てきます。Kubernetesの世界では、コンテナはPodという単位で扱われます。Podは一つ以上のコンテナをグループ化したものです。細かい説明は省略しますので、Podに馴染みのない方はKubernetesの世界のコンテナなんだなと思って、読んでいただけると幸いです。

Kubernetesのすごいところ1

Kubernetesの基本コンセプトとして、「リソースの管理はDeclarativeにできる」というものがあります。Declarativeというのは「宣言的に」という意味で、対義語は「Imperative(命令的に)」です。

よく宣言的と命令的の説明として以下のように言われます。

宣言的:「何が欲しいのか」といった目的だけを記述する
命令的:「どのようにしたいのか」といった目的のものを作るための手順を記述する

Kubernetesの世界での宣言的・命令的というのはどのようなものでしょうか。
命令的にリソースを管理するというのは、希望するリソースの状態まで手順に従って構築していく手法です。例えば、nginxイメージで動作し、`app: nginx`といったラベルを付与したPodを構築したいとします。命令的であれば以下のような手順でPodを構築します。

  1. Podをnginxイメージで作成する
  2. Podにapp: nginxと言ったラベルをつける

この作業で以下のようなPodが出来上がります。Kubernetesの世界ではラベルをつけることで、Podをグループ化します。

これに対して、宣言的にリソースを管理するというのは、設定ファイルに全ての希望する設定を書いて、その設定ファイルを適用する(APIサーバーに送信する)だけで、Podが作成できるというものです。まさに「何が欲しいのか」を書くだけですね。

例えば、上の例と同じ構成のPodを作成しようと思ったら、このような設定ファイルを書きます。設定ファイルが完成したら、kubectl apply コマンドを叩くだけです。

apiVersion: v1
kind: Pod
metadata: 
  name: sample-pod
  labels: 
    server: nginx
container: 
  name: nginx
  image: nginx

この設定ファイルに対してkubectl applyコマンドを叩くことで、もちろんですが以下のようなPodが出来上がります。

このように、どんなに複雑なPodを作成したい場合でも、その全てを設定ファイルの中に書くだけで実現できるのが宣言的なリソース管理です。命令的な管理であれば、複雑なPodを作成しようと思ったら手順がどんどん増えていきますよね。宣言的なリソース管理はとても便利なので、ぜひ体験していただきたいです。

Kubernetesのすごいところ2

Kubernetesにはすごい機能がたくさんあるのですが、その中でも代表的なものをいくつか紹介したいと思います。

オートスケーリング

Kubernetes上で運用していれば、急激なトラフィックの増加にも対応できます。水平Podオートスケーリングを使用すると、対象のPodのCPU使用率やメモリ使用率に基づいて、Podの数を増減させることができます。また、垂直Podオートスケーリングを使用すると、コンテナに割り当てられるCPUとメモリの量を自動的に増減させることができます。

さまざまなデプロイ戦略

Kubernetesを使用すると、さまざまなデプロイ戦略を取ることができます。例えば、Blue/Greenデプロイメントです。Blue/Greenデプロイメントは、既存のバージョンを残したまま、新しいバージョンを別のPodとしてデプロイし、ロードバランサを使用して一気にトラフィックを切り替える方法です。問題が発生した場合は即座に以前のバージョンに切り替えることができます。

またローリングアップデートも可能です。ローリングアップデートは、サービスを動かしているPodを少しずつ順番にアップデートしていくことでダウンタイムが発生しないように、新しいバージョンのサービスをデプロイする方法です。下の図は、appをv1からv2に移行している図です。Podが一つずつアップデートされています。これによりダウンタイムが発生せずにアップデートできます。ローリングアップデート中はトラフィックはv1とv2のどちらかに振り分けられることになります。

最後にカナリアリリースについても説明しようと思います。カナリアリリースは一部のトラフィックを新しいバージョンにルーティングし、大部分を既存のバージョンにルーティングすることで、少数のユーザーのみが新しいバージョンを使用できるようにする手法です。一部のユーザーで新しいバージョンをテストし、問題がないことが確認できたら全体に向けて、展開する戦略が取れます。

下の図のように新しいバージョンには、トラフィックを20%しか流さないように設定しておくことで、全体のユーザーの20%に向けてv2をテストすることができます。

オートヒーリング

オートヒーリングとは、Podが正常に動作しなくなった時にそのPodを削除し、新しいPodを自動で作成してくれる機能です。Kubernetesでは、Podをグループ化し、指定した数のPodが正常に動作するように保ってくれる機能があります。また、正常にPodが動作しているという判断基準もReadinessProbe、LivenessProbeという機能で設定することもできます。またNodeで障害が起きたことを検知すると、そのNode以外にPodが配置されるように再作成してくれます。

Podのスケジューリング

最後にPodのスケジューリングの機能について解説します。「Podをスケジュールする」とは、コントロールプレーンがNodeにPodを自動的に配置することを指します。スケジュールを詳細に設定することで、どのNodeにどのPodを配置させるかを設定することができます。

Kubernetesでは、Node Affinityという機能を使用して、どのNodeでPodを作成するかを設定することができます。またPod AffinityとPod Anti-Affinityという機能を使うと、「このPodが存在するNodeにPodを配置したい」や「このPodが存在するNodeにはPodを配置したくない」といった設定もできます。

Kubernetesのすごいところ3

 Kubernetesの魅力の一つとして、機能をリッチにするためのOSSが盛んに開発されていることが挙げられます。便利なOSSとして4つほど紹介したいと思います。

Istio(サービスメッシュ)

https://istio.io/latest/about/service-mesh/

Istioはサービス同士の通信を柔軟に制御するためのコンポーネントです。今流行りのマイクロサービスでは、複数のサービスが連携することになり、Kubernetesだけでは管理が難しい部分が出来てしまいます。サービス間の連携時に起きる問題を解決してくれるのがサービスメッシュであるlstioです。Istioを使用すると全てのPodにプロキシが介入するようになり、Podに出入りする通信は全てこのプロキシを経由するようになります。このプロキシにより、各指標の収集やサービスディスカバリ、サービス同士のセキュアな通信などが実現できます。

例えばサービスディスカバリに関しては、Kubernetes自体はカナリアリリースをネイティブにサポートしていません。よって、複数のリソースを調整してカナリアリリースを実現する必要があります。ですがIstioを使用すると一つの設定ファイルを書くことで、簡単にどのサービスに何%のトラフィックを流すかを指定できます。

また、KubernetesはPod間の通信を暗号化しないのですが、Istioは複数のPod同士が通信するときの暗号化や認証なども担当します。それにより、柔軟にサービス間のアクセス制御が行えたり、サービス同士の通信がセキュアに行えたりします。

Helm(パッケージマネージャー)

https://helm.sh/ja/docs/

HelmはKubernetesのためのパッケージ管理ツールで、アプリケーションや使用するツールを実行するためのリソース定義が全て含まれたものです。HomebrewやAptをイメージしてください。Kubernetes上でアプリケーションを構築するときに一から構築するのは、複雑でかなりの時間を要する場合があります。そのような場合はHelmで雛形のリソース定義セットをインストールし、変更したい部分だけを変更してデプロイすることで大幅に作業を短縮できます。
※HelmではDockerイメージ自体をカスタマイズできるわけではないので注意してください。

また、Helm上にチャートと呼ばれるパッケージを作成してパッケージ化することができます。これを使用して環境ごとの差異をHelmで管理することができます。チャートは、yamlファイルにGo言語のテンプレートライブラリのようなものを埋め込む形で記述します。興味がある方はドキュメントをご覧ください。

Algo CD(CI/CD)

https://argoproj.github.io/argo-cd/

ArgoCDは、Kubernetes用のGitOpsツールです。ArgoCDを使用することで、Github上の通常のyamlファイル、Helm、Kustomizeなどのファイルの変更を検知して、Kubernetes上のアプリケーションに自動デプロイさせることができます。GitOpsでは推奨されませんが、ローカルからファイルをアップロードさせて、デプロイさせることもできます。Githubとの統合では、ブランチやタグの追跡、特定のコミットに固定するなどがサポートされています。

Syncに関する設定を柔軟に行えるのもArgoCDの特徴で、例えばGitからリソースを定義しているファイルがなくなったとしてもArgoCDはそれを自動で削除しないように構成できます。これにより、操作ミスによるリソースの自動削除を防ぐことができます。また、Githubを経由せずにクラスタ自体に変更が適用された時に、Gitの状態にクラスタを適用させるかどうかなどの設定もあります。

またArgoCDの構成は、UIで管理することができます。UI上からCI環境を構築することができ、カスタマイズやアプリケーションの状態を確認することもできます。

Prometheus(監視ツール)

https://prometheus.io/

Prometheusはメトリクスを収集するツールです。Kubernetes単体では、各PodのCPU使用率やリクエスト数などのメトリクスを管理することは困難です。Prometheusを使用すると、UIベースでメトリクスを一括管理でき、クエリを実行し、結果をグラフ化できます。PrometheusはHelmからインストールして、設定をカスタマイズした上でデプロイできるので非常に簡単に環境を構築することができます。

例えば、次のクエリを実行してみます。

Process_resident_memory_bytes

すると、以下のようなグラフが作成されます。

このように、PrometheusのUIからクエリを書くことで様々なリソースのメトリクスを収集できます。また、アラート機能も実現することができます。このアラート機能は多機能で、グルーピングやミュート機能、高可用性クラスタに対応させる機能などがあります。

例えばグルーピングの機能は似たような種類のアラートを一つの通知にグルーピングして通知します。この機能を使用することで、同じようなアラートは一つにまとめられ、どのサービスがそのアラートを受け取ったのかを確認することができます。

もう一つ、ミュート機能も紹介します。ミュート機能では特定の時間帯は通知を送らないような設定にしたり、特定の通知が送信された後は特定の通知が送信されないように設定したりする機能があります。

Prometheusはメトリクス収集ツールなため、ログ収集の機能はありませんが、メトリクス収集に関してはかなり優秀なツールなので、ぜひお試しください。

Google Cloud で、Kubernetesを使おう

Google Cloud には、Google Kubernetes Engine(以降、GKE)と呼ばれるKubernetesクラスタのマネージドサービスが用意されています。 GKE を使用するとクラスタの管理をしなくて良いことはもちろんのこと、クラスタをセキュアにすることや簡単に Google Cloud のサービスとKubernetesを連携させることができるので、ご紹介したいと思います。

セキュアなクラスタを簡単に構築できる

GKE を使用すると、セキュアなクラスタを1つのコマンドの実行だけで作成することができます。具体的には、各Worker Node(Podが動作するVM)にパブリックIPアドレスを持たせない構成で構築できます。また、Control Plane(Worker Nodeを管理するVM)には、パブリックIPアドレスを持たせない、もしくはパブリックIPアドレスを持たせるが、承認されたネットワークからしかアクセスできないような構成で構築することができます。

また、GKE で使用するノードを保護するためのGKE Sandboxという機能も用意されています。GKE Sandboxを使用すると、コンテナで動作するアプリケーションはホストカーネルへのアクセスを通常よりも制限されます。これにより、コンテナの内部で悪意のあるコードが実行されたとしても、ホストや他のコンテナへの影響を大幅に減少させることができます。

さらに、GKE で動作するNodeはデフォルトではContainer-Optimize OS(以降、COS)と呼ばれるOSで動作します。COSはコンテナを動かすVM用に最適化されたOSで、コンテナが動作する環境に不必要なパッケージはカットされています。これにより、OSへの攻撃範囲を最小限に抑えることができます。

参考

1) プライベートクラスタについて
https://cloud.google.com/kubernetes-engine/docs/concepts/private-cluster-concept?hl=ja

2) GKE Sandboxについて
https://cloud.google.com/kubernetes-engine/docs/concepts/sandbox-pods

3) COSのセキュリティについて
https://cloud.google.com/container-optimized-os/docs/concepts/security?hl=ja
 

Ingressをカスタムできる

Ingressは、Kubernetesの世界でのHTTP(S)ロードバランサのことです。Kubernetes上でアプリケーションを公開するときによく使われる機能になります。GKE ではこのIngressに様々な機能を追加することができます。

例えば、Cloud CDNの機能です。IngressにCloud CDNをカスタムすると、静的ファイルがGoogleの世界中のロケーションにキャッシュされるようになり、レスポンス速度が向上します。

また、Cloud Armorをカスタムすることで、アプリケーションにアクセスできるユーザーをIPベースやリクエストヘッダ、リージョンコードなどで制御したり、DDoS攻撃やXSSなどのWAFを構築することができます。

参考

1)  Ingressがサポートしている機能
 https://cloud.google.com/kubernetes-engine/docs/how-to/ingress-features#feature_comparison

GKE クラスタのメトリクスを監視する

Google Cloud にはモニタリングツールが用意されていて、デフォルトでメトリクスが収集されます。Kubernetes単体で使用しようとすると、サードパーティツールを使用して構築する必要があるので、デフォルトで利用できるのは優れているポイントです。

Cloud Monitoring は、メトリクス収集ツールです。Prometheusと同じようにメトリクスの一元管理やアラートの設定などが行えます。例えば、Podの Receive bytes という指標では、以下のようなグラフが作成できます。

個人的には、Prometheusより見やすいと思うのですが、いかがでしょうか。他にもストレージ使用率やCPU使用率などたくさんの指標が存在します。

また、Cloud Monitoring の指標を使用することで、アラート機能を作成することができます。トリガーの条件には、指標の閾値を設定する方法や指標の存在を確認させる方法があります。Cloud Monitoringのアラートポリシーはとても柔軟に設定できるので、興味がある方はドキュメントをご覧ください。

最後に、Cloud Monitering の拡張機能として、Prometheusを統合させる選択肢もあります。この機能はPrometheusで収集される指標をCloud Monitering上で表示させる機能です。Cloud Monitoring では多くの指標がサポートされていますが、Prometheusにしかない指標を監視したい時はこの機能を使用します。

1)Prometheusの指標を外部指標として使用する
https://cloud.google.com/stackdriver/docs/solutions/GKE /prometheus?hl=ja

Nodeをオートスケーリングできる

GKE を使用すると、Nodeをオートスケーリングできます。Podが増えてくるとNodeのリソースも枯渇していきますが、Podを作成できるNodeがなくなった時に新しいNodeを作成してくれる機能です。逆に Podの数に対してNodeが多すぎる場合には自動で削除します。Google Cloud のVM(Node)にかかる料金は従量課金なので、必要なNodeを必要な時だけ動作させることができ、最大限コストを節約することができます。

参考

1)Nodeのオートスケーリング
https://cloud.google.com/kubernetes-engine/docs/concepts/cluster-autoscaler?hl=ja

最後に

本記事では、Kubernetesとは何か、GKE ってなにが便利なのかについて解説しました。GKE を使用すると簡単に様々な機能をKubernetesにカスタマイズできるので、ぜひ一度お試しください。

これから初めてクラウド サービスの導入をご検討されている方はもちろん、「 Google Cloud を使っているがもっと有効に活用したい」という方など、ぜひクラウドエースにご相談ください。クラウドエースでは、Google Cloud を最大限活用していただくことができるように、さまざまなサポート サービスをご用意してお待ちしております。

合わせて読みたい