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?

More than 1 year has passed since last update.

【ingress-nginx】リダイレクトの設定例

Last updated at Posted at 2022-06-22

ingressの役割

  • クラスター内のServiceに対する外部からのアクセス(主にHTTP)を管理するAPIオブジェクトで、負荷分散、SSL終端、名前ベースの仮想ホスティングの機能を提供する。
  • 一つのingress上に、複数のドメインの設定を行うことが可能。
    • ingress-nginxを使った場合は、バーチャルサーバ(バーチャルホスト)の機能を使って実現している。
      • 具体的には、nginx.confに以下のような設定が適用される(以下の例では、foo.example.combar.next-example.jpドメインをホストしている)。
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リソースの設定は、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

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?