前回の記事にてminikube環境を構築した。
その後、Kubernetesのチュートリアルを一通りこなした後、勉学のためLNMPスタックの構築を実施した際のメモ。
実行環境
前回記事と同様のため省略
構築する環境外観
こちらの記事(Docker × PHP7.3 × Laravel環境作ってみた)の環境構築手順を参考とさせていただき、最終的にこんな感じの構成を目指す。
なお、本記事ではLaravel
の構築については触れない。
構築するKubernetesオブジェクトについてのおさらい
ここで、構築にて使用するkubernetesオブジェクトについて簡単に説明する。
Pod
Kubernetesの中で最小のオブジェクト。
アプリケーションを実行する際の項目 (コンテナ、ストレージ、ネットワークIP、実行オプション) をカプセル化したもの。
今回は一つのPodにつき、一つのコンテナイメージが実行されるようにする。
Node
Podが動作する環境。複数のPodを動作させることが可能。
今回は特に操作しない。
Namespace
クラスタの仮想的な分割機能。
今回は特に操作せず、default
を使用。
Deployment
デプロイするアプリケーション (Pod) について、レプリケーション数、ローリングアップデートなどの制御を実施する。
Service
実行されているPodへのアクセス経路を提供する。
PodのIPアドレスは一意でないため、アクセスにはService名の指定が必要となる。
また、Podへのアクセス方式にはいくつか種類があり、今回は以下を使用する。
-
ClusterIP
: 外部疎通性のないアクセス方式。クラスタの内部IPを作成する。 -
NodePort
: 外部疎通性のあるアクセス方式。Nodeの指定ポートへのアクセスをコンテナに転送する。
ConfigMap
アプリケーションの設定データを管理する。
あとで更新が必要などの理由から、コンテナイメージに内包したくない設定については、こちらで持つようにする。
PersistentVolume (PV)
アプリケーションが使用できる、独立した永続化ストレージ。
PersistentVolumeClaim (PVC)
アプリケーションがPVを利用する際に経由される。
環境の構築作業
以下の手順で構築した。
nginx環境の構築
まず、PV, PVC, ConfigMapの構築から行う。こちらを行わずDeploymentの構築を実施すると失敗となった。
ConfigMapの作成
今回、nginx-phpポッド間の通信をservice経由とするので、nginxのdefault.conf
をコンテナに内包させずConfigMapとする。
default.conf
を以下のように記載。この際、phpポッドへのアクセスにservice名とPort:9000
を指定する。
server {
listen 80;
root /var/www/public/;
index index.php;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# php serviceに送信する設定にする。
fastcgi_pass lnmp-php-service:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
$ kubectl create configmap nginx-config --from-file={ホスト上のnginx.confの配置されているパス}
PV, PVCの作成
続いてPV, PVCの構築を行う。
今回、nginxポッドがphpアプリケーションを公開するため、ストレージはphpポッドと共有する。
ということでマニュフェストファイルを、lnmp-php-server-persistentvolumeclaim.yaml
として作成。
# PV
kind: PersistentVolume
apiVersion: v1
metadata:
name: php-server-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
# とりあえず100Miくらいの容量で試す
storage: 100Mi
# ホストないに作成したストレージへ、Kubernetes nodeがアクセスする際の制約事項
# 今回は、単一のnodeのみに書き込み/読み込みを可能とする設定とした
accessModes:
- ReadWriteOnce
hostPath:
# ホストマシンのどこにストレージを割り当てるか
path: '/root/src/lnmp/server'
---
# PVC
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: php-server-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Mi
コマンドを実行してpv, pvcを作成。
$ kubectl apply -f lnmp-php-server-persistentvolumeclaim.yaml
以下のkubectl
コマンドから、作成されていることが確認できた。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
php-server-pv-volume 100Mi RWO Retain Bound default/php-server-pv-claim manual 5d20h
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
php-server-pv-claim Bound php-server-pv-volume 100Mi RWO manual 5d20h
deploymentを作成
次に、deploymentを作成する。
マニュフェストファイルを、lnmp-nginx-deployment.yaml
として作成。
# Deployment設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: lnmp-nginx-deployment
labels:
app: lnmp
spec:
# レプリケーション設定、今回は1台のみの構成とする
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
# 配置するnginxコンテナ
containers:
- name: lnmp-nginx-deployment
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: nginx-persistent-storage
mountPath: /var/www
# default.conf共有パス
- name: nginx-config
# default.confの配置先
mountPath: /etc/nginx/conf.d
volumes:
# nginxの永続化ボリューム
- name: nginx-persistent-storage
persistentVolumeClaim:
claimName: php-server-pv-claim
# nginx設定のinject
- name: nginx-config
configMap:
name: nginx-config
items:
- key: default.conf
# マウントしたボリュームのmountPath配下に、どういう階層で登録されるかを記載
path: default.conf
mode: 0777
serviceを作成
つづいて、serviceを作成する。
マニュフェストファイルを、lnmp-nginx-service.yaml
として作成。
apiVersion: v1
kind: Service
metadata:
name: lnmp-nginx-service
spec:
selector:
app: nginx
type: NodePort
ports:
- port: 80
targetPort: 80
以下コマンドを実行し、デプロイを実施。
$ kubectl apply -f lnmp-nginx-deployment.yaml
$ kubectl apply -f lnmp-service-deployment.yaml
これでnginxの構築は完了。この時点でnginxサーバーのポートは確認できるけど、index.php
を配置していないので502
エラーになる。
mysql環境の構築
こちらも引き続き構築していく。
ConfigMapのデプロイ
mysql設定ファイル、my.cnf
をConfigMapとする。なお、これは元記事のものをそのまま使用する。
$ kubectl create configmap mysql-config --from-file={ホスト上のmy.cnfの配置されているパス}
PV, PVCの作成
元記事同様、mysqlのデータディレクトリをマウントするPV, PVCを作成。
kind: PersistentVolume
apiVersion: v1
metadata:
name: mysql-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
# とりあえず5Gでマウントする
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
# プルパスで記載しないとエラーになった
path: '/root/src/lnmp/mysql/db/data'
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
deploymentを作成
nginxの場合と同様、以下のマニュフェストファイルを作成し、デプロイ。
apiVersion: apps/v1
kind: Deployment
metadata:
name: lnmp-mysql-deployment
labels:
app: lnmp
spec:
replicas: 1
selector:
matchLabels:
app: lnmp
template:
metadata:
labels:
app: lnmp
spec:
containers:
- name: lnmp-mysql-deployment
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: root
- name: MYSQL_DATABASE
value: test_db
- name: TZ
value: 'Asia/Tokyo'
ports:
- containerPort: 3306
args:
- mysqld
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumeMounts:
# mysqlストレージ用パス
- name: mysql-persistent-storage
mountPath: /var/lib/mysql
# my.cnf共有パス
- name: mysql-config
# my.cnfの配置先
mountPath: /etc/mysql/conf.d
volumes:
# mysqlの永続化ボリューム
- name: mysql-persistent-storage
persistentVolumeClaim:
claimName: mysql-pv-claim
# mysql設定のinject
- name: mysql-config
configMap:
name: mysql-config
items:
- key: my.cnf
# マウントしたボリュームのmountPath配下に、どういう階層で登録されるかを記載
path: my.cnf
mode: 0644
serviceを作成
こちらもnginxの場合と同様のマニュフェストファイルを作成しデプロイする。
ただし、mysqlへの通信はクラスタ内ポッド間でのみ行われるので、Service.spec.type
をNodePort
ではなくClusterIP
としている。
apiVersion: v1
kind: Service
metadata:
name: lnmp-mysql-service
spec:
selector:
app: lnmp
type: ClusterIP
ports:
- port: 3306
targetPort: 3306
php環境の構築
deploymentを作成
phpコンテナをデプロイする。
デプロイするphpイメージは元記事のDockerfile
から作成する。
コンテナイメージを毎回dockerhub
から取得しようとしてエラーとなっていたため、コンテナ取得タイミングをIfNotPresent
とした。
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
# なんかdockerhubから取ろうとしてた
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9000
volumeMounts:
- name: php-persistent-storage
mountPath: /var/www
volumes:
# サーバーログ出力先(nginxと共有)
- name: php-persistent-storage
persistentVolumeClaim:
claimName: php-server-pv-claim
また、PV, PVCはnginxポッドと共有する。
serviceを作成
nginxポッドがアクセスするサービスを作成する。
こちらもクラスタ内ポッド間でのみの通信となるため、Service.spec.type
をClusterIP
としている。
apiVersion: v1
kind: Service
metadata:
name: lnmp-php-service
spec:
selector:
app: lnmp
type: ClusterIP
ports:
- port: 9000
protocol: TCP
php環境の動作確認
この段階でLNMP環境にアクセスできることを確認する。
nginxのdefault.confに従い、phpポッドの/var/www/public/
に、index.phpを配置してみる。
nginx, phpポッドに割り当てた/root/src/lnmp/server
に以下の内容のindex.phpを配置する。
<h1>kubenetes-php</h1>
<p>Served by Nginx</p>
<?php phpinfo();?>
この状態でnginxサーバーにアクセスしてみる。
$ kubectl get services/lnmp-nginx-service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
lnmp-nginx-service NodePort 10.98.216.9 <none> 80:32626/TCP 11d```
Podのアクセス先が32626
ポートだと確認できた。
http://localhost:32626
へブラウザからアクセスする。
phpの情報が出た!!
元記事ではLaravel
アプリケーションの構築までを実施していたが、長くなってしまうので一旦ここまで。