このドキュメントで説明するソフトウェアは、サポートされなくなったか、Extended Support期間中です。
現在サポートされているリリースにアップグレードすることをお薦めします。

第5章 Kubernetesのスタート・ガイド

この章では、Kubernetesの使用を開始して、コンテナ化されたアプリケーションをデプロイ、維持およびスケーリングする方法について説明します。

5.1 kubectlの基本

kubectlユーティリティは、クラスタに対してコマンドを実行するためにAPIサーバーとインタフェースするコマンドライン・ツールです。通常、このツールはクラスタのマスター・ノードで実行されます。これにより、実質的に、クラスタとクラスタ内のすべてのノードに完全な管理権限が付与されます。

kubectlユーティリティについては、次で詳しく説明しています。

https://kubernetes.io/docs/reference/kubectl/overview/

この項では、環境内のポッドとサービスの作成および管理を開始できるように、ツールの基本的な使用方法について説明します。

クラスタ内のノードに関する情報の取得

クラスタ内のすべてのノードおよび各ノードのステータスのリストを取得するには、kubectl getコマンドを使用します。このコマンドを使用して、Kubernetesでサポートされるあらゆる種類のリソースのリストを取得できます。この例では、nodesリソースは次のようになります。

$ kubectl get nodes
NAME                   STATUS    ROLES   AGE      VERSION
master.example.com     Ready     master  1h       v1.12.5+2.1.1.el7
worker1.example.com    Ready     <none>  1h       v1.12.5+2.1.1.el7
worker2.example.com    Ready     <none>  1h       v1.12.5+2.1.1.el7

任意のリソースに関する詳細情報を取得するには、kubectl describeコマンドを使用します。リソースの名前を指定した場合、出力は、そのリソースに関する情報のみに制限されます。それ以外の場合は、すべてのリソースの完全な詳細も画面に出力されます。

$ kubectl describe nodes worker1.example.com
Name:               worker1.example.com
Roles:              <none>   
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/hostname=worker1.example.com
Annotations:        flannel.alpha.coreos.com/backend-data: {"VtepMAC":"f2:24:33:ab:be:82"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 10.147.25.196
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true
...

ポッドでのアプリケーションの実行

実行中の単一のDockerコンテナでポッドを作成するには、kubectl createコマンドを使用できます。

$ kubectl create deployment --image nginx hello-world
deployment.apps/hello-world created

hello-worldを、ご使用のデプロイメントの名前に置き換えます。ポッドには、接頭辞としてデプロイメント名を使用した名前が付けられます。nginxを、DockerエンジンによってプルできるDockerイメージに置き換えます。

ヒント

デプロイメント、ポッドおよびサービスの名前は、DNS-1123ラベルと一致するための要件に従います。これらは、英数字(小文字)または-で構成され、先頭と末尾が英数字である必要があります。名前の検証に使用される正規表現は、'[a-z0-9]([-a-z0-9]*[a-z0-9])?'です。デプロイメントで検証されていない名前を使用すると、エラーが返されます。

Kubernetes内で新しいアプリケーションを実行する際に使用できる追加のオプション・パラメータは、数多く存在します。たとえば、起動する必要があるレプリカ・ポッドの数を実行時に指定することも、ポッド・コンポーネントの識別を容易にするためにデプロイメントにラベルを適用することもできます。使用可能なオプションの完全なリストを確認するには、kubectl run -hを実行します。

新しいアプリケーション・デプロイメントによって1つ以上のポッドが作成されたことを確認するには、kubectl get podsコマンドを使用します。

$ kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-5f55779987-wd857   1/1       Running   0          1m

kubectl describeを使用して、実行中のコンテナ、基準となったイメージ、現在ポッドをホストしているノードなど、ポッドの詳細ビューを表示します。

$ kubectl describe pods
Name:               hello-world-5f55779987-wd857
Namespace:          default
Priority:           0
PriorityClassName:  <none>
Node:               worker1.example.com/192.0.2.11
Start Time:         Mon, 10 Dec 2018 08:25:17 -0800
Labels:             app=hello-world
                    pod-template-hash=5f55779987
Annotations:        <none>
Status:             Running
IP:                 10.244.1.3
Controlled By:      ReplicaSet/hello-world-5f55779987
Containers:
  nginx:
    Container ID:   docker://417b4b59f7005eb4b1754a1627e01f957e931c0cf24f1780cd94fa9949be1d31
    Image:          nginx
    Image ID:       docker-pullable://nginx@sha256:5d32f60db294b5deb55d078cd4feb410ad88e6fe77500c87d3970eca97f54dba
    Port:           <none>
    Host Port:      <none>
    State:          Running
      Started:      Mon, 10 Dec 2018 08:25:25 -0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-s8wj4 (ro)
Conditions:
  Type              Status   
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-s8wj4:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-s8wj4
    Optional:    false
QoS Class:       BestEffort  
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
....

ポッド・デプロイメントのスケーリング

実行中のものと同じポッドのインスタンス数を変更するには、kubectl scale deploymentコマンドを使用できます。

$ kubectl scale deployment --replicas=3 hello-world
deployment.apps/hello-world scaled

ポッド・インスタンスの数が適切にスケーリングされていることを確認できます。

$ kubectl get pods
NAME                           READY     STATUS    RESTARTS   AGE
hello-world-5f55779987-tswmg   1/1       Running   0          18s
hello-world-5f55779987-v8w5h   1/1       Running   0          26m
hello-world-5f55779987-wd857   1/1       Running   0          18s

アプリケーションのサービス・オブジェクトの公開

通常、多くのアプリケーションはポッド内またはポッド間で内部的に通信することのみが必要ですが、Kubernetesクラスタ外のクライアントがアプリケーションとインタフェースできるように、アプリケーションを外部的に公開することが必要になる場合があります。そのためには、そのデプロイメントのサービス定義を作成します。

サービス・オブジェクトを使用してデプロイメントを公開するには、使用する必要があるサービス・タイプを定義する必要があります。クラウドベースのロード・バランシング・サービスを使用しない場合は、サービス・タイプをNodePortに設定できます。NodePortサービスにより、クラスタ内のすべてのノードに対するパブリックIPアドレス上の専用ポートで、クラスタ内で実行中のアプリケーションを公開します。新しいサービスを作成するには、kubectl expose deploymentを使用します。

$ kubectl expose deployment hello-world --port 80 --type=LoadBalancer
service/hello-world exposed

kubectl get servicesを使用して、クラスタで実行中の各種サービスをリストし、そのサービスへのアクセスに必要なポート情報を取得します。

$ kubectl get services
NAME          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
hello-world   LoadBalancer   10.102.42.160   <pending>     80:31847/TCP   3s
kubernetes    ClusterIP      10.96.0.1       <none>        443/TCP        5h13m

この例の出力では、クラスタ内部のポート80へのトラフィックがNodePort 31847にマップされていることがわかります。サービスにアクセスするために使用できる外部IPは、<pending>としてリストされています。これは、ポート31847でクラスタ内のいずれかのノードの外部IPアドレスに接続すると、そのサービスにアクセスできることを意味します。

このガイドの例として、Webブラウザを開いて、クラスタ内のいずれかのノード(http://worker1.example.com:31847/など)を参照すると、NGINXデモンストレーション・アプリケーションが表示されます。

サービスまたはデプロイメントの削除

オブジェクトはKubernetes内で簡単に削除でき、環境をクリーンアップできます。オブジェクトを削除するには、kubectl deleteコマンドを使用します。

サービスを削除するには、サービス・オブジェクトおよび削除するサービス名を指定します。

$ kubectl delete services hello-world

デプロイメント全体、およびそのデプロイメントで実行中のすべてのポッド・レプリカを削除するには、デプロイメント・オブジェクトとデプロイメントの作成に使用した名前を指定します。

$ kubectl delete deployment hello-world

名前空間の操作

名前空間を使用すると、リソースの使用方法をさらに分割し、特定のユースケースに限定された環境を提供できます。Kubernetesでは、デフォルトで、Kubernetesのシステム・コンポーネント用の名前空間、および名前空間が定義されていない他のすべてのデプロイメント用に使用する標準名前空間が構成されます。

既存の名前空間を表示するには、kubectl get namespacesコマンドとkubectl describe namespacesコマンドを使用します。

kubectlコマンドでは、リクエスト専用の名前空間を設定していない場合、デフォルトの名前空間のリソースのみが表示されます。そのため、Kubernetesシステムに固有のポッドを表示する必要がある場合は、リクエストで--namespaceオプションを使用して、名前空間をkube-systemに設定します。たとえば、単一マスター・ノードのクラスタでは次のようにします。

$ kubectl get pods --namespace=kube-system
NAME                                         READY   STATUS    RESTARTS   AGE
coredns-6c77847dcf-77grm                     1/1     Running   2          5h26m
coredns-6c77847dcf-vtk8k                     1/1     Running   2          5h26m
etcd-master.example.com                      1/1     Running   3          5h25m
kube-apiserver-master.example.com            1/1     Running   4          5h25m
kube-controller-manager-master.example.com   1/1     Running   4          5h25m
kube-flannel-ds-4c285                        1/1     Running   0          115m
kube-flannel-ds-ds66r                        1/1     Running   0          115m
kube-proxy-5lssw                             1/1     Running   0          117m
kube-proxy-tv2mj                             1/1     Running   3          5h26m
kube-scheduler-master.example.com            1/1     Running   3          5h25m
kubernetes-dashboard-64458f66b6-q8dzh        1/1     Running   4          5h26m

5.2 YAMLデプロイメントを使用したポッド構成

ポッドの作成とそれに関連する要件を簡略化するために、デプロイメントを構成するすべての要素を定義するデプロイメント・ファイルを作成できます。このデプロイメントでは、ポッド内にコンテナを生成するために使用するイメージとランタイム要件(あれば)、構成するサービス形式でのKubernetesのネットワーキングと記憶域の要件、およびマウントする必要のあるボリュームを定義します。

デプロイメントの詳細は、https://kubernetes.io/docs/concepts/workloads/controllers/deployment/を参照してください。

Kubernetesデプロイメント・ファイルは簡単に共有でき、Kubernetesでは、リモートでホストされたファイルに基づいてデプロイメントを作成することもできます。これにより、誰もが数分でデプロイメントを実行できます。デプロイメントを作成するには、次のコマンドを実行します。

$ kubectl create -f https://example.com/deployment.yaml

次の例では、2つのYAMLデプロイメント・ファイルを作成します。最初のものは、データ・ストア用の永続ボリュームでMySQLサーバーを実行するデプロイメントを作成するために使用されます。また、クラスタ内の他のポッドでこのリソースを消費できるようにするサービスも構成します。

2番目のデプロイメントでは、MySQLサーバーに直接アクセスする別のポッドでphpMyAdminコンテナが実行されます。このデプロイメントでは、Kubernetesクラスタの外部からphpMyAdminインタフェースにアクセスできるように、NodePortサービスも作成されます。

次の例は、YAMLデプロイメント・ファイルを使用して、完全なアプリケーションを実行するために必要なスコープとリソースを定義する方法を示しています。

重要

ここに示す例は、デモンストレーションのみを目的としています。これらは本番使用を意図したものではなく、望ましいデプロイメントまたは構成の方法を表すものではありません。

MySQLサーバーのデプロイメント

MySQLサーバーのデプロイメントを作成するには、エディタで単一のテキスト・ファイルmysql-db.yamlを作成します。ここでの説明では、各オブジェクトのブレークダウンをテキスト・ファイルで定義されているとおりに示します。これらの定義はすべて同じファイルで記述できます。

コンテナ内でデータベースを実行する際の問題の1つは、コンテナが永続的ではないことです。つまり、データベースでホストされているデータは、コンテナ自体の外部に格納する必要があります。Kubernetesでは、これらの永続データ・ストアの設定を永続ボリュームの形式で処理します。様々な永続ボリューム・タイプがあります。本番環境では、クラスタ内のすべてのノードからアクセス可能ななんらかの共有ファイル・システムが最適な実装の選択肢となる場合がありますが、この単純な例では、hostPathタイプを使用します。hostPathタイプを使用すると、コンテナを実行中のノードでローカル・ディスクを使用できます。

永続ボリューム仕様では、この目的専用にする必要がある記憶域サイズおよびサポートする必要があるアクセス・モードを定義できます。hostPathタイプの場合、データを格納する必要があるパスも定義されます。この場合、デモンストレーションのためにパス/tmp/dataを使用します。これらのパラメータは、独自の要件に従って変更する必要があります。

永続ボリューム・オブジェクトのYAMLファイルの定義は、次のようになります。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: "/tmp/data"

永続ボリューム・オブジェクトは、Kubernetes内でリソースとして独自のエンティティです。ポッドでこのリソースを使用するには、アクセスをリクエストし、アクセスのためのクレームに適用されるルールに従う必要があります。これは、永続ボリューム・クレームの形式で定義されます。ポッドは永続ボリューム・クレームを実質的に記憶域としてマウントします。

永続ボリューム・クレーム・オブジェクトのYAMLファイルの定義は、次のようになります。

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-pv-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

デプロイメントのサービスを定義することが重要です。これにより、ポッドで実行する予定のアプリケーションで使用されるTCPポートを指定します。この場合、MySQLサーバーはポート3306でリスニングします。最も重要なことは、サービスの名前は、実行中のノードに関係なく、クラスタ内のこのサービスにアクセスするために他のデプロイメントで使用できることです。このサービスでは、クラスタ内部ネットワークで実行中の他のコンポーネントのみがアクセスできるよう、デフォルトのClusterIPタイプが使用されるため、サービス・タイプは指定されません。このようにして、MySQLサーバーは、リクエストに対してKubernetesクラスタ内のポッドで実行中のコンテナから分離されます。

YAMLファイルのサービス定義は次のようになります。

---
apiVersion: v1
kind: Service
metadata:
  name: mysql-service
  labels:
    app: mysql
spec:
    selector:
      app: mysql
    ports:
      - port: 3306
    clusterIP: None

MySQLサーバー・インスタンスは、mysql/mysql-server:latest Dockerイメージを使用して、ポッドで実行中のDockerコンテナとして簡単に作成できます。ポッド定義で、この目的で以前に定義した永続ボリューム・クレームをアタッチするためのボリューム情報を指定します。また、使用する必要のあるイメージ、使用するコンテナ・ポート、ボリューム・マウント・ポイントおよびコンテナの実行に必要なすべての環境変数を含むコンテナ・パラメータも指定します。この場合、永続ボリューム・クレームを実行中の各コンテナ・インスタンスの/var/lib/mysqlにマウントし、イメージでの必要に応じて、環境変数としてMYSQL_ROOT_PASSWORD値を指定します。

---
apiVersion: v1
kind: Pod
metadata:
  name: mysql
  labels:
    app: mysql
spec:
  volumes:
    - name: mysql-pv-storage
      persistentVolumeClaim:
       claimName: mysql-pv-claim
  containers:
    - image: mysql:5.6 
      name: mysql  
      ports:
        - containerPort: 3306
          name: mysql
      volumeMounts:
        - mountPath: /var/lib/mysql
          name: mysql-pv-storage
      env:
        - name: MYSQL_ROOT_PASSWORD   
          value: "password"

MYSQL_ROOT_PASSWORD環境変数に指定されたpassword値を、セキュリティ要件に適したより適切な代替値に置き換えます。

YAMLデプロイメント・ファイルを作成したら、保存してから次を実行します。

$ kubectl create -f mysql-db.yaml
persistentvolume/mysql-pv-volume created
persistentvolumeclaim/mysql-pv-claim created
service/mysql-service created
pod/mysql created

ファイルで定義されているすべてのリソースおよびコンポーネントは、Kubernetesで作成およびロードされます。kubectlコマンドを使用して、必要に応じて各コンポーネントの詳細を表示できます。

phpMyAdminデプロイメント

デプロイメントで相互に提供されるサービスを相互接続および消費する方法を示すために、この例の最初の部分でデプロイしたバックエンドMySQLサーバーに接続する、phpMyAdmin Dockerインスタンスを設定できます。

phpMyAdminデプロイメントでは、標準のDockerイメージを使用してポッドで実行されるコンテナを作成し、また、クラスタ内の任意のノードからWebインタフェースにアクセスできるようにするNodePortサービスも定義します。

phpmyadmin.yamlという新しいファイルを作成してエディタで開き、次のテキストで説明されている2つのコンポーネント定義を追加します。

まず、サービス定義を作成します。このサービスでは、コンテナで使用するポート、および内部Kubernetesクラスタ・ネットワーク内でこのポートをマップするtargetPortを定義します。また、サービス・タイプを指定してNodePortに設定し、いずれかのクラスタ・ノードおよびNodePortサービス・タイプにより提供されるポート転送サービスを使用して、クラスタ・ネットワークの外部からサービスにアクセスできるようにします。

宣言は次のようになります。

apiVersion: v1
kind: Service
metadata:
  labels:
    name: phpmyadmin
  name: phpmyadmin
spec:
  ports:
    - port: 80
      targetPort: 80
  selector:
    name: phpmyadmin
  type: NodePort

最後に、phpMyAdminコンテナがロードされるポッドを定義します。ここでは、このコンテナに使用する必要のあるDockerイメージ、およびコンテナで使用するポートを指定できます。このイメージの実行に必要な環境変数を指定することもできます。特に、Dockerイメージでは、環境変数PMA_HOSTを設定して、MySQLサーバーのIPアドレスまたは解決可能なドメイン名を指定する必要があります。ここではどのIPアドレスを使用する必要があるかは推測できないため、ここで値としてmysql-service名を指定することで、Kubernetesにより自動的に処理できます。Kubernetesでは、このサービス定義を使用して、2つのポッドを自動的にリンクします。

ポッド定義は次のようになります。

---
apiVersion: v1
kind: Pod
metadata:
  name: phpmyadmin
  labels:
    name: phpmyadmin
spec:
  containers:
    - name: phpmyadmin
      image: phpmyadmin/phpmyadmin
      env:
        - name: PMA_HOST
          value: mysql-service
      ports:
        - containerPort: 80
          name: phpmyadmin

ファイルを保存してから、kubectl createコマンドを実行して、YAMLファイルをデプロイメントにロードします。

$ kubectl create -f phpmyadmin.yaml
service/phpmyadmin created
pod/phpmyadmin created

これが期待どおりに機能することを確認するには、NodePortサービスによって提供されるポート転送に使用されるポートを特定する必要があります。

$ kubectl get services phpmyadmin
NAME         CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
phpmyadmin   10.110.16.56   <nodes>       80:31485/TCP   1d

この出力例では、クラスタ・ネットワークのポート80が各クラスタ・ノードのポート30582にマップされます。ブラウザを開き、指定されたポートマッピング上のいずれかのクラスタ・ノードを指定します。たとえば、http://master.example.com:31485/です。phpMyAdminログイン・ページが表示され、MySQLサーバーをデプロイしたときにMYSQL_ROOT_PASSWORD環境変数として指定したパスワードを使用し、rootとしてphpMyAdminにログインできます。

5.3 永続記憶域の使用方法

データベース・デプロイメントに永続記憶域を使用する概念については、前の項第5.2項「YAMLデプロイメントを使用したポッド構成」を参照してください。データベースなどのステートフル・アプリケーションを操作する場合は、永続記憶域が不可欠です。これは、コンテナやさらにはポッド自体のライフサイクルを超えるデータを保持できることが重要であるためです。

Kubernetesでは永続記憶域はPersistentVolumeオブジェクトの形式で処理され、PersistentVolumeClaimを使用してポッドにバインドされます。PersistentVolumeは、ローカルにホストすることも、ネットワーク・ストレージ・デバイスやネットワーク・ストレージ・サービスでホストすることもできます。

デモンストレーションまたは小規模なデプロイメントでは、hostPath永続ボリューム・タイプによりローカル・ディスクにデータを格納すると便利ですが、一般的なKubernetes環境では複数のホストが必要となり、かつ、通常はなんらかのタイプのネットワーク・ストレージが含まれます。ネットワーク・ストレージを使用すると、レジリエンスの確保に役立ち、クラスタ環境を最大限に活用できます。ポッドを実行中のノードに障害が発生した場合は、代替ノードで新しいポッドを開始でき、ストレージ・アクセスを再開できます。このことは、レプリカ設定が正しく構成されているデータベース環境にとって特に重要です。

この項では、永続記憶域の構成に使用されるKubernetesコンポーネントについて、ネットワーク・ストレージを使用したデータのホストを中心に引き続き説明します。

5.3.1 永続記憶域の概念

Kubernetesでは、永続記憶域はPersistentVolumeサブシステムを使用して提供されます。永続記憶域を構成するには、次の用語を理解しておく必要があります。

  • PersistentVolume。  PersistentVolumeにより、使用される記憶域のタイプ、およびそれに接続するために使用する方法を定義します。これは、データの格納に使用される実際のディスクまたはネットワーク・ストレージ・サービスです。

  • PersistentVolumeClaim。  PersistentVolumeClaimにより、コンシューマ(ポッドなど)でPersistentVolumeのバインドに使用するパラメータを定義します。このクレームでは、コンシューマのリソースに適用する必要のある割当て制限およびアクセス・モードを指定できます。ポッドは、PersistentVolumeClaimを使用してボリュームにアクセスし、このボリュームをマウントできます。

  • StorageClass。  StorageClassは、ボリューム・プラグインを指定するオブジェクトです。これは、ユーザーがPersistentVolumeの記憶域を事前構成しなくてもPersistentVolumeClaimを定義できるようにする、プロビジョナとも呼ばれます。これを使用すると、PersistentVolumeClaimのライフサイクルに対して動的にプロビジョニングできるプール済リソースとして、類似したボリューム・タイプにアクセスできます。

PersistentVolumeは、静的または動的にプロビジョニングできます。

静的PersistentVolumeは手動で作成され、実際の記憶域へのアクセスに必要な詳細を含み、関連するPersistentVolumeClaimを持つ任意のポッドによって直接使用できます。

動的PersistentVolumeは、PersistentVolumeClaimが既存の静的PersistentVolumeと一致せず、既存のStorageClassがクレームでリクエストされた場合に自動的に生成されます。StorageClassは、動的にアクセス可能な記憶域のプールをホストするように定義できます。StorageClassの作成はオプション・ステップとなり、動的プロビジョニングを使用する場合にのみ必要です。

永続記憶域をプロビジョニングするプロセスは、次のとおりです。

  1. PersistentVolumeまたはStorageClassを作成します。

  2. PersistentVolumeClaimを作成します。

  3. PersistentVolumeClaimを使用するようにポッドを構成します。

この例では、記憶域を手動で構成し、静的プロビジョニングを使用していることを前提としています。いずれの場合も、PersistentVolumeが構成され、PersistentVolumeClaimが作成されて、最後にPersistentVolumeClaimを使用するためのポッドが作成されます。

5.3.2 NFSの構成

この例では、クラスタ内のすべてのノードへのアクセスを許可するようにNFSアプライアンスがすでに構成されていることを前提としています。NFSアプライアンスがOracle Cloud Infrastructureでホストされている場合、Kubernetesノードのホストに使用する仮想クラウド・ネットワーク(VCN)サブネットのセキュリティ・リストに、イングレス・ルールを作成する必要があります。NFSアクセスおよびNFSマウント用にポート2049および20049でトラフィックを許可するように、ルールを設定する必要があります。

クラスタ内の各ワーカー・ノードには、nfs-utilsパッケージもインストールされている必要があります。

# yum install nfs-utils

次のステップでは、オブジェクトごとにYAMLファイルを使用したデプロイメントについて説明します。

  1. YAMLファイルにPhysicalVolumeオブジェクトを作成します。たとえば、マスター・ノードで、ファイルpv-nfs.ymlを作成してエディタで開き、次のコンテンツを含めます。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: nfs
    spec:
      capacity:
        storage: 1Gi
      accessModes:
        - ReadWriteMany
      nfs:
        server: 192.0.2.100
        path: "/nfsshare"

    1Giを、使用可能な記憶域のサイズに置き換えます。192.0.2.100を、ご使用の環境のNFSアプライアンスのIPアドレスに置き換えます。/nfsshareを、NFSアプライアンス上のエクスポートされた共有名に置き換えます。

  2. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してPersistentVolumeを作成します。

    $ kubectl create -f pv-nfs.yml
    persistentvolume/nfs created
  3. YAMLファイルにPhysicalVolumeClaimオブジェクトを作成します。たとえば、マスター・ノードで、ファイルpvc-nfs.ymlを作成してエディタで開き、次のコンテンツを含めます。

    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: nfs
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 1Gi

    accessModesは、必要に応じてReadWriteMany値を変更することで変更できます。storageオプションの値を1Giから他の値に変更することにより、このクレームで使用可能な割当て制限を変更することもできます。

  4. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してPersistentVolumeClaimを作成します。

    $ kubectl create -f pvc-nfs.yml
    persistentvolumeclaim/nfs created
  5. PersistentVolumeおよびPersistentVolumeClaimが正しく作成され、PersistentVolumeClaimが正しいボリュームにバインドされていることを確認します。

    $ kubectl get pv,pvc
    NAME      CAPACITY   ACCESSMODES   RECLAIMPOLICY  STATUS   CLAIM         STORAGECLASS   REASON    AGE
    pv/nfs    1Gi        RWX           Retain         Bound    default/nfs                            7m
    
    NAME          STATUS    VOLUME    CAPACITY   ACCESSMODES   STORAGECLASS   AGE
    pvc/nfs       Bound     nfs       1Gi        RWX                          2m
  6. この時点で、PersistentVolumeClaimを使用してPersistentVolumeにバインドし、そこで使用可能なリソースを使用できるポッドを設定できます。次のステップの例では、ReplicationControllerを使用して、共有リソースを含むマウントパスへのPersistentVolumeのマウントにPersistentVolumeClaimを使用したWebサーバーを実行する、2つのレプリカ・ポッドを設定します。

    1. YAMLファイルにReplicationControllerオブジェクトを作成します。たとえば、マスター・ノードで、ファイルrc-nfs.ymlを作成してエディタで開き、次のコンテンツを含めます。

      apiVersion: v1
      kind: ReplicationController
      metadata:
        name: rc-nfs-test
      spec:
        replicas: 2
        selector:
          app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx
              ports:
                - name: nginx
                  containerPort: 80
              volumeMounts:
                  - name: nfs
                    mountPath: "/usr/share/nginx/html"
            volumes:
            - name: nfs
              persistentVolumeClaim:
                claimName: nfs
    2. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してReplicationControllerを作成します。

      $ kubectl create -f rc-nfs.yml
      replicationcontroller/rc-nfs-test created
    3. ポッドが作成されたことを確認します。

      $ kubectl get pods
      NAME                READY     STATUS    RESTARTS   AGE
      rc-nfs-test-c5440   1/1       Running   0          54s
      rc-nfs-test-8997k   1/1       Running   0          54s
    4. NFSアプライアンスで、/nfsshareエクスポートに索引ファイルを作成し、Webサーバー・ポッドがこのリソースにアクセスできることをテストします。次に例を示します。

      $ echo "This file is available on NFS" > /nfsshare/index.html
    5. Webサーバーの出力を確認できるようWebサーバー・ポートを公開するサービスを作成することも、各ポッドの/usr/share/nginx/htmlフォルダのコンテンツを単純に表示することもできます(NFS共有は、各インスタンスでこのディレクトリにマウントする必要があるため)。たとえば、マスター・ノードで次のようにします。

      $ kubectl exec rc-nfs-test-c5440 cat /usr/share/nginx/html/index.html
      This file is available on NFS
      $ kubectl exec rc-nfs-test-8997k cat /usr/share/nginx/html/index.html
      This file is available on NFS

さらに検証する場合は、ポッドが実行されているノードを停止します。新しいポッドが実行中のノードで生成され、即座にNFS共有のデータにアクセス可能となります。このようにして、ノード障害時のデータの永続性およびレジリエンスを確認できます。

5.3.3 iSCSIの構成

この例では、ブロック・デバイスをiSCSI LUNとしてクラスタ内のすべてのノードに公開するようにiSCSIサービスがすでに構成されていることを前提としています。iSCSIサーバーがOracle Cloud Infrastructureでホストされている場合、Kubernetesノードのホストに使用する仮想クラウド・ネットワーク(VCN)サブネットのセキュリティ・リストに、イングレス・ルールを作成する必要があります。ポート860および3260でトラフィックを許可するように、ルールを設定する必要があります。

クラスタ内の各ワーカー・ノードには、iscsi-initiator-utilsパッケージもインストールされている必要があります。

# yum install iscsi-initiator-utils

デバイスのイニシエータ名(iqn)を追加するには、クラスタのすべてのノードで/etc/iscsi/initiatorname.iscsiファイルを手動で編集する必要があります。このファイルを編集したら、iscsidサービスを再起動します。

Oracle Linux 7でのiSCSIの構成の詳細は、Oracle® Linux 7: 管理者ガイドを参照してください。

次のステップでは、オブジェクトごとにYAMLファイルを使用したデプロイメントについて説明します。

  1. YAMLファイルにPhysicalVolumeオブジェクトを作成します。たとえば、マスター・ノードで、ファイルpv-iscsi.ymlを作成してエディタで開き、次のコンテンツを含めます。

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: iscsi-pv
    spec:
      capacity:
        storage: 12Gi
      accessModes:
        - ReadWriteOnce
      iscsi:
         targetPortal: 192.0.2.100:3260
         iqn: iqn.2017-10.local.example.server:disk1
         lun: 0
         fsType: 'ext4'
         readOnly: false

    12Giを、使用可能な記憶域のサイズに置き換えます。192.0.2.100:3260を、ご使用の環境のiSCSIターゲットのIPアドレスとポート番号に置き換えます。iqn.2017-10.local.example.server:disk1を、iSCSI経由で使用するデバイスのiqnに置き換えます。

  2. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してPersistentVolumeを作成します。

    $ kubectl create -f pv-iscsi.yml
    persistentvolume/iscsi-pv created
  3. YAMLファイルにPhysicalVolumeClaimオブジェクトを作成します。たとえば、マスター・ノードで、ファイルpvc-iscsi.ymlを作成してエディタで開き、次のコンテンツを含めます。

    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: iscsi-pvc
    spec:
      accessModes:
        - ReadWriteOnce
      resources:
        requests:
          storage: 12Gi

    accessModesは、必要に応じてReadWriteOnce値を変更することで変更できます。iSCSIでサポートされているモードには、ReadWriteOnceおよびReadOnlyManyがあります。storageオプションの値を12Giから他の値に変更することにより、このクレームで使用可能な割当て制限を変更することもできます。

    iSCSIでは、読取り操作と書込み操作の両方がサポートされるため、すべてのポッドを単一ノード上でホストするよう制限されることに注意してください。スケジューラにより、同じPersistentVolumeClaimを含むポッドは、確実に同じワーカー・ノード上で自動的に実行されます。

  4. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してPersistentVolumeClaimを作成します。

    $ kubectl create -f pvc-iscsi.yml
    persistentvolumeclaim/iscsi-pvc created
  5. PersistentVolumeおよびPersistentVolumeClaimが正しく作成され、PersistentVolumeClaimが正しいボリュームにバインドされていることを確認します。

    $ kubectl get pv,pvc
    NAME         CAPACITY ACCESSMODES  RECLAIMPOLICY STATUS  CLAIM          STORAGECLASS REASON  AGE
    pv/iscsi-pv  12Gi     RWX          Retain        Bound   default/iscsi-pvc                   25s
    
    NAME            STATUS    VOLUME     CAPACITY   ACCESSMODES   STORAGECLASS   AGE
    pvc/iscsi-pvc   Bound     iscsi-pv   12Gi       RWX                          21s
    
  6. この時点で、PersistentVolumeClaimを使用してPersistentVolumeにバインドし、そこで使用可能なリソースを使用できるポッドを設定できます。次の例では、ReplicationControllerを使用して、共有リソースを含むマウントパスへのPersistentVolumeのマウントにPersistentVolumeClaimを使用したWebサーバーを実行する、2つのレプリカ・ポッドを設定します。

    1. YAMLファイルにReplicationControllerオブジェクトを作成します。たとえば、マスター・ノードで、ファイルrc-iscsi.ymlを作成してエディタで開き、次のコンテンツを含めます。

      apiVersion: v1
      kind: ReplicationController
      metadata:
        name: rc-iscsi-test
      spec:
        replicas: 2
        selector:
          app: nginx
        template:
          metadata:
            labels:
              app: nginx
          spec:
            containers:
            - name: nginx
              image: nginx
              ports:
                - name: nginx
                  containerPort: 80
              volumeMounts:
                  - name: iscsi
                    mountPath: "/usr/share/nginx/html"
            volumes:  
            - name: iscsi
              persistentVolumeClaim:
                claimName: iscsi-pvc
    2. マスター・ノードで次のコマンドを実行し、作成したYAMLファイルを使用してReplicationControllerを作成します。

      $ kubectl create -f rc-iscsi.yml
      replicationcontroller "rc-iscsi-test" created
    3. ポッドが作成されたことを確認します。

      $ kubectl get pods
      NAME                  READY     STATUS    RESTARTS   AGE
      rc-iscsi-test-05kdr   1/1       Running   0          9m
      rc-iscsi-test-wv4p5   1/1       Running   0          9m
    4. iSCSI LUNをマウント可能な任意のホストで、LUNをマウントして索引ファイルを作成し、Webサーバー・ポッドがこのリソースにアクセスできることをテストします。次に例を示します。

      # mount /dev/disk/by-path/ip-192.0.2.100\:3260-iscsi-iqn.2017-10.local.example.server\:disk1-lun-0 /mnt
      $ echo "This file is available on iSCSI" > /mnt/index.html
    5. Webサーバーの出力を確認できるようWebサーバー・ポートを公開するサービスを作成することも、各ポッドの/usr/share/nginx/htmlフォルダのコンテンツを単純に表示することもできます(NFS共有は、各インスタンスでこのディレクトリにマウントする必要があるため)。たとえば、マスター・ノードで次のようにします。

      $ kubectl exec rc-nfs-test-c5440 cat /usr/share/nginx/html/index.html
      This file is available on iSCSI
      $ kubectl exec rc-nfs-test-8997k cat /usr/share/nginx/html/index.html
      This file is available on iSCSI