制約を作成する

このページでは、Policy Controller の制約を定義する方法について説明します。

Policy Controller を使用すると、1 つ以上の制約オブジェクトを定義することにより、Kubernetes クラスタにポリシーを適用できます。制約がインストールされると、API サーバーへのリクエストは制約と照合され、準拠していない場合は拒否されます。以前から存在する準拠していないリソースは、監査時に報告されます。

すべての制約は、制約のスキーマとロジックを定義する制約テンプレートが基盤となります。制約テンプレートは、Google やサードパーティから提供されるものを使用することも、独自に作成することもできます。新しいテンプレートの作成の詳細については、制約テンプレートを作成するをご覧ください。

始める前に

制約テンプレート ライブラリを調べる

制約を定義するときは、拡張する制約テンプレートを指定します。Google が開発した一般的な制約テンプレートのライブラリがデフォルトでインストールされており、多くの組織では Rego で直接カスタム制約テンプレートを作成する必要はありません。Google が提供する制約テンプレートには、configmanagement.gke.io/configmanagement というラベルが付いています。

制約を一覧表示するには、次のコマンドを使用します。

kubectl get constrainttemplates \
    -l="configmanagement.gke.io/configmanagement=config-management"

制約テンプレートを記述して必須パラメータを確認するには、次のコマンドを使用します。

kubectl describe constrainttemplate CONSTRAINT_TEMPLATE_NAME

また、ライブラリ内のすべての制約テンプレートを表示することも可能です。

制約を定義する

制約は YAML を使用して定義します。Rego を理解して記述する必要はありません。代わりに、制約は制約テンプレートを呼び出して固有のパラメータを渡します。

構造化されたリポジトリを使用している場合は、cluster/ ディレクトリに制約を作成することをおすすめします。

制約には次のフィールドがあります。

  • 小文字の kind は、制約テンプレートの名前と対応します。
  • metadata.name は、制約の名前です。
  • match フィールドは、制約が適用されるオブジェクトを定義します。オブジェクトが制約の対象となるには、指定されたすべての条件を満たす必要があります。match 条件は、次のサブフィールドで定義されます。
    • kinds は、制約が適用されるリソースの種類です。一致する Kubernetes API グループのリスト apiGroups と、一致する種類のリスト kinds という 2 つのフィールドで指定されます。「*」はすべてに一致します。apiGroup エントリと kind エントリが少なくとも 1 つずつ一致すると、kinds 条件が満たされます。
    • scope は *、Cluster、または Namespace を受け入れ、クラスタ スコープのリソースと名前空間スコープのリソースのどちらか一方、または両方が選択されるかどうかを決定します(デフォルトは *)。
    • namespaces は、オブジェクトが属することができる名前空間名のリストです。オブジェクトは、これらの名前空間の少なくとも 1 つに属している必要があります。名前空間リソースは、その名前空間自体に属しているものとみなされます。
    • excludedNamespaces は、オブジェクトが属することができない名前空間のリストです。
    • labelSelector は、オブジェクトが満たす必要がある Kubernetes ラベル セレクターです。
    • namespaceSelectorは、オブジェクトが属する名前空間のラベル セレクターです。名前空間がオブジェクトを満たさない場合は、一致しません。名前空間リソースは、その名前空間自体に属しているものとみなされます。
  • parameters フィールドは、制約テンプレートが想定するものに基づいて、制約の引数を定義します。

次の ns-must-have-geo という制約は、Google が提供する制約テンプレート ライブラリに含まれている K8sRequiredLabels という制約テンプレートを呼び出します。この制約は、なんらかの値が設定されている geo ラベルが名前空間にあるかどうかを検証するよう、制約テンプレートが使用するパラメータを定義しています。

# ns-must-have-geo.yaml

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-geo
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels:
      - key: "geo"

制約を作成するには、kubectl apply -f を使用します。

kubectl apply -f ns-must-have-geo.yaml

制約を監査する

制約が正しく構成、インストールされている場合、制約を実際に適用する構成か、テストするだけの構成かにかかわらず、status.byPod[].enforced フィールドは true に設定されます。

デフォルトでは制約は適用され、制約に違反するクラスタのオペレーションは完了しなくなります。制約の spec.enforcementActiondryrun に設定すると、オペレーションを妨げることなく、status.violations フィールドで違反が報告されます。

監査の詳細については、制約を使用して監査するをご覧ください。

制約を同期するときの注意点

制約を同期するときは、次の注意点に留意してください。

結果整合性

制約は Git リポジトリに commit し、ClusterSelector または NamespaceSelector を使用して影響を制限できます。同期には結果整合性があるため、次の注意点に留意してください。

  • クラスタ オペレーションによって、同期されていない名前空間を参照する NamespaceSelector の制約がトリガーされると、制約が適用されてオペレーションが完了しません。つまり、不明な名前空間は「フェイル クローズ」します。
  • 名前空間のラベルを変更すると、一時的にキャッシュに古いデータが含まれる場合があります。

名前空間の名前やラベルを変更する必要性は最小限に抑えてください。また、名前やラベルが変更された名前空間に影響を与える制約をテストし、期待どおりに機能することを確かめてください。

参照制約用の Policy Controller の構成

参照制約は、名前空間など、監視するオブジェクトの種類を Policy Controller に指示する構成ファイルを作成した後、有効にする必要があります。

次の YAML マニフェストをファイルに保存し、kubectl で適用します。このマニフェストでは、名前空間と Ingresses を監視するように Policy Controller を構成します。エントリは、groupversionkind に監視するオブジェクトの各タイプの値を指定して、spec.sync.syncOnly の下に作成します。

apiVersion: config.gatekeeper.sh/v1alpha1
kind: Config
metadata:
  name: config
  namespace: "gatekeeper-system"
spec:
  sync:
    syncOnly:
      - group: ""
        version: "v1"
        kind: "Namespace"
      - group: "extensions"
        version: "v1beta1"
        kind: "Ingress"

参照制約を有効にする

参照制約では、その定義内の別のオブジェクトを参照します。たとえば、クラスタ内に一意のホスト名を持つ Ingress オブジェクトを求める制約を作成できます。制約テンプレートの Rego に文字列 data.inventory が含まれている場合、その制約は参照用です。

参照制約は、Policy Controller ではデフォルトで無効になっています。参照制約は、結果整合性が保証するだけのものであり、これによって生じるリスクがあります。

  • 過負荷の API サーバーでは、Policy Controller のキャッシュの内容が古くなる可能性があり、参照制約を「フェイル オープン」させることになります。つまり、適用アクションが機能していないときに、機能しているように見えるということです。たとえば、重複したホスト名での Ingress の作成が早すぎて、アドミッション コントローラによる重複の検出ができなくなる可能性があります。

  • 制約がインストールされる順序と、キャッシュが更新される順序は、どちらもランダムです。

こうしたリスクを理解したうえで、参照制約のサポートを有効にする場合は、Google Cloud Console で参照制約を有効にできます。詳細については、Policy Controller をインストールするをご覧ください。

また、config-management.yaml ファイルで policyController.referentialRulesEnabledtrue に設定することもできます。

apiVersion: configmanagement.gke.io/v1
kind: ConfigManagement
metadata:
  name: config-management
  namespace: config-management-system
spec:
  clusterName: my-cluster
  channel: dev
  policyController:
    enabled: true
    referentialRulesEnabled: true

すべての制約を一覧表示する

クラスタにインストールされているすべての制約を一覧表示するには、次のコマンドを使用します。

kubectl get constraint

制約を削除する

制約テンプレートを使用するすべての制約を見つけるには、次のコマンドを使用して、制約テンプレートの metadata.name と同じ kind を持つすべてのオブジェクトを一覧表示します。

kubectl get CONSTRAINT_TEMPLATE_NAME

制約を削除するには、その kindname を指定します。

kubectl delete CONSTRAINT_TEMPLATE_NAME CONSTRAINT_NAME

制約で使用していた制約テンプレートを削除する場合は、制約の kind をメモします。

制約を削除すると、API サーバーによって制約に削除済みのマークが付けられ、その後直ちに制約の適用が停止します。

すべての制約テンプレートを削除する

spec.policyController.templateLibraryInstalledfalse に設定します。この設定により、Anthos Config Management がライブラリを自動的に再インストールすることが防止されます。

すべての制約テンプレートとすべての制約を削除するには、次のコマンドを使用します。

kubectl delete constrainttemplate --all

制約テンプレート ライブラリを復元する

制約テンプレート ライブラリを無効にした場合や、すべての制約テンプレートをアンインストールした場合は、Anthos Config Management の構成ファイルの spec.policyController.templateLibraryInstalledtrue に設定することでそれを復元できます。

トラブルシューティング

制約テンプレートの作成エラー

disallowed ref に関するエラーが表示された場合は、参照制約が有効になっていることを確認してください。たとえば、始めに参照制約を設定せずに制約テンプレートで data.inventory を使用すると、エラーは次のようになります。

admission webhook "validation.gatekeeper.sh" denied the request: check refs failed on module {templates["admission.k8s.gatekeeper.sh"]["MyTemplate"]}: disallowed ref data.inventory...

次のステップ