k8s Ingress
L7ロードバランシングを提供するリソース
Ingressはクラスター外からクラスター内ServiceへのHTTPとHTTPSのルートを公開します。トラフィックのルーティングはIngressリソース上で定義されるルールによって制御されます。
と書かれている通り、Serviceに対するロードバランシングになる
前提条件として、必ずIngress Controllerが必要
Ingress ControllerはIngressリソースの作成や変更を検知して、いい感じにしてくれるやつ
Controllerはだいたいそういう役割
大きく分けて二個
GKE Ingress Controller
Nginx Ingress Controller
どちらもIngressリソースの作成時に処理を行うコントローラ
クラスタ外のロードバランサを利用したIngress
GKE Ingress
クラスタ内にIngress用のPodをデプロイするIngress
Nginx Ingress
Ingressリソースの定義yaml
code:ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
spec以下に、ロードバランサやプロキシサーバを設定するための全ての情報を持つ
httpはhttpプロトコルでのリクエストに対する設定
httpsもある
デフォルトのバックエンド
ルールが設定されていないIngressは、全てのトラフィックをデフォルトのバックエンドに転送する
defaultBackendはIngressコントローラのオプション設定で、Ingress側では設定しない
リソースバックエンド
Resourceバックエンドは、Ingressオブジェクトと同じnamesapceにある他のk8sリソースを指すObjectRef
ResourceはServiceの設定と排他であるため、両方を設定するとバリデーションに失敗する
よくある用途は、静的なアセットが入ったオブジェクトストレージを設定すること
code:ingress-resource-backend.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ingress-resource-backend
spec:
defaultBackend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: static-assets
rules:
- http:
paths:
- path: /icons
pathType: ImplementationSpecific
backend:
resource:
apiGroup: k8s.example.com
kind: StorageBucket
name: icon-assets
パスのタイプ
Ingressのそれぞれのパスは対応するパスのタイプを持つ。
pathTypeが明示的に指定されていないパスはバリデーションに通らない
ImplementationSpecific
パスの一致はIngressClassに依存する。Ingressの実装はこれを独立したpathTypeと扱うことも、PrefixやExactと同一のパスタイプと扱うこともできる
どゆこと?osamtimizer.icon
Exact
大文字小文字を区別して完全に一致するURLパスと一致
Prefix
/で分割されたURLと前方一致で一致する。大文字小文字は区別され、パスの要素対要素で比較される。
パス要素は/で分割あsれたパスの中のラベルのリストを参照する
ホスト名のワイルドカード
完全一致かワイルドカードで指定できる
*.foo.com
bar.foo.com: 一致する
baz.bar.foo.com: 一致しない
foo.com: 一致しない
Ingress Class
Ingressは異なったコントローラで実装されるため、しばしば異なった設定を必要とする
IngressClassリソースは、この種別のIngressを実装すべきコントローラの名称を含む追加の設定情報を含む。
各IngressはIngressClassリソースへの参照によって種別を指定するべき
code:esternal-lb.yaml
apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
name: external-lb
spec:
controller: example.com/ingress-controller
parameters:
apiGroup: k8s.example.com
kind: IngressParameters
name: external-lb
IngressClassに対してcontrollerを指定できる
この時点ではなんともだけど、Ingressを作成するときにIngressClassを指定できる?
Ingressのタイプ
単一ServiceのIngress
k8sには、単一のServiceを公開できるようにする既存の概念がある
ルールなしでデフォルトのバックエンドを指定することにより、Ingressでこれを実現できる
code:trest-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
spec:
defaultBackend:
service:
name: test
port:
number: 80
code:bash
# k get ingress test-ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
test-ingress external-lb * 203.0.113.123 80 59s
203.0.133.123はIngressControllerによって割り当てられたIPで、作成したIngressを利用するためのもの
リクエストのシンプルなルーティング
code:simple-fanout-example.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: simple-fanout-example
spec:
rules:
- host: foo.bar.com
http:
paths:
- path: /foo
pathType: Prefix
backend:
service:
name: service1
port:
number: 4200
- path: /bar
pathType: Prefix
backend:
service:
name: service2
port:
number: 8080
foo.bar.com/fooへのリクエストをservice1:4200へ
foo.bar.com/barへのリクエストをservice2:8080へ
code:bash
$ k describe ingress simple-fanout-example
Name: simple-fanout-example
Namespace: default
Address: 178.91.123.132
Default backend: default-http-backend:80 (10.8.2.3:8080)
Rules:
Host Path Backends
---- ---- --------
foo.bar.com
/foo service1:4200 (10.8.0.90:4200)
/bar service2:8080 (10.8.0.91:8080)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ADD 22s loadbalancer-controller default/test
名前ベースのバーチャルホスティング
こっちの方が使う場面多そうosamtimizer.icon
ロードバランサーに対して、Hostヘッダーに基づいてリクエストを転送するように指示する
code:name-virtual-host-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
foo.bar.com/をservice1:80に
bar.foo.com/をservice2:80に
これ、foo.bar.com/hogeだったらどうなるんだろうosamtimizer.icon
rules項目でのホストの設定がないIngressを作成すると、IngressコントローラのIPアドレスに対するwebトラフィックは、要求されている名前ベースのバーチャルホストなしにマッチさせることができる
例えば、以下のIngressはfirst.bar.comに対するトラフィックをservice1へ、
second.foo.comに対するトラフィックをservice2へ、
リクエストにおいてホスト名が指定されていない(リクエストヘッダがない)トラフィックはservice3に転送する
そんなリクエストあるんかなosamtimizer.icon
code:name-virtual-host-ingress-no-third-host.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: name-virtual-host-ingress-no-third-host
spec:
rules:
- host: first.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: second.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service3
port:
number: 80
TLS
TLSの秘密鍵と証明書を含んだSecretを指定することにより、Ingressをセキュアにできる
Ingressは単一のTLSポートである443番のみサポートし、IngressでTLS終端を行うことを想定している
IngressからServiceやPodへのトラフィックは平文になる
IngressのTLS設定のセクションで異なるホストを指定すると、それらのホストはSNI TLSエクステンションを介して指定されたホスト名に対し、同じポート上で多重化される
わからんosamtimizer.icon
TLSのSecretはtls.crt, tls.keyというキーを含める必要があり、TLSを使用するための証明書と秘密鍵を含む値となる
code:tls-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: testsecret-tls
namespace: default
data:
tls.crt: base64 encoded cert
tls.key: base64 encoded key
type: kubernetes.io/tls
IngressでこのSecretを参照すると、クライアントとロードバランサー間の通信にTLSを使用するようIngressコントローラに指示することになる
作成したTLS Secretは、https-example.foo.comのFQDNを含む証明書から作成したものであることを確認する必要がある
code:tls-example-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: tls-example-ingress
spec:
tls:
- hosts:
- https-example.foo.com
secretName: testsecret-tls
rules:
- host: https-example.foo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service1
port:
number: 80
証明書まわり、Helmでいい感じになる気がしているosamtimizer.icon