Kubernetesリバースプロキシ

この例では、Next-Gen WAF エージェントがサイドカーコンテナとして実行され、すべての受信リクエストを検査のためにプロキシし、その後上流のアプリケーションコンテナへ転送します。

Next-Gen WAF エージェントを統合する

Next-Gen WAF エージェントは、各 Pod にサイドカーとしてインストールすることも、特定の要件向けに Service としてインストールすることもできます。

Kubernetes における Next-Gen WAF エージェントの推奨インストール方法は、sigsci-agent を Pod にサイドカーとして統合することです。これは、sigsci-agent を Kubernetes Pod の追加コンテナとして追加することを意味します。サイドカーとして動作することで、エージェントは Pod 内のアプリケーション/Service と共にスケーリングすることになり、個別にスケーリングする必要がなくなります。ただし、状況によっては sigsci-agent コンテナを Service としてインストールし、アプリケーションとは別にスケーリングした方が適している場合もあります。

sigsci-agent コンテナは、インストールタイプや使用するモジュールに応じてさまざまな方法で設定できます。

コンテナフック preStop を使用すると、Pod のシャットダウンを遅らせ、ドレインタイムアウトを確実に満たすことができます。

preStop:
exec:
command:
- sleep
- "30"

デフォルトでは、エージェントは予備的な検査のために迅速な起動とパフォーマンス準備を優先します。ただし、ルールや設定データを読み込んだ後にのみトラフィックを検査したい場合、迅速な起動が必ずしも望ましいとは限りません。その場合は、Startup Probe を設定してエージェントの起動を遅延させることを検討してください。

エージェントコンテナイメージを取得および更新する

公式の signalsciences/sigsci-agent コンテナイメージが Docker Hub で利用可能です。

独自のイメージをビルドしたい場合や、イメージをカスタマイズする必要がある場合は、sigsci-agent のビルド手順に従ってください。

これらの手順では、latest バージョンのエージェントを imagePullPolicy: Always で参照しており、ローカルにすでにエージェントが存在する場合でも最新のエージェントバージョンを取得します。これは、ドキュメントが古くならないようにし、このドキュメントを参照するすべての人が古い状態のままのエージェントを使うことを防ぐためです。ただし、インストールの一貫性を維持する必要がある場合や、特定バージョンのエージェントを維持する必要がある場合は、この方法が適さない可能性があります。このような場合は、エージェントのバージョンを指定する必要があります。Docker Hub 上のイメージにはバージョンがタグ付けされており、バージョンのリストは Docker Hub で確認できます

latest イメージを使用するか特定のバージョンを使用するかにかかわらず、エージェントを最新の状態に保つために考慮すべき項目がいくつかあります。

latest コンテナイメージを使用する

latestイメージを使用することを選択した場合は、エージェントを最新の状態に保つ方法を検討する必要があります。

  • imagePullPolicy: Always オプションを使用した場合、起動のたびに最新のイメージが取得され、エージェントは継続的に更新を受け取ります。

  • あるいは、起動時に常にプルするのではなく、定期的に手動でローカルキャッシュを更新する方法もあります。

    $ docker pull signalsciences/sigsci-agent:latest

    次に、latestimagePullPolicy: Never 設定で使用して、起動時にプルが実行されないようにします (上記のように手動でのみ)。

    - name: sigsci-agent
    image: signalsciences/sigsci-agent:latest
    imagePullPolicy: Never
    ...

バージョン管理されたコンテナイメージを使用する

特定のバージョンのエージェントを使用するには、latestをエージェントのバージョン(ここではx.xx.xで表されます)に置き換えてください。この場合、画像は変わらないはずなので、imagePullPolicy: IfNotPresentを変更することもおすすめします。

- name: sigsci-agent
image: signalsciences/sigsci-agent:x.xx.x
imagePullPolicy: IfNotPresent
...

この方法では、指定したエージェントバージョンがプルされ、ローカルにキャッシュされます。この方法を使用する場合、後からエージェントイメージを更新しやすくするため、Helm などを使ってエージェントイメージをパラメータ化することを推奨します。

コンテナイメージにカスタムタグを使用する

ローカルエージェントイメージにカスタムタグを適用することも可能です。これを行うには、エージェントイメージを (バージョンまたは latest で) プルし、カスタムタグを適用し、そのカスタムタグを設定で使用します。ローカルイメージは手動でのみ更新されるように imagePullPolicy: Never を指定する必要があります。その後、エージェントを最新の状態に保つために、ローカルイメージを定期的に更新する必要があります。

例:

$ docker pull signalsciences/sigsci-agent:latest
$ docker tag signalsciences/sigsci-agent:latest signalsciences/sigsci-agent:testing

次に、このイメージタグを設定で使用します。

- name: sigsci-agent
image: signalsciences/sigsci-agent:testing
imagePullPolicy: Never
...

エージェントコンテナを設定する

エージェントの設定は通常、環境変数を通じて行います。ほとんどの設定オプションは環境変数として利用可能です。環境変数名は、設定オプション名をすべて大文字にし、SIGSCI_ を接頭辞として付け、ダッシュ (-) をアンダースコア (_) に置き換えたものになります。たとえば、max-procs オプションは SIGSCI_MAX_PROCS 環境変数になります。利用可能なオプションの詳細については、エージェント設定ドキュメントを参照してください。

sigsci-agent コンテナには設定が必要ないくつかのオプションがあります。

  • エージェント認証情報 (Agent Access KeyAgent Secret Key)。

  • 一時ファイルを書き込むためのボリューム。

エージェントの認証情報

sigsci-agent の認証情報は、2つの環境変数で設定されます。これらの変数が設定されていない場合、エージェントは起動しません。

  • SIGSCI_ACCESSKEYID : Agent Access Key は、エージェントが設定されている Next-Gen WAF コントロールパネル上のサイト (ワークスペース) を識別します。

  • SIGSCI_SECRETACCESSKEY: Agent Secret Key はエージェントを認証・認可するための共有秘密鍵です。

これらの値は非常に機密性が高いため、Kubernetes の組み込み secrets 機能を使用することを推奨します。この構成では、エージェントは Deployment 設定内にハードコードされた値を読み取るのではなく、Secrets データから値を取得します。これにより、エージェント認証情報のローテーションも、1か所を変更するだけで管理しやすくなります。

secrets 機能を使うには、value オプションではなく valueFrom オプションを使用します。例 :

env:
- name: SIGSCI_ACCESSKEYID
valueFrom:
secretKeyRef:
# Update my-site-name-here to the correct site (workspace) name or similar identifier
name: sigsci.my-site-name-here
key: accesskeyid
- name: SIGSCI_SECRETACCESSKEY
valueFrom:
secretKeyRef:
# Update my-site-name-here to the correct site (workspace) name or similar identifier
name: sigsci.my-site-name-here
key: secretaccesskey

secrets 機能は、Kubernetes 内のさまざまなストアにシークレットを保持します。このガイドでは、例として汎用のシークレットストアを使用していますが、同等のストアであればどれでも使用できます。エージェントのシークレットは、以下の例のような YAML を使用して汎用のシークレットストアに追加できます。

apiVersion: v1
kind: Secret
metadata:
name: sigsci.my-site-name-here
stringData:
accesskeyid: 12345678-abcd-1234-abcd-1234567890ab
secretaccesskey: abcdefg_hijklmn_opqrstuvwxy_z0123456789ABCD

これは、次のように kubectl を使用してコマンドラインから作成することもできます。

$ kubectl create secret generic sigsci.my-site-name-here \
--from-literal=accesskeyid=12345678-abcd-1234-abcd-1234567890ab \
--from-literal=secretaccesskey=abcdefg_hijklmn_opqrstuvwxy_z0123456789ABCD

Kubernetes の secrets 機能に関する詳細は、Kubernetes のドキュメントを参照してください。

エージェント一時ボリューム

セキュリティ強化のため、sigsci-agent コンテナはルートファイルシステムを読み取り専用としてマウントして実行することを推奨します。ただし、エージェントは RPC 通信用のソケットファイルのような一時ファイルや、位置情報データなどの定期的に更新されるファイルを書き込む必要があります。

読み取り専用のルートファイルシステムでこれを実現するには、書き込み可能なボリュームをマウントする必要があります。この書き込み可能なボリュームは、同じポッド内の他のコンテナに RPC ソケットファイルを公開するために共有することもできます。

書き込み可能なボリュームを作成する推奨方法は、組み込みの emptyDir ボリュームタイプを使用することです。これは通常、次の例のように Deployment の volumes セクションで設定します。

volumes:
- name: sigsci-tmp
emptyDir: {}

その後、コンテナはこのボリュームを /sigsci/tmp にマウントします。

volumeMounts:
- name: sigsci-tmp
mountPath: /sigsci/tmp

公式エージェントコンテナイメージのデフォルト設定では、一時ボリュームが /sigsci/tmp にマウントされます。エージェントコンテナ用にこれを変更する必要がある場合、次のエージェント設定オプションもデフォルトから新しいマウント場所に合わせて変更する必要があります。

  • rpc-address デフォルトは /sigsci/tmp/sigsci.sock

  • shared-cache-dir はデフォルトで /sigsci/tmp/cache です

Next-Gen WAF モジュールを使用せず、Next-Gen WAF エージェントを Web アプリケーションの前段にリバースプロキシとして配置する

Web アプリケーションが Next-Gen WAF モジュールをサポートしていない場合 (またはモジュールをインストールしないことを選択する場合)、同じポッド内の Web アプリケーションの前でリバースプロキシとして動作するように sigsci-agent コンテナを設定することができます。

サイドカーコンテナで Next-Gen WAF エージェントをリバースプロキシモードとして実行するには、次の設定が必要です。

  • リバースプロキシモードで以下のように設定した sigsci-agent コンテナを Pod に追加します。

    • 受信リクエストをリッスンする (新しいポートを使用する、またはアプリケーション/Kubernetes Service の設定を変更する)

    • リクエストを Web アプリケーションコンテナへプロキシする

  • emptyDir{} ボリュームを追加して、sigsci-agent が一時的なデータを書き込む場所とします。

以下の設定では、ポート 8000サンプルのアプリケーション (helloworld) を公開し、sigsci-agent を新しいポート 8001 のリバースプロキシリスナーとして、サンプル Web アプリケーションポート 8000 を使用して追加します。

Next-Gen WAF エージェントをリバースプロキシとして追加する

...
containers:
# Example helloworld app running on port 8000 without sigsci configured
- name: helloworld
image: signalsciences/example-helloworld:latest
imagePullPolicy: IfNotPresent
args:
- localhost:8000
ports:
- containerPort: 8000
# Next-Gen WAF agent running in reverse proxy mode (SIGSCI_REVPROXY_LISTENER configured)
- name: sigsci-agent
image: signalsciences/sigsci-agent:latest
imagePullPolicy: Always
env:
- name: SIGSCI_ACCESSKEYID
valueFrom:
secretKeyRef:
name: sigsci.my-site-name-here
key: accesskeyid
- name: SIGSCI_SECRETACCESSKEY
valueFrom:
secretKeyRef:
name: sigsci.my-site-name-here
key: secretaccesskey
# Configure the revproxy listener to listen on a new port 8001
# forwarding to the app on the original port 8000 as the upstream
- name: SIGSCI_REVPROXY_LISTENER
value: "http:{listener='http://0.0.0.0:8001',upstreams='http://0.0.0.0:8000',access-log='/dev/stdout'}"
ports:
- containerPort: 8001
securityContext:
# The sigsci-agent container should run with its root filesystem read only
readOnlyRootFilesystem: true
volumeMounts:
# Default volume mount location for sigsci-agent writeable data
# NOTE: Also change `SIGSCI_SHARED_CACHE_DIR` (default `/sigsci/tmp/cache`)
# if mountPath is changed, but best not to change.
- name: sigsci-tmp
mountPath: /sigsci/tmp

注: 上記の変更は、sigsci個のシークレットがシステムに追加されたことを前提としています。

Deployment に Next-Gen WAF エージェント用の一時ボリュームの定義を追加する

ポッド内の他のコンテナが使用するためのエージェント一時ボリュームを定義する必要があります。この例では、組み込みの emptyDir: {} ボリュームタイプを使用しています。

...
volumes:
# Define a volume where sigsci-agent will write temp data and share the socket file,
# which is required with the root filesystem is mounted read only
- name: sigsci-tmp
emptyDir: {}

Service 定義を変更し、Next-Gen WAF エージェントをリバースプロキシとして追加する

上記の例では、sigsci-agent リバースプロキシは新しいポートでリッスンし、元のアプリケーションのリスナーはそのまま残されています。しかし、エージェント追加をできるだけシームレスに行うために、元のアプリケーションポートで受けたリクエストを sigsci-agent にルーティングしたい場合もあります。その1つの方法が、トラフィックを Web アプリケーションに直接送るのではなく sigsci-agent のリバースプロキシのリスナーポートへルーティングするように Kubernetes の Service 定義を変更することです。

Next-Gen WAF エージェントのポートを指すように Service 定義を変更する

アプリケーションを直接指すのではなく、sigsci-agent のリバースプロキシのリスナーポートを指すように、Service の targetPort を変更します。その後、sigsci-agent がアプリケーションポートへプロキシします。

apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
ports:
- name: http
port: 8000
# Target is now sigsci-agent on port 8001
targetPort: 8001
selector:
app: helloworld
type: LoadBalancer