Kubernetesにおけるポッドとサービスの究極ガイド

Kubernetesは強力なコンテナオーケストレーションプラットフォームですが、その全ての機能を活用するためには、ポッドとサービスが基盤となる役割を果たしていることを理解することが重要です。この記事では、それらが何であり、どのように連携してKubernetesクラスター内で実行されているアプリケーションへのアクセスを公開および管理するかについて詳しく見ていきます。

ポッドとは何ですか?

ポッドは、Kubernetesで作成および管理できる最小のデプロイ可能なコンピューティングユニットです。

ポッドを作成する前に、Kubernetesクラスターで利用可能なAPIリソースを確認しましょう。これには、kubectl api-resourcesコマンドを使用できます。このコマンドは、Kubernetes APIサーバーでサポートされているAPIリソースをリストアップし、それらの短い名前、APIグループ、および名前空間の有無を含めます。これは、カスタムリソースを使用したり新しいKubernetesの機能を探求する際に、クラスターの機能を理解するのに役立ちます。kubectl explainコマンドは、個々のリソースに関する詳細情報を提供することでこれを補完します。

簡単なNginxコンテナを実行するポッドの基本的なポッド構成ファイルを作成してみましょう。

nginx-pod.yamlという名前のファイルを作成してください。

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

使用されている用語の簡単な説明は以下の通りです:

  • apiVersion: v1:APIバージョンを指定します。
  • kind: Pod:この構成がポッド用であることを示します。
  • metadata:name:ポッドの名前。
  • メタデータ: ラベル: ポッドを整理し選択するために使用できるキーと値のペア。
  • 仕様:コンテナ: ポッド内で実行されるコンテナのリスト。
  • 仕様:コンテナ:名前: コンテナの名前。
  • 仕様:コンテナ:イメージ: 使用するコンテナイメージ(この場合、最新のNginxイメージ)。
  • 仕様:コンテナ:ポート: コンテナから公開するポート。

設定ファイルを適用してポッドを作成するには、kubectlを使用します:

  • kubectl apply -f nginx-pod.yaml

ポッドのステータスを確認して、作成されて実行されていることを確認してください:

  • kubectl get pods

次のような出力が表示されるはずです:

Shell

 

NAME         READY   STATUS    RESTARTS    AGE
nginx-pod    1/1     Running   0           10s

次に、ポッドを削除します:

  • kubectl delete pod nginx-pod

出力は次のようになります:

Shell

 

kubectl get pod
No resources found in default namespace.

サービスとは何ですか?

Kubernetes内のNginxポッドのためのサービスを作成することで、Nginxアプリケーションを公開し、クラスター内外からアクセスできるようにします。以下は、Nginxポッドのためのサービスを作成する手順です。

Nginxポッドが実行されていることを確認するために、まだ持っていない場合は、nginx-pod.yamlという名前のYAMLファイルを作成します:

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

ポッドの設定を適用します:

  • kubectl apply -f nginx-pod.yaml

`nginx-service.yaml` という名前の YAML ファイルを作成して、Service を定義します:

YAML

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
       targetPort: 80
  type: ClusterIP

いくつかの注意点:

  • selector: Nginx Pod に一致するラベルセレクターです。
  • app: nginx: これは Nginx Pod のラベルに一致する必要があります。
  • type: ClusterIP: Service のタイプです。ClusterIP は Service をクラスター内のみでアクセス可能にします。NodePort または LoadBalancer を使用して Service を外部に公開することもできます。

Service 設定を kubectl を使用して適用します:

  • kubectl apply -f nginx-service.yaml
  • kubectl get services
Shell

 

NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-service    ClusterIP   10.96.0.1        <none>        80/TCP    10s

Service が ClusterIP タイプであるため、クラスター内でのみアクセス可能です。クラスターの外からアクセスするには、Service タイプを NodePort または LoadBalancer に変更できます。

Service を外部に公開するために NodePort を使用するには、nginx-service.yaml ファイルを修正します:

YAML

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
       targetPort: 80
      nodePort: 30007  # Specify a node port in the range 30000-32767 (optional)
  type: NodePort

更新された Service 設定を適用します:

  • kubectl apply -f nginx-service.yaml

これで、ノードの IP アドレスとノードポートを使用して Nginx アプリケーションにアクセスできるようになります(例: http://<node-ip>:30007)。

マルチコンテナポッド

1つのポッドごとに1つのコンテナを使用すると、最大の細かい粒度と切り離しが提供されます。ただし、1つのポッド内に複数のコンテナ(時にはコンポジットコンテナとも呼ばれる)を展開すると有益なシナリオもあります。これらの副次的コンテナはさまざまな役割を果たすことができます:ログの処理や主要コンテナの拡張(サイドカーの概念)、外部システムへのプロキシとして機能する(アンバサダーの概念)、またはデータを外部形式に合わせる(アダプターの概念)。これらの副次的コンテナは、主要コンテナが処理しないタスクを実行することで主要コンテナを補完します。

以下は、Nginxサーバーを実行する主要コンテナとログの処理のためのサイドカーとして機能する副次的コンテナを含むKubernetesポッド構成の例です。サイドカーのコンテナは、NginxのアクセスログをテイルできるようにするためにBusyBoxのようなシンプルなログコンテナを使用しています。

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-logging-sidecar
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  - name: log-sidecar
    image: busybox:latest
    command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  volumes:
  - name: shared-logs
    emptyDir: {}

その後、以下の手順を実行します:

  • YAML構成をファイルに保存します。たとえば、nginx-with-logging-sidecar.yamlとします。
  • kubectl apply -f nginx-with-logging-sidecar.yamlを使用して構成を適用します。
  • ポッドが実行されていることを確認します:kubectl get pods
  • サイドカーのコンテナのログをチェックして、Nginxのアクセスログを確認します:kubectl logs -f <pod-name> -c log-sidecar

これらの手順に従うことで、既存のPodを削除し、新しい構成を適用して、Nginxコンテナとログ用のサイドカーコンテナを持つPodをセットアップします。これにより、新しい構成がKubernetesクラスター内でアクティブかつ稼働していることが保証されます。

Kubernetesのマルチコンテナポッドは、より柔軟で効率的なアプリケーションの展開と管理を可能にするいくつかの利点を提供します。

マルチコンテナポッドパターン

サイドカーパターン

サイドカーコンテナは、ログ記録、構成管理、またはプロキシなどの補助機能を提供することで、主要なアプリケーションを強化できます。このパターンは、主要なコンテナを変更することなく機能を拡張するのに役立ちます。サイドカーコンテナは、メインアプリケーションコンテナからのログを収集して転送することでログ処理を行うことができます。

アンバサダーパターン

アンバサダーコンテナは、プロキシとして機能し、主要なアプリケーションと外部サービス間の通信を管理します。これにより、統合と構成が簡素化されることがあります。アンバサダーコンテナは、SSL終端処理やAPIゲートウェイ機能を扱うことがあります。

アンバサダーパターンは、サイドカーコンテナを使用して主要なアプリケーションと外部サービス間の通信を管理することを含みます。このパターンは、プロキシ処理、負荷分散、または安全な接続の管理などのタスクを扱うことができ、主要なアプリケーションコンテナから複雑さを抽象化します。

  • 主要アプリケーションコンテナ: HTTPリクエストを行うシンプルなウェブサーバー
  • アンバサダーコンテナ: 外部APIへのリクエストを管理するように設定されたEnvoyプロキシ
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ambassador
spec:
  containers:
  - name: web-app
    image: python:3.8-slim
    command: ["python", "-m", "http.server", "8000"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  - name: envoy-proxy
    image: envoyproxy/envoy:v1.18.3
    args: ["-c", "/etc/envoy/envoy.yaml"]
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  volumes:
  - name: config-volume
    configMap:
      name: envoy-config

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: envoy-config
data:
  envoy.yaml: |
    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 8080
        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: external_service
              http_filters:
              - name: envoy.filters.http.router
      clusters:
      - name: external_service
        connect_timeout: 0.25s
        type: LOGICAL_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: external_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: api.example.com
                    port_value: 80

この例は、Kubernetesにおけるアンバサダーパターンを示しており、Envoyプロキシが主要なアプリケーションコンテナの外部通信を管理する中間者として機能します。このパターンは、通信の複雑さを抽象化し、モジュラリティと保守性を向上させます。

アダプターパターン

アダプターコンテナは、主要なアプリケーションと外部システム間のデータを変更または変換し、互換性と統合を確保します。例えば、アダプターコンテナはログデータを外部のロギングサービスの要件を満たすように再フォーマットすることができます。

Kubernetesにおけるアダプターパターンは、サイドカーコンテナを使用して主要なアプリケーションコンテナと外部システム間のデータを変換することを含みます。これは、主要なアプリケーションが外部システムによって提供された形式と異なる特定の形式でデータを必要とする場合に便利です。

例えば、カスタム形式でログを生成する主要なアプリケーションコンテナがあるとします。これらのログを特定の標準化された形式で要求される外部ロギングサービスに送信する必要があります。ログデータを外部サービスに送信する前に、アダプターコンテナを使用してログデータを必要な形式に変換することができます。

  • 主要なアプリケーションコンテナ: カスタム形式でログを記述するシンプルなアプリケーションです。
  • アダプターコンテナ: カスタムログを読み取り、それらをJSON形式に変換して外部ロギングサービスに送信するコンテナです。
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-adapter
spec:
  containers:
  - name: log-writer
    image: busybox
    command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
  - name: log-adapter
    image: busybox
    command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
    - name: json-logs
      mountPath: /var/log/json
  - name: log-sender
    image: busybox
    command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
    volumeMounts:
    - name: json-logs
      mountPath: /var/log/json
  volumes:
  - name: shared-logs
    emptyDir: {}
  - name: json-logs
    emptyDir: {}

この例は、Kubernetesにおけるアダプターパターンを示しており、アダプターコンテナがプライマリアプリケーションコンテナからデータを必要な形式に変換して外部システムに送信する前に変換する役割を果たしています。このパターンは、サイドカーコンテナ内でデータ形式の変換を処理することで、アプリケーションと外部サービスを統合するのに役立ちます。

概要

要約すると、pods:

  • Kubernetesにおける最小のデプロイ可能な単位です。
  • 実行中のプロセスの単一のインスタンスを表します。
  • 1つ以上のコンテナを含めることができます。

Services:

  • ポッドにアクセスするための安定したIPアドレスとDNS名を提供します。
  • 一連のポッド間で負荷分散を可能にします。
  • クラスタ内でのサービスの検出を容易にします。

Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services