0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHPフレームワークFlow】Flowをk8s上で動かす

0
Posted at

はじめに

前略、ローカルで動かしている学習用のFlowアプリケーションをKubernetesで動かしてみようと思います。

docker-composeからk8sに移行する

以前の記事で、ローカルで動かしているFlowアプリケーションをocker-copmposeで動かせるようにしました。

そろそろKubernetesも試したくなってきたので、移行してみようと思います。

元のdocker-compose.yaml

こちらが元のDockerFileです。
以下以外にもgrafanaありますが、動作確認するだけなら不要なので割愛しています。

services:
  app:
    container_name: app
    build:
      context: .
      dockerfile: ./Docker/local/Dockerfile
    ports:
      - "8082:8081"
    volumes:
      - flow-logs:/app/Data/Logs

  db:
    container_name: mysql
    image: mysql:8.0.36
    volumes:
      - db_data4:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: hogehoge
      MYSQL_DATABASE: mydatabase
    ports:
      - "3306:3306"

  valkey:
    image: valkey/valkey:9.1.1
    container_name: valkey-container
    volumes:
      - valkey_data:/data
    ports:
      - "6379:6379"

volumes:
  db_data4: {}
  app_data4: {}
  valkey_data: {}

実装

というわけで実装していきましょう。

今回はMacのDocker Desktopに内蔵されているKubernetesを利用します。

  • macOS
  • Docker Desktop
  • Kubernetes: Docker Desktop内蔵(Kubeadm方式)

事前にDocker DesktopにてKubernetesを有効化しておきましょう。

image.png

ディレクトリ構成

ディレクトリ構成は以下です。

$ tree -L 3 --dirsfirst
.
├── Docker
│   └── local
│       ├── Dockerfile
│       └── entrypoint.sh
├── k8s
│   ├── app
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   ├── mysql
│   │   ├── deployment.yaml
│   │   ├── pvc.yaml
│   │   └── service.yaml
│   ├── valkey
│   │   ├── deployment.yaml
│   │   └── service.yaml
│   └── namespace.yaml
└── docker-compose.yaml

namespace.yaml

まずはnamespaceです。
k8sでは管理したいリソースを配置する空間としてnamespaceという概念が存在ます。
今回はアプリケーション、DB、キャッシュサーバをすべて同一のnamespace上で管理します。

シンプルに名前だけ定義しました。のちのリソースごとのマニフェストファイルでこのnamespaceに配置することを宣言します。

# k8s/namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: flow-play-ground

app

まずはアプリケーションのマニフェストファイルです。

deployment.yaml

細かい書き方の説明は割愛しますが、ポイントは以下の通り

  • metadataに所属するnamespaceを記載
  • specには管理するPodの定義を追加
    • selectorはこのdeploymentで管理する対象のPodを記述
    • templateには管理するPodの定義を記述
      • metadataには付与する情報を記述(selectorの対象になるように)
      • specには作成するPodの情報を記載(コンテナイメージ、環境変数など)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flow-app
  namespace: flow-play-ground
spec:
  replicas: 1
  selector:
    matchLabels:
      app: flow-app
  template:
    metadata:
      labels:
        app: flow-app
    spec:
      containers:
        - name: php
          image: flow-play-ground-app:latest 
          imagePullPolicy: Never
          workingDir: /app
          env:
            - name: FLOW_CONTEXT
              value: Development

コンテナイメージはdocker-composeで動かしていた時と同じものを利用しています。
事前にbuildしておく必要があるのでやっておきましょう。

DockerFileはこちら
Dockerfile
# =============================
# 1. Composer install stage
# =============================
FROM php:8.5-cli AS composer

# zip / unzip が必要(Composer が zip アーカイブを解凍する)
# RUN apt-get update && apt-get install -y \
#     unzip git \
#     && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# Composer を入れる(公式推奨のコピー)
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer


# 非rootユーザーを作成
RUN adduser --disabled-password --gecos '' appuser 

# アプリケーションコードをコピー
COPY ./ /app

# composer update
# RUN composer install --no-interaction --prefer-dist

# =============================
# 2. Application stage
# =============================
# ベースイメージ
FROM php:8.5-cli

# 必要なPHP拡張モジュールをインストール
RUN docker-php-ext-install pdo_mysql

# phpredisのinstall
RUN pecl install redis && docker-php-ext-enable redis 

# 作業ディレクトリを設定
WORKDIR /app

# 非rootユーザーを作成
RUN adduser --disabled-password --gecos '' appuser 

# アプリケーションコードをコピー
COPY --from=composer /app /app

# エントリポイントスクリプトをコピー
COPY ./Docker/local/entrypoint.sh /usr/local/bin/entrypoint.sh

# スクリプトに実行権限を付与
RUN chmod +x /usr/local/bin/entrypoint.sh
  
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
entrypoint.sh
#!/bin/bash
# Data配下のファイルを削除
rm -rf /app/Data

# Docker用の設定ファイルに置き換え
rm /app/Configuration/Settings.yaml
cp /app/Configuration/Settings.yaml_forDocker /app/Configuration/Settings.yaml

# Application配下のファイルをDistributionPackagesの内容で置き換え
# NOTE: 新しくcloneする場合は不要
# rm -f /app/Packages/Application/*
# cp -r /app/DistributionPackages/* /app/Packages/Application/

# Neos.Welcomeの設定ファイルをDocker用に置き換え
rm /app/Packages/Application/Neos.Welcome/Configuration/Settings.yaml
cp /app/Packages/Application/Neos.Welcome/Configuration/Container/Settings.yaml /app/Packages/Application/Neos.Welcome/Configuration/Settings.yaml

# 実行できるように権限を変更
chown -R appuser /app
chmod -R 775 /app

# データベースマイグレーション
su - appuser -c "cd /app ; ./flow doctrine:update"

echo "Server running. Please go to http://localhost:8081 to browse the application."

# サーバーを起動
su - appuser -c "cd /app ; ./flow server:run --host=0.0.0.0"



service.yaml

Serviceには通信に関する内容を記載します。
このPodは外部からアクセス可能とするため、type: LoadBalancerというtypeを指定しています。
8081で通信を受け付けます。

apiVersion: v1
kind: Service
metadata:
  name: flow-app
  namespace: flow-play-ground
spec:
  type: LoadBalancer
  selector:
    app: flow-app
  ports:
    - port: 8081
      targetPort: 8081

mysql

続いてDBです。

deployment.yaml

ほぼアプリと同様です。
違いとしては、データを永続化できるようVolumeをマウントしていることくらいです。
後述するpvc.yamlで定義するボリュームを利用しています。

DB名やパスワードはsecretsやconfigmapを使うべきですが、いったん動かしたいのでこのままにしています。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql
  namespace: flow-play-ground
spec:
  replicas: 1
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: mysql
  template:
    metadata:
      labels:
        app: mysql
    spec:
      containers:
        - name: mysql
          image: mysql:8.0.36
          ports:
            - containerPort: 3306
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: hogehoge
            - name: MYSQL_DATABASE
              value: mydatabase
          volumeMounts:
            - name: data
              mountPath: /var/lib/mysql
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: mysql-data

service.yaml

続いてserviceです。
appと違い外から通信する必要はありません。
typeはデフォルトのClusterIPになり、これはクラスタ内からのみアクセスできるIPが払い出される形です。
appからはServiceで定義したmysqlというホスト名で接続できます。

apiVersion: v1
kind: Service
metadata:
  name: mysql
  namespace: flow-play-ground
spec:
  selector:
    app: mysql
  ports:
    - port: 3306
      targetPort: 3306

pvc.yaml

pvc.yamlはDBを永続化するためのボリュームを定義しました。
PersistentVolumeClaimとは容量など必要なスペックを指定してボリュームを要求するときに使う定義です。ここでは、5Giのボリュームを要求しています。

accessModesのReadWriteOnceは「1台のノードからのみ読み書き可能」という定義です。
DBのノードから読み書きできれば十分です。

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data
  namespace: flow-play-ground
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi

valkey

最後にキャッシュサーバのvalkeyです。

deployment.yaml

deploymentです。特に変わったところなし。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: valkey
  namespace: flow-play-ground
spec:
  replicas: 1
  selector:
    matchLabels:
      app: valkey
  template:
    metadata:
      labels:
        app: valkey
    spec:
      containers:
        - name: valkey
          image: valkey/valkey:9.1.1
          ports:
            - containerPort: 6379

service.yaml

serviceです。
こちらもDB同様typeはデフォルトのClusterIPで十分です。

apiVersion: v1
kind: Service
metadata:
  name: valkey
  namespace: flow-play-ground
spec:
  selector:
    app: valkey
  ports:
    - port: 6379
      targetPort: 6379

起動

まずはnamespaceの作成を行います。

kubectl apply -f k8s/namespace.yaml

続いて起動です。

$ kubectl apply -R -f k8s             
deployment.apps/flow-app configured
service/flow-app unchanged
deployment.apps/mysql configured
persistentvolumeclaim/mysql-data unchanged
service/mysql unchanged
namespace/flow-play-ground unchanged
deployment.apps/valkey configured
service/valkey unchanged

起動後、kubectl get podsで起動しているかを確認します。
RunningになってればOKです。

$ kubectl get pods -n flow-play-ground
NAME                        READY   STATUS    RESTARTS   AGE
flow-app-5fdbcdb776-7w729   1/1     Running   0          22s
mysql-76cd56cb9b-72k5x      1/1     Running   0          22s
valkey-f79d7b6cb-p9t48      1/1     Running   0          22s

最後に停止です。
Podの数を0にすることでnamespaceを残したまま停止できます。

$ kubectl scale deployment --all -n flow-play-ground --replicas=0
deployment.apps/flow-app scaled
deployment.apps/mysql scaled
deployment.apps/valkey scaled

以下のようになっていれば停止できています。

$ kubectl get pods -n flow-play-ground                           
No resources found in flow-play-ground namespace.

動作確認

最後に動作確認です。起動させた状態で以下のようにリクエストを投げたところ、無事にレスポンスが返ってきました!
(データは事前に投入していました)

image.png

おわりに

今回はFlowプロジェクトをローカルのk8sで起動してみました。
思いの外サクッと動いてくれてよかったです。
今後は、今回は割愛したgurafanaなどの移行やArgoCDを用いたgitopsなども試してみようと思います。

ここまでご覧いただきありがとうございました!

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?