Kubernetes ConfigMapsを安全に使う方法
Kuria Macharia
2022年9月9日
0 分で読めますConfigMapsは、Kubernetesでキーと値のペアとしてデータを保存するAPIオブジェクトです。構成設定を含む辞書のようなものです。ConfigMapに保存する情報としては、ホスト名、公開認証情報、接続文字列、URLなどが挙げられます。
ConfigMapを使うと、アプリケーションのコードと構成を切り離せるため、アプリケーションに影響を与えずに構成を変更できます。たとえば、開発環境、テスト環境、本番環境ごとに異なる構成を設定できます。
ただし、ConfigMapsに保存されるデータは暗号化されないため、使用にはセキュリティ上の課題が伴う点に注意が必要です。そのため、ConfigMapsを使うのが適切なケースと、安全性が不十分なケースを理解しておく必要があります。
この記事では、ConfigMapsの仕組み、安全な使い方、そしてより安全なデータストレージを利用すべきケースについて解説します。
KubernetesにおけるConfigMaps
ConfigMapsの使い方を見る前に、その仕組みとKubernetesにおける役割について、技術的な詳細を確認しましょう。
ConfigMapsの仕組み
ConfigMapsは、キーと値のペアをプレーンデータまたはバイナリデータとして保存します。これは、specフィールドを使う他のKubernetesオブジェクトとは異なります。ConfigMapsは、バイナリデータをBase64エンコード文字列として、プレーンデータをUTF-8のバイト列として柔軟に保存できます。
クラスターからConfigMapsにアクセスする方法は次のとおりです。
データボリュームとしてマウントする。
同じKubernetes名前空間内のPodからリモートでアクセスする。
Podから分離し、他のKubernetesクラスターコンポーネントが使用できるようにする。
PodはConfigMapsを構成ファイル、環境変数、またはコマンドライン引数として使用できます。
ConfigMapsを扱う際は、サイズ上限が1 MBであることに注意が必要です。より大規模なデータセットには、データベース、個別のファイルマウント、ファイルサービスなど、別のストレージを検討しましょう。
ConfigMapsの役割
ConfigMapsの最も重要な役割は、アプリケーションコードと構成設定を分離し、アプリケーションのポータビリティを高めることです。この分離により、開発環境からテスト環境へ、さらに本番環境へと効率的に移行できます。
Kubernetesを使う際にConfigMapがどのように役立つか、例を見てみましょう。ここでは、アプリケーションをローカルで構築し、マネージドKubernetesサービスのプロバイダーを利用してデプロイするとします。
データベースにローカルからアクセスするには、環境変数DATABASE_HOSTをlocalhostまたは127.0.0.1に設定します。本番環境に移行する際は、この変数の値をデータベースコンポーネントに接続できる値に変更する必要があります。
ConfigMapsを安全に使う
始める前に、ローカルのKubernetesクラスターでConfigMapを作成するための前提条件を確認しましょう。
最新バージョンのDocker Desktop
VS Codeなどのコードエディター。
このデモでは、YAMLでConfigMapを作成し、ボリュームとしてマウントする方法を紹介します。この方法なら、Kubernetesリソースを作成するのと同じ手順でConfigMapを作成できます。
mongo-config.yamlという名前のファイルを作成し、次のコードを追加します。
次に、以下のコマンドを使って、上記のファイルからConfigMapを作成します。
では、ConfigMapの利用方法を見てみましょう。このデモでは、上記で作成したConfigMapを環境変数として使います。ConfigMapを利用するには、以下のコードのようにPodのYAMLにenvFromプロパティを追加します。
上記のコードスニペットでは、envFromを使ってコンテナからConfigMapの情報にアクセスしています。
最後に、以下のコマンドを実行して作成するPodにConfigMapを関連付けます。
これにより、ConfigMapを環境変数としてコンテナから利用できるようになります。
KubernetesのSecrets
Secretsは、ConfigMapsといくつかの共通点があるため、安全な代替手段として紹介されることがよくあります。
データの保存にキーと値のペアを使う。
どちらも、Podからボリューム内のファイルとして利用できる。
環境変数として利用できる(ただし、これは推奨されません)。
APIサーバー経由でアクセスするオブジェクト型である。
どちらもサイズ上限が1 MBのため、大規模なデータには適さない。
Secretsは、Kubernetesで機密データを暗号化して保存するためのオブジェクトです。Secretsに保存すべきデータには、パスワード、APIキー、トークン、データベース接続文字列などがあります。これにより、機密データをアプリケーションコードから分離できます。この分離によって、クラスターやアプリケーションを危険にさらす機密データの漏えいリスクを軽減できます。Secretsを環境変数に使うべきではありません。Liz RiceとMichael Hausenblasbokkは著書Kubernetes Securityで、次のように述べています。
クラッシュやエラーの際、環境変数がログに出力されることがよくある
kubectl describe podを実行すると、環境変数の値がプレーンテキストで表示される
docker inspectを実行すると、環境変数の値がプレーンテキストで表示される
非公開にしたいデータの種類に応じて、複数の種類のSecretsから選択できます。最もよく使われるのはOpaqueで、任意のユーザー定義データを扱います。基本認証にはbasic-authタイプを使います。
デフォルトでは、Secretsは暗号化されず、APIサーバーのストレージであるetcdに保存されます。APIにアクセスできる人は誰でも、Secretsにアクセスして変更できます。アクセスを制限するには、次の対策が必要です。
保存データの暗号化を有効にする(多くの、あるいはすべてのマネージドKubernetesプロバイダーでは、クラスター作成時にオプションとして設定できます)。
RBACルールを有効にして設定し、読み取りと編集を制限する。
RBACを使ってSecretsの作成者を制限する。
ConfigMapsとSecretsの違い
ConfigMapsとSecretsには共通点がありますが、同じものではありません。どちらも、セキュリティ要件に応じた特定の用途に適しています。
ConfigMapsとSecretsの主な違いは、保存するデータの機密性です。SecretsはデータをBase64エンコードで難読化しますが、ConfigMapsのデータはプレーンテキストです。ただし、ConfigMapsにもプレーンテキストをBase64エンコード文字列として保存できます。
もう1つの違いは、Kubernetesには複数種類のSecretsがあることです。隠したい機密データに応じて、使用するSecretの種類を選択できます。
ConfigMapsを使う場合
ConfigMapsは、アプリケーションデータと構成コードを切り離すのに非常に効果的です。たとえば、従業員データを扱うアプリケーションコンテナがあり、MySQLデータベースに接続するとします。データベース接続の構成をコンテナにハードコードすると、開発環境から本番環境に移行する際に混乱が生じます。本番環境では開発用データベースを使えないためです。
configMapを使えば、コンテナの外部にある個別のファイルに構成データを保存して、アプリケーションを簡単に移行できます。環境を変更する際に必要なのは、データベース参照を簡単に変更することだけです。
kubectl describe configmaps <name>を実行すると、ConfigMapsに含まれるデータを簡単に表示できます。また、データはプレーンテキストで表示されるため、簡単に編集できます。こうした機能は、環境(開発、テスト、本番)に応じて構成を変更するには便利ですが、機密データの取り扱いには適していません。機密データはKubernetes Secretsに保存し、暗号化してアクセスを制限する必要があります。
Secretsを使う場合
ConfigMapsと同様に、Secretsもデータをアプリケーションコードから切り離します。これにより、Podの作成や変更時に機密データが漏えいするのを防げます。
ここで、従業員データの例に戻りましょう。この場合、アプリケーションがデータベースに正常に接続するには、サーバーホスト、ポート、データベース名、ユーザー名、パスワードが必要です。
2つのコードスニペットを比べてみましょう。1つ目はConfigMapでデータを扱う方法、2つ目はSecretでデータを扱う方法を示しています。
ConfigMapは次のようになります。
上記のconfigMap YAMLファイルには、サーバーホスト、サーバーポート、データベース名など、機密ではないデータベース接続情報が含まれています。
Secretsファイルは次のようになります。
上記のSecret YAMLファイルでは、基本認証情報を扱うSecretのタイプとしてbasic-authが指定されています。stringDataには、非公開にすべきデータが含まれています。この場合は、ユーザー名とパスワードです。
上記の例では、Secretsを使ってデータベースのユーザー名とパスワードを非公開にできました。また、Podの作成時や変更時にこれらの情報が漏えいするリスクもなくなります。
Kubernetesの構成セキュリティ
ConfigMapは、Kubernetesで機密性のない構成データをキーと値のペアで保存するAPIオブジェクトです。デフォルトではデータがプレーンテキストで保存され、アプリケーションコードと構成を分離できます。SecretsもKubernetesのAPIオブジェクトで、機密性の高い構成データをキーと値のペアで暗号化して保存します。これにより、クラスターやアプリケーションを危険にさらす機密データの漏えいリスクを軽減できます。
アプリケーションコードと構成を分離した安全なKubernetesクラスターを作るには、機密データをSecretsに、機密性のない構成をConfigMapsに保存しましょう。また、ConfigMapsとSecretsへのアクセスを制限するため、RBACを有効にすることも重要です。これにより、許可されていない構成へのアクセスや変更のリスクを軽減できます。
ソースコードの段階からインフラを保護
Snykはワークフロー内のIaCセキュリティとコンプライアンスを自動化し、構成ドリフトや不足しているリソースを検出します。
