第6章 ネットワークの管理

6.1. 概要

このトピックでは、プロジェクトの分離および発信トラフィックの制御を含む、全般的なクラスターネットワークの管理について説明します。

Pod ごとの帯域幅の制限などの Pod レベルのネットワーク機能については、Pod の管理で説明されています。

6.2. Pod ネットワークの管理

クラスターが ovs-multitenant SDN プラグインを使用するように設定されている場合、管理者 CLI を使用してプロジェクトの別個の Pod オーバーレイネットワークを管理することができます。必要な場合は、プラグイン設定手順について「SDN の設定」セクションを参照してください。

6.2.1. プロジェクトネットワークへの参加

プロジェクトを既存のプロジェクトネットワークに参加させるには、以下を実行します。

$ oc adm pod-network join-projects --to=<project1> <project2> <project3>

上記の例で、<project2> および <project3> のすべての Pod およびサービスから、<project1> のすべての Pod およびサービスへのアクセスが可能となり、その逆の場合も可能になります。サービスは、IP または完全修飾 DNS 名 (<service>.<pod_namespace>.svc.cluster.local) のいずれかでアクセスできます。たとえば、プロジェクト myprojectdb という名前のサービスにアクセスするには、db.myproject.svc.cluster.local を使用します。

または、特定のプロジェクト名を指定する代わりに --selector=<project_selector> オプションを使用することもできます。

6.3. プロジェクトネットワークの分離

プロジェクトネットワークをクラスターから分離したり、その逆を実行するには、以下を実行します。

$ oc adm pod-network isolate-projects <project1> <project2>

上記の例では、<project1> および <project2> のすべての Pod およびサービスは、クラスター内のグローバル以外のプロジェクトの Pod およびサービスにアクセスできず、その逆も実行できません。

または、特定のプロジェクト名を指定する代わりに --selector=<project_selector> オプションを使用することもできます。

6.3.1. プロジェクトネットワークのグローバル化

プロジェクトからクラスター内のすべての Pod およびサービスにアクセスできるようにするか、その逆を可能にするには、以下を実行します。

$ oc adm pod-network make-projects-global <project1> <project2>

上記の例では、<project1> および <project2> のすべての Pod およびサービスはクラスター内のすべての Pod およびサービスにアクセスでき、その逆の場合も可能になります。

または、特定のプロジェクト名を指定する代わりに --selector=<project_selector> オプションを使用することもできます。

6.4. ルートおよび Ingress オブジェクトにおけるホスト名の競合防止の無効化

OpenShift Container Platform では、ルートおよび ingress オブジェクトのホスト名の競合防止はデフォルトで有効にされています。これは、cluster-admin ロールのないユーザーは、作成時にのみルーターまたは ingress オブジェクトのホスト名を設定でき、その後は変更できなくなることを意味しています。ただし、ルートおよび ingress オブジェクトのこの制限は、一部またはすべてのユーザーに対して緩和することができます。

警告

OpenShift Container Platform はオブジェクト作成のタイムスタンプを使用して特定のホスト名の最も古いルートや ingress オブジェクトを判別するため、ルートまたは ingress オブジェクトは、古いルートがそのホスト名を変更したり、ingress オブジェクトが導入される場合に新規ルートのホスト名をハイジャックする可能性があります。

OpenShift Container Platform クラスター管理者は、作成後でもルートのホスト名を編集できます。また、特定のユーザーがこれを実行できるようにロールを作成することもできます。

$ oc create clusterrole route-editor --verb=update --resource=routes.route.openshift.io/custom-host

次に、新規ロールをユーザーにバインドできます。

$ oc adm policy add-cluster-role-to-user route-editor user

ingress オブジェクトのホスト名の競合防止を無効にすることもできます。これを実行することで、cluster-admin ロールを持たないユーザーが作成後も ingress オブジェクトのホスト名を編集できるようになります。これは、ingress オブジェクトのホスト名の編集を許可する場合などに Kubernetes の動作に依存する OpenShift Container Platform のインストールで役に立ちます。

  1. 以下を master.yaml ファイルに追加します。

    admissionConfig:
      pluginConfig:
        openshift.io/IngressAdmission:
          configuration:
            apiVersion: v1
            allowHostnameChanges: true
            kind: IngressAdmissionConfig
          location: ""
  2. 変更を有効にするために、マスターサービスを再起動します。

    $ systemctl restart atomic-openshift-master-api atomic-openshift-master-controllers

6.5. Egress トラフィックの制御

クラスター管理者は、ホストレベルで数多くの静的 IP アドレスを特定ノードに割り当てることができます。アプリケーション開発者がそれぞれのアプリケーションサービスに専用 IP アドレスを必要とする場合、ファイアウォールアクセスを要求するプロセスでこのアドレスを要求することができます。その後、開発者はデプロイメント設定の nodeSelector を使用して、開発者のプロジェクトから egress ルーターをデプロイし、静的 IP アドレスが事前に割り当てられたホストに Pod が到達することを確認できます。

egress Pod のデプロイメントでは、宛先に到達するために必要なソース IP のいずれか、保護されるサービスの宛先 IP、およびゲートウェイ IP を宣言します。Pod のデプロイ後は、サービスを作成して、egress ルーター Pod にアクセスし、そのソース IP を企業ファイアウォールに追加できます。その後、開発者はプロジェクトで作成された egress ルーターサービスへのアクセス情報を取得します (例: service.project.cluster.domainname.com)。

開発者が外部の firewalled サービスにアクセスする必要がある場合、実際の保護されたサービス URL ではなくアプリケーション (例: JDBC 接続情報) で、egress ルーター Pod のサービス (service.project.cluster.domainname.com) に対して呼び出し実行することができます。

さらに、静的 IP アドレスをプロジェクトに割り当て、指定されたプロジェクトからの発信外部接続すべてに認識可能な起点を設定できます。これは、トラフィックと特定の宛先に送信するために使用されるデフォルトの egress ルーターとは異なります。詳細は、「外部プロジェクトトラフィックの固定 IP の有効化」セクションを参照してください。

注記

egress ルーターは OpenShift Dedicated では利用できません。

OpenShift Container Platform クラスター管理者は、以下を使用して egress トラフィックを制御できます。

ファイアウォール
egress ファイアウォールを使用すると、受け入れ可能な発信トラフィックポリシーを実施し、特定のエンドポイントまたは IP 範囲 (サブネット) のみを動的エンドポイント (OpenShift Container Platform 内の Pod) が通信できる受け入れ可能なターゲットとすることができます。
ルーター
egress ルーターを使用することで、識別可能なサービスを作成し、トラフィックを特定の宛先に送信できます。これにより、それらの外部の宛先はトラフィックを既知のソースから送られるものとして処理します。これにより namespace の特定の Pod のみがトラフィックをデータベースにプロキシー送信するサービス (egress ルーター) と通信できるよう外部データベースが保護されるため、セキュリティー対策として役立ちます。
iptables
上記の OpenShift Container Platform 内のソリューションのほかにも、発信トラフィックに適用される iptables ルールを作成することができます。これらのルールは、egress ファイアウォールよりも多くのオプションを許可しますが、特定のプロジェクトに制限することはできません。

6.5.1. 外部リソースへのアクセスを制限するための Egress ファイアウォールの使用

OpenShift Container Platform クラスター管理者は egress ファイアウォールを使用して、一部またはすべての Pod がクラスター内からアクセスできる外部アドレスを制限できます。これにより、以下が可能になります。

  • Pod の対話を内部ホストに制限し、パブリックインターネットへの接続を開始できないようにする。

    または

  • Pod の対話をパブリックインターネットに制限し、(クラスター外の) 内部ホストへの接続を開始できないようにする。

    または

  • Pod が接続する理由のない指定された内部サブネット/ホストに到達できないようにする。

プロジェクトを複数の異なる egress ポリシーを持つように設定できます。たとえば、<project A> の指定した IP 範囲へのアクセスを許可する一方で、同じアクセスを <project B> に対して拒否することができます。または、アプリケーション開発者の (Python) pip mirror からの更新を制限したり、更新を必要なソースからの更新のみに強制的に制限したりすることができます。

注意

Pod アクセスを egress ポリシーで制限するには、ovs-multitenant または ovs-networkpolicy プラグインを有効にする必要があります。

プロジェクト管理者は、EgressNetworkPolicy オブジェクトを作成することも、プロジェクトで作成するオブジェクトを編集することもできません。また、EgressNetworkPolicy の作成に関連して他のいくつかの制限があります。

  • デフォルトプロジェクト (および oc adm pod-network make-projects-global でグローバルにされたその他のプロジェクト) には egress ポリシーを設定することができません。
  • (oc adm pod-network join-projects を使用して) 2 つのプロジェクトをマージする場合、マージしたプロジェクトのいずれでも egress ポリシーを使用することはできません。
  • いずれのプロジェクトも複数の egress ポリシーオブジェクトを持つことができません。

上記の制限のいずれかに違反すると、プロジェクトの egress ポリシーに障害が発生し、すべての外部ネットワークトラフィックがドロップされる可能性があります。

oc コマンドまたは REST API を使用して egress ポリシーを設定します。oc [create|replace|delete] を使用して EgressNetworkPolicy オブジェクトを操作できます。api/swagger-spec/oapi-v1.json ファイルには、オブジェクトを実際に機能させる方法についての API レベルの詳細情報が含まれます。

egress ポリシーを設定するには、以下を実行します。

  1. 対象とするプロジェクトに移動します。
  2. 必要なポリシー詳細情報で JSON ファイルを作成します。以下は例になります。

    {
        "kind": "EgressNetworkPolicy",
        "apiVersion": "v1",
        "metadata": {
            "name": "default"
        },
        "spec": {
            "egress": [
                {
                    "type": "Allow",
                    "to": {
                        "cidrSelector": "1.2.3.0/24"
                    }
                },
                {
                    "type": "Allow",
                    "to": {
                        "dnsName": "www.foo.com"
                    }
                },
                {
                    "type": "Deny",
                    "to": {
                        "cidrSelector": "0.0.0.0/0"
                    }
                }
            ]
        }
    }

    上記のサンプルがプロジェクトに追加されると、IP 範囲 1.2.3.0/24 およびドメイン名 www.foo.com へのトラフィックが許可されますが、その他のすべての外部 IP アドレスへのアクセスは拒否されます。このポリシーは外部トラフィックにのみ適用されるため、その他すべての Pod へのトラフィックは影響を受けません。

    EgressNetworkPolicy のルールは順番にチェックされ、一致する最初のルールが実施されます。上記の例の 3 つの例が維持される場合、0.0.0.0/0 ルールが最初にチェックされ、すべてのトラフィックに一致し、それらすべてを拒否するため、1.2.3.0/24 および www.foo.com へのトラフィックは許可されません。

    ドメイン名の更新は、ローカルの非権威サーバーのドメインの TTL (time to live) 値か、または TTL をフェッチできない場合は 30 分の値に基づいてポーリングされます。Pod は必要な場合には、同じローカルの非権威サーバーのドメインを解決します。そうでない場合には、egress ネットワークポリシーコントローラーと Pod で認識されるドメインの IP アドレスが異なり、egress ネットワークが予想通りに実施されない場合があります。上記の例で www.foo.com10.11.12.13 に解決され、DNS TTL が 1 分に設定されていますが、後に 20.21.22.23 に変更されたとします。OpenShift Container Platform は最長 1 分後にこれらの変更に対応します。

注記

egress ファイアウォールは、DNS 解決用に Pod が置かれるノードの外部インターフェースに Pod が常にアクセスできるようにします。DNS 解決がローカルノード上のいずれかによって処理されない場合は、Pod でドメイン名を使用している場合には DNS サーバーの IP アドレスへのアクセスを許可する egress ファイアウォールを追加する必要があります。デフォルトインストーラーはローカル dnsmasq をセットアップするため、このセットアップを使用する場合は、ルールを追加する必要はありません。

  1. JSON ファイルを使用して EgressNetworkPolicy オブジェクトを作成します。

    $ oc create -f <policy>.json
注意

ルートを作成してサービスを公開すると、EgressNetworkPolicy は無視されます。Egress ネットワークポリシーサービスのエンドポイントのフィルターは、ノード kubeproxy で実行されます。ルーターが使用される場合は、kubeproxy はバイパスされ、egress ネットワークポリシーの実施は適用されません。管理者は、ルートを作成するためのアクセスを制限してこのバイパスを防ぐことができます。

6.5.2. 外部リソースから Pod トラフィックを認識可能にするための Egress ルーターの使用

OpenShift Container Platform egress ルーターは、他の用途で使用されていないプライベートソース IP アドレスを使用して、指定されたリモートサーバーにトラフィックをリダイレクトするサービスを実行します。このサービスにより、Pod はホワイトリスト IP アドレスからのアクセスのみを許可するように設定されたサーバーと通信できるようになります。

重要

egress ルーターはすべての発信接続のために使用されることが意図されていません。多数の egress ルーターを作成することで、ネットワークハードウェアの制限を引き上げる可能性があります。たとえば、すべてのプロジェクトまたはアプリケーションに egress ルーターを作成すると、ソフトウェアの MAC アドレスのフィルターにフォールバックする前にネットワークインターフェースが処理できるローカル MAC アドレス数の上限を超えてしまう可能性があります。

重要

現時点で、egress ルーターには Amazon AWS との互換性がありません。AWS に macvlan トラフィックとの互換性がないためです。

デプロイメントに関する考慮事項

Egressルーターは 2 つ目の IP アドレスおよび MAC アドレスをノードのプライマリーネットワークインターフェースに追加します。OpenShift Container Platform をベアメタルで実行していない場合は、ハイパーバイザーまたはクラウドプロバイダーが追加のアドレスを許可するように設定する必要があります。

Red Hat OpenStack Platform

OpenShift Container Platform を Red Hat OpenStack Platform を使ってデプロイしている場合、OpenStack 環境で IP および MAC アドレスのホワイトリストを作成する必要があります。これを行わないと、通信は失敗します

neutron port-update $neutron_port_uuid \
  --allowed_address_pairs list=true \
  type=dict mac_address=<mac_address>,ip_address=<ip_address>
Red Hat Enterprise Virtualization
Red Hat Enterprise Virtualization を使用している場合は、EnableMACAntiSpoofingFilterRulesfalse に設定する必要が あります。
VMware vSphere
VMware vSphere を使用している場合は、vSphere 標準スイッチのセキュリティー保護についての VMWare ドキュメントを参照してください。vSphere Web クライアントからホストの仮想スイッチを選択して、VMWare vSphere デフォルト設定を表示し、変更します。

とくに、以下が有効にされていることを確認します。

Egress ルーターモード

egress ルーターは、リダイレクトモードHTTP プロキシーモードの 2 つの異なるモードで実行できます。リダイレクトモードは、HTTP および HTTPS 以外のすべてのサービスで機能します。HTTP および HTTPS サービスの場合は、HTTP プロキシーモードを使用します。

6.5.2.1. リダイレクトモードでの Egress ルーター Pod のデプロイ

リダイレクトモードでは、egress ルーターは、トラフィックを独自の IP アドレスから 1 つ以上の宛先 IP アドレスにリダイレクトするために iptables ルールをセットアップします。予約されたソース IP アドレスを使用する必要のあるクライアント Pod は、宛先 IP に直接接続するのでなく、egress ルーターに接続するように変更される必要があります。

  1. 上記を使用して Pod 設定を作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: egress-1
      labels:
        name: egress-1
      annotations:
        pod.network.openshift.io/assign-macvlan: "true" 1
    spec:
      initContainers:
      - name: egress-router
        image: registry.access.redhat.com/openshift3/ose-egress-router
        securityContext:
          privileged: true
        env:
        - name: EGRESS_SOURCE 2
          value: 192.168.12.99
        - name: EGRESS_GATEWAY 3
          value: 192.168.12.1
        - name: EGRESS_DESTINATION 4
          value: 203.0.113.25
        - name: EGRESS_ROUTER_MODE 5
          value: init
      containers:
      - name: egress-router-wait
        image: registry.access.redhat.com/openshift3/ose-pod
      nodeSelector:
        site: springfield-1 6
    1
    プライマリーネットワークインターフェースで Macvlan ネットワークインターフェースを作成し、これを Pod のネットワークプロジェクトに移行してから egress-router コンテナーを起動します。"true" の周りの引用符はそのまま残します。これらを省略すると、エラーが発生します。プライマリーネットワークインターフェース以外のネットワークインターフェースで Macvlan インターフェースを作成するには、アノテーションの値を該当インターフェースの名前に設定します。たとえば、 eth1 を使用します。
    2
    ノードが置かれている物理ネットワークの IP アドレスで、この Pod で使用するようにクラスター管理者が予約します。
    3
    ノードで使用されるデフォルトゲートウェイと同じ値です。
    4
    トラフィックの送信先となる外部サーバー。この例では、Pod の接続は 203.0.113.25 にリダイレクトされます。ソース IP アドレスは 192.168.12.99 です。
    5
    これは egress ルーターイメージに対して、これが「init コンテナー」としてデプロイされていることを示しています。以前のバージョンの OpenShift Container Platform (および egress ルーターイメージ) はこのモードをサポートしておらず、通常のコンテナーとして実行される必要がありました。
    6
    Pod はラベル site=springfield-1 の設定されたノードにのみデプロイされます。
  2. 上記の定義を使用して Pod を作成します。

    $ oc create -f <pod_name>.json

    Pod が作成されているかどうかを確認するには、以下を実行します。

    $ oc get pod <pod_name>
  3. egresss ルーターを参照するサービスを作成し、他の Pod が Pod の IP アドレスを見つけられるようにします。

    apiVersion: v1
    kind: Service
    metadata:
      name: egress-1
    spec:
      ports:
      - name: http
        port: 80
      - name: https
        port: 443
      type: ClusterIP
      selector:
        name: egress-1

    Pod がこのサービスに接続できるようになります。これらの接続は、予約された egress IP アドレスを使用して外部サーバーの対応するポートにリダイレクトされます。

egress ルーターのセットアップは、openshift3/ose-egress-router イメージで作成される「init コンテナー」で実行され、このコンテナーは Macvlan インターフェースを設定し、iptables ルールをセットアップできるように特権モード実行されます。iptables ルールのセットアップ終了後に、これは終了し、openshift3/ose-pod コンテナーが Pod が強制終了されるまで (特定のタスクを実行しない) 実行状態になります。

環境変数は egress-router イメージに対し、使用するアドレスを指示します。これは、EGRESS_SOURCE を IP アドレスとして、また EGRESS_GATEWAY をゲートウェイとして使用するよう Macvlan を設定します。

NAT ルールが設定され、Pod のクラスター IP アドレスの TCP または UDP ポートへの接続が EGRESS_DESTINATION の同じポートにリダイレクトされるようにします。

クラスター内の一部のノードのみが指定されたソース IP アドレスを要求でき、指定されたゲートウェイを使用できる場合、受け入れ可能なノードを示す nodeName または nodeSelector を指定することができます。

6.5.2.2. 複数の宛先へのリダイレクト

前の例では、任意のポートでの egress Pod (またはその対応するサービス) への接続は単一の宛先 IP にリダイレクトされます。ポートによっては複数の異なる宛先 IP を設定することもできます。

apiVersion: v1
kind: Pod
metadata:
  name: egress-multi
  labels:
    name: egress-multi
  annotations:
    pod.network.openshift.io/assign-macvlan: "true"
spec:
  initContainers:
  - name: egress-router
    image: registry.access.redhat.com/openshift3/ose-egress-router
    securityContext:
      privileged: true
    env:
    - name: EGRESS_SOURCE
      value: 192.168.12.99
    - name: EGRESS_GATEWAY
      value: 192.168.12.1
    - name: EGRESS_DESTINATION
      value: | 1
        80   tcp 203.0.113.25
        8080 tcp 203.0.113.26 80
        8443 tcp 203.0.113.26 443
        203.0.113.27
    - name: EGRESS_ROUTER_MODE
      value: init
  containers:
  - name: egress-router-wait
    image: registry.access.redhat.com/openshift3/ose-pod
1
ここでは、複数行の文字列に YAML 構文を使用しています。詳細は以下を参照してください。

EGRESS_DESTINATION の各行は以下の 3 つのタイプのいずれかになります。

  • <port> <protocol> <IP address>: これは、指定される <port> への着信接続が指定される <IP address> の同じポートにリダイレクトされることを示します。<protocol>tcp または udp のいずれかになります。上記の例では、最初の行がローカルポート 80 から 203.0.113.25 のポート 80 にトラフィックをリダイレクトしています。
  • <port> <protocol> <IP address> <remote port>: 接続が <IP address> の別の <remote port> にリダイレクトされるのを除き、上記と同じになります。この例では、2 番目と 3 番目の行ではローカルポート 8080 および 8443 を 203.0.113.26 のリモートポート 80 および 443 にリダイレクトしています。
  • <fallback IP address>: EGRESS_DESTINATION の最後の行が単一 IP アドレスである場合、それ以外のポートの接続はその IP アドレス (上記の例では 203.0.113.27) の対応するポートにリダイレクトされます。フォールバック IP アドレスがない場合、他のポートでの接続は単純に拒否されます。)

6.5.2.3. ConfigMap の使用による EGRESS_DESTINATION の指定

宛先マッピングのセットのサイズが大きいか、またはこれが頻繁に変更される場合、ConfigMap を使用して一覧を外部で維持し、egress ルーター Pod がそこから一覧を読み取れるようにすることができます。これには、プロジェクト管理者が ConfigMap を編集できるという利点がありますが、これには特権付きコンテナーが含まれるため、管理者は Pod 定義を直接編集することはできません。

  1. EGRESS_DESTINATION データを含むファイルを作成します。

    $ cat my-egress-destination.txt
    # Egress routes for Project "Test", version 3
    
    80   tcp 203.0.113.25
    
    8080 tcp 203.0.113.26 80
    8443 tcp 203.0.113.26 443
    
    # Fallback
    203.0.113.27

    空の行とコメントをこのファイルに追加できることに注意してください。

  2. このファイルから ConfigMap オブジェクトを作成します。

    $ oc delete configmap egress-routes --ignore-not-found
    $ oc create configmap egress-routes \
      --from-file=destination=my-egress-destination.txt

    ここで、egress-routes は作成される ConfigMap オブジェクトの名前で、my-egress-destination.txt はデータの読み取り元のファイルの名前です。

  3. 前述のように egress ルーター Pod 定義を作成しますが、ConfigMap を環境セクションの EGRESS_DESTINATION に指定します。

        ...
        env:
        - name: EGRESS_SOURCE
          value: 192.168.12.99
        - name: EGRESS_GATEWAY
          value: 192.168.12.1
        - name: EGRESS_DESTINATION
          valueFrom:
            configMapKeyRef:
              name: egress-routes
              key: destination
        - name: EGRESS_ROUTER_MODE
          value: init
        ...
注記

egress ルーターは、ConfigMap が変更されても自動的に更新されません。更新を取得するには Pod を再起動します。

6.5.2.4. Egress ルーター HTTP プロキシー Pod のデプロイ

HTTP プロキシーモードでは、egress ルーターはポート 8080 で HTTP プロキシーとして実行されます。これは、HTTP または HTTPS ベースのサービスと通信するクライアントの場合にのみ機能しますが、通常それらを機能させるのにクライアント Pod への多くの変更は不要です。環境変数を設定することで、プログラムは HTTP プロキシーを使用するように指示されます。

  1. 例として以下を使用して Pod を作成します。

    apiVersion: v1
    kind: Pod
    metadata:
      name: egress-http-proxy
      labels:
        name: egress-http-proxy
      annotations:
        pod.network.openshift.io/assign-macvlan: "true" 1
    spec:
      initContainers:
      - name: egress-router-setup
        image: registry.access.redhat.com/openshift3/ose-egress-router
        securityContext:
          privileged: true
        env:
        - name: EGRESS_SOURCE 2
          value: 192.168.12.99
        - name: EGRESS_GATEWAY 3
          value: 192.168.12.1
        - name: EGRESS_ROUTER_MODE 4
          value: http-proxy
      containers:
      - name: egress-router-proxy
        image: registry.access.redhat.com/openshift3/ose-egress-http-proxy
        env:
        - name: EGRESS_HTTP_PROXY_DESTINATION 5
          value: |
            !*.example.com
            !192.168.1.0/24
            *
    1
    プライマリーネットワークインターフェースで Macvlan ネットワークインターフェースを作成してから、これを Pod のネットワークプロジェクトに移行し、egress-router コンテナーを起動します。"true" の周りの引用符をそのまま残します。これらを省略すると、エラーが発生します。
    2
    ノード自体が置かれている物理ネットワークの IP アドレスで、この Pod で使用するためにクラスター管理者が予約します。
    3
    ノード自体で使用されるデフォルトゲートウェイと同じ値。
    4
    これは egress ルーターイメージに対し、これが HTTP プロキシーの一部としてデプロイされているため、iptables のリダイレクトルールを設定できないことを示します。
    5
    プロキシーの設定方法を指定する文字列または YAML の複数行文字列です。これは、init コンテナーの他の環境変数ではなく、HTTP プロキシーコンテナーの環境変数として指定されることに注意してください。

    EGRESS_HTTP_PROXY_DESTINATION 値に以下のいずれかを指定できます。また、* を使用することができます。これは「すべてのリモート宛先への接続を許可」することを意味します。設定の各行には、許可または拒否する接続の 1 つのグループを指定します。

    • IP アドレス (例: 192.168.1.1) は該当する IP アドレスへの接続を許可します。
    • CIDR 範囲 (例: 192.168.1.0/24) は CIDR 範囲への接続を許可します。
    • ホスト名 (例: www.example.com) は該当ホストへのプロキシーを許可します。
    • *. が先に付けられるドメイン名 (例: *.example.com) は該当ドメインおよびそのサブドメインのすべてへのプロキシーを許可します。
    • 上記のいずれかに ! を付けると、接続は許可されるのではなく、拒否されます。
    • 最後の行が * の場合、拒否されていないすべてのものが許可されます。または、許可されていないすべてのものが拒否されます。
  2. egresss ルーターを参照するサービスを作成し、他の Pod が Pod の IP アドレスを見つけられるようにします。

    apiVersion: v1
    kind: Service
    metadata:
      name: egress-1
    spec:
      ports:
      - name: http-proxy
        port: 8080 1
      type: ClusterIP
      selector:
        name: egress-1
    1
    http ポートが常に 8080 に設定されていることを確認します。
  3. http_proxy または https_proxy 変数を設定して、クライアント Pod (egress プロキシー Pod ではない) を HTTP プロキシーを使用するように設定します。

        ...
        env:
        - name: http_proxy
          value: http://egress-1:8080/ 1
        - name: https_proxy
          value: http://egress-1:8080/
        ...
    1
    手順 2 で作成されたサービス。
    注記

    すべてのセットアップに http_proxy および https_proxy 環境変数が必要になる訳ではありません。上記を実行しても作業用セットアップが作成されない場合は、Pod で実行しているツールまたはソフトウェアについてのドキュメントを参照してください。

リダイレクトする egress ルーターの上記の例と同様に、ConfigMap を使用して EGRESS_HTTP_PROXY_DESTINATION を指定することもできます。

6.5.2.5. Egress ルーター Pod のフェイルオーバーの有効化

レプリケーションコントローラーを使用し、ダウンタイムを防ぐために egress ルーター Pod の 1 つのコピーを常に確保できるようにします。

  1. 以下を使用してレプリケーションコントローラーの設定ファイルを作成します。

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: egress-demo-controller
    spec:
      replicas: 1 1
      selector:
        name: egress-demo
      template:
        metadata:
          name: egress-demo
          labels:
            name: egress-demo
          annotations:
            pod.network.openshift.io/assign-macvlan: "true"
        spec:
          initContainers:
          - name: egress-demo-init
            image: registry.access.redhat.com/openshift3/ose-egress-router
            env:
            - name: EGRESS_SOURCE
              value: 192.168.12.99
            - name: EGRESS_GATEWAY
              value: 192.168.12.1
            - name: EGRESS_DESTINATION
              value: 203.0.113.25
            - name: EGRESS_ROUTER_MODE
              value: init
            securityContext:
              privileged: true
          containers:
          - name: egress-demo-wait
            image: registry.access.redhat.com/openshift3/ose-pod
          nodeSelector:
            site: springfield-1
    1
    replicas1 に設定されていることを確認します。1 つの Pod のみが指定される EGRESS_SOURCE 値を随時使用できるためです。これは、ルーターの単一コピーのみがラベル site=springfield-1 が設定されたノードで実行されることを意味します。
  2. この定義を使用して Pod を作成します。

    $ oc create -f <replication_controller>.json
  3. 検証するには、レプリケーションコントローラー Pod が作成されているかどうかを確認します。

    $ oc describe rc <replication_controller>

6.5.3. 外部リソースへのアクセスを制限するための iptables ルールの使用

クラスター管理者の中には、EgressNetworkPolicy のモデルや egress ルーターの対象外の発信トラフィックに対してアクションを実行する必要のある管理者がいる場合があります。この場合には、iptables ルールを直接作成してこれを実行することができます。

たとえば、特定の宛先へのトラフィックをログに記録するルールを作成したり、1 秒ごとに設定される特定数を超える発信接続を許可しないようにしたりできます。

OpenShift Container Platform はカスタム iptables ルールを自動的に追加する方法を提供していませんが、管理者がこのようなルールを手動で追加できる場所を提供します。各ノードは起動時に、filter テーブルに OPENSHIFT-ADMIN-OUTPUT-RULES という空のチェーンを作成します (チェーンがすでに存在していないと仮定します)。管理者がこのチェーンに追加するすべてのルールは、Pod からクラスター外にある宛先へのすべてのトラフィックに適用されます (それ以外のトラフィックには適用されません)。

この機能を使用する際には、注意すべきいくつかの点があります。

  1. 各ノードにルールが作成されていることを確認するのは管理者のタスクになります。OpenShift Container Platform はこれを自動的に確認する方法は提供しません。
  2. ルールは egress ルーターによってクラスターを退出するトラフィックには適用されず、ルールは EgressNetworkPolicy ルールが適用された後に実行されます (そのため、EgressNetworkPolicy で拒否されるトラフィックは表示されません)。
  3. ノードには「外部」IP アドレスと「内部」SDN IP アドレスの両方があるため、Pod からノードまたはノードからマスターへの接続の処理は複雑になります。そのため、一部の Pod とノード間/Pod とマスター間のトラフィックはこのチェーンを通過しますが、他の Pod とノード間/Pod とマスター間のトラフィックはこれをバイパスする場合があります。

6.6. 外部プロジェクトトラフィックの静的 IP の有効化

クラスター管理者は特定の静的 IP アドレスをプロジェクトに割り当て、トラフィックが外部から容易に識別できるようにできます。これは、トラフィックを特定の宛先に送信するために使用されるデフォルトの egress ルーターの場合とは異なります。

識別可能な IP トラフィックは起点を可視化することで、クラスターのセキュリティーを強化します。これが有効にされると、指定されたプロジェクトからのすべての発信外部接続は同じ固定ソース IP を共有します。つまり、すべての外部リソースがこのトラフィックを認識できるようになります。

egress ルーターの場合とは異なり、これは EgressNetworkPolicy ファイアウォールルールに基づいて実行されます。

静的 IP を有効にするには、以下を実行します。

  1. 必要な IP で NetNamespace を更新します。

    $ oc patch netnamespace <project_name> -p '{"egressIPs": ["<IP_address>"]}'

    たとえば、MyProject プロジェクトを IP アドレス 192.168.1.100 に割り当てるには、以下を実行します。

    $ oc patch netnamespace MyProject -p '{"egressIPs": ["192.168.1.100"]}'

    egressIPs フィールドは配列ですが、単一 IP アドレスに設定される必要があります。複数の IP を設定すると、他の IP は無視されます。

  2. egress IP を必要なノードホストに手動で割り当てます。ノードホストの HostSubnet オブジェクトの egressIPs フィールドを設定します。そのノードホストに割り当てる必要のある任意の数の IP を含めることができます。

    $ oc patch hostsubnet <node_name> -p \
      '{"egressIPs": ["<IP_address_1>", "<IP_address_2>"]}'

    たとえば node1 に egress IPs 192.168.1.100、192.168.1.101 および 192.168.1.102 が必要である場合が、以下のようになります。

    $ oc patch hostsubnet node1 -p \
      '{"egressIPs": ["192.168.1.100", "192.168.1.101", "192.168.1.102"]}'
    重要

    Egress IP はプライマリーネットワークインターフェースの追加の IP として実装され、ノードのプライマリー IP と同じサブネットに置かれる必要があります。一部のクラウドまたは仮想マシンソリューションを使用する場合に、プライマリーネットワークインターフェースで追加の IP アドレスを許可するには追加の設定が必要になる場合があります。

プロジェクトに対して上記が有効にされる場合、そのプロジェクトからのすべての egress トラフィックはその egress IP をホストするノードにルーティングされ、(NAT を使用して) その IP アドレスに接続されます。egressIPsNetNamespace で設定されているものの、その egress IP をホストするノードがない場合、namespace からの egress トラフィックはドロップされます。

6.7. マルチキャストの有効化

重要

現時点で、マルチキャストは低帯域幅の調整またはサービスの検出での使用に最も適しており、高帯域幅のソリューションとしては適していません。

OpenShift Container Platform の Pod 間のマルチキャストトラフィックはデフォルトで無効にされています。プロジェクトの対応する netnamespace オブジェクトにアノテーションを設定することで、プロジェクトごとにマルチキャストを有効にすることができます。

$ oc annotate netnamespace <namespace> \
    netnamespace.network.openshift.io/multicast-enabled=true

アノテーションを削除してマルチキャストを無効にします。

$ oc annotate netnamespace <namespace> \
    netnamespace.network.openshift.io/multicast-enabled-

ネットワークを結合している場合、すべてのプロジェクトで有効にされるようにマルチキャストを各プロジェクトの netnamespace で有効にする必要があります。マルチキャストをデフォルトプロジェクトで有効にするには、これを kube-service-catalog プロジェクトおよび グローバルにされたその他すべてのプロジェクトでも有効にする必要があります。

注記

マルチキャストのグローバルプロジェクトは、ユニキャストの場合のクラスター内のすべてのプロジェクトと通信するという文脈で「グローバル」なのではなく、マルチキャストによって他のグローバルプロジェクトのみと通信します。

6.8. NetworkPolicy の有効化

ovs-subnet および ovs-multitenant プラグインにはネットワークの分離についての独自のレガシーモデルがありますが、Kubernetes NetworkPolicy はサポートしません。ただし、NetworkPolicy サポートは、ovs-networkpolicy プラグインを使用すると利用できます。

ovs-networkpolicy プラグインを使用するよう設定されるクラスターでは、ネットワークの分離は完全に NetworkPolicy オブジェクトによって制御されます。デフォルトで、プロジェクトのすべての Pod は他の Pod およびネットワークのエンドポイントからアクセスできます。プロジェクト内の 1 つ以上の Pod を分離するには、そのプロジェクトで NetworkPolicy オブジェクトを作成し、許可する着信接続を指定します。プロジェクト管理者は独自のプロジェクト内で NetworkPolicy オブジェクトの作成および削除を実行できます。

Pod を参照する NetworkPolicy オブジェクトを持たない Pod は完全にアクセスできますが、Pod を参照する 1 つ以上の NetworkPolicy オブジェクトを持つ Pod は分離されます。これらの分離された Pod は 1 つ以上の NetworkPolicy オブジェクトで許可される接続のみを受け入れます。

複数の異なるシナリオに対応するいくつかの NetworkPolicy オブジェクト定義を見てみましょう。

  • すべてのトラフィックを拒否

    プロジェクトに「deny by default (デフォルトで拒否)」を実行させるには、すべての Pod に一致するが、トラフィックを一切許可しない NetworkPolicy オブジェクトを追加します。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: deny-by-default
    spec:
      podSelector:
      ingress: []
  • プロジェクト内の Pod からの接続のみを許可

    Pod が同じプロジェクト内の他の Pod からの接続を受け入れるが、他のプロジェクトの Pod からの接続を拒否するように設定するには、以下を実行します。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-same-namespace
    spec:
      podSelector:
      ingress:
      - from:
        - podSelector: {}
  • Pod ラベルに基づいて HTTP および HTTPS トラフィックのみを許可

    特定のラベル (以下の例の role=frontend) の付いた Pod への HTTP および HTTPS アクセスのみを有効にするには、以下と同様の NetworkPolicy オブジェクトを追加します。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-http-and-https
    spec:
      podSelector:
        matchLabels:
          role: frontend
      ingress:
      - ports:
        - protocol: TCP
          port: 80
        - protocol: TCP
          port: 443

NetworkPolicy オブジェクトは加算されるものです。つまり、複数の NetworkPolicy オブジェクトを組み合わせて複雑なネットワーク要件を満すことができます。

たとえば、先の例で定義された NetworkPolicy オブジェクトの場合、同じプロジェト内に allow-same-namespaceallow-http-and-https ポリシーの両方を定義することができます。これにより、ラベル role=frontend の付いた Pod は各ポリシーで許可されるすべての接続、つまり、同じ namespace の Pod からのすべての接続、および すべて の namespace の Pod からのポート 80 443 での接続を受け入れます。

6.8.1. NetworkPolicy およびルーター

ovs-multitenant プラグインを使用する場合、ルーターからすべての namespace へのトラフィックは自動的に許可されます。これは、ルーターは通常 デフォルトの namespace にあり、すべての namespace がその namespace の Pod からの接続を許可するためです。ただし ovs-networkpolicy プラグインを使用すると、これは自動的に実行されません。そのため、デフォルトで namespace を分離するポリシーがある場合は、ルーターがこれにアクセスできるように追加の手順を実行する必要があります。

1 つのオプションとして、すべてのソースからのアクセスを許可する各サービスのポリシーを作成できます。以下は例になります。

kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
  name: allow-to-database-service
spec:
  podSelector:
    matchLabels:
      role: database
  ingress:
  - ports:
    - protocol: TCP
      port: 5432

これにより、ルーターはサービスにアクセスできますが、同時に他のユーザーの namespace にある Pod もこれにアクセスできます。これらの Pod は通常はパブリックルーターを使用してサービスにアクセスできるため、これによって問題が発生することはないはずです。

または、ovs-multitenant プラグインの場合のように、デフォルト namespace からの完全アクセスを許可するポリシーを作成することもできます。

  1. ラベルをデフォルト namespace に追加します。

    重要

    これはクラスター全体に対して 1 回のみ実行する必要があります。クラスター管理ロールには、ラベルを namespace に追加することが求められます。

    $ oc label namespace default name=default
  2. その namespace からの接続を許可するポリシーを作成します。

    注記

    接続を許可するそれぞれの namespace についてこの手順を実行します。プロジェクト管理者ロールを持つユーザーがポリシーを作成できます。

    kind: NetworkPolicy
    apiVersion: networking.k8s.io/v1
    metadata:
      name: allow-from-default-namespace
    spec:
      podSelector:
      ingress:
      - from:
        - namespaceSelector:
            matchLabels:
              name: default

6.8.2. 新規プロジェクトのデフォルト NetworkPolicy の設定

クラスター管理者は、新規プロジェクトの作成時に、デフォルトのプロジェクトテンプレートを変更してデフォルトの NetworkPolicy オブジェクト (1 つ以上) の自動作成を有効にできます。これを実行するには、以下を行います。

  1. 新規プロジェクトのテンプレートの変更」で説明されているように、カスタムプロジェクトテンプレートを作成し、マスターがこれを使用するように設定します。
  2. 必要な NetworkPolicy オブジェクトを含むようにテンプレートを編集します。

    $ oc edit template project-request -n default
    注記

    NetworkPolicy オブジェクトを既存テンプレートに含めるには、oc edit コマンドを使用します。現時点では、oc patch を使用してオブジェクトを Template リソースに追加することはできません。

    1. それぞれのデフォルトポリシーを objects 配列の要素として追加します。

      objects:
      ...
      - apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: allow-from-same-namespace
        spec:
          podSelector:
          ingress:
          - from:
            - podSelector: {}
      - apiVersion: networking.k8s.io/v1
        kind: NetworkPolicy
        metadata:
          name: allow-from-default-namespace
        spec:
          podSelector:
          ingress:
          - from:
            - namespaceSelector:
                matchLabels:
                  name: default
      ...

6.9. 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
重要

haproxy.router.openshift.io/hsts_header 値にパラメーターのスペースやその他の値が入っていないことを確認します。max-age のみが必要になります。

必須の max-age パラメーターは、HSTS ポリシーの有効期間 (秒単位) を示します。クライアントは、ホストから HSTS ヘッダーのある応答を受信する際には常に max-age を更新します。max-age がタイムアウトになると、クライアントはポリシーを破棄します。

オプションの includeSubDomains パラメーターは、クライアントに対し、ホストのすべてのサブドメインがホストど同様に処理されるように指示します。

max-age が 0 より大きい場合、オプションの preload パラメーターは外部サービスがこのサイトをそれぞれの HSTS プリロードのリストに含めることを許可します。たとえば、Google などのサイトは preload が設定されているサイトの一覧を作成します。ブラウザーはこれらのリストを使用し、サイトと対話する前でも HTTPS 経由でのみ通信するサイトを判別できます。preload 設定がない場合、ブラウザーはヘッダーを取得するために HTTPS 経由でサイトと通信している必要があります。

6.10. スループットの問題のトラブルシューティング

OpenShift Container Platform でデプロイされるアプリケーションでは、特定のサービス間で非常に長い待ち時間が発生するなど、ネットワークのスループットの問題が生じることがあります。

Pod のログが問題の原因を指摘しない場合は、以下の方法を使用してパフォーマンスの問題を分析します。

  • ping または tcpdump などのパケットアナライザーを使用して 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 アドレスです。以下のコマンドを実行して Pod の IP アドレスを取得します。
    # oc get pod <podname> -o wide

    tcpdump は 2 つの Pod 間のすべてのトラフィックが含まれる /tmp/dump.pcap のファイルを生成します。理想的には、ファイルサイズを最小限に抑えるために問題を再現するすぐ前と問題を再現したすぐ後ににアナライザーを実行することが良いでしょう。以下のようにノード間でパケットアナライザーを実行することもできます (式から SDN を排除する)。

    # tcpdump -s 0 -i any -w /tmp/dump.pcap port 4789
  • ストリーミングのスループットおよび UDP スループットを測定するために iperf などの帯域幅測定ツールを使用します。ボトルネックの特定を試行するには、最初に Pod から、次にノードからツールを実行します。iperf3 ツールは RHEL 7 の一部として組み込まれています。

iperf3 のインストールおよび使用についての詳細は、こちらの Red Hat ソリューションを参照してください。