LoginSignup
1
1

Istioでラウンドロビンで負荷分散してみる

Last updated at Posted at 2024-01-25

TL;DR

Webアプリケーションに来るリクエストをIstioで負荷分散してみました。
Github: https://github.com/cacapouh/istio-example

デプロイ対象のWebアプリケーション

リクエストの回数をレスポンスするアプリケーションをデプロイします。
以下はそのためのPythonスクリプトおよびDockerfileです。

main.py
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)
Dockerfile
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にしています。

deployment.yml
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設定です。

service.yml
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を設定しています。

gateway.yml
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へのリクエストをラウンドロビンで負荷分散させるようにしています。

destination_rule.yml
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ポートに流すようにしています。

virtual_service.yml
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回送った結果です。

リクエストを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になっているので、正常にラウンドロビンで負荷分散できていそうです :thumbsup:

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1