AWSのKubernetesのingressコントローラーとしてAWS LoadbBanacer Controllerがあります。 これ、使うとALBが自動で起動されて使うことができます。つまり、ALBの仕様に完全に依存する形のIngress Controllerです。
ALBは高機能な反面、ingressとして使うと少々クセがある感じがしたので覚え書きとしてまとめていきます。 仕様に制限があるのでその制限を回避する方法も載せていきます。
なお、現時点での最新版、v2.7での情報です。
1. リスナールールを「条件」「アクション」に分けてアノテーションで記載する
ALBにはリスナールールという仕組みがあり、AWS LoadBalancer Controllerではこの仕組みを制御できます。
Application Load Balancer のリスナールール - Elastic Load Balancing
リスナールールはアクセスを「条件」と「アクション」に分けて記述する機能です。 AWS LoadBalancer Controllerを使うとIngressでこのリスナールールを表現することができます。
条件
条件はalb.ingress.kubernetes.io/conditions.${conditions-name} で、ここにSourceIPやらリクエストメソッドはGETやらの条件をつけることができます。
アクション
アクションはalb.ingress.kubernetes.io/actions.${action-name}で、ここにリダイレクトするなり、特定のKuernetes のservice resourceに転送するなりのアクションをつけることができます。
これは実際におこなった設定なのですが「password変更のRESTful APIを塞ぎたい」場合、以下のようなアノテーションをingressに設定することになります。
alb.ingress.kubernetes.io/conditions.deny-password-login: > [{"Field":"http-request-method", "httpRequestMethodConfig":{"Values":["POST"]}}] alb.ingress.kubernetes.io/actions.deny-password-login: > {"Type": "fixed-response", "fixedResponseConfig":{"statusCode":"403"}}
conditionでPOST、actionで403のレスポンスを返す、としています。conditionとactionで名前を合わせることで一対の設定となります。 これをingressのruleに設定します。以下のようにすれば、example.com/api/session に対して上記のアノテーションを設定することができます。
rules: - host: example.com http: paths: - backend: service: name: deny-password-login 👈annotationで設定した名前を指定する port: name: use-annotation path: /api/session pathType: Exact
2.「条件」の個数制限に注意する
ALBの仕様として、「条件」は5つまでしか設定できません。
Application Load Balancer のクォータ - Elastic Load Balancing
この個数を超えるとingressを設定してもALBには設定は反映されません。AWS LoadbBanacer Controllerのログにはエラーが出力されますが、Ingress ControllerのPodやIngressは見かけ上異常なく見えるので注意が必要です。
3. pathTypeの仕様に注意する
IngressではpathTypeによって完全一致か前方一致かを指定できます。
ImplementationSpecific
(実装に特有): このパスタイプでは、パスとの一致はIngressClassに依存します。Ingressの実装はこれを独立したpathType
と扱うことも、Prefix
やExact
と同一のパスタイプと扱うこともできます。Exact
: 大文字小文字を区別して完全に一致するURLパスと一致します。Prefix
:/
で分割されたURLと前方一致で一致します。大文字小文字は区別され、パスの要素対要素で比較されます。パス要素は/
で分割されたパスの中のラベルのリストを参照します。リクエストがパス p に一致するのは、Ingressのパス p がリクエストパス p と要素単位で前方一致する場合です。
簡単に言えばExact
は完全一致、Prefix
は前方一致で、AWS LoadbBanacer Controllerを使った場合でもその仕様は変わりません。
ただし、pathTypeはALBの「条件」に設定されるため、前述の個数制限は留意する必要があります。
たとえば、先ほど出した例は Exact
を使いましたが、
rules: - host: example.com http: paths: - backend: service: name: deny-password-login port: name: use-annotation path: /api/session pathType: Exact 👈これね
この場合は自動的に2つ「条件」を使うことになります。
- HTTPホストヘッダーが
example.com
- パスパターンが
/api/session
そのため、他の条件(リクエストメソッドやソースIPなど)は3つつけることができます。
さて、Prefix
はどうなるのでしょう?
rules: - host: example.com http: paths: - backend: service: name: deny-password-login port: name: use-annotation path: /api/session pathType: Prefix
この場合は3つ「条件」を使います。
- HTTPホストヘッダーが
example.com
- パスパターンが
/api/session
- パスパターンが
/api/session/*
そのため、他の条件(リクエストメソッドやソースIPなど)は2つになります。
いちばんわかりにくいImplementationSpecific
の場合はどうなるのでしょうか?
これは指定したそのままがALBに設定されます。
path: /api/session pathType: ImplementationSpecific
↑たとえばこの場合はExactと同じように、2つ「条件」を使うことになります。example.com/api/session
には適用されますが example.com/api/session/hoge
には適用されない設定です。
path: /api/session/* pathType: ImplementationSpecific
これはExactでもPrefixでもない指定になって、2つ「条件」を使うことになります。 example.com/api/session
には適用されず、example.com/api/session/hoge
には適用されます。
こういう感じなので、AWS LoadbBanacer Controller を使う場合は設定が思った通りに反映されているかALBを確認しながらやると良いです。
4. 制限は回避できる
ここまで条件の指定は5つまでしかない、ということを口すっぱく言ってきましたが、この仕様は回避することができます。 たとえばソースIPをたくさん条件に指定したい場合は以下のように複数アノテーションを作ればよいです。
alb.ingress.kubernetes.io/actions.allow-from-certain-ips1: > {"Type": "forward", "ForwardConfig": {"TargetGroups": [{"ServiceName": "exampleservice", "ServicePort": "80"}]}} alb.ingress.kubernetes.io/conditions.allow-from-certain-ips1: > [{"Field":"source-ip", "sourceIpConfig": {"values":["8.8.4.0/24", "8.8.8.0/24", "8.34.208.0/20"]}}] alb.ingress.kubernetes.io/actions.allow-from-certain-ips2: > {"Type": "forward", "ForwardConfig": {"TargetGroups": [{"ServiceName": "exampleservice", "ServicePort": "80"}]}} alb.ingress.kubernetes.io/conditions.allow-from-certain-ips2: > [{"Field":"source-ip", "sourceIpConfig": {"values":["8.35.192.0/20", "23.236.48.0/20", "23.251.128.0/19"]}}]
- host: example.jp http: paths: - backend: service: name: allow-from-certain-ips1 port: name: use-annotation path: /example/* pathType: ImplementationSpecific - host: example.jp http: paths: - backend: service: name: allow-from-certain-ips2 port: name: use-annotation path: /example/* pathType: ImplementationSpecific
これは特定のソースIPからexample.jp/example/*
にアクセスした場合はそのままexampleserviceに通すことを意味しています。
どうでしょう?AWS LoadBalancer Controllerの深淵を少しは覗くことができたでしょうか??
なんだか難しそうには見えますが、慣れてしまうと割と高機能なALBの機能を活用できるので便利です。
誰か困っている人に届きますように……