ゼロからGKEにDjango+Reactをデプロイする(6)ServiceとIngress
(5)Deploymentの続きです。
やりたいこと
Djagno+Reactの構成でアプリケーションを開発してGoogle Kubernetes Engineにデプロイしたいけれども
まとまったチュートリアルが有りそうで無かったので書きました。
ただまだ完全ではない点があると思いますが、少し経験がある方ならすぐに利用できるんじゃないかと思っています。
注意
これは未経験の趣味エンジニアがポートフォリオを作成するためにデプロイと格闘した記録です。
不備があれば何卒御指摘をお願い致します。。
目指す姿
環境
$ node --version
v12.14.1
$ npm --version
6.13.7
$ python --version
Python 3.7.4
$ docker --version
Docker version 19.03.8
OS windows10 pro
デプロイ
Serviceの追加
KubernetesにデプロイしたコンテナはServiceかIngressを使って外部公開することができます。
Serviceを使って外部公開する場合、ServiceタイプをLoadBalancerにするかExternalNameにして外部公開する方法がありますが、今回はIngressを使ってServiceを公開する構成にしたいと思います。
ServiceもDeploymentと同様、yml形式でマニフェストファイルを作成し、kubectlでGKEにリソースを追加することができます。
# ファイルの作成
\gke-django-tutorial\manifests\type nul > service.yml
kind: Service
apiVersion: v1
metadata:
name: frontend-node-service
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 80
protocol: TCP
---
kind: Service
apiVersion: v1
metadata:
name: backend-node-service
spec:
type: NodePort
selector:
app: backend
ports:
- port: 80
targetPort: 80
protocol: TCP
ServiceタイプをNodePortとしました。
外部からのリクエストはIngressのLoadBalancerがServiceに転送し、Serviceはノードの80ポート(backend-Django)に転送しています。
ノードの80ポートはPod内のリバースプロキシ(Nginx)に転送され、アプリケーションとのやり取りが実現します。
# Serviceの追加
\gke-django-tutorial\manifests\kubectl create -f service.yml
service/frontend-node-service created
service/backend-node-service created
# Serviceの確認
\gke-django-tutorial\manifests\kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-node-service NodePort 10.28.5.61 <none> 80:31332/TCP 32s
frontend-node-service NodePort 10.28.8.91 <none> 30:31535/TCP 35s
kubernetes ClusterIP 10.28.0.1 <none> 443/TCP 22h
Ingressの追加
HTTP(S)ロードバランサを作成するIngressを使ってアプリケーションを公開します。
# Ingressの追加
\gke-django-tutorial\manifests\type nul > ingress.yml
Ingressの実態はIngressコントローラーであり、Ingressコントローラーは指定することができます。
GKEでIngressコントローラーを指定しない場合、デフォルトでCloud LoadBalancerが適用されます。
今回はデフォルトで進めていきます。
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress-service
namespace: default
annotations:
kubernetes.io/ingress.class: gce
spec:
rules:
- http:
paths:
- path: /*
backend:
serviceName: frontend-node-service
servicePort: 80
- path: /api/*
backend:
serviceName: backend-node-service
servicePort: 80
- path: /admin/*
backend:
serviceName: backend-node-service
servicePort: 80
# Ingressの追加
\gke-django-tutorial\manifests\kubectl create -f ingress.yml
ingress.extensions/ingress-service created
# 確認
\gke-django-tutorial\manifests\kubectl get ingress
NAME HOSTS ADDRESS PORTS AGE
ingress-service * 34.95.105.61 80 112s
ADDRESSが外部公開用のIPアドレスになります。これで外部へ公開ができたと思いきや、コンソールを確認すると backend services are in UNHEALTHY state
なるメッセージが確認できます。
Podへのヘルスチェックに対応する
外部公開するIngressを通して公開されるServiceはロードバランサからのヘルスチェックに応答する必要があります。
このヘルスチェックはデフォルトでは /
パスに対するGETリクエストに対し、HTTP200ステータスのレスポンスを期待しています。
frontendのReact側では /
パスに対してHTTP200ステータスを返答しますが、backendのDjango側では /
への返答は追加していません。
ヘルスチェックのリクエスト先はDeploymentを使って変更することができます。
- 参考:
今回はPod内に追加したリバースプロキシ(Nginx)にヘルスチェック用の location=/healthz
を追加していました。
今回はヘルスチェックへのパスを /healthz
に変更し、Pod内のリバースプロキシは /healthz
に対してHTTP200ステータスを返答するようにします。
コンソール上から Compute Engine > ヘルスチェック
を確認すると、Serviceに対するヘルスチェック先のパス一覧が表示されます。
backendサービス, frontendサービスのポートと一致する使用リソースのパスを /healthz
に変更しておきましょう。
今回のサービスのポートは次のように確認すると、31332と31535です。
# Serviceの確認
\gke-django-tutorial\manifests\kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
backend-node-service NodePort 10.28.5.61 <none> 80:31332/TCP 32s
frontend-node-service NodePort 10.28.8.91 <none> 30:31535/TCP 35s
kubernetes ClusterIP 10.28.0.1 <none> 443/TCP 22h