OpenPolicyAgent を使用してプロキシ構成を Kubernetes ワークロードに挿入する


企業サービスが企業プロキシの背後にあることは珍しくありません.企業サービスから抜け出すには、このプロキシ アクセスを構成して、それを介してアクセスする必要があります.同じことが、o Kubernetes を実行するサービスにも当てはまります.

これを行う 1 つの方法は、次のようなプロキシ文字列を含む Secret リソースを手動で作成することです.

kubectl create secret generic corporate-proxy --from-literal=authentication-string="http://{USERNAME}:{PASSWORD}@{PROXY_ADDRESS}:{PROXY_PORT}" --from-literal=no-proxy-string="localhost,127.0.0.1,0.0.0.0,10.0.0.0/8,cattle-system.svc,10.42.0.0/24,.svc,.cluster.local,example.com"


そして、それを Kubernetes アプリケーション リソースの環境にマウントします.

apiVersion: v1
kind: Pod
metadata:
  name: appWithProxy
  namespace: default
spec:
  containers:
  - name: appWithProxy
    image: yourApplication
    env:
    - name: HTTP_PROXY
      valueFrom:
        secretKeyRef:
          name: corporate-proxy
          key: authentication-string
    - name: NO_PROXY
      valueFrom:
        secretKeyRef:
          name: corporate-proxy
          key: no-proxy-string


そのコンテナーに exec 接続すると、そのプロキシを使用してパブリック リソースにアクセスできます.

curl --proxy $HTTP_PROXY http://ipinfo.io/json


ただし、これは面倒な手動プロセスであり、プロキシ アクセスを必要とするリソースごとに繰り返す必要があります.

OpenPolicyAgent Gatekeeper が行う多くのことの中で、さまざまなスコープ ルールに基づいて Kubernetes API リクエストを変更し、環境変数などをそのスコープを満たすリソースに挿入できるようにします.

これは、Mutating Admission Webhook を使用して行われます.たとえば、 Mutating Admission Webhook to inject environment variables like these proxy settings を使用して、リクエストを変更して PodDeployment などのリソースを作成し、プロキシ構成データを挿入します. (リンクされた例では) Webhook の検証など、他の種類の Webhook があります.これは、ワークロードにラベルや適切な名前が付いていることを確認するなどのことを行い、Admission Webhook による他のアクションを指示します.

このシナリオでは、 OPA Gatekeeper がこれの多くを行いますが、代わりに、ミューテーションとスコープはポリシーによって決定されます.私たちの場合、要求に応じて変更したいリソースを含む名前空間を作成し、上記の corporate-proxy リソース Secret を環境変数としてマウントします.

OPA は facilities for testing these policies も提供します.

installing OPA Gatekeeper の後:

kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.7/deploy/gatekeeper.yaml


または、あなたが Rancher user, Gatekeeper can be installed and enabled from the UI の場合.

次に、ModifySet リソースを定義できます.

apiVersion: mutations.gatekeeper.sh/v1beta1
kind: ModifySet
metadata:
  name: demo-annotation-owner
  namespace: proxy-test
spec:
    applyTo:
      - groups: [""]
        versions: ["v1"]
        kinds: ["Pod", "Deployment"]
    match:
      scope: Namespaced
      kinds:
        - apiGroups: ["*"]
          kinds: ["Pod"]
    location: "spec.containers[name:*].env"
    parameters:
      values:
        fromList:
          - name: HTTP_PROXY
            valueFrom:
              secretKeyRef:
                name: corporate-proxy
                key: authentication-string
          - name: NO_PROXY
            valueFrom:
              secretKeyRef:
                name: corporate-proxy
                key: authentication-string


これは proxy-test 名前空間にデプロイされ、数行下では、 scopeNamespaced に設定されています.つまり、その名前空間内の一致するリソースにのみ以下が適用されます.

API サーバーがその名前空間であり、任意の apiGroup ("*") に一致し、kind: Pod の要求を渡す場合、次のような仕様を読み取ります.

apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
  namespace: proxy-test
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    env:
    - name: SOME_EXISTING_VAR
      value: "Present"
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default

spec.containers を参照すると、このリクエストには env ブロックが含まれていないため、上記の Secret ( secret/corporate-proxy ) がこの仕様に挿入され、上記の Yaml で表された env が追加されますが、JSON として挿入することもできます.

[{"name": "HTTP_PROXY", "valueFrom": {"secretKeyRef": {"name": "corporate-proxy", "key": "authentication-string"}}}]

Pod を作成します.

これをテストするには、上記の仕様を使用して 2 つの Pods を作成します.1 つは proxy-test 名前空間に、もう 1 つは別の名前空間に作成します.

cat << EOF >> proxy.yaml
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
  namespace: proxy-test
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    env:
    - name: SOME_EXISTING_VAR
      value: "Present"
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default
EOF

kubectl apply -f proxy.yaml


と別のもの:

cat << EOF >> no-proxy.yaml
apiVersion: v1
kind: Pod
metadata:
  name: shell-demo
  namespace: default
spec:
  volumes:
  - name: shared-data
    emptyDir: {}
  containers:
  - name: nginx
    image: nginx
    env:
    - name: SOME_EXISTING_VAR
      value: "Present"
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html
  dnsPolicy: Default
EOF

kubectl apply -f no-proxy.yaml


名前空間 kubectl describePod を実行すると、次のように表示されます.

root@ubuntu-proxy-k3s:~# kubectl describe pod/shell-demo -n proxy-test
Name:         shell-demo
Namespace:    proxy-test
...
Containers:
  nginx:
    Image:      nginx
...
    Environment:
      SOME_EXISTING_VAR:     "Present"
      HTTP_PROXY:  <set to the key 'authentication-string' in secret 'corporate-proxy'>  Optional: false
      NO_PROXY:    <set to the key 'authentication-string' in secret 'corporate-proxy'>  Optional: false

default 名前空間のものには環境セットがありません.

これらの ModifySet リソースは、他の多くのスコープ、および location キーで指定したマニフェストの任意の部分に基づいて変更するように記述し、上記で行ったようにパラメーターの下に value を割り当てることができます. OPA Gatekeeper リソースを使用してリソースを変更する他の例は、here にあります.