TL;DR
Webアプリケーションに来るリクエストをIstioで負荷分散してみました。
Github: https://github.com/cacapouh/istio-example
デプロイ対象のWebアプリケーション
リクエストの回数をレスポンスするアプリケーションをデプロイします。
以下はそのためのPythonスクリプトおよびDockerfileです。
import os
from bottle import route, run
count = 0
@route('/')
def index():
global count
count = count + 1
return "{}: {}!".format(count, os.environ["HOSTNAME"])
run(host='0.0.0.0', port=8080)
FROM python:3.9
RUN mkdir /work
WORKDIR /work
COPY requirements.txt /work
RUN pip install -r ./requirements.txt
COPY main.py /work
ENTRYPOINT python main.py
以下は上記のDockerfileのビルド方法です。
ここではsimple-app
という名前でビルドしています。
docker build . -t simple-app
minikube image load simple-app:latest # Minikubeの場合
デプロイ対象のマニフェストファイル群
この記事で取り扱うマニフェストファイルは以下の5つです。
- deployment.yml
- WebアプリをデプロイするためのDeploymentを取り扱います
- service.yml
- WebアプリにアクセスするためのServiceを取り扱います
- gateway.yml
- IstioのGatewayを取り扱います
- Gatewayリソースとは、外部からのトラフィックを受け付けて、
ロードバランシングするプロキシです
- destination_rule.yml
- IstioのDestinationRuleを取り扱います
- DestinationRuleとは、特定のサービスへのトラフィックを制御するためのリソースです。
- virtual_service.yml
- IstioのVirtual Serviceを取り扱います
- VirtualServiceリソースとは、トラフィックのルーティング設定を行うものです
deployment.yml
以下は、PythonのWebアプリを取り扱うDeploymentリソース設定です。
ラウンドロビンの挙動を確かめる関係でレプリカ数を2にしています。
apiVersion: apps/v1
kind: Deployment
metadata:
name: simple-app-deployment
labels:
app: simple-app
spec:
replicas: 2
selector:
matchLabels:
app: simple-app
template:
metadata:
labels:
app: simple-app
spec:
containers:
- name: simple-app
image: "simple-app:latest"
imagePullPolicy: IfNotPresent
service.yml
以下はPythonのWebアプリにアクセスするためのService設定です。
apiVersion: v1
kind: Service
metadata:
name: simple-app-service
spec:
selector:
app: simple-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 8080
gateway.yml
以下はIstioのGatewayの設定です。
80ポートへのアクセスであれば、
どのようなホストでもHTTPリクエストを受け付けるようにしています。
spec.selector
は、どのIstioイングレスゲートウェイのPodがそのGatewayリソースの設定を使用するかを決定するために使用されます。ここでは、IstioがデフォルトでイングレスゲートウェイのPodに付与するラベルingressgateway
を設定しています。
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: istio-ingressgateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
destination_rule.yml
以下はIstioのDestinationRule設定です。
simple-app-service
へのリクエストをラウンドロビンで負荷分散させるようにしています。
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: simple-app-destinationrule
spec:
host: simple-app-service
trafficPolicy:
loadBalancer:
simple: ROUND_ROBIN
virtual_service.yml
以下はIstioのVirtualService設定です。
istio-ingressgateway
というGatewayを介して入るトラフィックを、
simple-app-service
というサービスの80ポートに流すようにしています。
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: simple-app-virtualservice
spec:
hosts:
- "*"
gateways:
- istio-ingressgateway
http:
- route:
- destination:
host: simple-app-service
port:
number: 80
デモンストレーション
上記のマニフェストファイル群は、Helm Chartでまとめていまして、
こちらのリポジトリでhelm install simple-app ./helm
コマンドを実行することにより、デプロイ可能です。
以下は、デプロイした後にリクエストを1000回送った結果です。
for i in {1..1000}
do
curl "http://127.0.0.1:80"
echo "Request $i completed"
done
1: simple-app-deployment-dd44b5ff4-6fc7q!Request 1 completed
1: simple-app-deployment-dd44b5ff4-nk7z4!Request 2 completed
2: simple-app-deployment-dd44b5ff4-6fc7q!Request 3 completed
3: simple-app-deployment-dd44b5ff4-6fc7q!Request 4 completed
2: simple-app-deployment-dd44b5ff4-nk7z4!Request 5 completed
4: simple-app-deployment-dd44b5ff4-6fc7q!Request 6 completed
3: simple-app-deployment-dd44b5ff4-nk7z4!Request 7 completed
4: simple-app-deployment-dd44b5ff4-nk7z4!Request 8 completed
5: simple-app-deployment-dd44b5ff4-6fc7q!Request 9 completed
6: simple-app-deployment-dd44b5ff4-6fc7q!Request 10 completed
5: simple-app-deployment-dd44b5ff4-nk7z4!Request 11 completed
7: simple-app-deployment-dd44b5ff4-6fc7q!Request 12 completed
...(中略)...
495: simple-app-deployment-dd44b5ff4-nk7z4!Request 990 completed
496: simple-app-deployment-dd44b5ff4-6fc7q!Request 991 completed
497: simple-app-deployment-dd44b5ff4-6fc7q!Request 992 completed
496: simple-app-deployment-dd44b5ff4-nk7z4!Request 993 completed
497: simple-app-deployment-dd44b5ff4-nk7z4!Request 994 completed
498: simple-app-deployment-dd44b5ff4-6fc7q!Request 995 completed
498: simple-app-deployment-dd44b5ff4-nk7z4!Request 996 completed
499: simple-app-deployment-dd44b5ff4-6fc7q!Request 997 completed
499: simple-app-deployment-dd44b5ff4-nk7z4!Request 998 completed
500: simple-app-deployment-dd44b5ff4-6fc7q!Request 999 completed
500: simple-app-deployment-dd44b5ff4-nk7z4!Request 1000 completed
deployment.yml
でレプリカ数を2つに設定していましたので、
標準出力には2つのPod名が登場しています。
カウント値がちょうど500対500になっているので、正常にラウンドロビンで負荷分散できていそうです