Kubernetes基礎 #2 - Kubeコントロール

Last Edited: 3/15/2025

このブログ記事では、Kubernetesにおけるkubectlの基礎を紹介します。

DevOps

前回の記事では、Kubernetesを始めるために必要な基本的なコンポーネントとリソースについて理解しました。 この記事では、リソースについてさらに深く掘り下げ、それらの設定方法とkubectlを使用してクラスターを制御する方法を示します。

Minikube

kubectlの使用を始める前に、実験環境をセットアップする必要があります。これはminikubeを利用することで簡単に行えます。 Minikubeは、開発者が本番規模のクラウド環境を使用せずに、Kubernetesを簡単に実験できるように、複数のオペレーティングシステム上にローカルKubernetesクラスターを実装します。 Minikubeは、こちらにリンクされている公式ドキュメントの指示に従ってインストールできます。

kubectlもminikubeのインストール中に依存関係としてインストールされるはずです。minikube start --driver=dockerを使用してDockerでminikubeをクラスターで実行できます。 これにより、kubectlが自動的にminikubeを使用するように設定されます。クラスターはマスターとワーカーの両方として機能する1つのノードのみで構成されています。 本番環境では、通常、複数のマスターノードと別々のワーカーノードをセットアップしますが、kubectlの使用方法を学ぶ上ではクラスターのセットアップは関係ありません。 minikube statusでセットアップが完了したことを確認でき、実験後はminikube delete -allですべてを削除できます。

デプロイメントの設定

前回の記事で説明したように、Kubernetesクラスターを設定するには、リソース、デプロイメント、サービス、コンフィグマップ、シークレット(オプションでイングレス)をセットアップする必要があります。 まず、以下のようなYAMLファイルを使用して、ポッドの設計図としてデプロイメントをセットアップできます。

frontend.yaml
apiVersion: apps/v1
kind: Deployment
# デプロイメントのメタデータ
metadata:
  name: frontend-deployment
  labels:
    app: frontend
# デプロイメントのスペック
spec:
  replicas: 3 # ポットの数
  # ラベルを使用してデプロイメントに属するポッドを特定
  selector:
    matchLabels:
      app: frontend
  # ポットのテンプレート
  template:
    metadata:
      labels: # matchLabelsはこのラベルを参照
        app: frontend
    spec:
      containers:
        - name: frontend
          image: frontend-image # Dockerにインストールされたイメージ
          ports:
            - containerPort: 3000

templateフィールドには各ポッドの設計図が含まれており、メタデータとコンテナ(それぞれに名前、イメージ、コンテナポートがある)を割り当てます。 templateの下のメタデータ内のlabelsは、同じコンテナを実行する異なる名前のポッドを識別するために使用できるキーと値のペアです。selectorフィールドを使用すると、 Kubernetesはラベルを使用してどのポッドがデプロイメントに属しているかを知ることができるため、指定された数のレプリカが実行されているかどうかなどを監視できます。

トップレベルのmetadataの下のlabelフィールドはオプションですが、通常ラベルを含めます。また、多くの場合app:<名前>ラベルを使用しますが、 任意のキーと値のペアに設定することもできます。デプロイメントの設定をクラスターに適用するには、kubectl apply -f frontend.yamlを使用できます。 このコマンドを見てみると、コマンドにはdeploymentが含まれておらず、代わりにYAMLファイルではkindに異なる値を使用していることに気づくことができます。 これは、kubectlがどのリソースにもkubectl applyを使用して、kindに異なる値を含むファイルにを適用するためです。

サービスの設定

次に、上記のデプロイメントのためのサービスを設定できます。サービスのファイルはデプロイメントのファイルと同じ構造を持ち、metadataspecを含みます。 以下はサービスを構成するためのYAMLファイルの例です。

frontend.yaml
# ... デプロイメントの設定
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: ClusterIP # (ClusterIP = 内部サービス, NodePort = 外部サービス)
  selector:
    app: frontend # ネットワークをこのラベルを持つポッドに送る
  ports:
    - name: frontend-port
      protocol: TCP
      port: 3000 # サービスのポート
      targetPort: 3000 # デプロイメントのコンテナのポート
      #nodePort: 30000 
      # (type=NodePortの場合、ノードのIP:ノードのポートからサービスにアクセス可能)
      # (ノードポートは30000~32767の範囲でなければならない)

上記はデプロイメントの内部サービスを設定します。通常、各デプロイメントにサービスを設定するため、対応するデプロイメントと同じファイルにサービス構成を---を使用して含め、一緒に適用することができます。 テスト用にサービスタイプを外部に設定することもできますが、通常はすべてのサービスを内部として設定し、イングレスコントローラーへのアクセスを制限するか、 ロードバランサーサービス(次の記事で説明します)を使用します。

コンフィグマップとシークレットの設定

環境変数を管理しやすくし、環境変数の小さな変更後にクラスター全体を再構築する必要をなくすために、 以下のようなYAMLファイルで簡単に設定できるconfig mapsとsecretsを利用できます。

## frontend-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: frontend-config
data:
  backend-url: backend-service # backend.yamlに設定されている場合
 
## frontend-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: frontend-secret
type: Opaque # ユーザーが自由にキーバリューを設定できるタイプ
data: # base64エンコードされた文字列 (事前に暗号化済み)
  user: ZGF0YWJhc2V1c2Vy
  password: ZGF0YWJhc2VwYXNzd29yZA==

secretsには組み込みの暗号化メカニズムがなく、データは事前に暗号化する必要があることに注意が必要です。 また、dataフィールドは値にbase64エンコードされた文字列を想定していますが、代わりにstringDataフィールドを使用することで純粋な文字列を保存するように変更できます。 config mapでサービスの名前を参照すると、サービスの有効なIPに変換されるため、他のサービスやデプロイメントの再構築プロセスを引き起こすことなく、 サービスのネットワーク構成を変更できます。以下は、ポッド内のコンテナがこれらの環境変数を使用する方法を示しています。

frontend.yaml
# ...
  template:
    # ...
    spec:
      # ...
      containers:
        - name: frontend
          image: frontend-image
          ports:
            - containerPorts: 3000
          env:
            - name: BACKEND_URL
              valueFrom:
                configMapKeyRef:
                  name: frontend-config # config mapの名前
                  key: backend-url # 値を参照するキー
            - name: PASSWORD
              valueFrom:
                secretKeyRef:
                  name: frontend-secret
                  key: password  

config mapsとsecretsに保存されている環境変数を参照する唯一の違いはフィールド名(configMapKeyRefsecretKeyRef)です。 デプロイメントはconfig mapsとsecretsの環境変数に依存する可能性があるため、デプロイメントとサービスを適用する前にconfig mapsとsecretsを適用するのが一般的です。

クラスターの監視

kubectlを使用すると、YAMLファイルで定義された構成を適用するだけでなく、クラスター内のコンポーネントとリソースのステータスを監視することもできます。 すべてを見るにはkubectl get allを使用でき、特定のコンポーネントやリソースをkubectl get <resource>で確認できます。 より詳細な情報を得るにはkubectl get <resource> -o wideを使用できます。

また、kubectl logs <pod-name>を使用して個々のポッドからログを表示でき、-fフラグを追加してログをストリーミングすることもできます。 kubectl describe <resource> <resource-name>でリソースの詳細を確認することもできます。 ファイルに基づいてリソースのレプリカ数をkubectl scale --replicas=3 -f frontend.yamlで変更したり、 名前に基づいてkubectl scale --replicas=3 deployment/frontendのようなコマンドで変更したりすることもできます。 これらのコマンドには多くのオプションとフラグがあるため、詳細については本記事の最後に引用されている公式ドキュメントを確認することをお勧めします。

結論

この記事では、minikubeがローカルクラスターをどのように設定できるか、YAMLファイルでリソースをどのように構成できるか、 kubectlを使用してどのように構成をクラスターに適用できるかを紹介しました。これらのコマンドを試して、kubectlの使用に関する実践的な経験を得ることをお勧めします。 外部サービスを作成し、ノードIPとポートを取得し、ブラウザからアクセスすることでクラスターを正しく設定できるかをテストできます。 次の記事では、本番環境に近い環境でクラスターのエントリーポイントを設定する方法について説明します。

リソース