ingressの役割
- クラスター内のServiceに対する外部からのアクセス(主にHTTP)を管理するAPIオブジェクトで、負荷分散、SSL終端、名前ベースの仮想ホスティングの機能を提供する。
- 一つのingress上に、複数のドメインの設定を行うことが可能。
- ingress-nginxを使った場合は、バーチャルサーバ(バーチャルホスト)の機能を使って実現している。
- 具体的には、
nginx.conf
に以下のような設定が適用される(以下の例では、foo.example.com
とbar.next-example.jp
ドメインをホストしている)。
- 具体的には、
- ingress-nginxを使った場合は、バーチャルサーバ(バーチャルホスト)の機能を使って実現している。
nginx.conf
http {
:
:
## start server foo.example.com
server {
server_name foo.example.com ;
# Custom code snippet configured for host foo.example.com
location ~* "^/bar/(.*)" {
#
# some config comes here
#
}
}
## end server foo.example.com
## start server bar.next-example.jp
server {
server_name bar.next-example.jp ;
location ~* "^/(.*)" {
}
location ~* "^/" {
}
}
## end server bar.next-example.jp
}
前提
- Ingressリソースが動作するためには、クラスターでIngressコントローラーが実行されている必要がある。
- Ingressコントローラーの一つにIngress NGINX Controllerがある。
- 今回対象とするのは、このコントローラー上で設定されるIngressリソース。
- クラスター内に複数のIngressコントローラーが存在する場合にどのIngressコントローラーを使用するかを示すために、複数のcontrollerをデプロイした時は、適切な
spec.ingressClassName
フィールドを指定する必要がある(例:ingressClassName: nginx
)。- ドキュメントでは、
ingress.class
のアノテーションとなっている箇所がある。ingressClassName
フィールドはこのアノテーションを置き換えるものだが、完全に等価ではない。- 実運用上は、
ingress.class
のアノテーションは使わず、ingressClassName
フィールドを使えば良い認識(ingress.class
は、kubernetes v1.22+で非推奨となる)。 - 単一のIngressコントローラーのみが存在する場合も、
ingressClassName
フィールドを指定しておけば間違いない。
- 実運用上は、
- ドキュメントでは、
- Ingressコントローラーの一つにIngress NGINX Controllerがある。
参照ドキュメント
- Ingressリソースの設定は、
nginx.conf
に反映される。そのため、nginxの設定が理解できていると、イメージしやすい。
設定例
PATHに応じてリダイレクトを行う
単一のドメインにリダイレクトを行う場合は、ドキュメントに書かれている通り、nginx.ingress.kubernetes.io/permanent-redirect: https://www.google.com
というアノテーションが使えます。
PATHに応じてリダイレクトを行う場合は、以下のいずれかを使う必要があります。
-
nginx.ingress.kubernetes.io/server-snippet
-
nginx.conf
のserverディレクティブに設定が追加されます。 - server-snippet は1つのホストにつき1回しか設定できない。
-
-
nginx.ingress.kubernetes.io/configuration-snippet
-
nginx.conf
のlocationディレクティブに設定が追加されます。 - 既存のlocationディレクティブがあった場合、その全てに、ここで設定したものがネストして追加される(以下、例)
-
location ~* "^/foo/(.*)" { // 既存の location directive
location ~* "^/foo/(.*)" { // configuration-snippet を使って追加された location directive。本来は、既存の location directive に追加したいが、ネストして追加される。
}
}
location ~* "^/bar/(.*)" { // 既存の location directive
location ~* "^/foo/(.*)" { // configuration-snippet を使って追加された location directive。ここに追加する意味は本来ないが、追加される。
}
}
location ~* "^/" { // 既存の location directive
location ~* "^/foo/(.*)" { // configuration-snippet を使って追加された location directive。ここに追加する意味は本来ないが、追加される。
}
}
以下、configuration-snippet
を使った例。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: sample-ingress-nginx
annotations:
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/use-regex: "true"
nginx.ingress.kubernetes.io/configuration-snippet: |
rewrite ^/$ https://example.com permanent;
rewrite ^/en\/?$ https://example.com/en/foo permanent;
rewrite ^/ja\/?$ https://example.com/ja/foo permanent;
rewrite ^/(.*) https://another-example.com/$1 permanent;
cert-manager.io/issuer: "sample-letsencrypt-issuer"
spec:
ingressClassName: nginx
tls:
- hosts:
- sample.example.com
secretName: sample-letsencrypt-cert
rules:
- host: sample.example.com
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: sample-service
port:
number: 80
以下、server-snippet
で、location
+ return 301
を使った例だが、この設定ではSSL証明書が発行されなかった。
SSL証明書発行時には、発行要求を受け付けるために temporary の ingress が立ち上がるが、そこでうまくリクエストを処理できないのではないかと思われるが、詳細は不明。
annotations:
:
nginx.ingress.kubernetes.io/server-snippet: |
location ~ ^/((foo|bar)\/?)?$ {
return 301 https://redirect1-sample.example.com/$1;
}
location ~ ^/(.*) {
return 301 https://redirect2-sample.example.com/$1;
}
cert-manager.io/v1 設定例
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: sample-letsencrypt-issuer
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: foo@example.com
privateKeySecretRef:
name: sample-acme-client-letsencrypt
solvers:
- http01:
ingress:
class: nginx
備考
ingress-nginxの設定をする上で、nginxの設定を理解しておくことは重要です。
パフォーマンスに関しては、以下の記事が参考になります。
https://www.getpagespeed.com/server-setup/nginx-locations-performance-impact-and-optimizations
- 可能な限り、正規表現ではなく、完全一致を使う。
-
rewrite
ではなく、nested locations
を使う。- しかし、上記の例では、
location
+return
では SSL証明書の発行ができなかったため、rewrite
を使っている。
- しかし、上記の例では、
nginx.conf の設定を確認する
NAMESPACE=ingress-nginx
kubectl get pods --namespace=$NAMESPACE
// で pod を確認し、以下のコマンドで指定する。
kubectl exec --stdin --tty --namespace=$NAMESPACE ingress-nginx-controller-844c488f4b-85h6j -- cat /etc/nginx/nginx.conf
// or
kubectl exec -it -n $NAMESPACE ingress-nginx-controller-844c488f4b-85h6j -- cat /etc/nginx/nginx.conf
ingress のログを見る
kubectl logs ingress-nginx-controller-5849c9f946-dqczh -n $NAMESPACE -f
ingress の pod にログインする
kubectl exec -it -n $NAMESPACE ingress-nginx-controller-844c488f4b-85h6j -- /bin/bash
その他、参考URL
- ingress-nginx Installation Guide
- https://medium.com/ww-engineering/kubernetes-nginx-ingress-traffic-redirect-using-annotations-demystified-b7de846fb43d
- https://blog.grasys.io/post/tsunoda/nginx-rewrite/
- https://stackoverflow.com/questions/58993607/passing-parameters-down-to-permanent-redirect-in-ingress-nginx
- https://docs.nginx.com/nginx/admin-guide/web-server/web-server/
- https://blog.cybozu.io/entry/2015/11/20/080000
- http://nginx.org/en/docs/http/converting_rewrite_rules.html
- https://heartbeats.jp/hbblog/2012/04/nginx05.html