kakakakakku blog

Weekly Tech Blog: Keep on Learning!

Kubernetes と OPA を組み合わせて Deployment の spec.replicas に対して「最低個数」を制限する

前回の記事では Kubernetes と OPA (Open Policy Agent) を組み合わせて「ラベル強制」を試した.OPA を使ってできることをより把握するために,今回は Deploymentspec.replicas に対して「最低個数」を制限できるようにする.なお OPA のインストール手順などは前回の記事を参照してもらえればと!Kubernetes v1.20 を使う.

kakakakakku.hatenablog.com

CRD k8sminreplicas.constraints.gatekeeper.sh を追加する

さっそく「レプリカ最低個数」のために必要な設定を適用する.まず,ConstraintTemplate からレプリカ数を判定する CRD として K8sMinReplicas を作る.強制するためには Rego を使って実装をする必要があり,今回は以下の k8sminreplicas.yaml を使う.簡単に言うと,制限する parameters.min とマニフェストの spec.replicas を比較している.

apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
  name: k8sminreplicas
spec:
  crd:
    spec:
      names:
        kind: K8sMinReplicas
      validation:
        # Schema for the `parameters` field
        openAPIV3Schema:
          properties:
            min:
              type: integer
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8sminreplicas
        violation[{"msg": msg, "details": {"missing_replicas": missing}}] {
          provided := input.review.object.spec.replicas
          required := input.parameters.min
          missing := required - provided
          missing > 0
          msg := sprintf("you must provide %v more replicas", [missing])
        }

kubectl apply コマンドで k8sminreplicas.yaml を適用すると,新しく CRD として k8sminreplicas.constraints.gatekeeper.sh が追加された.準備 OK👌

$ kubectl apply -f k8sminreplicas.yaml
constrainttemplate.templates.gatekeeper.sh/k8sminreplicas created

$ kubectl get crds
NAME                                                 CREATED AT
configs.config.gatekeeper.sh                         2021-08-02T05:00:00Z
constraintpodstatuses.status.gatekeeper.sh           2021-08-02T05:00:00Z
constrainttemplatepodstatuses.status.gatekeeper.sh   2021-08-02T05:00:00Z
constrainttemplates.templates.gatekeeper.sh          2021-08-02T05:00:00Z
k8sminreplicas.constraints.gatekeeper.sh             2021-08-02T05:10:00Z

Deploymet で「レプリカ最低個数」を試す

Deploymet「レプリカ最低個数」の制限を試す.以下のように K8sMinReplicas でマニフェストを作る.Rego で実装した通り parameters.min に最低個数 2 を設定している.よって spec.replicas = 1 だとエラーになる.

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sMinReplicas
metadata:
  name: deployment-must-have-min-replicas
spec:
  match:
    kinds:
      - apiGroups: ["apps"]
        kinds: ["Deployment"]
  parameters:
    min: 2

実際に deployment-must-have-min-replicas.yaml を適用する.

$ kubectl apply -f deployment-must-have-min-replicas.yaml
k8sminreplicas.constraints.gatekeeper.sh/deployment-must-have-min-replicas created

さっそく以下の2種類のマニフェストを適用する.

  • 🆖 my-nginx1.yaml ... spec.replicas = 1
  • 🆗 my-nginx2.yaml ... spec.replicas = 2

📁 my-nginx1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine

📁 my-nginx2.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-nginx
  template:
    metadata:
      labels:
        app: my-nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.21-alpine

結果として my-nginx1.yaml「レプリカ最低個数」の制限でエラーになる.violation に設定した you must provide 1 more replicas というエラーも出ている.

$ kubectl apply -f my-nginx1.yaml
Error from server ([deployment-must-have-min-replicas] you must provide 1 more replicas): error when creating "nginx.yaml": admission webhook "validation.gatekeeper.sh" denied the request: [deployment-must-have-min-replicas] you must provide 1 more replicas

$ kubectl apply -f my-nginx2.yaml
deployment.apps/my-nginx created

まとめ

前回に引き続き OPA (Open Policy Agent) を試した.Deploymentspec.replicas に対して「最低個数」を制限できるようにした.実践的に使えそうなポリシーだと思う.現状まだ Rego をスラスラと書くことができず,サンプルなどをコピーしているため,より複雑なポリシーなどを書けるように勉強を続けていくぞ!