NginxIngressControllerのタイムアウト設定

Pocket

記事概要

Kubernetes上に構築したサービスをクラスタ外に公開するためには一般的に「IngressController」を利用する。
Nginx IngressControllerをよく使うが、これのタイムアウト設定についてあまり詳しく書かれていなかったので補足していく。

Nginx IngressControllerの設定値

筆者が構築する場合は以下のようにhelmでyamlを生成している。

RELEASE_NAME=<test等任意の名前>
CHART_VERSION=<helmchartのバージョン>
INSTALL_NAMESPACE=<インストール先のネームスペース>
helm template ${RELEASE_NAME} ingress-nginx/ingress-nginx --version ${CHART_VERSION} --namespace ${INSTALL_NAMESPACE} --values helm.values.yaml > helm.yaml

helm.values.yaml にはhelm実行時の引数をまとめて記載しておくことができる。
設定できる値はドキュメントに記載されている。
IngressControllerに対して何かしら設定する場合は以下のようにhelm.values.yamlを設定する。

controller:
  config:
    # https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/
    hsts: "false"
    enable-modsecurity: "false"
    custom-http-errors: '403,413,404'
    enable-access-log-for-default-backend: "false"

このようにhelm templateでyamlを生成して管理する利点としては、helm chartのバージョンアップで変わった部分があればhelm.yamlの比較でわかることである。
生成したyamlはGitOpsで管理しているため、間違いが起こりにくい。
ここで設定した値はIngressリソースのannotationsで上書きできるものも多々ある。

タイムアウトの設定

バックエンドからN秒以内にレスポンスがなかった場合にIngressControllerから504を返すように実装したいとする。
このときどうするべきかAKS上で下図のような構成を構築して検証してみた。

検証結果

今回の場合はリクエストを受け付けた後、時間がかかる処理を実行中にタイムアウトしてしまうという想定でサンプルを実装した。
結果としてproxy-read-timeoutの時間でタイムアウトした。
ただし小さい値で設定するとタイムアウト時間が数秒ずれていた。

proxy-connect-timeout proxy-send-timeout proxy-read-timeout proxy-next-upstream-timeout 結果
5 50 55 5 55秒で504発生
5 50 90 5 90秒で504発生

ネットワークポリシーを使ってネットワーク的に遮断した場合はproxy-next-upstream-timeoutの値でタイムアウトが発生した。

proxy-connect-timeout proxy-send-timeout proxy-read-timeout proxy-next-upstream-timeout 結果
5 50 55 10 10秒で504発生
5 50 55 0 10分以上応答なし

デフォルト値

ドキュメントによるとそれぞれの項目のデフォルト値は下表のようになっている。
proxy-next-upstream-timeoutはデフォルト値0のまま応答がないと何も返ってこないのできちんと設定したほうが良いだろう。

設定
proxy-connect-timeout 5
proxy-send-timeout 60
proxy-read-timeout 60
proxy-next-upstream-timeout 0(設定なし)

まとめ

  1. タイムアウトのデフォルト値はConfigMapで設定する。
  2. Ingressリソースのannotationsで上書きできる。
  3. proxy-next-upstream-timeoutのデフォルト値は0なので5等の値に設定しておいたほうが良い。
Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です