前回記事の続きとなる。
kubernetes上に作成したLNMP環境に対してLaravelプロジェクトをデプロイした際のメモ。
Laravelプロジェクトの構築
今回、構築作業にヒューマンオペレーションが入り込むのを極力避けることを目的とし、Laravelプロジェクト作成をコンテナログインからのコマンド実行以外で実施することとした。
Laravelプロジェクトの初期化
Pod作成時にcommand
から実施してしまうと、Pod起動の度にプロジェクトの作成がされてしまう。
ということで、Laravelプロジェクトの初期化限定で、Jobオブジェクトを利用することにした。
Jobの作成
Job
は、コンテナを利用し処理を実行するリソースである。
Jobにて作成されたコンテナは、マニフェストファイルに記載されているタスク完了後、削除される。
今回は1回限りのタスクを実行するので、completions(成功回数):1/parallelism(並列度):1/backoffLimit(失敗許容回数):0
とする。
また、今回、spec.ttlSecondsAfterFinished: 30
とし、Laravelプロジェクト作成後、30sでPodを削除するようにする。
これを利用し、phpポッドの利用するPVに対してLaravelプロジェクトのデプロイのみ行う。
apiVersion: batch/v1
kind: Job
metadata:
name: laravel-init-job
labels:
app: lnmp
spec:
# One Shot Task
completions: 1
parallelism: 1
backoffLimit: 0
# 実行後30sでJob実行Podを削除
ttlSecondsAfterFinished: 30
template:
metadata:
labels:
app: lnmp
spec:
containers:
- name: laravel-init
image: laravel
imagePullPolicy: IfNotPresent
# laravelプロジェクトの初期構築
command:
- sh
- -c
args:
- "composer create-project --prefer-dist laravel/laravel '' \
&& chmod 777 -R ./storage/ \
&& chmod 777 -R ./bootstrap/"
volumeMounts:
- name: php-persistent-storage
mountPath: /var/www
restartPolicy: Never
volumes:
- name: php-persistent-storage
persistentVolumeClaim:
claimName: php-server-pv-claim
上記Job
マニフェストファイルlaravel-init-job.yaml
をデプロイ。
$ kubectl apply -f laravel-init-job.yaml
Job実行時の不具合
Job実行時に以下のエラーとなった。
Creating a "laravel/laravel" project at "./"
Installing laravel/laravel (v8.1.0)
As there is no 'unzip' command installed zip files are being unpacked using the PHP zip extension.
This may cause invalid reports of corrupted archives. Besides, any UNIX permissions (e.g. executable) defined in the archives will be lost.
Installing 'unzip' may remediate them.
- Installing laravel/laravel (v8.1.0): Downloading (100%)
Created project in /var/www/public
> @php -r "file_exists('.env') || copy('.env.example', '.env');"
Loading composer repositories with package information
Updating dependencies (including require-dev)
Killed
なんかkilled
となり、インストールに失敗している。当然Laravelプロジェクトは作成されていない。
こちらの記事([PHP] composer install が killed で失敗するときの原因と対処)にドンピシャで答えが載っていた。
どうやらメモリが足らないのが原因だったらしい。今回、phpのデプロイメントにはメモリ制限は設けていないので、ホストのメモリがそもそも足りていないと思われる。
ということでminikubeサーバーのメモリを2.5G
から4.0G
へ増やし、マウントしていたボリュームphp-persistent-storage
内のファイルを削除。
再びJobを実行することでLaravelの作成に成功した。
Jobを実行したPodが削除されない
spec.ttlSecondsAfterFinished: 30
としたにも関わらず、Jobを実行したPodがstatus: terminating
のまま残り続けた。
調べてみると、こちらの記事(Kubernetes で Complete/Failed となった Job を自動削除する)にて説明がされていた。
どうやらTTLAfterFinished
は、フィーチャーゲートなる実験的機能であるらしい。
ということで、以下コマンドからminikube
を起動し、機能を有効化する。(kubernetes > v1.12以上である必要がある。)
$ minikube start --feature-gates=TTLAfterFinished=true
この状態でJobを実行することで、Podがコマンド終了後に削除されるようになった。
Laravel環境変数ファイル(.env)をConfigMap化
mysql-phpポッド間の通信をサービス経由で実行するにあたり、Laravelの.env
ファイルにサービス名を指定する必要がある。
そこで、.env
をConfigMap
とし、コンテナ外部から設定できるようにする。
.envの修正
こちらの記事(docker-composeでLaravelの開発環境を整える方法とその解説)を参考にし、.env
の以下箇所を修正
DB_CONNECTION=mysql
# mysql-php間の通信で利用するService名
DB_HOST=lnmp-mysql-service
DB_PORT=3306
DB_DATABASE=test_db
DB_USERNAME=user
DB_PASSWORD=password
ConfigMapの作成
以下コマンドを実行し、ConfigMap laravel-env
を作成する。
$ kubectl create configmap laravel-env --from-file={ホスト上の.envの配置されているパス}
ConfigMapをマウント
phpのDeploymentに作成したConfigMapをマウントし、再度読み込む。
この際、以前作成したボリュームと、ConfigMapのマウントパスが被ってしまいエラーとなった。
そこで、こちらの記事(KubernetesのConfigMapを使ってWordpressのphp.iniを書き換える)を参照し、マウント先をsubPath
を使用してファイル自体へと変更。
apiVersion: apps/v1
kind: Deployment
metadata:
name: lnmp-php-deployment
labels:
app: lnmp
spec:
replicas: 1
selector:
matchLabels:
app: lnmp
template:
metadata:
labels:
app: lnmp
spec:
containers:
- name: lnmp-php-deployment
image: laravel
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9000
volumeMounts:
- name: php-persistent-storage
mountPath: /var/www
- name: laravel-env
mountPath: /var/www/.env
# マウント先をファイル自体へと変更する。
subPath: .env
volumes:
# サーバーログ出力先(nginxと共有)
- name: php-persistent-storage
persistentVolumeClaim:
claimName: php-server-pv-claim
# laravel .envをinject
- name: laravel-env
configMap:
name: laravel-env
items:
- key: .env
path: .env
mode: 0644
その後、Deploymentの作成を実施した。
mysqlの初期化
dbの初期化を実施。これはphpポッド内でコマンドを実行して行った。(極力手作業を避けたいとはなんだったのか……?)
$ php artisan migrate
Migration table created successfully.
というメッセージが表示され、php-mysqlポッド間の通信設定が正常に設定できていることが確認できた。
Laravelプロジェクトへのアクセス
これでLaravel環境に必要な物が一通り揃ったはずなので、アクセスしてみる。
以下コマンドを実行し、nginxのホスト上のポートを確認しアクセス。
[root@kube ~]# kubectl describe service/lnmp-nginx-service | grep NodePort
Type: NodePort
NodePort: <unset> 32626/TCP
Laravel初期画面が出た!!
(地味にLaravelがブラウザのダークテーマに対応しているのに驚いた。)
まとめ
Job
を利用し、Laravelプロジェクトの初期化を実施することができた。
今回はJob
の実行タスクをプロジェクトの初期化のみとしたが、これをGithub
から取得するタスクに変更したりすることで、実装環境の均等化を図ったりできるんだろか?
でもそうなれば、Job
の管理が大変になるような気もする。どうやっているんだろう?