0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

KongのRate Limiting Advanced PluginとRedis Sentinelを組み合わせて使う

Last updated at Posted at 2024-07-03

Kong Gatewayで流量制限をする際にはRate Limiting Pluginを使うが、これはOSS版とEnterprise版(Rate Limiting Advanced Plugin)で機能差がある。
機能比較した結果を一部抜粋したものが以下となる。

機能 Rate Limiting Plugin Rate Limiting Advanced Plugin
ライセンス OSS Konnect PremiumかEnterpriseのライセンス要
アルゴリズム 固定ウィンドウ スライディングウィンドウ、固定ウィンドウ
カウントポリシー local, cluster, redis(*) local, cluster, redis

*:Redis単体のみ。ClusterやSentinelは未サポート。

アルゴリズムの説明はこちらのブログが詳しいので、詳細が必要な場合は参考にするとよい。
ポリシーについては以下公式ドキュメントの記述を意訳したものとなる。

種類 長所 短所
local パフォーマンスへの影響は最小限 精度は低くなる。ローカルで持つため、複数ノードでDataPlaneを構成した場合、LBで均等に分散しないと偏りが生じるリスクあり
cluster ControlPlaneのDBを使うため追加コンポーネントなしで正確にカウントできる 各リクエスト毎にDBへのRead/Writeが発生するため、性能影響大(ただしsync_rateで調整可)。またDB-Less構成では利用不可
redis 正確かつclusterよりも性能影響低 Redis のインストールが必要。localと比べると性能影響大

上記より以下が言える。

  • 流量制御で正確さが求められ、かつ高トラフィックを捌くようなケースではRedisが最適
  • 上記のようなケースでは必然的にRedisの冗長性も求められるため、Redis Sentinelなどが必要

ということで、厳し目の流量制御が必要な場合はRate Limiting Advanced PluginでRedis Sentinel or Clusterが必要となる。
前置きが長くなったが、今回は硬くて正確な流量制限が必要な場合に取る構成となる、Rate Limiting Advanced PluginとRedis Sentinelを組み合わせた構成の作り方を確認する。
(SentinelにするかClusterにするかは迷ったが、こちらを参考にSentinelの方が良さげだったのでSentinelを選択した)

検証環境

今回は以下の環境で検証した。

  • EKS
  • Kong Gateway Enterprise 3.6 (Helmで構築済み)

RedisはKong Gatewayと同じクラスタ内に構築し、Serviceでアクセスするようにする。

検証

Redis Sentinelの構築

BitnamiにあるHelm Chartが使えそうなのでこれを使う。
最初にBitnamiのリポジトリを追加する。

helm repo add bitnami https://charts.bitnami.com/bitnami

インストールする。

helm upgrade -i redis bitnami/redis --set sentinel.enabled=true -n redis --create-namespace --wait --debug

インストールが終わるとStatefulSetでRedis Podが展開されていることが分かる。

$ kubectl get pod -n redis
NAME           READY   STATUS    RESTARTS   AGE
redis-node-0   2/2     Running   0          40m
redis-node-1   2/2     Running   0          40m
redis-node-2   2/2     Running   0          39m

動作確認のため、試しに繋いでみる。
redis-cliを使うためにredisのPodを起動する。

kubectl run redis --image redis -n default

Redisのパスワードを取得する。

REDIS_PASSWORD=$(kubectl get secret -n redis redis -o jsonpath={.data.redis-password} | base64 -d)

Redis Sentinelに対し、マスターがどれかを聞いてみる。

kubectl exec -it -n default redis -- redis-cli -a $REDIS_PASSWORD -h redis.redis.svc -p 26379 sentinel get-master-addr-by-name mymaster

以下のような出力が得られれば接続に成功している。

Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
1) "redis-node-0.redis-headless.redis.svc.cluster.local"
2) "6379"

Service/Routeの作成

Kong GatewayのService/Routeを設定する。
ここではバックエンドのサービスはhttpbin.orgとし、Proxyにパス/myhttpbinでアクセス出来るようにする。
構築はKong ManagerからUIで行ってもいいが、ここではdeckコマンドを利用するものとする。
まずdeck用のYAMLを作成する。

cat <<EOF > ./svc-rt.yaml
_format_version: "3.0"
_workspace: redis-test
services:
- host: httpbin.org
  name: httpbin-svc
  port: 443
  protocol: https
  routes:
  - name: httpbin-rt
    paths:
    - /myhttpbin
    preserve_host: false
    protocols:
    - http
    - https
    request_buffering: true
    response_buffering: true
    strip_path: true
EOF

ここでは便宜上新しくWorkspaceとしてredis-testを作成している。
作成したYAMLを適用する。

deck gateway sync ./svc-rt.yaml

念の為動作確認としてhttpbin.org/user-agentにProxy経由でアクセスしてみる。

PROXY=<Kong GatewayのProxyのアドレス>
curl $PROXY/myhttpbin/user-agent

問題なければ以下のような出力が得られる。

{
  "user-agent": "curl/8.6.0"
}

Rate Limit Advanced Pluginの設定

ここでは作成したRouteに対してRate Limit Advanced Pluginを設定する。
Pluginの設定はこちらでもdeckコマンドを利用して設定する。
deckコマンドでPluginを設定する場合、先程のService/RouteのYAMLに追記する形で書くか、deck file add-pluginsというコマンドで既存の設定に別途Pluginだけ追加する方法がある。
ここではdeck file add-pluginsを使うやり方で設定する。
Pluginの設定ファイルを以下で作成する。

cat <<EOF > ./plugin-rate-limiting-adv.yaml
_format_version: "1.0"
add-plugins:
- selectors:
  - $..routes[*]
  overwrite: true
  plugins:
  - name: rate-limiting-advanced
    config:
      limit:
      - 5
      window_size:
      - 30
      identifier: ip
      sync_rate: 0
      namespace: redis
      strategy: redis
      redis:
        sentinel_role: master
        sentinel_addresses:
        - redis.redis:26379
        sentinel_master: mymaster
        sentinel_password: $REDIS_PASSWORD
        password: $REDIS_PASSWORD
EOF

細かい書き方については公式ドキュメントを参照して欲しい。
Rate Limitingの設定として、ウィンドウサイズを30秒、1つのウィンドウのアクセスの上限を5回とし、同期のタイミング(sync_rate)を0に設定して常時同期するようにした。
Redisに関する設定はsentinel_rolesentinel_addressessentinel_masterが必須パラメータであり、Helmでデフォルトで入れると認証も必要となるのでパスワードもあわせて設定した。
Service/Routeに足す形で作成したPluginの設定を適用する。

deck file add-plugins -s svc-rt.yaml plugin-rate-limiting-adv.yaml | deck gateway sync -

コマンドを補足すると、-s svc-rt.yamlでPluginを追加するソースのファイルを指定し、deck file add-pluginsはデフォルトで標準出力にYAMLを吐くので、それをdeck gateway syncに渡している。(最後の-はパイプで渡された標準出力をファイルとして渡している)

動作確認

実際にRedisに記録されることを確認する。
Rate Limiting Advanced Pluginを設定したパスにリクエストをいくつか発行する。

for((i=0; i<20; i++)); do curl -i $PROXY/myhttpbin/user-agent; sleep .5; done

Redisの中を確認する。

kubectl exec -it -n default redis -- redis-cli -a $REDIS_PASSWORD -h redis.redis.svc -p 6379 keys "*"

以下のようにRedis内にキーが作られていることが確認できる。

Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
1) "1720000830:30:redis"

これにより、アクセスの状況がRedisに残っている事が確認できた。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?