はじめに
この記事は GameWith Advent Calendar 2018の20日目です。
基本小心者なので、 packagist や npm に library 等を登録することは、あるものの記事を書くというのは初めてです。なので、お手柔らかに見ていただければと思います
今回は、 比較的ありがちな kubernetes の Web Application 構成についてお話しさせていただきます。
構成について
まず kubernetes で初めて設計する際に悩む箇所ですが、大雑把に2つのパターンになると思います。
NGINX と PHP をまとめるパターン
こちらのケースの方は 1 Pod で済みますし、サンプルでも比較的多く見かける構成だと思います。
NGINX と PHP を分けるパターン
上の図のパターンと比べると複雑になりますが、 NGINX
と PHP
を分けるパターンです。
Ingress
経由で NGINX Service
にアクセスし、 特定の NGINX Pod
に処理を割り振ります。
NGINX Pod
が PHP Service
にアクセスし、 PHP Pod
に処理を割り振ります。
結局どっちが良いのか
基本的には NGINX と PHP
を分けるパターン が良いかと思います。
Pod はアプリケーション単位で分けるのが基本と言われておりますが、運用や負荷テストをすると顕著に理解できます。
例えば以下のリソース使用量を見てください。
$ kubectl top pod
NAME CPU(cores) MEMORY(bytes)
php-deployment-xxxxxxxx-yyyy1 34m 57Mi
php-deployment-xxxxxxxx-yyyy2 28m 53Mi
php-deployment-xxxxxxxx-yyyy3 32m 52Mi
nginx-deployment-xxxxxxxx-yyyy1 1m 5Mi
nginx-deployment-xxxxxxxx-yyyy2 1m 5Mi
上記のように NGINX
と PHP
ではリソースの消費量が大抵桁外れに違うので、スケールする単位・タイミングが違います。なので、 NGINX
と PHP
を一緒にすると、負荷の高い方に影響されてスケールするため、高負荷なサービスほど必要以上にリソースを消費してしまいます。以上の事から、リソースは分けるべきだと個人的に思います。
定義について
こちらはあくまでもサンプルです。図のイメージと定義を照らし合わせて頂ければ良いかなと思う程度で記載しています。コピペで動作はしないので予めご理解願います
hpa などの auto scale に関しては今回省略しています。また、 Deployments や Services などの詳細に関しましては公式を見て頂く方が確実かと思いますので、リンクを貼り付けさせていただきます。
PHP の定義
apiVersion: apps/v1
kind: Deployment
metadata:
name: php-deployment
labels:
app: php
spec:
replicas: 2
selector:
matchLabels:
app: php
template:
metadata:
labels:
app: php
spec:
containers:
- name: php
image: hoge/dummy:commit_id
ports:
- containerPort: 9000
workingDir: /app
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.13
command: ["/cloud_sql_proxy",
"-instances=hoge:fuga:piyo=tcp:3306",
"-credential_file=/secrets/cloudsql/credentials.json",
"-verbose=false"]
volumeMounts:
- name: cloudsql-oauth-credentials
mountPath: /secrets/cloudsql
readOnly: true
volumes:
- name: cloudsql-oauth-credentials
secret:
secretName: cloudsql-oauth-credentials
restartPolicy: Always
apiVersion: v1
kind: Service
metadata:
name: php-service
labels:
app: php-service
spec:
type: ClusterIP
ports:
- port: 9000
selector:
app: php
NGINX の定義
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: hoge/fuga:piyo
ports:
- containerPort: 80
workingDir: /var/www/html
restartPolicy: Always
apiVersion: v1
kind: Service
metadata:
name: nginx-service
labels:
app: nginx-service
spec:
type: NodePort
ports:
- port: 80
targetPort: 80
selector:
app: nginx
server {
...
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# fastcgi_pass に service (Cluster IP) を定義します
fastcgi_pass php-service:9000;
fastcgi_index index.php;
include conf.d/common/fastcgi_params.conf;
}
}
Ingress (L7 LB) の定義
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: ingress-ip
spec:
backend:
serviceName: nginx-service
servicePort: 80
終わりに
次回書くことがありましたら、 BAD Knowhow
でも書かせていただこうと思います