グレンジ Advent Calendar 2017 24日目担当の 石川 です.
株式会社グレンジで,サーバサイドエンジニアをしています.
概要
Minikube
を利用したPHPのローカル環境構築について解説します.
Minikube
は,Kubernetes
をローカルで実行するためのツールです.
Kubernetes
は,コンテナ化されたアプリケーションをマネージするためのオープンソフトウェアです.
また,今回の記事は,Macを利用して検証した記事です.
他環境の方は,ところどころ読み替えて下さい.
準備
VirtualBoxのインストール
今回は,Minikube
の実行環境にVirtualBoxを利用します.
Download VirtualBoxのOS X hosts
のリンクからVirtualBoxをダウンロードして,インストールします.
gcloudのインストール
kubectl
(Kubernetes
を利用するためのコマンド)を利用するために,gcloud
をインストールし,更にkubectl
コマンドをインストールします.
※bash
を利用している方は,zsh
をbash
に変更して実行して下さい.
$ curl https://sdk.cloud.google.com | zsh
$ exec -l $SHELL
$ gcloud init
上記で,gcloud
コマンドはインストールされました.
今,インストールされている.gcloud
のコンポーネントリストを確認します.
$ gcloud components list
Your current Cloud SDK version is: 180.0.1
The latest available version is: 180.0.1
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ Components │
├───────────────┬──────────────────────────────────────────────────────┬──────────────────────────┬───────────┤
│ Status │ Name │ ID │ Size │
├───────────────┼──────────────────────────────────────────────────────┼──────────────────────────┼───────────┤
│ Not Installed │ App Engine Go Extensions │ app-engine-go │ 97.7 MiB │
│ Not Installed │ Cloud Bigtable Command Line Tool │ cbt │ 4.0 MiB │
│ Not Installed │ Cloud Bigtable Emulator │ bigtable │ 3.5 MiB │
│ Not Installed │ Cloud Datalab Command Line Tool │ datalab │ < 1 MiB │
│ Not Installed │ Cloud Datastore Emulator │ cloud-datastore-emulator │ 17.7 MiB │
│ Not Installed │ Cloud Datastore Emulator (Legacy) │ gcd-emulator │ 38.1 MiB │
│ Not Installed │ Cloud Pub/Sub Emulator │ pubsub-emulator │ 33.2 MiB │
│ Not Installed │ Emulator Reverse Proxy │ emulator-reverse-proxy │ 14.5 MiB │
│ Not Installed │ Google Container Local Builder │ container-builder-local │ 3.7 MiB │
│ Not Installed │ Google Container Registry's Docker credential helper │ docker-credential-gcr │ 2.2 MiB │
│ Not Installed │ gcloud Alpha Commands │ alpha │ < 1 MiB │
│ Not Installed │ gcloud Beta Commands │ beta │ < 1 MiB │
│ Not Installed │ gcloud app Java Extensions │ app-engine-java │ 118.4 MiB │
│ Not Installed │ gcloud app PHP Extensions │ app-engine-php │ 21.9 MiB │
│ Not Installed │ gcloud app Python Extensions │ app-engine-python │ 6.2 MiB │
│ Not Installed │ kubectl │ kubectl │ 12.2 MiB │
│ Installed │ BigQuery Command Line Tool │ bq │ < 1 MiB │
│ Installed │ Cloud SDK Core Libraries │ core │ 7.5 MiB │
│ Installed │ Cloud Storage Command Line Tool │ gsutil │ 3.3 MiB │
└───────────────┴──────────────────────────────────────────────────────┴──────────────────────────┴───────────┘
To install or remove components at your current SDK version [180.0.1], run:
$ gcloud components install COMPONENT_ID
$ gcloud components remove COMPONENT_ID
To update your SDK installation to the latest version [180.0.1], run:
$ gcloud components update
kubectl
はデフォルトでは,インストールされていません.
gcloud components install COMPONENT_ID
で必要なコンポーネントをインストールできるので,下記のように実行してkubectl
をインストールします.
$ gcloud components install kubectl
Minikube
Minikubeのインストール
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.22.3/minikube-darwin-amd64 && chmod +x minikube && sudo mv minikube /usr/local/bin/
※記事を書いた時点では,v0.24.1
が最新ですが,意図した通りに動かない部分があったので,minikubeのバージョンを意図的に落としています.
また,brewを利用した下記のようなインストール方法もあります.
brew cask install minikube
Minikubeの起動
$ minikube start
ダッシュボードの起動
上手く起動できているか,ダッシュボードを確認してみます.
$ minikube dashboard
minikubeの終了
Minikube
の終了の仕方は,下記の通りです.
$ minikube stop
Dockerのインストール
Docker Community Editionから自分の環境にそってダウンロード,インストールします.
DockerHubアカウント作成
Docker Hubでアカウントを作成しておきます.
アカウントを作成したら,docker login
コマンドで,Docker Hubに作成したアカウントでログインします.
Dockerイメージの作成
Kubernetes
で利用するDocker
イメージを作成します.
今回は,Nginx
のイメージとPHP
のイメージを利用します.
Nginx
ファイル構成
conf.d/
myapp.conf
Dockerfile
nginx.conf
nginx.conf
user nginx;
worker_processes 1;
pid /run/nginx.pid;
events {
worker_connections 768;
}
http {
sendfile off;
access_log stdout;
error_log stderr;
include /etc/nginx/conf.d/*.conf;
}
include /etc/nginx/conf.d/*.conf;
により後述する.myapp.conf
の設定を読み込ませるようにしています.
myapp.conf
今回作成するPHPファイルをNginxを通して実行させ,結果を返すための設定ファイルです.
server {
listen 80;
root /app;
access_log stdout;
error_log stderr;
location ~ \.php$ {
fastcgi_pass php-fpm-service:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /app$fastcgi_script_name;
include fastcgi_params;
}
}
root /app;
では,実行するプログラムのディレクトリを設定しています.
access_log stdout;
とすることにより,アクセスログを標準出力しています.Kubernetesでは,標準出力されたログを自動で回収してくれます.
location ~ \.php$ {
内で,拡張子がphp
に該当するものの場合の処理を記載しています.
fastcgi_pass
には,名前解決できるアドレスやIPアドレス,UNIXソケットなどを指定することができますが,ここでは,kubernetesで起動するServiceの名前とポート番号(php-fpm-service:9000)を指定しています.
Dockerfile
NginxのDockerイメージを作成するのに利用しています.
FROM nginx:1.13.7
ADD ./nginx.conf /etc/nginx/nginx.conf
RUN rm /etc/nginx/conf.d/default.conf
ADD ./conf.d/ /etc/nginx/conf.d
同じディレクトリにあるnginx.conf
をイメージ内の/etc/nginx/nginx.conf
に配置し,デフォルトの設定ファイル(default.conf)を削除した後,conf.d
ディレクトリの内容を/etc/nginx/conf.d
ディレクトリに追加しています.
イメージのビルド
上記ファイルを作成したら,Dockerfile
のあるディレクトリで下記を実行します.
※nginx-advent2017
は,DockerHub
でCreate repository
で,作成したリポジトリです.
$ docker build -t yasunoriishikawa/nginx-advent2017 .
イメージのpush
先程作成した,Docker Hub
のリポジトリにDockerイメージをpush
します.
$ docker push yasunoriishikawa/nginx-advent2017:latest
PHP
ファイル構成
app/
index.php
phpinfo.php
php-fpm.d/
www.conf
Dockerfile
php-fpm.conf
php.ini
index.php
サンプルプログラムです.
<html>
<head>
<meta charset="UTF-8">
<title>グレンジ Advent Calendar 2017</title>
<style>
body {
font-family: Verdana, sans-serif;
font-size: 14px;
padding: 40px;
}
</style>
</head>
<body>
<h1>グレンジ Advent Calendar 2017</h1>
<p>Today is <?php echo date('m/d/Y H:i:s'); ?>.</p>
</body>
</html>
www.conf
アプリケーションのNginxの設定ファイルです.
[www]
user = www-data
group = www-data
listen = 9000
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
listen = 9000
で,listenするポートを指定しています.
Dockerfile
PHPのDockerイメージを作成するのに利用しています.
FROM php:7.2.0-fpm
ADD ./php.ini /usr/local/etc/php/php.ini
ADD ./php-fpm.conf /usr/local/etc/php-fpm.conf
ADD ./php-fpm.d/ /usr/local/etc/php-fpm.d
RUN sed -i "s/;date.timezone =/date.timezone = Asia\/Tokyo/" /usr/local/etc/php/php.ini
ADD app/ /app
基本的には,Nginx同様にファイルを追加していますが,大きな違いとしては,php.iniのtimezoneをAsia/Tokyo
に設定しています.
php-fpm.conf
php-fpmの設定ファイルです.
[global]
pid = /var/run/php7-fpm.pid
error_log = stdout
include=/usr/local/etc/php-fpm.d/*.conf
php.ini
内容が大きいので,こちらを参照して下さい.
Kubernetes
Kubernetes
を利用して実際に,アプリケーションを実行できるようにします.
構成図
今回作成する環境は,下記のようなイメージになります.
192.168.99.100
は,minikubeが外部からのリクエストを受け付けているIPになります.
※IPは環境によって異なる場合があります.
また,今回はnginx
で受けたリクエストをphp-fpm
で実行し,その結果を返すようにしています.
リクエストは,nginx-service
が192.168.99.100:30001
を通して受け取り,nginxのPod
が,php-fpm-service
を通じて,php-fpmのPod
にリクエストを届け処理した結果をレスポンスとして返します.
用語説明
実際にkubernetesを利用して環境を作成する前に基本的な用語を簡単に説明します.
Pod
1つか複数のコンテナをデプロイする単位.今回は,Nginxのコンテナ
とPHP-FPMのコンテナ
を起動するので,それぞれのPodを作成することになります.
Deployment
Deploymentは,Pod(実際はReplicaSetsもです)を管理しています.DeploymentにPodが利用するイメージ(コンテナ)や,作成するPod(レプリカ)の数などを設定することで,常に指定されたイメージを設定した数だけ保つことができます.
Service
アプリケーションのエンドポイントです.今回は,nginx-service
とphp-fpm-service
という2つのServiceを作成します.
このエンドポイントを利用して,Pod
とPod
あるいは外部
とPod
が通信することになります.
main.yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30001
protocol: TCP
selector:
app: nginx
---
apiVersion: v1
kind: Service
metadata:
name: php-fpm-service
labels:
app: php-fpm
spec:
selector:
app: php-fpm
ports:
- protocol: TCP
port: 9000
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: yasunoriishikawa/nginx-advent2017:latest
ports:
- containerPort: 80
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: php-fpm
spec:
replicas: 1
template:
metadata:
labels:
app: php-fpm
spec:
containers:
- name: php-fpm
image: yasunoriishikawa/phpfpm-advent2017:latest
ports:
- containerPort: 9000
※image
の部分は,先程作成したDocker Hub
のイメージを指定して下さい.
yamlを大別すると下記のような構成になっています.
- Service
- nginx-service
- php-fpm-service
- Deployment
- nginx
- php-fpm
nginx-service(Service)
nginxのNetwork Proxyの役割を設定しています.
selector
にapp: nginx
と設定されていることで,先で説明したnginxのPodとのネットワークを管理しています.
nodePort: 30001
により,ホストでアクセスされる際のポート(外部からアクセスするときに使用するポート)を指定しています.
※ポートはデフォルトで,30000-32767まで利用できます.
php-fpm-service(Service)
php-fpmのNexwork Proxyの役割を設定しています.
基本的には,nginx-serviceと同様の設定ですが,管理対象は,php-fpmのPodであり,外部アクセスの必要性がないので,nodePort
は,設定していません.
nginx(Deployment)
nginxサーバのpodを管理しています.
Dockerイメージとして,yasunoriishikawa/nginx-advent2017:latest
を利用し,コンテナを80番ポートで起動し,1つのPod(replicas: 1)を管理しています.
php-fpm(Deployment)
php-fpm実行サーバのpodを管理しています.
Dockerイメージとして,yasunoriishikawa/phpfpm-advent2017:latest
を利用し,コンテナを9000番ポートで1つのPodを管理しています.
リソースの起動
実際に起動するには,下記のコマンドを実行して下さい.
$ kubectl apply -f main.yaml
確認
http://192.168.99.100:30001/index.phpにアクセスしてみて下さい.
※環境によってIPアドレスが異なることがあります.その際は,$ minikube ip
を実行して,自分の環境のIPアドレスを確認してみて下さい.
以下のようなページが表示されていれば,成功です.
ダッシュボードの確認
$ minikube dashboard
で,ダッシュボードを確認すると先程作成した.nginx
とphp
のdeployment
,pod
そして,service
が作成されていることが分かります.
リソースの停止
$ kubectl delete -f main.yaml
最後に
この記事で利用したプログラムは,GitHubで公開しています.
この記事を読んで頂いた方が,少しでもKubernetesに興味を持っていただければ幸いです.
参考
- gcloud
- kubernetes
- Download VirtualBox
- Docker
- サンプル
- 図書