Ubuntu16.04でKubernetesを使用してPHPアプリケーションをデプロイする方法
著者は、 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ディレクトリを作成します。
mkdir definitions
新しく作成されたdefinitionsディレクトリに移動します。
cd definitions
php_service.yamlファイルを作成して、PHP-FPMサービスを作成します。
nano php_service.yaml
kindをServiceとして設定して、このオブジェクトがサービスであることを指定します。
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ファイルを指定します。
サービスを作成します。
kubectl apply -f php_service.yaml
この出力は、サービスの作成を確認します。
Outputservice/php created
サービスが実行されていることを確認します。
kubectl get svc
PHP-FPMサービスが実行されていることがわかります。
OutputNAME 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という名前の新しいファイルを作成し、エディターで開きます。
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サービスを作成します。
kubectl apply -f nginx_service.yaml
サービスの実行中は、次の出力が表示されます。
Outputservice/nginx created
以下を実行すると、実行中のすべてのサービスを表示できます。
kubectl get svc
出力にPHP-FPMサービスとNginxサービスの両方が表示されます。
OutputNAME 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
実行できるサービスを削除する場合は、次の点に注意してください。
kubectl delete svc/service_name
PHP-FPMおよびNginxサービスを作成したので、アプリケーションコードと構成ファイルを保存する場所を指定する必要があります。
ステップ2—DigitalOceanストレージプラグインのインストール
Kubernetesは、環境にストレージスペースを作成できるさまざまなストレージプラグインを提供します。 このステップでは、 DigitalOceanストレージプラグインをインストールして、DigitalOceanにブロックストレージを作成します。 インストールが完了すると、ブロックストレージの作成に使用するdo-block-storageという名前のストレージクラスが追加されます。
まず、DigitalOceanAPIトークンを保存するようにKubernetesシークレットオブジェクトを設定します。 シークレットオブジェクトは、SSHキーやパスワードなどの機密情報を、同じ名前空間内の他のKubernetesオブジェクトと共有するために使用されます。 名前空間は、Kubernetesオブジェクトを論理的に分離する方法を提供します。
secret.yamlという名前のファイルをエディターで開きます。
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-tokenをstringDataとして追加します。
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
シークレットを作成します。
kubectl apply -f secret.yaml
シークレットを作成すると、次の出力が表示されます。
Outputsecret/digitalocean created
次のコマンドで秘密を表示できます。
kubectl -n kube-system get secret digitalocean
出力は次のようになります。
OutputNAME TYPE DATA AGE digitalocean Opaque 1 41s
Opaqueタイプは、このシークレットが読み取り専用であることを意味します。これは、stringDataシークレットの標準です。 詳しくはシークレットデザインスペックをご覧ください。 DATAフィールドには、このシークレットに保存されているアイテムの数が表示されます。 この場合、1つのキーが保存されているため、1と表示されます。
シークレットが配置されたので、DigitalOceanブロックストレージプラグインをインストールします。
kubectl apply -f https://raw.githubusercontent.com/digitalocean/csi-digitalocean/master/deploy/kubernetes/releases/csi-digitalocean-v0.3.0.yaml
次のような出力が表示されます。
Outputstorageclass.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という名前のファイルをエディターで開きます。
nano code_volume.yaml
次のパラメータと値をファイルに追加して、PVCcodeに名前を付けます。
code_volume.yaml
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: code
PVCのspecには、次のアイテムが含まれています。
accessModesこれはユースケースによって異なります。
resources–必要なストレージスペース
DigitalOceanブロックストレージは単一ノードにのみマウントされるため、accessModesをReadWriteOnceに設定します。 このチュートリアルでは、少量のアプリケーションコードを追加する方法について説明します。したがって、このユースケースでは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を作成します。
kubectl apply -f code_volume.yaml
次の出力は、オブジェクトが正常に作成され、1GBのPVCをボリュームとしてマウントする準備ができていることを示しています。
Outputpersistentvolumeclaim/code created
使用可能な永続ボリューム(PV)を表示するには:
kubectl get pv
PVが一覧表示されます。
OutputNAME 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 PolicyとStatusを除いて、構成ファイルの概要です。 Reclaim Policyは、PVにアクセスしているPVCが削除された後、PVで何が行われるかを定義します。 Deleteは、KubernetesとDigitalOceanインフラストラクチャからPVを削除します。 Reclaim PolicyとStatusの詳細については、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という新しいファイルを開きます。
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: phpとtier: 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.initContainersのinstallコンテナの下に、次の行を追加します。
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デプロイメントを作成します。
kubectl apply -f php_deployment.yaml
デプロイメントの作成時に、次の出力が表示されます。
Outputdeployment.apps/php created
要約すると、この展開は、指定されたイメージをダウンロードすることから始まります。 次に、PersistentVolumeClaimからPersistentVolumeを要求し、initContainersをシリアルに実行します。 完了すると、コンテナが実行され、volumesが指定されたマウントポイントにマウントされます。 これらの手順がすべて完了すると、ポッドが稼働します。
次のコマンドを実行して、デプロイメントを表示できます。
kubectl get deployments
次の出力が表示されます。
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE php 1 1 1 0 19s
この出力は、デプロイメントの現在の状態を理解するのに役立ちます。 Deploymentは、目的の状態を維持するコントローラーの1つです。 作成したtemplateは、DESIRED状態がphpという名前のポッドの1つのreplicasを持つことを指定します。 CURRENTフィールドは、実行中のレプリカの数を示しているため、これはDESIREDの状態と一致する必要があります。 残りのフィールドについては、KubernetesDeploymentsのドキュメントをご覧ください。
このデプロイメントが開始したポッドは、次のコマンドで表示できます。
kubectl get pods
このコマンドの出力は、デプロイメントを作成してから経過した時間によって異なります。 作成直後に実行すると、出力は次のようになります。
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-bf8zd 0/1 Init:0/1 0 9s
列は次の情報を表します。
Ready:このポッドを実行しているreplicasの数。Status:ポッドのステータス。Initは、Initコンテナが実行中であることを示します。 この出力では、1つの初期化コンテナのうち0が実行を終了しました。Restarts:ポッドを開始するためにこのプロセスが再開された回数。 この数は、初期化コンテナのいずれかに障害が発生した場合に増加します。 デプロイメントは、目的の状態に達するまで再起動します。
起動スクリプトの複雑さによっては、ステータスがpodInitializingに変わるまでに数分かかる場合があります。
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 0/1 podInitializing 0 39s
これは、Init Containersが終了し、コンテナーが初期化されていることを意味します。 すべてのコンテナが実行されているときにコマンドを実行すると、ポッドのステータスがRunningに変わります。
OutputNAME READY STATUS RESTARTS AGE php-86d59fd666-lkwgn 1/1 Running 0 1m
これで、ポッドが正常に実行されていることがわかります。 ポッドが起動しない場合は、次のコマンドを使用してデバッグできます。
- ポッドの詳細情報を表示します。
kubectl describe pods pod-name
- ポッドによって生成されたログを表示します。
kubectl logs pod-name
- ポッド内の特定のコンテナのログを表示します。
kubectl logs pod-name container-name
アプリケーションコードがマウントされ、PHP-FPMサービスが接続を処理する準備が整いました。 これで、Nginxデプロイメントを作成できます。
ステップ5—Nginxデプロイメントを作成する
このステップでは、ConfigMapを使用してNginxを構成します。 ConfigMapは、他のKubernetesオブジェクト定義で参照できるKey-Value形式で設定を保持します。 このアプローチにより、必要に応じてイメージを再利用したり、別のNginxバージョンと交換したりできる柔軟性が得られます。 ConfigMapを更新すると、それをマウントしているポッドに変更が自動的に複製されます。
エディターを使用して、ConfigMap用のnginx_configMap.yamlファイルを作成します。
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を作成します。
kubectl apply -f nginx_configMap.yaml
次の出力が表示されます。
Outputconfigmap/nginx-config created
ConfigMapの作成が完了し、Nginxデプロイメントを構築できるようになりました。
エディターで新しいnginx_deployment.yamlファイルを開くことから始めます。
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を使用するには、pathをkeyの内容を保持するファイルの名前に設定します。 キー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デプロイメントを作成します。
kubectl apply -f nginx_deployment.yaml
次の出力は、デプロイメントが作成されたことを示しています。
Outputdeployment.apps/nginx created
次のコマンドを使用してデプロイメントを一覧表示します。
kubectl get deployments
NginxとPHP-FPMの展開が表示されます。
OutputNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 1 1 1 0 16s php 1 1 1 1 7m
両方のデプロイメントによって管理されているポッドを一覧表示します。
kubectl get pods
実行中のポッドが表示されます。
OutputNAME READY STATUS RESTARTS AGE nginx-7bf5476b6f-zppml 1/1 Running 0 32s php-86d59fd666-lkwgn 1/1 Running 0 7m
すべてのKubernetesオブジェクトがアクティブになったので、ブラウザでNginxサービスにアクセスできます。
実行中のサービスを一覧表示します。
kubectl get services -o wide
Nginxサービスの外部IPを取得します。
OutputNAME 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サービスをコンテナ化して、それらを個別に管理できるようにしました。 このアプローチにより、プロジェクトの成長に伴うスケーラビリティが向上するだけでなく、リソースを効率的に使用できるようになります。 また、将来サービスを簡単に更新できるように、アプリケーションコードをボリュームに保存しました。