第2章 Kubernetes によるコンテナーのオーケストレーション

2.1. 概要

Kubernetes は、Docker コンテナーのオーケストレーションおよび管理を行うためのツールです。以下の手順では、単一システムの Kubernetes サンドボックスをセットアップします。

  • Kubernetes で、2 つのコンテナーおよび yaml ファイルを使用し、コンテナーをデプロイする。
  • Kubernetes でコンテナーを管理する。

この手順では、Kubernetes を実際に使用し、その機能を学習するためのサンドボックスをセットアップします。この手順では、通常は別々の Kubernetes Master システムや複数の Kubernetes Node システムにあるサービスが単一システムで実行されます。

2.2. Kubernetes について

Docker はコンテナーフォーマットを定義し、個々のコンテナーを構築し、管理しますが、オーケストレーションツールは一連のコンテナーをデプロイし、管理するために必要です。Kubernetes は Docker コンテナーのオーケストレーションを行うためのツールです。必要なコンテナーイメージを構築した後に、Kubernetes Master を使用して Pod に 1 つ以上のコンテナーをデプロイすることができます。Master はその Pod のコンテナーを、コンテナーが実行される Kubernetes Node にプッシュします。

たとえば、Kubernetes Master および Node はどちらも同じコンピューターにあり、そのコンピューターは RHEL 7 Server または RHEL 7 Atomic Host のいずれかであるとします。Kubernetes は Kubenetes Master および Node の機能を実装するために一連サービスデーモンに依存します。Kubernetes Master および Node については以下を理解しておく必要があります。

  • Master: Kubernetes Master では、API 呼び出しを Kubernets クラスターの Pod、レプリケーションコントローラー、サービス、ノードその他のコンポーネントを制御するサービスに指定します。通常これらの呼び出しは、kubectl コマンドを実行して行われます。コンテナーは Master から Node 上で実行されるようにデプロイされます。
  • Node: Node はコンテナーのランタイム環境を提供するシステムです。

Pod の定義は設定ファイル (yaml または json 形式) に保存されます。以下の手順を使用して、単一の RHEL 7 または RHEL Atomic システムをセットアップし、これを Kubernetes Master および Node として設定し、yaml ファイルを使用して Pod に各コンテナーを定義し、それらのコンテナーを Kubernetes を使用してデプロイします (kubectl コマンド)。

2.3. Kubernetes Pod からのコンテナーの実行

Docker コンテナーを構築し、Kubernetes を使用してオーケストレーションを行うには RHEL 7 または RHEL Atomic システムが必要です。Kubernetes Master および Node システムには、異なるサービスデーモンのセットが必要です。以下の手順では、両方のサービスデーモンのセットが同じシステムで実行されます。

コンテナー、システムおよびサービスを配置したら、kubectl コマンドを使用し、それらのコンテナーが Kubernetes Node (この場合はローカルシステム) で実行されるようにデプロイします。

以下にその手順を示します。

2.3.1. Kubernetes で Docker コンテナーをデプロイするためのセットアップ

Kubernetes を準備するには、RHEL 7 または RHEL Atomic をインストールし、firewalld を無効にしてから 2 つのコンテナーを取得する必要があります。

  1. RHEL 7 または RHEL Atomic システムのインストール: この Kubernetes サンドボックスシステムについては、まず RHEL 7 または RHEL Atomic システムをインストールし、システムのサブスクライブを実行してから、Docker サービスのインストールおよび起動を行います。基本的な RHEL または RHEL Atomic システムをセットアップして Kubernetes で使用する方法の詳細は、以下を参照してください。

    Get Started with Docker Formatted Container Images on Red Hat Systems (Docker フォーマットのコンテナーイメージの使用方法)

  2. Kubernetes のインストール: RHEL 7 システムの場合は、kubernetes および etcd パッケージをインストールします。これにより、kubernetes-node および kubernetes-master パッケージも取得できます (これらのパッケージは RHEL Atomic にすでにインストールされています)。

    # yum install kubernetes etcd
  3. firewalld の無効化: RHEL 7 ホストを使用している場合は firewalld サービスが無効にされていることを確認します (firewalld サービスは Atomic Host にはインストールされていません)。RHEL 7 では以下を入力して firewalld サービスを無効にし、これを停止します。

    # systemctl disable firewalld
    # systemctl stop firewalld
  4. Docker コンテナーの取得: RHEL Atomic Host のスタートガイドの指示に従って以下の 2 つのコンテナーを構築し、それらのコンテナーのイメージを両方のノードで利用できるようにします (つまり、いずれかのノードで docker images コマンドを入力する際に 2 つのイメージが表示されるようにします)。

    コンテナーの構築およびテストを実行した後は、停止します (docker stop mydbforweb および docker stop mywebwithdb を実行)。

2.3.2. Kubernetes の起動

Kubernetes Master および Node サービスはどちらもローカルシステム上で実行されるため、Kubernetes 設定ファイルを変更する必要はありません。Master および Node サービスはローカルホストで相互を参照し、サービスはローカルホストでのみ利用可能になります。

  1. apiserver ファイルの設定: デフォルトで kube-apiserver サービスの許可制御機能を使用するには、Pod を起動するすべてのユーザー用にアカウントをセットアップする必要があります。これにより、Kubernetes プロバイダーは、ユーザーアカウント別に使用を追跡し、制限することができます。この一体型の例では、/etc/kubernetes/apiserver ファイルを開き、KUBE_ADMISSION_CONTROL 値を変更して --admission_control オプションから "ServiceAccount" を削除することでこの機能を無効にすることができます。以下の行は、元の行 (コメントアウトされた行) および ServiceAccount が削除された新規の行を示しています (これらの 2 つの行は折り返されますが、2 行に分割されているように表示される場合もあります)。

    # KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
    KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
  2. Kubernetes Master サービスデーモンの起動: Kubernetes Master に関連付けられたいくつかのサービスを起動する必要があります。

    # for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do
        systemctl restart $SERVICES
        systemctl enable $SERVICES
        systemctl status $SERVICES
    done
  3. Kubernetes Node サービスデーモンの起動: Kubernetes Node に関連付けられたいくつかのサービスを起動する必要があります。

    # for SERVICES in docker kube-proxy.service kubelet.service; do
        systemctl restart $SERVICES
        systemctl enable $SERVICES
        systemctl status $SERVICES
    done
  4. サービスの確認: ss コマンドを実行して、サービスが実行されているポートを確認します。

    # ss -tulnp | grep -E "(kube)|(etcd)"
  5. etcd サービスのテスト: 以下のように curl コマンドを使用して etcd サービスを確認します。

    # curl -s -L http://localhost:2379/version
    {"etcdserver":"2.1.1","etcdcluster":"2.1.0"}

注意: RHEL Atomic Host 7.1.4 以降では、etcd ユーティリティーはポート 2379 を使用します。古いバージョンの RHEL Atomic Host を実行している場合は、上記のコマンドの 2379 を 4001 に置き換えます。

2.3.3. Kubernetes によるコンテナー Pod の起動

ローカルシステムで Master および Node サービスを実行し、2 つのコンテナーイメージを配置したら、Kubernetes Pod を使用してコンテナーを起動できます。以下はいくつかの注意点です。

  • 複数の Pod: 単一の Pod で複数のコンテナーを起動できますが、それらのコンテナーを別々の Pod に配置すると、各コンテナーは他のコンテナーを起動することなく、複数のインスタンスを必要に応じて複製できます。
  • Kubernetes サービス: この手順では、データベースおよび Web サーバーの Pod 用に Kubernetes サービスを定義し、コンテナーが Kubernetes からそれらのサービスを見つけられるようにします。データベースおよび Web サーバーは、ターゲット Pod が実行されている IP アドレス、ポート番号、またはノードを認識しない場合でも相互を識別できます。

以下の手順は、2 つの Pod を起動し、テストする方法について説明しています。

重要: yaml ファイルのインデントを維持することは重要です。yaml ファイルのスペースは、フォーマットを整理された状態に保つために使用されます (構造を維持するための波括弧などの文字は不要です)。

  1. データベース Kubernetes サービスの作成: db-service.yaml ファイルを作成して、データベースサービスを Kubernetes に提供する Pod を特定します。

    Kubernetes:
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: db
      name: db-service
      namespace: default
    spec:
      ports:
      - port: 3306
      selector:
        name: db
  2. データベースサーバーのレプリケーションコントローラーファイルの作成: データベースサーバーの Pod をデプロイするために使用する db-rc.yaml ファイルを作成します。以下を設定します。

    kind: "ReplicationController"
    apiVersion: "v1"
    metadata:
      name: "db-controller"
    spec:
      replicas: 1
      selector:
        name: "db"
      template:
        spec:
          containers:
            - name: "db"
              image: "dbforweb"
              ports:
                - containerPort: 3306
        metadata:
          labels:
            name: "db"
          selectorname: "db"
      labels:
        name: "db"
  3. Web サーバーの Kubernetes サービスファイルの作成: Web サーバーの Pod をデプロイするために使用する webserver-service.yaml ファイルを作成します。以下を設定します。

    Kubernetes:
    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: webserver
      name: webserver-service
      namespace: default
    spec:
      ports:
      - port: 80
      selector:
        name: webserver
  4. Web サーバーのレプリケーションコントローラーファイルの作成: Web サーバーの Pod をデプロイするために使用する webserver-rc.yaml ファイルを作成します。以下を設定します。

    kind: "ReplicationController"
    apiVersion: "v1"
    metadata:
      name: "webserver-controller"
    spec:
      replicas: 1
      selector:
        name: "webserver"
      template:
        spec:
          containers:
            - name: "apache-frontend"
              image: "webwithdb"
              ports:
                - containerPort: 80
        metadata:
          labels:
            name: "webserver"
            uses: db
      labels:
        name: "webserver"
  5. kubectl を使用したコンテナーのオーケストレーション: 現在のディレクトリーにある 2 つの yaml ファイルを使用して以下のコマンドを実行し、コンテナーの実行を開始するために Pod を起動します。

    # kubectl create -f db-service.yaml
    services/db-service
    # kubectl create -f db-rc.yaml
    replicationcontrollers/db-controller
    # kubectl create -f webserver-service.yaml
    services/webserver-service
    # kubectl create -f webserver-rc.yaml
    replicationcontrollers/webserver-controller
  6. rc、pod、およびサービスの確認: 以下のコマンドを実行し、レプリケーションコントローラー、Pod、およびサービスがすべて実行されていることを確認します。

    # kubectl get rc
    CONTROLLER             CONTAINER(S)      IMAGE(S)    SELECTOR         REPLICAS
    db-controller          db                dbforweb    name=db          1
    webserver-controller   apache-frontend   webwithdb   name=webserver   1
    # kubectl get pod
    NAME                         READY     STATUS    RESTARTS   AGE
    db-controller-tiu56          1/1       Running   0          48m
    webserver-controller-s5b81   1/1       Running   0          33m
    # kubectl get service
    NAME                LABELS          SELECTOR         IP(S)            PORT(S)
    db-service          name=db         name=db          10.254.232.194   3306/TCP
    kubernetes          component=...   <none>           10.254.0.1       443/TCP
    webserver-service   name=webserver  name=webserver   10.254.104.45    80/TCP
  7. コンテナーの確認: 2 つのコンテナーがどちらも実行中で、Web サーバーコンテナーがデータベースサーバーを認識する場合、以下のように kubectl コマンドを使って Pod を確認し、curl コマンドを実行してすべてが機能していることを確認できます。

    # kubectl get pods
    # curl http://localhost:80/cgi-bin/action
    <html>
    <head>
    <title>My Application</title>
    </head>
    <body>
    <h2>RedHat rocks</h2>
    <h2>Success</h2>
    </body>
    </html>

ローカルホストに Web ブラウザーをインストールしている場合は、Web ブラウザーを開いて、出力の行がきちんと表示されていることを確認します。ブラウザーで URL の http://localhost/cgi-bin/action を開きます。

2.4. Kubernetes Pod の確認

問題が発生した場合には、原因を判別するためのいくつかの方法があります。たとえば、コンテナー内のサービスを調べることができます。これを実行するには、コンテナー内のログを調べて原因を確認できます。以下のコマンドを実行します (最後の引数を、確認する Pod の名前に置き換えます)。

そのほかにも、firewalld を無効にしなかったことが問題の原因となることがあります。firewalld がアクティブな場合は、サービスがコンテナー間でのポートへのアクセスを試行する際にポートへのアクセスがブロックされる可能性があります。ホスト上で必ず systemctl stop firewalld ; systemctl disable firewalld を実行してください。

2 つの Pod を持つアプリケーションの作成時に間違いがあった場合、レプリケーションコントローラーとサービスを削除することができます (Pod はレプリケーションコントローラーが削除されるとなくなります)。その後に、yaml ファイルを修正し、それらを作成し直すことができます。以下に、レプリケーションコントローラーおよびサービスを削除する方法を示します。

# kubectl delete rc webserver-controller
replicationcontrollers/webserver-controller
# kubectl delete rc db-controller
replicationcontrollers/db-controller
# kubectl delete service webserver-service
services/webserver-service
# kubectl delete service db-service

Pod だけ削除することがないようにしてください。レプリケーションコントローラーを削除せずに Pod を削除すると、レプリケーションコントローラーは新規の Pod を起動して削除した Pod の置き換えを行います。

上記の例は、簡単に Kubernetes を起動する方法です。ただし、同じシステムで Master と Node を 1 つずつ使用しているだけなので、拡張性がありません。拡張性のある設定をするには、Kubernetes クラスターを作成して Docker フォーマットのコンテナーイメージを実行する に記載の手順に従って設定することが推奨されます。