著者は、 Write for DOnations プログラムの一環として、 Open Internet / FreeSpeechを選択して寄付を受け取りました。

序章

Kubernetesは、オープンソースのコンテナオーケストレーションシステムです。 これにより、ダウンタイムを気にすることなく、コンテナーを作成、更新、およびスケーリングできます。

PHPアプリケーションを実行するために、NginxはPHP-FPMのプロキシとして機能します。 この設定を単一のコンテナにコンテナ化するのは面倒なプロセスになる可能性がありますが、Kubernetesは両方のサービスを別々のコンテナで管理するのに役立ちます。 Kubernetesを使用すると、コンテナを再利用および交換可能に保つことができ、新しいバージョンのNginxまたはPHPがリリースされるたびにコンテナイメージを再構築する必要がなくなります。

このチュートリアルでは、PHP 7アプリケーションをKubernetesクラスターにデプロイし、NginxとPHP-FPMを別々のコンテナーで実行します。 また、DigitalOceanのBlockStorage システムを使用して、構成ファイルとアプリケーションコードをコンテナーイメージの外部に保持する方法についても学習します。 このアプローチでは、イメージを再構築するのではなく、構成ボリュームを渡すことで、Web/プロキシサーバーを必要とするすべてのアプリケーションでNginxイメージを再利用できます。

注:このチュートリアルは、 Kubeadm で作成されたKubernetesクラスターでテストされています。これは、DigitalOcean Managed Kubernetes(DOKS)製品とは大きく異なります。 DOKSを使用している場合は、公式の DigitalOceanKubernetes製品ドキュメントで最新情報とチュートリアルを確認してください。

前提条件

  • Kubernetesオブジェクトの基本的な理解。 詳細については、Kubernetesの概要の記事をご覧ください。
  • Ubuntu16.04で実行されているKubernetesクラスター。 これを設定するには、 Ubuntu16.04チュートリアルでKubeadmを使用してKubernetes1.10クラスターを作成する方法を実行します。
  • DigitalOceanアカウントと、ストレージボリュームを作成するための読み取りおよび書き込み権限を持つAPIアクセストークン。 APIアクセストークンがない場合は、ここから作成できます。
  • Githubなどの公的にアクセス可能なURLでホストされているアプリケーションコード。

ステップ1—PHP-FPMおよびNginxサービスの作成

このステップでは、PHP-FPMおよびNginxサービスを作成します。 サービスにより、クラスター内から一連のポッドにアクセスできます。 クラスタ内のサービスは、IPアドレスを必要とせずに、名前を介して直接通信できます。 PHP-FPMサービスはPHP-FPMポッドへのアクセスを許可し、NginxサービスはNginxポッドへのアクセスを許可します。

NginxポッドはPHP-FPMポッドをプロキシするため、サービスにそれらを見つける方法を指示する必要があります。 IPアドレスを使用する代わりに、Kubernetesの自動サービス検出を利用して、人間が読み取れる名前を使用してリクエストを適切なサービスにルーティングします。

サービスを作成するには、オブジェクト定義ファイルを作成します。 すべてのKubernetesオブジェクト定義は、少なくとも次のアイテムを含むYAMLファイルです。

  • apiVersion:定義が属するKubernetesAPIのバージョン。
  • kind:このファイルが表すKubernetesオブジェクト。 たとえば、podまたはserviceです。
  • metadata:これには、オブジェクトのnameと、それに適用する可能性のあるlabelsが含まれます。
  • spec:これには、コンテナーイメージやコンテナーへのアクセス元のポートなど、作成するオブジェクトの種類に応じた特定の構成が含まれます。

まず、Kubernetesオブジェクト定義を保持するディレクトリを作成します。

マスターノードにSSHで接続し、Kubernetesオブジェクト定義を保持するdefinitionsディレクトリを作成します。

  1. mkdir definitions

新しく作成されたdefinitionsディレクトリに移動します。

  1. cd definitions

php_service.yamlファイルを作成して、PHP-FPMサービスを作成します。

  1. nano php_service.yaml

kindServiceとして設定して、このオブジェクトがサービスであることを指定します。

php_service.yaml
...
apiVersion: v1
kind: Service

PHP-FPMへのアクセスを提供するため、サービスにphpという名前を付けます。

php_service.yaml
...
metadata:
  name: php

さまざまなオブジェクトをラベルで論理的にグループ化します。 このチュートリアルでは、ラベルを使用して、オブジェクトをフロントエンドやバックエンドなどの「層」にグループ化します。 PHPポッドはこのサービスの背後で実行されるため、tier: backendというラベルを付けます。

php_service.yaml
...
  labels:
    tier: backend

サービスは、selectorラベルを使用して、アクセスするポッドを決定します。 これらのラベルに一致するポッドは、ポッドがサービスの前に作成されたか後に作成されたかに関係なく、サービスされます。 チュートリアルの後半で、ポッドのラベルを追加します。

tier: backendラベルを使用して、ポッドをバックエンド層に割り当てます。 また、app: phpラベルを追加して、このポッドがPHPを実行することを指定します。 metadataセクションの後にこれらの2つのラベルを追加します。

php_service.yaml
...
spec:
  selector:
    app: php
    tier: backend

次に、このサービスへのアクセスに使用するポートを指定します。 このチュートリアルでは、ポート9000を使用します。 specの下のphp_service.yamlファイルに追加します。

php_service.yaml
...
  ports:
    - protocol: TCP
      port: 9000

完成したphp_service.yamlファイルは次のようになります。

php_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: php
  labels:
    tier: backend
spec:
  selector:
    app: php
    tier: backend
  ports:
  - protocol: TCP
    port: 9000

CTRL + oを押してファイルを保存し、CTRL + xを押してnanoを終了します。

サービスのオブジェクト定義を作成したので、サービスを実行するには、kubectl applyコマンドと-f引数を使用して、php_service.yamlファイルを指定します。

サービスを作成します。

  1. kubectl apply -f php_service.yaml

この出力は、サービスの作成を確認します。

Output
service/php created

サービスが実行されていることを確認します。

  1. kubectl get svc

PHP-FPMサービスが実行されていることがわかります。

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m php ClusterIP 10.100.59.238 <none> 9000/TCP 5m

Kubernetesがサポートするさまざまなサービスタイプがあります。 phpサービスは、デフォルトのサービスタイプClusterIPを使用します。 このサービスタイプは内部IPを割り当て、クラスター内からのみサービスに到達できるようにします。

PHP-FPMサービスの準備ができたので、Nginxサービスを作成します。 nginx_service.yamlという名前の新しいファイルを作成し、エディターで開きます。

  1. nano nginx_service.yaml

このサービスはNginxポッドを対象としているため、nginxという名前を付けます。 また、バックエンド層に属するtier: backendラベルを追加します。

nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend

phpサービスと同様に、セレクターラベルapp: nginxおよびtier: backendでポッドをターゲットにします。 デフォルトのHTTPポートであるポート80でこのサービスにアクセスできるようにします。

nginx_service.yaml
...
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80

Nginxサービスは、DropletのパブリックIPアドレスからインターネットにパブリックにアクセスできます。 your_public_ipは、 DigitalOcean CloudPanelから見つけることができます。 spec.externalIPsの下に、次を追加します。

nginx_service.yaml
...
spec:
  externalIPs:
  - your_public_ip

nginx_service.yamlファイルは次のようになります。

nginx_service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  selector:
    app: nginx
    tier: backend
  ports:
  - protocol: TCP
    port: 80
  externalIPs:
  - your_public_ip    

ファイルを保存して閉じます。 Nginxサービスを作成します。

  1. kubectl apply -f nginx_service.yaml

サービスの実行中は、次の出力が表示されます。

Output
service/nginx created

以下を実行すると、実行中のすべてのサービスを表示できます。

  1. kubectl get svc

出力にPHP-FPMサービスとNginxサービスの両方が表示されます。

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 13m nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 50s php ClusterIP 10.100.59.238 <none> 9000/TCP 8m

実行できるサービスを削除する場合は、次の点に注意してください。

  1. kubectl delete svc/service_name

PHP-FPMおよびNginxサービスを作成したので、アプリケーションコードと構成ファイルを保存する場所を指定する必要があります。

ステップ2—DigitalOceanストレージプラグインのインストール

Kubernetesは、環境にストレージスペースを作成できるさまざまなストレージプラグインを提供します。 このステップでは、 DigitalOceanストレージプラグインをインストールして、DigitalOceanにブロックストレージを作成します。 インストールが完了すると、ブロックストレージの作成に使用するdo-block-storageという名前のストレージクラスが追加されます。

まず、DigitalOceanAPIトークンを保存するようにKubernetesシークレットオブジェクトを設定します。 シークレットオブジェクトは、SSHキーやパスワードなどの機密情報を、同じ名前空間内の他のKubernetesオブジェクトと共有するために使用されます。 名前空間は、Kubernetesオブジェクトを論理的に分離する方法を提供します。

secret.yamlという名前のファイルをエディターで開きます。

  1. nano secret.yaml

シークレットオブジェクトにdigitaloceanという名前を付け、kube-systemnamespaceに追加します。 kube-system名前空間は、Kubernetesの内部サービスのデフォルトの名前空間であり、さまざまなコンポーネントを起動するためにDigitalOceanストレージプラグインによっても使用されます。

secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system

シークレットは、specキーの代わりに、dataまたはstringDataキーを使用して必要な情報を保持します。 dataパラメーターは、取得時に自動的にデコードされるbase64エンコードデータを保持します。 stringDataパラメーターは、作成または更新中に自動的にエンコードされるエンコードされていないデータを保持し、シークレットを取得するときにデータを出力しません。 このチュートリアルでは、便宜上stringDataを使用します。

access-tokenstringDataとして追加します。

secret.yaml
...
stringData:
  access-token: your-api-token

ファイルを保存して終了します。

secret.yamlファイルは次のようになります。

secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: digitalocean
  namespace: kube-system
stringData:
  access-token: your-api-token

シークレットを作成します。

  1. kubectl apply -f secret.yaml

シークレットを作成すると、次の出力が表示されます。

Output
secret/digitalocean created

次のコマンドで秘密を表示できます。

  1. kubectl -n kube-system get secret digitalocean

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

Output
NAME TYPE DATA AGE digitalocean Opaque 1 41s

Opaqueタイプは、このシークレットが読み取り専用であることを意味します。これは、stringDataシークレットの標準です。 詳しくはシークレットデザインスペックをご覧ください。 DATAフィールドには、このシークレットに保存されているアイテムの数が表示されます。 この場合、1つのキーが保存されているため、1と表示されます。

シークレットが配置されたので、DigitalOceanブロックストレージプラグインをインストールします。

  1. kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.0.yaml

次のような出力が表示されます。

Output
storageclass.storage.k8s.io/do-block-storage created serviceaccount/csi-attacher created clusterrole.rbac.authorization.k8s.io/external-attacher-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-attacher-role created service/csi-attacher-doplug-in created statefulset.apps/csi-attacher-doplug-in created serviceaccount/csi-provisioner created clusterrole.rbac.authorization.k8s.io/external-provisioner-runner created clusterrolebinding.rbac.authorization.k8s.io/csi-provisioner-role created service/csi-provisioner-doplug-in created statefulset.apps/csi-provisioner-doplug-in created serviceaccount/csi-doplug-in created clusterrole.rbac.authorization.k8s.io/csi-doplug-in created clusterrolebinding.rbac.authorization.k8s.io/csi-doplug-in created daemonset.apps/csi-doplug-in created

DigitalOceanストレージプラグインをインストールしたので、アプリケーションコードと構成ファイルを保持するためのブロックストレージを作成できます。

ステップ3—永続ボリュームの作成

シークレットを配置し、ブロックストレージプラグインをインストールすると、永続ボリュームを作成する準備が整います。 永続ボリューム(PV)は、ポッドのライフサイクルとは無関係に存続する、指定されたサイズのブロックストレージです。 永続ボリュームを使用すると、アプリケーションコードを失うことを心配せずに、ポッドを管理または更新できます。 永続ボリュームには、PersistentVolumeClaimまたはPVCを使用してアクセスします。これにより、PVが必要なパスにマウントされます。

code_volume.yamlという名前のファイルをエディターで開きます。

  1. nano code_volume.yaml

次のパラメータと値をファイルに追加して、PVCcodeに名前を付けます。

code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code

PVCのspecには、次のアイテムが含まれています。

  • accessModesこれはユースケースによって異なります。
      ReadWriteOnce –単一ノードによる読み取り/書き込みとしてボリュームをマウントしますReadOnlyMany –多くのノードによる読み取り専用としてボリュームをマウントしますReadWriteMany –多くのノードによる読み取り/書き込みとしてボリュームをマウントします
  • resources –必要なストレージスペース

DigitalOceanブロックストレージは単一ノードにのみマウントされるため、accessModesReadWriteOnceに設定します。 このチュートリアルでは、少量のアプリケーションコードを追加する方法について説明します。したがって、このユースケースでは1GBで十分です。 ボリュームに大量のコードまたはデータを保存する予定の場合は、要件に合わせてstorageパラメーターを変更できます。 ボリュームの作成後にストレージの量を増やすことはできますが、ディスクの縮小はサポートされていません。

code_volume.yaml
...
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

次に、Kubernetesがボリュームのプロビジョニングに使用するストレージクラスを指定します。 DigitalOceanブロックストレージプラグインによって作成されたdo-block-storageクラスを使用します。

code_volume.yaml
...
  storageClassName: do-block-storage

code_volume.yamlファイルは次のようになります。

code_volume.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: code
spec:
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: do-block-storage

ファイルを保存して終了します。

kubectlを使用して、codePersistentVolumeClaimを作成します。

  1. kubectl apply -f code_volume.yaml

次の出力は、オブジェクトが正常に作成され、1GBのPVCをボリュームとしてマウントする準備ができていることを示しています。

Output
persistentvolumeclaim/code created

使用可能な永続ボリューム(PV)を表示するには:

  1. kubectl get pv

PVが一覧表示されます。

Output
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13 1Gi RWO Delete Bound default/code do-block-storage 2m

上記のフィールドは、Reclaim PolicyStatusを除いて、構成ファイルの概要です。 Reclaim Policyは、PVにアクセスしているPVCが削除された後、PVで何が行われるかを定義します。 Deleteは、KubernetesとDigitalOceanインフラストラクチャからPVを削除します。 Reclaim PolicyStatusの詳細については、KubernetesPVドキュメントをご覧ください。

DigitalOceanブロックストレージプラグインを使用して、永続ボリュームを正常に作成しました。 永続ボリュームの準備ができたので、デプロイメントを使用してポッドを作成します。

ステップ4—PHP-FPMデプロイメントの作成

このステップでは、Deploymentを使用してPHP-FPMポッドを作成する方法を学習します。 デプロイメントは、 ReplicaSets を使用してポッドを作成、更新、および管理するための統一された方法を提供します。 更新が期待どおりに機能しない場合、Deploymentはポッドを前のイメージに自動的にロールバックします。

Deployment spec.selectorキーは、管理するポッドのラベルを一覧表示します。 また、templateキーを使用して、必要なポッドを作成します。

このステップでは、Initコンテナの使用法も紹介します。 Init Containers は、ポッドのtemplateキーで指定された通常のコンテナーの前に、1つ以上のコマンドを実行します。 このチュートリアルでは、InitContainerがwgetを使用してGitHubGistからサンプルindex.phpファイルをフェッチします。 サンプルファイルの内容は次のとおりです。

index.php
<?php
echo phpinfo(); 

デプロイメントを作成するには、エディターでphp_deployment.yamlという新しいファイルを開きます。

  1. nano php_deployment.yaml

このデプロイメントはPHP-FPMポッドを管理するため、デプロイメントオブジェクトにphpという名前を付けます。 ポッドはバックエンド層に属しているため、tier: backendラベルを使用して、デプロイメントをこのグループにグループ化します。

php_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend

デプロイメントspecの場合、replicasパラメーターを使用して、このポッドのコピーをいくつ作成するかを指定します。 replicasの数は、ニーズと利用可能なリソースによって異なります。 このチュートリアルでは、レプリカを1つ作成します。

php_deployment.yaml
...
spec:
  replicas: 1

この展開では、app: phpおよびtier: backendラベルに一致するポッドを管理します。 selectorキーの下に以下を追加します:

php_deployment.yaml
...
  selector:
    matchLabels:
      app: php
      tier: backend

次に、Deployment specには、ポッドのオブジェクト定義にtemplateが必要です。 このテンプレートは、ポッドを作成するための仕様を定義します。 まず、phpサービスselectorsとデプロイメントのmatchLabelsに指定されたラベルを追加します。 template.metadata.labelsの下にapp: phptier: backendを追加します。

php_deployment.yaml
...
  template:
    metadata:
      labels:
        app: php
        tier: backend

ポッドには複数のコンテナとボリュームを含めることができますが、それぞれに名前が必要です。 ボリュームごとにマウントパスを指定することで、ボリュームをコンテナに選択的にマウントできます。

まず、コンテナがアクセスするボリュームを指定します。 アプリケーションコードを保持するためにcodeという名前のPVCを作成したので、このボリュームにもcodeという名前を付けます。 spec.template.spec.volumesの下に、以下を追加します。

php_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

次に、このポッドで実行するコンテナーを指定します。 Dockerストアにはさまざまなイメージがありますが、このチュートリアルではphp:7-fpmイメージを使用します。

spec.template.spec.containersの下に、以下を追加します。

php_deployment.yaml
...
      containers:
      - name: php
        image: php:7-fpm

次に、コンテナがアクセスする必要のあるボリュームをマウントします。 このコンテナはPHPコードを実行するため、codeボリュームにアクセスする必要があります。 また、mountPathを使用して、マウントポイントとして/codeを指定します。

spec.template.spec.containers.volumeMountsの下に、次を追加します。

php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

ボリュームをマウントしたので、ボリュームにアプリケーションコードを取得する必要があります。 これを実現するために、以前にFTP / SFTPを使用したか、SSH接続を介してコードを複製したことがあるかもしれませんが、この手順では、Initコンテナを使用してコードをコピーする方法を示します。

セットアッププロセスの複雑さに応じて、単一のinitContainerを使用してアプリケーションをビルドするスクリプトを実行するか、コマンドごとに1つのinitContainerを使用できます。 ボリュームがinitContainerにマウントされていることを確認してください。

このチュートリアルでは、busyboxを含む単一のInitContainerを使用してコードをダウンロードします。 busyboxは、これを実現するために使用するwgetユーティリティを含む小さな画像です。

spec.template.specの下に、initContainerを追加し、busyboxイメージを指定します。

php_deployment.yaml
...
      initContainers:
      - name: install
        image: busybox

Init Containerは、codeボリュームにアクセスして、その場所にコードをダウンロードできるようにする必要があります。 spec.template.spec.initContainersの下で、ボリュームcode/codeパスにマウントします。

php_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

各初期化コンテナはcommandを実行する必要があります。 Init Containerは、wgetを使用して、コードGithubから/code作業ディレクトリにダウンロードします。 -Oオプションは、ダウンロードしたファイルに名前を付け、このファイルにindex.phpという名前を付けます。

注:プルするコードを信頼してください。 サーバーにプルする前に、ソースコードを調べて、コードの機能に問題がないことを確認してください。

spec.template.spec.initContainersinstallコンテナの下に、次の行を追加します。

php_deployment.yaml
...
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

完成したphp_deployment.yamlファイルは次のようになります。

php_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: php
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: php
      tier: backend
  template:
    metadata:
      labels:
        app: php
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      containers:
      - name: php
        image: php:7-fpm
        volumeMounts:
        - name: code
          mountPath: /code
      initContainers:
      - name: install
        image: busybox
        volumeMounts:
        - name: code
          mountPath: /code
        command:
        - wget
        - "-O"
        - "/code/index.php"
        - https://raw.githubusercontent.com/do-community/php-kubernetes/master/index.php

ファイルを保存して、エディターを終了します。

kubectlを使用してPHP-FPMデプロイメントを作成します。

  1. kubectl apply -f php_deployment.yaml

デプロイメントの作成時に、次の出力が表示されます。

Output
deployment.apps/php created

要約すると、この展開は、指定されたイメージをダウンロードすることから始まります。 次に、PersistentVolumeClaimからPersistentVolumeを要求し、initContainersをシリアルに実行します。 完了すると、コンテナが実行され、volumesが指定されたマウントポイントにマウントされます。 これらの手順がすべて完了すると、ポッドが稼働します。

次のコマンドを実行して、デプロイメントを表示できます。

  1. kubectl get deployments

次の出力が表示されます。

Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s

この出力は、デプロイメントの現在の状態を理解するのに役立ちます。 Deploymentは、目的の状態を維持するコントローラーの1つです。 作成したtemplateは、DESIRED状態がphpという名前のポッドの1つのreplicasを持つことを指定します。 CURRENTフィールドは、実行中のレプリカの数を示しているため、これはDESIREDの状態と一致する必要があります。 残りのフィールドについては、KubernetesDeploymentsのドキュメントをご覧ください。

このデプロイメントが開始したポッドは、次のコマンドで表示できます。

  1. kubectl get pods

このコマンドの出力は、デプロイメントを作成してから経過した時間によって異なります。 作成直後に実行すると、出力は次のようになります。

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s

列は次の情報を表します。

  • Ready:このポッドを実行しているreplicasの数。
  • Status:ポッドのステータス。 Initは、Initコンテナが実行中であることを示します。 この出力では、1つの初期化コンテナのうち0が実行を終了しました。
  • Restarts:ポッドを開始するためにこのプロセスが再開された回数。 この数は、初期化コンテナのいずれかに障害が発生した場合に増加します。 デプロイメントは、目的の状態に達するまで再起動します。

起動スクリプトの複雑さによっては、ステータスがpodInitializingに変わるまでに数分かかる場合があります。

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s

これは、Init Containersが終了し、コンテナーが初期化されていることを意味します。 すべてのコンテナが実行されているときにコマンドを実行すると、ポッドのステータスがRunningに変わります。

Output
NAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m

これで、ポッドが正常に実行されていることがわかります。 ポッドが起動しない場合は、次のコマンドを使用してデバッグできます。

  • ポッドの詳細情報を表示します。
  1. kubectl describe pods pod-name
  • ポッドによって生成されたログを表示します。
  1. kubectl logs pod-name
  • ポッド内の特定のコンテナのログを表示します。
  1. kubectl logs pod-name container-name

アプリケーションコードがマウントされ、PHP-FPMサービスが接続を処理する準備が整いました。 これで、Nginxデプロイメントを作成できます。

ステップ5—Nginxデプロイメントを作成する

このステップでは、ConfigMapを使用してNginxを構成します。 ConfigMapは、他のKubernetesオブジェクト定義で参照できるKey-Value形式で設定を保持します。 このアプローチにより、必要に応じてイメージを再利用したり、別のNginxバージョンと交換したりできる柔軟性が得られます。 ConfigMapを更新すると、それをマウントしているポッドに変更が自動的に複製されます。

エディターを使用して、ConfigMap用のnginx_configMap.yamlファイルを作成します。

  1. nano nginx_configMap.yaml

ConfigMapにnginx-configという名前を付け、tier: backendマイクロサービスにグループ化します。

nginx_configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend

次に、ConfigMapのdataを追加します。 キーにconfigという名前を付け、Nginx構成ファイルの内容を値として追加します。 このチュートリアルのサンプルNginx構成を使用できます。

Kubernetesはリクエストをサービスの適切なホストにルーティングできるため、PHP-FPMサービスの名前をIPアドレスの代わりにfastcgi_passパラメーターに入力できます。 nginx_configMap.yamlファイルに以下を追加します。

nginx_configMap.yaml
...
data:
  config : |
    server {
      index index.php index.html;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      root ^/code^;

      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass php:9000;
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

nginx_configMap.yamlファイルは次のようになります。

nginx_configMap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-config
  labels:
    tier: backend
data:
  config : |
    server {
      index index.php index.html;
      error_log  /var/log/nginx/error.log;
      access_log /var/log/nginx/access.log;
      root /code;
      
      location / {
          try_files $uri $uri/ /index.php?$query_string;
      }

      location ~ \.php$ {
          try_files $uri =404;
          fastcgi_split_path_info ^(.+\.php)(/.+)$;
          fastcgi_pass php:9000;
          fastcgi_index index.php;
          include fastcgi_params;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }

ファイルを保存して、エディターを終了します。

ConfigMapを作成します。

  1. kubectl apply -f nginx_configMap.yaml

次の出力が表示されます。

Output
configmap/nginx-config created

ConfigMapの作成が完了し、Nginxデプロイメントを構築できるようになりました。

エディターで新しいnginx_deployment.yamlファイルを開くことから始めます。

  1. nano nginx_deployment.yaml

展開にnginxという名前を付け、ラベルtier: backendを追加します。

nginx_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend

展開specに1つのreplicasが必要であることを指定します。 この展開では、ラベルapp: nginxおよびtier: backendのポッドを管理します。 次のパラメータと値を追加します。

nginx_deployment.yaml
...
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend

次に、ポッドtemplateを追加します。 展開selector.matchLabelsに追加したものと同じラベルを使用する必要があります。 以下を追加します。

nginx_deployment.yaml
...
  template:
    metadata:
      labels:
        app: nginx
        tier: backend

Nginxに、前に作成したcodePVCへのアクセスを許可します。 spec.template.spec.volumesの下に、次を追加します。

nginx_deployment.yaml
...
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code

ポッドは、ConfigMapをボリュームとしてマウントできます。 ファイル名とキーを指定すると、その値をコンテンツとして持つファイルが作成されます。 ConfigMapを使用するには、pathkeyの内容を保持するファイルの名前に設定します。 キーconfigからファイルsite.confを作成します。 spec.template.spec.volumesの下に、以下を追加します。

nginx_deployment.yaml
...
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf

警告:ファイルが指定されていない場合、keyの内容がボリュームのmountPathに置き換わります。 これは、パスが明示的に指定されていない場合、宛先フォルダー内のすべてのコンテンツが失われることを意味します。

次に、ポッドを作成する画像を指定します。 このチュートリアルでは、安定性のためにnginx:1.7.9イメージを使用しますが、他のNginxイメージはDockerストアで見つけることができます。 また、ポート80でNginxを利用できるようにします。 spec.template.specの下に以下を追加します:

nginx_deployment.yaml
...
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80

NginxとPHP-FPMは同じパスでファイルにアクセスする必要があるため、codeボリュームを/codeにマウントします。

nginx_deployment.yaml
...
        volumeMounts:
        - name: code
          mountPath: /code

nginx:1.7.9イメージは、/etc/nginx/conf.dディレクトリの下にあるすべての構成ファイルを自動的にロードします。 このディレクトリにconfigボリュームをマウントすると、ファイル/etc/nginx/conf.d/site.confが作成されます。 volumeMountsの下に以下を追加します。

nginx_deployment.yaml
...
        - name: config
          mountPath: /etc/nginx/conf.d

nginx_deployment.yamlファイルは次のようになります。

nginx_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    tier: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
      tier: backend
  template:
    metadata:
      labels:
        app: nginx
        tier: backend
    spec:
      volumes:
      - name: code
        persistentVolumeClaim:
          claimName: code
      - name: config
        configMap:
          name: nginx-config
          items:
          - key: config
            path: site.conf
      containers:
      - name: nginx
        image: nginx:1.7.9
        ports:
        - containerPort: 80
        volumeMounts:
        - name: code
          mountPath: /code
        - name: config
          mountPath: /etc/nginx/conf.d

ファイルを保存して、エディターを終了します。

Nginxデプロイメントを作成します。

  1. kubectl apply -f nginx_deployment.yaml

次の出力は、デプロイメントが作成されたことを示しています。

Output
deployment.apps/nginx created

次のコマンドを使用してデプロイメントを一覧表示します。

  1. kubectl get deployments

NginxとPHP-FPMの展開が表示されます。

Output
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m

両方のデプロイメントによって管理されているポッドを一覧表示します。

  1. kubectl get pods

実行中のポッドが表示されます。

Output
NAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m

すべてのKubernetesオブジェクトがアクティブになったので、ブラウザでNginxサービスにアクセスできます。

実行中のサービスを一覧表示します。

  1. kubectl get services -o wide

Nginxサービスの外部IPを取得します。

Output
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 39m <none> nginx ClusterIP 10.102.160.47 your_public_ip 80/TCP 27m app=nginx,tier=backend php ClusterIP 10.100.59.238 <none> 9000/TCP 34m app=php,tier=backend

ブラウザで、http://your_public_ipと入力してサーバーにアクセスします。 php_info()の出力が表示され、Kubernetesサービスが稼働中であることが確認されます。

結論

このガイドでは、PHP-FPMサービスとNginxサービスをコンテナ化して、それらを個別に管理できるようにしました。 このアプローチにより、プロジェクトの成長に伴うスケーラビリティが向上するだけでなく、リソースを効率的に使用できるようになります。 また、将来サービスを簡単に更新できるように、アプリケーションコードをボリュームに保存しました。