第15章 ルートの作成
15.1. ルート設定
15.1.1. HTTP ベースのルートの作成
ルートを使用すると、公開された URL でアプリケーションをホストできます。これは、アプリケーションのネットワークセキュリティー設定に応じて、セキュリティー保護または保護なしを指定できます。HTTP ベースのルートとは、セキュアではないルートで、基本的な HTTP ルーティングプロトコルを使用してセキュリティー保護されていないアプリケーションポートでサービスを公開します。
以下の手順では、hello-openshift
アプリケーションを例に、Web アプリケーションへのシンプルな HTTP ベースのルートを作成する方法を説明します。
前提条件
-
OpenShift CLI (
oc
) がインストールされている。 - 管理者としてログインしている。
- あるポートを公開する Web アプリケーションと、そのポートでトラフィックをリッスンする TCP エンドポイントがあります。
手順
次のコマンドを実行して、
hello-openshift
というプロジェクトを作成します。$ oc new-project hello-openshift
以下のコマンドを実行してプロジェクトに Pod を作成します。
$ oc create -f https://raw.githubusercontent.com/openshift/origin/master/examples/hello-openshift/hello-pod.json
以下のコマンドを実行して、
hello-openshift
というサービスを作成します。$ oc expose pod/hello-openshift
次のコマンドを実行して、
hello-openshift
アプリケーションに対して、セキュアではないルートを作成します。$ oc expose svc hello-openshift
結果として生成される
Route
リソースを検査すると、以下のようになります。上記で作成されたセキュアでないルートの YAML 定義
apiVersion: route.openshift.io/v1 kind: Route metadata: name: hello-openshift spec: host: hello-openshift-hello-openshift.<Ingress_Domain> 1 port: targetPort: 8080 to: kind: Service name: hello-openshift
- 1
<Ingress_Domain>
はデフォルトの Ingress ドメイン名です。
注記デフォルトの ingress ドメインを表示するには、以下のコマンドを実行します。
$ oc get ingresses.config/cluster -o jsonpath={.spec.domain}
15.1.2. ルートのタイムアウトの設定
Service Level Availability (SLA) で必要とされる、低タイムアウトが必要なサービスや、バックエンドでの処理速度が遅いケースで高タイムアウトが必要なサービスがある場合は、既存のルートに対してデフォルトのタイムアウトを設定することができます。
前提条件
- 実行中のクラスターでデプロイ済みの Ingress コントローラーが必要になります。
手順
oc annotate
コマンドを使用して、ルートにタイムアウトを追加します。$ oc annotate route <route_name> \ --overwrite haproxy.router.openshift.io/timeout=<timeout><time_unit> 1
- 1
- サポートされる時間単位は、マイクロ秒 (us)、ミリ秒 (ms)、秒 (s)、分 (m)、時間 (h)、または日 (d) です。
以下の例では、2 秒のタイムアウトを
myroute
という名前のルートに設定します。$ oc annotate route myroute --overwrite haproxy.router.openshift.io/timeout=2s
15.1.3. HTTP Strict Transport Security の有効化
HTTP Strict Transport Security (HSTS) ポリシーは、ホストで HTTPS トラフィックのみを許可するセキュリティーの拡張機能です。デフォルトで、すべての HTTP 要求はドロップされます。これは、web サイトとの対話の安全性を確保したり、ユーザーのためにセキュアなアプリケーションを提供するのに役立ちます。
HSTS が有効にされると、HSTS はサイトから Strict Transport Security ヘッダーを HTTPS 応答に追加します。リダイレクトするルートで insecureEdgeTerminationPolicy
値を使用し、HTTP を HTTPS に送信するようにします。ただし、HSTS が有効にされている場合は、要求の送信前にクライアントがすべての要求を HTTP URL から HTTPS に変更するためにリダイレクトの必要がなくなります。これはクライアントでサポートされる必要はなく、max-age=0
を設定することで無効にできます。
HSTS はセキュアなルート (edge termination または re-encrypt) でのみ機能します。この設定は、HTTP またはパススルールートには適していません。
手順
ルートに対して HSTS を有効にするには、
haproxy.router.openshift.io/hsts_header
値を edge termination または re-encrypt ルートに追加します。apiVersion: v1 kind: Route metadata: annotations: haproxy.router.openshift.io/hsts_header: max-age=31536000;includeSubDomains;preload 1 2 3
- 1
max-age
は唯一の必須パラメーターです。これは、HSTS ポリシーが有効な期間 (秒単位) を測定します。クライアントは、ホストから HSTS ヘッダーのある応答を受信する際には常にmax-age
を更新します。max-age
がタイムアウトになると、クライアントはポリシーを破棄します。- 2
includeSubDomains
はオプションです。これが含まれる場合、クライアントに対し、ホストのすべてのサブドメインがホストと同様に処理されるように指示します。- 3
preload
はオプションです。max-age
が 0 より大きい場合、preload
をhaproxy.router.openshift.io/hsts_header
に組み込むことにより、外部サービスはこのサイトをそれぞれの HSTS プリロード一覧に含めることができます。たとえば、Google などのサイトはpreload
が設定されているサイトの一覧を作成します。ブラウザーはこれらの一覧を使用し、サイトと対話する前でも HTTPS 経由で通信できるサイトを判別できます。preload
設定がない場合、ブラウザーはヘッダーを取得するために HTTPS 経由でサイトと通信している必要があります。
15.1.4. スループット関連の問題のトラブルシューティング
OpenShift Container Platform でデプロイされるアプリケーションでは、特定のサービス間で非常に長い待ち時間が発生するなど、ネットワークのスループットの問題が生じることがあります。
Pod のログが問題の原因を指摘しない場合は、以下の方法を使用してパフォーマンスの問題を分析します。
ping または tcpdump などのパケットアナライザーを使用して Pod とそのノード間のトラフィックを分析します。
たとえば、問題を生じさせる動作を再現している間に各 Pod で tcpdump ツールを実行します。両サイトでキャプチャーしたデータを確認し、送信および受信タイムスタンプを比較して Pod への/からのトラフィックの待ち時間を分析します。待ち時間は、ノードのインターフェイスが他の Pod やストレージデバイス、またはデータプレーンからのトラフィックでオーバーロードする場合に OpenShift Container Platform で発生する可能性があります。
$ tcpdump -s 0 -i any -w /tmp/dump.pcap host <podip 1> && host <podip 2> 1
- 1
podip
は Pod の IP アドレスです。oc get pod <pod_name> -o wide
コマンドを実行して Pod の IP アドレスを取得します。
tcpdump は 2 つの Pod 間のすべてのトラフィックが含まれる
/tmp/dump.pcap
のファイルを生成します。理想的には、ファイルサイズを最小限に抑えるために問題を再現するすぐ前と問題を再現したすぐ後ににアナライザーを実行することが良いでしょう。以下のようにノード間でパケットアナライザーを実行することもできます (式から SDN を排除する)。$ tcpdump -s 0 -i any -w /tmp/dump.pcap port 4789
ストリーミングのスループットおよび UDP スループットを測定するために iperf などの帯域幅測定ツールを使用します。ボトルネックの特定を試行するには、最初に Pod から、次にノードからツールを実行します。
- iperf のインストールおよび使用についての詳細は、こちらの Red Hat ソリューション を参照してください。
15.1.5. Cookie に使用によるルートのステートフル性の維持
OpenShift Container Platform は、すべてのトラフィックを同じエンドポイントにヒットさせることによりステートフルなアプリケーションのトラフィックを可能にするスティッキーセッションを提供します。ただし、エンドポイント Pod が再起動、スケーリング、または設定の変更などによって終了する場合、このステートフル性はなくなります。
OpenShift Container Platform は Cookie を使用してセッションの永続化を設定できます。Ingress コントローラーはユーザー要求を処理するエンドポイントを選択し、そのセッションの Cookie を作成します。Cookie は要求の応答として戻され、ユーザーは Cookie をセッションの次の要求と共に送り返します。Cookie は Ingress コントローラーに対し、セッションを処理しているエンドポイントを示し、クライアント要求が Cookie を使用して同じ Pod にルーティングされるようにします。
cookie は、HTTP トラフィックを表示できないので、パススルールートで設定できません。代わりに、ソース IP アドレスをベースに数が計算され、バックエンドを判断します。
バックエンドが変わると、トラフィックが間違ったサーバーに転送されてしまい、スティッキーではなくなります。ソース IP を非表示にするロードバランサーを使用している場合は、すべての接続に同じ番号が設定され、トラフィックは同じ Pod に送られます。
15.1.5.1. Cookie を使用したルートのアノテーション
ルート用に自動生成されるデフォルト名を上書きするために Cookie 名を設定できます。これにより、ルートトラフィックを受信するアプリケーションが Cookie 名を認識できるようになります。Cookie を削除すると、次の要求でエンドポイントの再選択が強制的に実行される可能性があります。そのためサーバーがオーバーロードしている場合には、クライアントからの要求を取り除き、それらの再分配を試行します。
手順
指定される cookie 名でルートにアノテーションを付けます。
$ oc annotate route <route_name> router.openshift.io/cookie_name="<cookie_name>"
ここでは、以下のようになります。
<route_name>
- Pod の名前を指定します。
<cookie_name>
- cookie の名前を指定します。
たとえば、ルート
my_route
に cookie 名my_cookie
でアノテーションを付けるには、以下を実行します。$ oc annotate route my_route router.openshift.io/cookie_name="my_cookie"
変数でルートのホスト名を取得します。
$ ROUTE_NAME=$(oc get route <route_name> -o jsonpath='{.spec.host}')
ここでは、以下のようになります。
<route_name>
- Pod の名前を指定します。
cookie を保存してからルートにアクセスします。
$ curl $ROUTE_NAME -k -c /tmp/cookie_jar
ルートに接続する際に、直前のコマンドによって保存される cookie を使用します。
$ curl $ROUTE_NAME -k -b /tmp/cookie_jar
15.1.6. パスベースのルート
パスベースのルートは、URL に対して比較できるパスコンポーネントを指定します。この場合、ルートのトラフィックは HTTP ベースである必要があります。そのため、それぞれが異なるパスを持つ同じホスト名を使用して複数のルートを提供できます。ルーターは、最も具体的なパスの順に基づいてルートと一致する必要があります。ただし、これはルーターの実装によって異なります。
以下の表は、ルートのサンプルおよびそれらのアクセシビリティーを示しています。
ルート | 比較対象 | アクセス可能 |
---|---|---|
www.example.com/test | www.example.com/test | はい |
www.example.com | いいえ | |
www.example.com/test および www.example.com | www.example.com/test | はい |
www.example.com | はい | |
www.example.com | www.example.com/text | Yes (ルートではなく、ホストで一致) |
www.example.com | はい |
パスが 1 つでセキュリティー保護されていないルート
apiVersion: v1
kind: Route
metadata:
name: route-unsecured
spec:
host: www.example.com
path: "/test" 1
to:
kind: Service
name: service-name
- 1
- パスは、パスベースのルートに唯一追加される属性です。
ルーターは TLS を終了させず、要求のコンテンツを読み込みことができないので、パスベースのルーティングは、パススルー TLS を使用する場合には利用できません。
15.1.7. ルート固有のアノテーション
Ingress コントローラーは、公開するすべてのルートのデフォルトオプションを設定できます。個別のルートは、アノテーションに個別の設定を指定して、デフォルトの一部を上書きできます。Red Hat では、ルートアノテーションの Operator 管理ルートへの追加はサポートしません。
複数のソース IP またはサブネットのホワイトリストを作成するには、スペースで区切られたリストを使用します。他の区切りタイプを使用すると、一覧が警告やエラーメッセージなしに無視されます。
変数 | 説明 | デフォルトで使用される環境変数 |
---|---|---|
|
ロードバランシングアルゴリズムを設定します。使用できるオプションは |
パススルールートの |
|
関連の接続を追跡する cookie の使用を無効にします。 | |
| このルートに使用するオプションの cookie を指定します。名前は、大文字、小文字、数字、"_" または "-" を任意に組み合わせて指定する必要があります。デフォルトは、ルートのハッシュ化された内部キー名です。 | |
|
ルーターからバッキングされる Pod に対して許容される接続最大数を設定します。 | |
|
| |
|
同じソース IP アドレスで行われる同時 TCP 接続の数を制限します。数値を受け入れます。 | |
|
同じソース IP アドレスを持つクライアントが HTTP 要求を実行できるレートを制限します。数値を受け入れます。 | |
|
同じソース IP アドレスを持つクライアントが TCP 接続を確立するレートを制限します。数値を受け入れます。 | |
| ルートのサーバー側のタイムアウトを設定します。(TimeUnits) |
|
| このタイムアウトは、クリアテキスト、エッジ、再暗号化、またはパススルーのルートを介した Web Socket などトンネル接続に適用されます。cleartext、edge、または reencrypt のルートタイプでは、このアノテーションは、タイムアウト値がすでに存在するタイムアウトトンネルとして適用されます。パススルーのルートタイプでは、アノテーションは既存のタイムアウト値の設定よりも優先されます。 |
|
|
設定できるのは、Ingress Controller または ingress config です。このアノテーションでは、ルーターを再デプロイし、HA プロキシーが haproxy |
|
| バックエンドのヘルスチェックの間隔を設定します。(TimeUnits) |
|
| ルートのホワイトリストを設定します。ホワイトリストは、承認したソースアドレスの IP アドレスおよび CIDR 範囲の一覧をスペース区切りにします。ホワイトリストに含まれていない IP アドレスからの要求は破棄されます。 ホワイトリストの許可される IP アドレスおよび CIDR 範囲の最大数は 61 です。 | |
| edge terminated または re-encrypt ルートの Strick-Transport-Security ヘッダーを設定します。 | |
|
Syslog ヘッダーの | |
| バックエンドの要求の書き換えパスを設定します。 | |
| Cookie を制限するために値を設定します。値は以下のようになります。
この値は、re-encrypt および edge ルートにのみ適用されます。詳細は、SameSite cookie のドキュメント を参照してください。 | |
|
ルートごとに
|
|
環境変数を編集することはできません。
ルータータイムアウト変数
TimeUnits
は数字、その後に単位を指定して表現します。 us
*(マイクロ秒)、ms
(ミリ秒、デフォルト)、s
(秒)、m
(分)、h
*(時間)、d
(日)
正規表現: [1-9][0-9]*(us
\|ms
\|s
\|m
\|h
\|d
)
変数 | デフォルト | 説明 |
---|---|---|
|
| バックエンドでの後続の liveness チェックの時間の長さ。 |
|
| クライアントがルートに接続する場合の TCP FIN タイムアウトの期間を制御します。接続切断のために送信された FIN が指定の時間内に応答されない場合は、HAProxy が接続を切断します。小さい値を設定し、ルーターでリソースをあまり使用していない場合には、リスクはありません。 |
|
| クライアントがデータを確認するか、送信するための時間の長さ。 |
|
| 最大接続時間。 |
|
| ルーターからルートをバッキングする Pod の TCP FIN タイムアウトを制御します。 |
|
| サーバーがデータを確認するか、送信するための時間の長さ。 |
|
| TCP または WebSocket 接続が開放された状態で保つ時間数。このタイムアウト期間は、HAProxy が再読み込みされるたびにリセットされます。 |
|
|
新しい HTTP 要求が表示されるまで待機する最大時間を設定します。この値が低すぎる場合には、ブラウザーおよびアプリケーションの
有効なタイムアウト値には、想定した個別のタイムアウトではなく、特定の変数を合計した値に指定することができます。たとえば、 |
|
| HTTP 要求の伝送にかかる時間。 |
|
| ルーターがリロードし、新規の変更を受け入れる最小の頻度を許可します。 |
|
| HAProxy メトリクスの収集タイムアウト。 |
ルート設定のカスタムタイムアウト
apiVersion: v1
kind: Route
metadata:
annotations:
haproxy.router.openshift.io/timeout: 5500ms 1
...
- 1
- HAProxy 対応の単位 (
us
、ms
、s
、m
、h
、d
) で新規のタイムアウトを指定します。単位が指定されていない場合は、ms
がデフォルトになります。
パススルールートのサーバー側のタイムアウト値を低く設定し過ぎると、WebSocket 接続がそのルートで頻繁にタイムアウトする可能性があります。
特定の IP アドレスを 1 つだけ許可するルート
metadata: annotations: haproxy.router.openshift.io/ip_whitelist: 192.168.1.10
複数の IP アドレスを許可するルート
metadata: annotations: haproxy.router.openshift.io/ip_whitelist: 192.168.1.10 192.168.1.11 192.168.1.12
IP アドレスの CIDR ネットワークを許可するルート
metadata: annotations: haproxy.router.openshift.io/ip_whitelist: 192.168.1.0/24
IP アドレスと IP アドレスの CIDR ネットワークの両方を許可するルート
metadata: annotations: haproxy.router.openshift.io/ip_whitelist: 180.5.61.153 192.168.1.0/24 10.0.0.0/8
書き換えターゲットを指定するルート
apiVersion: v1
kind: Route
metadata:
annotations:
haproxy.router.openshift.io/rewrite-target: / 1
...
- 1
- バックエンドの要求の書き換えパスとして
/
を設定します。
ルートに haproxy.router.openshift.io/rewrite-target
アノテーションを設定すると、要求をバックエンドアプリケーションに転送する前に Ingress コントローラーがこのルートを使用して HTTP 要求のパスを書き換える必要があることを指定します。spec.path
で指定されたパスに一致する要求パスの一部は、アノテーションで指定された書き換えターゲットに置き換えられます。
以下の表は、spec.path
、要求パス、および書き換えターゲットの各種の組み合わせについてのパスの書き換え動作の例を示しています。
Route.spec.path | 要求パス | 書き換えターゲット | 転送された要求パス |
---|---|---|---|
/foo | /foo | / | / |
/foo | /foo/ | / | / |
/foo | /foo/bar | / | /bar |
/foo | /foo/bar/ | / | /bar/ |
/foo | /foo | /bar | /bar |
/foo | /foo/ | /bar | /bar/ |
/foo | /foo/bar | /baz | /baz/bar |
/foo | /foo/bar/ | /baz | /baz/bar/ |
/foo/ | /foo | / | 該当なし (要求パスがルートパスに一致しない) |
/foo/ | /foo/ | / | / |
/foo/ | /foo/bar | / | /bar |
15.1.8. ルートの受付ポリシーの設定
管理者およびアプリケーション開発者は、同じドメイン名を持つ複数の namespace でアプリケーションを実行できます。これは、複数のチームが同じホスト名で公開されるマイクロサービスを開発する組織を対象としています。
複数の namespace での要求の許可は、namespace 間の信頼のあるクラスターに対してのみ有効にする必要があります。有効にしないと、悪意のあるユーザーがホスト名を乗っ取る可能性があります。このため、デフォルトの受付ポリシーは複数の namespace 間でのホスト名の要求を許可しません。
前提条件
- クラスター管理者の権限。
手順
以下のコマンドを使用して、
ingresscontroller
リソース変数の.spec.routeAdmission
フィールドを編集します。$ oc -n openshift-ingress-operator patch ingresscontroller/default --patch '{"spec":{"routeAdmission":{"namespaceOwnership":"InterNamespaceAllowed"}}}' --type=merge
イメージコントローラー設定例
spec: routeAdmission: namespaceOwnership: InterNamespaceAllowed ...
15.1.9. Ingress オブジェクトを使用したルートの作成
一部のエコシステムコンポーネントには Ingress リソースとの統合機能がありますが、ルートリソースとは統合しません。これに対応するために、OpenShift Container Platform は Ingress オブジェクトの作成時に管理されるルートオブジェクトを自動的に作成します。これらのルートオブジェクトは、対応する Ingress オブジェクトが削除されると削除されます。
手順
OpenShift Container Platform コンソールで Ingress オブジェクトを定義するか、または oc
create
コマンドを実行します。Ingress の YAML 定義
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: frontend annotations: route.openshift.io/termination: "reencrypt" 1 spec: rules: - host: www.example.com http: paths: - backend: service: name: frontend port: number: 443 path: / pathType: Prefix tls: - hosts: - www.example.com secretName: example-com-tls-certificate
- 1
route.openshift.io/termination
アノテーションは、Route
のspec.tls.termination
フィールドを設定するために使用できます。Ingress
にはこのフィールドがありません。許可される値はedge
、passthrough
、およびreencrypt
です。その他のすべての値は警告なしに無視されます。アノテーション値が設定されていない場合は、edge
がデフォルトルートになります。デフォルトのエッジルートを実装するには、TLS 証明書の詳細をテンプレートファイルで定義する必要があります。route.openshift.io/termination
アノテーションでpassthrough
の値を指定する場合は、仕様でpath
を''
に設定し、pathType
をImplementationSpecific
に設定します。spec: rules: - host: www.example.com http: paths: - path: '' pathType: ImplementationSpecific backend: service: name: frontend port: number: 443
$ oc apply -f ingress.yaml
ルートを一覧表示します。
$ oc get routes
結果には、
frontend-
で始まる名前の自動生成ルートが含まれます。NAME HOST/PORT PATH SERVICES PORT TERMINATION WILDCARD frontend-gnztq www.example.com frontend 443 reencrypt/Redirect None
このルートを検査すると、以下のようになります。
自動生成されるルートの YAML 定義
apiVersion: route.openshift.io/v1 kind: Route metadata: name: frontend-gnztq ownerReferences: - apiVersion: networking.k8s.io/v1 controller: true kind: Ingress name: frontend uid: 4e6c59cc-704d-4f44-b390-617d879033b6 spec: host: www.example.com path: / port: targetPort: https tls: certificate: | -----BEGIN CERTIFICATE----- [...] -----END CERTIFICATE----- insecureEdgeTerminationPolicy: Redirect key: | -----BEGIN RSA PRIVATE KEY----- [...] -----END RSA PRIVATE KEY----- termination: reencrypt to: kind: Service name: frontend