第3章 Kubernetes クラスターを作成して Docker フォーマットのコンテナーイメージを実行する

3.1. 概要

Kubernetes を使用すると、1 つのシステム (Kubernetes Master) の Docker フォーマットのコンテナーを実行し、管理することができ、それらのコンテナーを他のシステム (Kubernetes Node) にデプロイし、実行することができます。Kubernetes 自体はシステムサービスのセットで構成されており、これにより、Pod と呼ばれる場所で Docker コンテナーを起動し、管理することができます。それらの Pod は複数のノードで実行でき、Kubernetes サービス によって相互に接続できます。Pod はいったん定義されると、ニーズに合わせて簡単に拡張/縮小することができます。

以下の手順では、次の作業を行います。

  • 1 つの Kubernetes Masterと 2 つの Kubernetes Node (minion とも呼ばれる) として使用する 3 つの RHEL Atomic ホストまたは Red Hat Enterprise Linux 7 システムをセットアップ。
  • Flannel を使用したコンテナー間のネットワークの設定。
  • サービス、Pod およびレプリケーションコントローラーを定義するデータファイル (yaml 形式) の作成。

この手順で起動するサービスには、etcd、kube-apiserver、kubecontroller-manager、kube-proxy、kube-scheduler、および kubelet が含まれます。yaml ファイルからコンテナーを起動したり、その他の方法で Kubernetes 環境を管理したりするには、kubectl コマンドを実行します。以下の手順では、以下のいずれかのシステムが実行されていることを仮定しています。

  • RHEL 7.2 Atomic Host: RHEL 7.2 を使用していない場合は、atomic host upgrade を実行して RHEL Atomic host を再起動します。
  • RHEL 7.2 サーバー: RHEL サーバーには少なくとも以下のバージョンが含まれている必要があります (含まれていない場合は yum upgrade kubernetes etcd docker flannel を実行します)。

    • kubernetes-1.2
    • etcd-2.2
    • docker-1.6
    • flannel-0.2

本書の改訂前のバージョンを使用している場合は、設定をこの最新ソフトウェアにアップグレードする方法について「Upgrading a Kubernetes Cluster」という記事を参照してください。

注意: Kubernetes および関連サービスは RHEL Atomic Host に組み込まれています。Atomic の長期的な目標は可能な限りスリム化することであるため、Kubernetes ソフトウェアは最終的にはベースの RHEL Atomic システムから削除され、Docker フォーマットコンテナーのセットに組み込まれる予定です。この移行に役立つ機能として、Kubernetes Master をセットアップするためのほとんど機能はコンテナーで利用できます。そのため、この手順の実行過程でコンテナーから一部の Kubernetes Master サービスを実行することを選択できます。

3.2. Kubernetes によるコンテナーのデプロイ準備

まずは、最新の RHEL Atomic Host または RHEL 7 Server インストールメディアを取得して、3 つのノードのそれぞれにそれらのオペレーティングシステムの 1 つをインストールする必要があります。「Red Hat Enterprise Linux Atomic Host スタートガイド」にある指示では、ベアメタルか、またはいくつかの異なる仮想環境のいずれかで実行するために Atomic をセットアップする方法についての情報を提供しています。その後、Kubernets をセットアップする前にいくつかのシステム設定を行う必要があります。

  1. インストールメディアの取得: 以下のように RHEL Atomic Host または RHEL Server メディアを取得します。

    • RHEL Atomic Host 7.2 メディア: Red Hat Enterprise Linux Downloads に移動し、利用可能なメディアから選択して、RHEL Atomic Host 7.2 メディアを取得します。
    • RHEL 7.2 Server メディア: Red Hat Enterprise Linux Downloads に移動し、利用可能なメディアから選択して、Red Hat Enterprise Linux 7.2 Server メディアを取得します。
  2. RHEL または RHEL Atomic Host システムのインストール: この手順では、3 つ以上の RHEL Atomic Host システムがインストールされる必要があります。インストール時は以下を実行してください。

    • ネットワークインターフェースを設定し、インターフェースが Kubernetes クラスターの他のシステムと通信できるようにします。
    • 使用するコンテナーのサイズと数に対応する十分なディスク領域を確保します。
    • インストールの完了時にシステムを再起動し、追加の設定を実行します。
  3. NTP (Network Time Protocol) の設定: クラスター (Master および Node) のすべてのシステムで、時刻が同期されている必要があります。それらのシステムに Network Time Protocol デーモン (ntpd) または Chrony デーモン (chronyd) をセットアップする方法については、『RHEL 7 システム管理者のガイド』を参照してください。
  4. DNS または /etc/hosts の設定: システムが DNS で相互に接続できるようにするか、またはそれらの名前および IP アドレスを /etc/hosts に追加します。たとえば、各システムの /etc/hosts ファイルにあるエントリーは以下のように表示されます。

    192.168.122.119   master
    192.168.122.196   node1
    192.168.122.27    node2
  5. 各システムのサブスクライブ: 以下のように subscription-manager コマンドを使用して 3 つのシステムすべてのサブスクライブを行います。

    # subscription-manager register --auto-attach --username=<rhnuser> --password=<password>
  6. 各システムのアップグレード: 使用しているのが RHEL Server または RHEL Atomic Host システムであるかに応じて、最新ソフトウェアへのアップグレードの方法は異なります。さらに、RHEL Atomic Host では Docker がすでにインストールされていますが、RHEL Server で Docker を取得するには、2 つのリポジトリーを有効にし、Docker パッケージをインストールする必要があります。

    RHEL Atomic Host システムで、以下を入力します。

    # atomic host upgrade
    # reboot

    RHEL Server システムで、以下を入力します。

    # yum upgrade -y
    # subscription-manager repos --enable=rhel-7-server-extras-rpms
    # subscription-manager repos --enable=rhel-7-server-optional-rpms
    # yum install docker
  7. firewalld の無効化: RHEL 7 ホストを使用している場合、firewalld サービスが無効にされていることを確認します (firewalld サービスは RHEL Atomic Host にはインストールされていません)。RHEL 7 で以下を入力し、firewall サービスを無効にし、これを停止します。

    # systemctl disable firewalld
    # systemctl stop firewalld
  8. Docker の起動および有効化: Docker サービスが各システムで実行されていることを確認するには (マスターのコンテナーから Kubernetes を実行する場合はマスターを含む)、以下を実行します。

    # systemctl restart docker
    # systemctl enable docker
    # systemctl status docker
    * docker.service - Docker Application Container Engine
       Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
      Drop-In: /usr/lib/systemd/system/docker.service.d
               |-flannel.conf
       Active: active (running) since Wed 2015-11-04 15:37:10 EST; 22h ago
    ...
  9. Docker コンテナーの取得: 以下にある説明に従って 2 つのイメージを構築します。「簡易 Apache Web サーバーをコンテナーに構築する」および「簡易データベースサーバーをコンテナーに構築する
  10. コンテナーの各ノードへのインポート: 各イメージを各ノードにコピーし、それらを各ノードにロードします。イメージを構築したシステムから開始して、以下を実行します。

    # docker export mydbforweb > dbforweb.tar
    # docker export mywebwithdb > webwithdb.tar
    # scp dbforweb.tar webwithdb.tar node1:/tmp
    # scp dbforweb.tar webwithdb.tar node2:/tmp

    各ノードで以下を実行します。

    # cat /tmp/webwithdb.tar | docker import - webwithdb
    # cat /tmp/dbforweb.tar | docker import - dbforweb
    # docker images | grep web
    dbforweb  latest  2e48be49fec4  About a minute ago  568.7 MB
    webwithdb latest  5f2daa2e04e9  2 minutes ago       408.6 MB

    注意: コンテナーを各ノードにインポートする代わりに、プライベートのコンテナーレジストリーを作成し、後で作成する yaml ファイルが、コンテナーの起動時にレジストリーを参照するようにできます。

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

3 つの RHEL Atomic Host の基本的なセットアップが完了しました。Kubernetes のセットアップを開始することができます。

3.3. Kubernetes のセットアップ

これらの 3 つのシステムが配置されたら、次に Kubernetes をセットアップします。この手順は、以下の条件によって若干異なります。

  • マスターまたはノードのセットアップ
  • RHEL Server または RHEL Atomic Host システムの使用
  • ホスト上の systemd サービスから、またはホスト上のコンテナーからのマスターサービスの実行 (ノードサービスのコンテナー化されたバージョンはまだ利用できません)

重要: ノードを起動する前にマスターを設定し、起動するようにしてください。マスターを起動する前にノードを起動すると、ノードを Kubernetes に適切に登録できない場合があります。

3.4. Master での Kubernetes のセットアップ

以下の手順は、Kubernetes Master 上でサービスをセットアップし、実行する方法について説明しています。

  1. Kubernetes のインストール: RHEL 7 システムをお使いの場合、kubernetes パッケージおよび etcd パッケージをマスターにインストールしてください (これらは RHEL Atomic にすでにインストールされています)。

    # yum install kubernetes-master etcd
  2. etcd サービスの設定: /etc/etcd/etcd.conf を編集します。etcd サービスは、すべてのインターフェースでポート 2380 (ETCD_LISTEN_PEER_URLS) およびポート 2379 (ETCD_LISTEN_CLIENT_URLS) を listen し、ローカルホストの 2380 (ETCD_LISTEN_PEER_URLS) を listen するように設定される必要があります。このファイルのコメントが外されている行は以下のように表示されます。

    ETCD_NAME=default
    ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
    ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
    ETCD_LISTEN_PEER_URLS="http://localhost:2380"
    ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"
  3. Kubernete 設定ファイルの編集: /etc/kubernetes/config ファイルを編集し、KUBE_MASTER 行を変更してマスターサーバーの場所を特定します (デフォルトでは 127.0.0.1 を参照します)。他の設定はそのままにします。変更される行は以下のように表示されます。

    KUBE_MASTER="--master=http://master.example.com:8080"
  4. Kubernetes apiserver の設定: /etc/kubernetes/apiserver を編集し、新規の KUBE_ETCD_SERVERS 行 (下記) を追加し、apiserver 設定ファイルの他の行を確認し、変更します。KUBE_API_ADDRESS を変更して、ローカルホストだけではなく、すべてのネットワークアドレス(0.0.0.0) で listen するようにします。Kuberntes がサービスに割り当てるように使用できる KUBE_SERVICE_ADDRESS のアドレス範囲を設定します (後述するこのアドレスの説明を参照してください)。最後に "ServiceAccount" という項目を KUBE_ADMISSION_CONTROL 命令から削除します (以下は、新規の行です。その上の元の行はコメントアウトされています)。以下は例になります。

    KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
    KUBE_ETCD_SERVERS="--etcd_servers=http://127.0.0.1:2379"
    KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
    # KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
    KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"

    以下は、使用する KUBE_SERVICE_ADDRESSES アドレス範囲のいくつかの注意点です。

    • アドレス範囲は、Kubernetes が Kubernetes サービスに割り当てるために使用します。
    • この例では、アドレス範囲 10.254.0.0/16 は、必要に応じて Kubernets が割り当てることのできる 10.254 サブネットのセットを使用します。たとえば、10.254.1.X、10.254.2.X などになります。
    • このアドレス範囲が環境内の他の場所では使用されません。
    • 割り当てられる各アドレス範囲はノード内でのみ使用され、そのノード外ではルーティングすることはできません。
    • このアドレス範囲は flannel が使用する範囲とは異なります (flannel のアドレス範囲は Pod に割り当てられます)。
  5. マスターサービスの起動: kubernetes サービスは、ホストのファイルシステムまたはコンテナーのいずれかから実行することを選択できます。etcd サービスは現時点ではホストから実行する必要があります。どの方法にするかを定めてから、以下の該当するコマンドに従ってください。

    • ホストから実行: Kubernetes Master サービスをホストのファイルシステムから直接実行するには、複数の systemd サービスを有効にし、起動する必要があります。マスターから以下の for ループを実行して、マスターで Kubernetes systemd サービスを起動し、有効にします。

      # for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do
          systemctl restart $SERVICES
          systemctl enable $SERVICES
          systemctl status $SERVICES
          done
    • コンテナーから実行: (systemctl を使用して) ホストから Kubernetes Master サービスを実行する代わりに、コンテナーからそれらを実行することができます。Kubernetes を完全にコンテナー化することが長期的な目標になりますが、一部のコンポーネントは現在も開発中です。この手順は、コンテナーから実行される Kubernetes サービスを手動で試行する方法を示しています。「Running Kubernetes from Containers」の記事を参照し、手順が実行可能になり次第利用できるより永続的なソリューションを確認してください。

      コンテナー化された Kubernetes Master サービスを実行するには、サービスが停止しており、systemd から無効にされていることを確認する必要があります。次に、以下のようにコンテナーサービスを設定する必要があります。

      • Kubernetes Master の systemd サービスの無効化: マスターで以下の for ループを実行します。結果として、すべてのシンボリックリックが削除され、すべてのサービスで非アクティブまたは失敗と表示されるはずです。etcd を systemd サービスとして使用します。

        # for SERVICES in kube-apiserver kube-controller-manager kube-scheduler; do
            systemctl stop $SERVICES
            systemctl disable $SERVICES
            systemctl is-active $SERVICES
            done
        # systemctl restart etcd ; systemctl enable etcd
      • Kubernetes Master コンテナーの取得: 必要なコンテナーを取得するには、以下を実行します。

        # docker pull rhel7/kubernetes-controller-mgr
        # docker pull rhel7/kubernetes-apiserver
        # docker pull rhel7/kubernetes-scheduler
      • Kubernetes Master サービスの起動: マスターで kubernetes サービスを起動するには、以下を入力します。
      # docker run -v /etc/kubernetes/:/etc/kubernetes --net=host -d \
         rhel7/kubernetes-apiserver
      
      # docker run -v /etc/kubernetes/:/etc/kubernetes --net=host -d \
         rhel7/kubernetes-controller-mgr
      
      # docker run -v /etc/kubernetes/:/etc/kubernetes --net=host -d \
         rhel7/kubernetes-scheduler
      • Κubernetes Master サービスの確認: kubernetes サービスが systemd サービスとして実行されていないため、systemctl を使用してサービスが実行中であることを確認することはできません。それらが実行されていることを確認するには、ps コマンドを実行できます。
    # ps -ef | grep kube
    root  2566   1507  0 11:26 ?  00:00:26 /usr/bin/kube-apiserver --logtostderr=true ...
    root  2619   1507  0 11:26 ?  00:00:13 /usr/bin/kube-controller-manager ...
    root  2671   1507  0 11:26 ?  00:00:01 /usr/bin/kube-scheduler --logtostderr=true ...

3.5. Node での Kubernetes のセットアップ

2 つの Kubernetes ノード (この例では node1.example.com および node2.example.com) のいずれかで、いくつかの設定ファイルを編集し、複数の Kubernetes systemd サービスを起動し、有効にする必要があります。

  1. Kubernetes のインストール: ノードが RHEL 7 システムの場合、各ノードに kubernetes-node パッケージをインストールします。Kubernetes は RHEL Atomic にすでにインストールされています。

    # yum install kubernetes-node
  2. /etc/kubernetes/config の編集: このファイルの KUBE_MASTER 行を編集し、マスターの位置 (デフォルトでは 127.0.0.1) を特定します。その他の設定はそのままにします。

    KUBE_MASTER="--master=http://master.example.com:8080"
  3. /etc/kubernetes/kubelet の編集: 各ノードにあるこのファイルで、以下のように KUBELET_ADDRESS (すべてのネットワークインターフェースで listen するように 0.0.0.0)、KUBELET_HOSTNAME (hostname_override をローカルシステム node1 または node2 のホスト名または IP アドレスに置き換える) を変更し、KUBELET_ARTS を "--register-node=true" に設定し、KUBELET_API_SERVER を設定します (--api_servers=http://master.example.com:8080 またはマスターの他の場所に設定)。

    KUBELET_ADDRESS="--address=0.0.0.0"
    KUBELET_HOSTNAME="--hostname-override=node?"
    KUBELET_ARGS="--register-node=true"
    KUBELET_API_SERVER="--api_servers=http://master.example.com:8080"
  4. /etc/kubernetes/proxy の編集: このファイルを設定する必要はありません。KUBE_PROXY_ARGS が設定されている場合、これをコメントアウトすることができます。

    # KUBE_PROXY_ARGS="--master=http://master.example.com:8080"
  5. Kubernetes Node の systemdサービスの起動: 各ノードで、Kubernetes Node と関連付けられた複数のサービスを起動する必要があります。

    # for SERVICES in docker kube-proxy.service kubelet.service; do
        systemctl restart $SERVICES
        systemctl enable $SERVICES
        systemctl status $SERVICES
    done
  6. サービスの確認: 3 つのシステムのそれぞれに対して netstat コマンドを実行し、サービスが実行されているポートを確認します。etcd サービスはマスターでのみ実行されます。

    • マスター:

      # netstat -tulnp | grep -E "(kube)|(etcd)"
    • ノード:

      # netstat -tulnp | grep kube

      注意: この手順では firewalld サービスが Atomic にインストールされていません (また RHEL で無効しておく必要があります) が、システム上のポートへのアクセスをブロックするために iptables ルールを直接使用することもできます。それを使用した後は、この netstat コマンドを実行すると、Kubernetes クラスターを機能させるために各システムでアクセス可能な状態にしておく必要のあるポートが表示されます。そのため、個別のファイアウォールルールを作成して、これらのポートへのアクセスを開くことができます。

  7. etcd サービスのテスト: これらの 3 つのシステムのいずれかから curl コマンドを実行して、etcd サービスが実行中でアクセス可能であることを確認します。

    # curl -s -L http://master.example.com:2379/version
    {"etcdserver":"2.2.0","etcdcluster":"2.2.0"}
  8. ノードの確認: マスターから以下のコマンドを入力して、マスターが 2 つのノードと通信していることを確認します。

    # kubectl get nodes
    NAME              LABELS                                   STATUS
    node1.example.com kubernetes.io/hostname=node1.example.com Ready
    node2.example.com kubernetes.io/hostname=node2.example.com Ready

これで、Kubernetes クラスターが設定されました。次にこの設定を使用してネットワークを設定し、Kubernetes サービス、レプリケーションコントローラーおよび Pod をデプロイして、コンテナーのデプロイを開始することができます。

3.6. Kubernetes の Flannel ネットワークのセットアップ

flannel パッケージには、Kubernetes クラスターのマスターとノード間のネットワークを設定できる機能が含まれています。flanneled サービスは、(マスターで) etcd サーバーへのネットワーク設定を含んだ json 設定ファイルを作成し、アップデートして設定します。次に flanneld systemd サービスをマスターとおよび各ノードに設定してその etcd サーバーを指定し、flanneld サービスを起動します。この手順では、その方法を説明します。

注意: etcd サービスは、flanneld が起動する前に実行されている必要があります。flanneld および docker がノードで起動しない場合は、etcd がマスターで稼働していることを確認し、各ノードを再起動するようにしてください。

この例では、flannel は kubernetes 環境のすべてのノードで使用されるアドレス範囲 10.20.0.0/16 を割り当てます。これにより、マスターと両ノードのネットワークインターフェースに割り当てられる範囲内に別個の /24 サブネットを使用できます。この例の 3 つのシステムの場合、以下の手順を実行すると、以下のアドレス範囲が flannel.1 および docker0 インターフェースに割り当てられます。

  • マスター:

    • flannel.1: 10.20.21.0/16
  • node1:

    • flannel.1: 10.20.26.0/16
    • docker0: 10.20.26.1/24
  • node2:

    • flannel.1: 10.20.37.0/16
    • docker0: 10.20.37.1/24

重要: docker0 インターフェースは、この手順の実行時にはすでに配置されているため、flanneld により docker0 に割り当てられる IP アドレス範囲はすぐには有効になりません。flanneld アドレス範囲を有効にするには、docker を停止 (systemctl stop docker) して docker0 インターフェースを削除し、docker インターフェースを再起動 (systemctl start docker) する必要があります。この手順の実行時には、単に再起動するよう指示されます。

  1. flannel のインストール: flannel パッケージは RHEL Atomic にプリインストールされています。ただし RHEL 7 を使用している場合は、以下のようにマスターと各ノードに flannel パッケージをインストールできます。

    # yum install flannel
  2. flannel 設定ファイルの作成: マスターで、flannel 設定ファイル (json 形式) の IP アドレスのセットおよびネットワークの種類を指定します。この例では、以下の内容を含む flannel-config.json というファイルを作成しています。

    {
      "Network": "10.20.0.0/16",
      "SubnetLen": 24,
      "Backend": {
        "Type": "vxlan",
        "VNI": 1
      }
    }
  3. flannel 設定の etcd サービスへのアップロード: マスターで flannel 設定ファイルを etcd サービスにアップロードするには、以下を入力します。

    # etcdctl set coreos.com/network/config < flannel-config.json
      {"action":"set","node":{"key":"/coreos.com/network/config","value":"{\n\"Network\":  \"10.20.0.0/16\",\n\"SubnetLen\": 24,\n\"Backend\": {\n\"Type\":  \"vxlan\",\n\"VNI\": 1\n      }\n}\n","modifiedIndex":10,"createdIndex":10},"prevNode":{"key":"/coreos.com/network/config","value":"","modifiedIndex":9,"createdIndex":9}}

    次に、アップロードが適切に完了したことを確認します。

    # etcdctl get coreos.com/network/config
    {
      "Network": "10.20.0.0/16",
      "SubnetLen": 24,
      "Backend": {
        "Type": "vxlan",
        "VNI": 1
      }
    }
  4. flanneld のオーバーレイネットワークの設定: flanneld systemd サービスが起動すると、オプションの /etc/sysconfig/flanneld ファイルを読み込んで、flanneld デーモンに渡します。マスターおよび両ノードで /etc/sysconfig/flanneld を編集して、etcd サービス (マスター) を含むシステムの名前または IP アドレス名を追加します。FLANNEL_ETCD_KEY 行はそのままにします。

    FLANNEL_ETCD="http://master.example.com:2379"
    FLANNEL_ETCD_KEY="/coreos.com/network"
  5. マスターとノードでの flanneld の起動: 以下のように最初にマスター、次に 2 つのノードで flanneld サービスを起動し、有効にします。

    # systemctl restart flanneld
    # systemctl enable flanneld
    # systemctl status flanneld
  6. flannel.1 ネットワークインターフェースの確認: 任意のシステムから以下のコマンドを実行して、flannel.1 ネットワークインターフェースが各システム上に適切に設定されていることを確認します。最初のコマンドは、各ノードで ip a コマンドを実行し、flannel.1 インターフェースを確認します。2 つ目のコマンドは、サブネットが各システムの flannel に対して設定されている内容を示します。

    # for i in 1 2; do ssh root@node$i ip a l flannel.1; done | grep 'inet '
    root@node1's password: password
        inet 10.20.26.0/16 scope global flannel.1
    root@node2's password: password
        inet 10.20.37.0/16 scope global flannel.1
    # for i in master node1 node2; \
         do echo --- $i ---; ssh root@$i cat /run/flannel/subnet.env; done
    root@master's password: password
    --- master ---
    FLANNEL_SUBNET=10.20.21.1/24
    FLANNEL_MTU=1450
    root@node1's password: password
    --- node1 ---
    FLANNEL_SUBNET=10.20.26.1/24
    FLANNEL_MTU=1450
    root@node2's password: password
    --- node2 ---
    FLANNEL_SUBNET=10.20.37.1/24
    FLANNEL_MTU=1450
  7. ノードの再起動: docker の systemd サービスが flannel の変更を選択するようにし、すべてのネットワークインターフェースが適切に起動することを確認するには、各ノードで以下を実行して、再起動します。

    # systemctl reboot
  8. flannel アドレスを取得するためのコンテナーの起動: 各ノードで flannel ネットワークのアドレス範囲を確認し、ネットワークからアドレスが選択されることを確認するためにイメージを実行します。

    # ip a | grep flannel
    3: flannel.1:  mtu 1450 qdisc noqueue state UNKNOWN
    inet 10.20.26.0/16 scope global flannel.1
    # docker run -d --name=mydbforweb dbforweb
    # docker inspect --format='{{.NetworkSettings.IPAddress}}' mydbforweb
    10.20.26.2
    # docker stop mydbforweb
    # docker rm mydbforweb

3.7. Kubernetes によるサービス、レプリケーションコントローラー、およびコンテナー Pod の起動

Kubernetes クラスターを設定したら、Kubernetes サービスをセットアップするために必要な yaml ファイルを作成し、レプリケーションコントローラーを定義し、コンテナーの Pod を起動できます。前述の 2 つのコンテナー (Web および DB) を使用して、以下の種類の Kubernetes オブジェクトを作成します。

  • サービス: Kubernetes サービスを作成すると、特定の IP アドレスおよびポート番号をラベルに割り当てることができます。Pod および IP アドレスは Kubernetes と連携するため、そのラベルを必要なサービスの場所を特定するために Pod 内で使用できます。
  • レプリケーションコントローラー: レプリケーションコントローラーを定義すると、起動する Pod を設定するだけではなく、起動する各 Pod のレプリカの数を設定することができます。Pod が停止すると、レプリケーションコントローラーは別の Pod を起動し、これを置き換えます。
  • Pod: Pod は 1つ以上のコンテナーを、コンテナーの実行に関係したオプションと共にロードします。

この例では、2 つの Pod が相互に通信できるようにするために必要なサービスオブジェクト (yaml ファイル) を作成します。次に、前述の Web サーバーおよびデータベースサーバーのコンテナーを起動し、維持するための Pod を特定するレプリケーションコントローラーを作成します。本書で使用されるすべての yaml および json 設定ファイルを取得するには、以下の tarball をダウンロードします。

kube_files.tar

  1. データベースサーバー用の Kubernetes サービスのデプロイ:マスター上で、データベースサーバーコンテナーを特定の IP アドレスとポートに関連付けるためにラベルを指定する Kubernetes サービスの yaml ファイルを作成します。以下は、db-service.yaml というファイルを使用した例です。

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: db
      name: db-service
      namespace: default
    spec:
      ports:
      - port: 3306
      selector:
        name: db

    このサービスは外部から直接アクセスされません。webserver コンテナーがこれにアクセスします。セレクターおよびラベルの名前を db に設定します。サービスを起動するには、マスターで以下を入力します。

    # kubectl create -f db-service.yaml
    service "db-service" created
  2. データベースサーバー用の Kubernetes ReplicationController のデプロイ: 実行しているデータベース Pod の数 (この場合は 2 つ) を指定するレプリケーションコントローラーの yaml ファイルを作成します。この例では、ファイルの名前は db-rc.yaml です。

    kind: ReplicationController
    apiVersion: v1
    metadata:
       name: db-controller
    spec:
      replicas: 2
      selector:
        name: db
      template:
        spec:
          containers:
          - name: db
            image: dbforweb
            ports:
              - containerPort: 3306
        metadata:
          labels:
            name: "db"
          selectorname: "db"
      labels:
        name: "db"

    webserver pod のレプリケーションコントローラーを起動するには、以下を入力します。

    # kubectl create -f db-rc.yaml
    replicationcontroller "db-controller" created
  3. Web サーバー用の Kubernetes サービスの yaml ファイルの作成とその起動: マスター上で Kubernetes サービスの yaml ファイルを作成します。このファイルは、Web サーバーのコンテナーを特定の IP アドレスおよびポートに関連付けるラベルを指定します。以下は、webserver-service.yaml ファイルを使用した例です。

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        name: webserver
      name: webserver-service
      namespace: default
    spec:
      ports:
      - port: 80
      publicIPs:
      - 192.168.122.15
      selector:
        name: webserver

    porrtalIP は、/etc/kubernetes/apiserver ファイルで設定される範囲内にある必要があります (この場合は 10.254.100.0/24)。publicIPs 値は、ノードのいずれかにある外部ネットワークに関連付けられた IP アドレスと連携する必要があります (node2 では eth0 インターフェースの IP アドレスは 192.168.122.15 です)。これにより、サービスが外部にも利用可能になります。セレクターおよびラベルの名前は webserver に設定します。サービスを起動するには、マスターで以下を入力します。

    # kubectl create -f webserver-service.yaml
    service "webserver-service" created

    apiserver および追加したばかりの 2 つのサービスが実行中の状態で、以下のコマンドを入力し、それらのサービスを表示します。

    # kubectl get services
    NAME              LABELS                                  SELECTOR
              IP(S)          PORT(S)
    db-service        name=db                                 name=db
              10.254.192.67  3306/TCP
    kubernetes        component=apiserver,provider=kubernetes
              10.254.255.128 443/TCP
    kubernetes-ro     component=apiserver,provider=kubernetes
              10.254.139.205 80/TCP
    webserver-service name=webserver                          name=webserver
              10.254.134.105 80/TCP
  4. Web サーバー用の Kubernetes ReplicationController のデプロイ: 実行している webserver Pod の数を特定するレプリケーションコントローラーの yaml ファイルを作成します。以下の yaml ファイルに基づいて、レプリケーションコントローラーは 「webserver」ラベルの付いた 2 つの Pod を常に実行するようにします。Pod 定義はレプリケーションコントローラーの yaml ファイル内にあるため、別の Pod の yaml ファイルは不要です。以下は、webserver-rc.yaml というファイルの例です。

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: webserver-controller
    spec:
      replicas: 2
      selector:
        name: webserver
      template:
        spec:
          containers:
            - name: apache-frontend
              image: webwithdb
              ports:
                - containerPort: 80
        metadata:
          labels:
            name: webserver
            uses: db
      labels:
        name: "webserver"

    webserver pod のレプリケーションコントローラーを起動するには、以下を入力します。

    # kubectl create -f webserver-rc.yaml
    replicationcontroller "webserver-controller" created

3.8. Kubernetes の確認

アプリケーションが機能していることを確認するには、2 つの curl コマンドを実行して、Web サーバーからデータを取得することができます。クラスターが適切に機能していることを確認するには、いくつかの kubectl コマンドを実行できます。

  1. Web サーバーの確認: 以下のコマンドを実行して、Web サーバーからデータを取得します。Pod アドレスを使用して web サービスにアクセスします。

    # kubectl get endpoints | grep web
    NAME                ENDPOINTS                         AGE
    webserver-service   10.20.11.3:80,10.20.55.2:80       3d
    # curl http://10.20.11.3/index.html
    The Web Server is Running
    # curl http://10.20.11.3/cgi-bin/action
    <html>
    <head>
    <title>My Application</title>
    </head>
    <body>
    <h2>RedHat rocks</h2>
    <h2>Success</h2>
    </body>
    </html>
  2. Kubernetes クラスターの確認: マスターから以下のいくつかのコマンドを実行すると、クラスターを確認できます。

    # kubectl get pods
    # kubectl get replicationControllers
    # kubectl get services
    # kubectl get nodes
  3. Kubernetes Node の確認およびコンテナーの一時停止: Pod が長い間保留状態になっている場合は、Pod が起動しようとしているコンテナーを選択したノードで起動できないことが原因である場合があります。特定のノード上で実行されているコンテナーをチェックアウトするには、そのノードにログインしてから docker ps コマンドを入力します。

    # docker ps
    CONTAINER ID        IMAGE                                     COMMAND                  CREATED             STATUS              PORTS               NAMES
    b28a863e0aca        dbforweb                                  "/usr/bin/mysqld_safe"   2 hours ago         Up 2 hours                              k8s_db...
    b138c90519a1        webwithdb                                 "/usr/sbin/httpd -D F"   2 hours ago         Up 2 hours                              k8s_apache...
    872c5acf3ec8        beta.gcr.io/google_containers/pause:2.0   "/pause"                 2 hours ago         Up 2 hours                              k8s_POD...
    e117af93e4f4        beta.gcr.io/google_containers/pause:2.0   "/pause"                 2 hours ago         Up 2 hours                              k8s_POD...

    上記の出力は、マスターから 2 つのレプリケーションコントローラーが正常に起動されたことを示しています。dbforweb および webwithdb コンテナーはこのノード上で実行されています。ただし、コマンド /pause を実行している他の 2 つのコンテナーも実行中のコンテナーの一覧に表示されていることに注意してください。

    pause コンテナーは特殊なタイプのコンテナーです。ここに示されるコンテナーはアップストリームの Kubernetes プロジェクトから取られています。各 Pod について、pause コンテナーは Pod 内の最後のネットワーク名前空間をノード上で予約するために使用され、Pod が行き来する際に名前空間が確保されるようにします。デフォルトのすべての pause コンテナーが実行するアクションは休止 (sleep) のみです。このコンテナーは Kubernetes により自動的に取得されます。

    pause コンテナーに関する潜在的な問題とは、取得元となるレジストリーから切断された状態で Kubernetes クラスターを実行する必要がある場合に、必ず pause コンテナーを取得してから接続を切断する必要がある点にあります。

    直前の例で使用されたデフォルトのコンテナーの代わりとして他の pause コンテナーを使用することもできます。正式な Red Hat の pause コンテナーは rhel7/pod-infrastructure と呼ばれており、まもなく利用可能になります。

3.9. Kubernetes の削除

クラスターの使用が終了したら、適切に削除できるように特定の方法で削除する必要があります。

ここで、順序は重要になります。replicationController を削除する前に Pod を削除すると、Pod は再起動します。以下のようになります。

# kubectl delete replicationControllers webserver-controller
# kubectl delete replicationControllers db-controller
# kubectl delete services webserver-service
# kubectl delete services db-service
# kubectl get pods
POD                                  IP          CONTAINER(S)    ...
89d8577d-bceb-11e4-91c4-525400a6f1a0 10.20.26.4  apache-frontend ...
8d30f2de-bceb-11e4-91c4-525400a6f1a0 10.20.26.5  db              ...
# kubectl delete pods 89d8577d-bceb-11e4-91c4-525400a6f1a0
# kubectl delete pods 8d30f2de-bceb-11e4-91c4-525400a6f1a0

Kubernetes クラスターを継続して使用する場合は、各ノードで以下を実行して、サービスが稼働していることを確認します。

# for SERVICES in docker kube-proxy.service kubelet.service; do
    systemctl restart $SERVICES
    systemctl status $SERVICES
    done

ノードの使用を終了した場合は、以下のようにマスターから削除できます。

# kubectl delete node node1.example.com
# kubectl delete node node2.example.com

3.10. 添付ファイル

kube_files.tar