3
2

More than 3 years have passed since last update.

kubernetes上にLaravel環境を構築した際のメモ

Posted at

前回記事の続きとなる。

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ファイルにサービス名を指定する必要がある。

そこで、.envConfigMapとし、コンテナ外部から設定できるようにする。

.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の管理が大変になるような気もする。どうやっているんだろう?

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2