Skip to content

Admission webhook should enforce valid resources definition #2661

Closed

Description

@jarom-pdk

If a user accidentally defines their resources such that the request is greater than the limit the operator will accept the cluster definition but will not be able to start the pod. Ideally the configuration would be rejected as it is in other cases such as when no storage size has been configured.

Invalid Config:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cnpg-issue-resources
spec:
  description: "Fails to Create Pod for Cluster"
  imageName: ghcr.io/cloudnative-pg/postgresql:15.3
  instances: 1

  storage:
    storageClass: standard
    size: 1Gi

  resources:
    requests:
      cpu: 50m
      memory: 256Mi
    limits:
      cpu: 75m
      memory: 128Mi

The above configuration incorrectly has a greater memory request than what the limits allow. When applied to my cluster: kubectl apply -f cnpg-issue-resources.yaml you will get a message indicating the cluster is created: cluster.postgresql.cnpg.io/cnpg-issue-resources created. Watching the logs in the operator we see the message for the job creation Creating new Job, the next message logged is an error Unable to create job.

CNPG is left with a cluster in an incomplete state which will never become available.

% kubectl get cluster cnpg-issue-resources
NAME                   AGE   INSTANCES   READY   STATUS               PRIMARY
cnpg-issue-resources   65m   1                   Setting up primary

The PVC created based on the cluster config manifest indicates it has been bound as well.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  annotations:
    cnpg.io/nodeSerial: "1"
    cnpg.io/operatorVersion: 1.20.2
    cnpg.io/pvcStatus: initializing
    pv.kubernetes.io/bind-completed: "yes"
    pv.kubernetes.io/bound-by-controller: "yes"
    volume.beta.kubernetes.io/storage-provisioner: pd.csi.storage.gke.io
    volume.kubernetes.io/storage-provisioner: pd.csi.storage.gke.io
  creationTimestamp: "2023-08-31T22:15:27Z"

Logs from the operator:

cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:14:52Z","logger":"cluster-resource","msg":"default","version":"v1","name":"cnpg-issue-resources","namespace":"test"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:14:52Z","logger":"cluster-resource","msg":"validate create","version":"v1","name":"cnpg-issue-resources","namespace":"test"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:15:27Z","logger":"cluster-resource","msg":"default","version":"v1","name":"cnpg-issue-resources","namespace":"test"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:15:27Z","logger":"cluster-resource","msg":"validate create","version":"v1","name":"cnpg-issue-resources","namespace":"test"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:15:27Z","msg":"no orphan PVCs found, skipping the restored cluster reconciliation","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name":"cnpg-issue-resources","namespace":"test"},"namespace":"test","name":"cnpg-issue-resources","reconcileID":"ac13adfc-1c0e-4914-b3d5-e3bece9b4871","uuid":"e3769c8b-484b-11ee-a5f3-72d6aa6f68c1"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:15:27Z","msg":"Creating new Job","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name":"cnpg-issue-resources","namespace":"test"},"namespace":"test","name":"cnpg-issue-resources","reconcileID":"ac13adfc-1c0e-4914-b3d5-e3bece9b4871","uuid":"e3769c8b-484b-11ee-a5f3-72d6aa6f68c1","name":"cnpg-issue-resources-1-initdb","primary":true}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"error","ts":"2023-08-31T22:15:27Z","msg":"Unable to create job","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name":"cnpg-issue-resources","namespace":"test"},"namespace":"test","name":"cnpg-issue-resources","reconcileID":"ac13adfc-1c0e-4914-b3d5-e3bece9b4871","uuid":"e3769c8b-484b-11ee-a5f3-72d6aa6f68c1","job":{"namespace":"test","name":"cnpg-issue-resources-1-initdb"},"error":"Job.batch \"cnpg-issue-resources-1-initdb\" is invalid: [spec.template.spec.containers[0].resources.requests: Invalid value: \"256Mi\": must be less than or equal to memory limit, spec.template.spec.initContainers[0].resources.requests: Invalid value: \"256Mi\": must be less than or equal to memory limit]","stacktrace":"github.com/cloudnative-pg/cloudnative-pg/pkg/management/log.(*logger).Error\n\tpkg/management/log/log.go:128\ngithub.com/cloudnative-pg/cloudnative-pg/controllers.(*ClusterReconciler).createPrimaryInstance\n\tcontrollers/cluster_create.go:1004\ngithub.com/cloudnative-pg/cloudnative-pg/controllers.(*ClusterReconciler).ReconcilePods\n\tcontrollers/cluster_controller.go:645\ngithub.com/cloudnative-pg/cloudnative-pg/controllers.(*ClusterReconciler).reconcileResources\n\tcontrollers/cluster_controller.go:499\ngithub.com/cloudnative-pg/cloudnative-pg/controllers.(*ClusterReconciler).reconcile\n\tcontrollers/cluster_controller.go:335\ngithub.com/cloudnative-pg/cloudnative-pg/controllers.(*ClusterReconciler).Reconcile\n\tcontrollers/cluster_controller.go:145\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Reconcile\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:118\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:314\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:265\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:226"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"error","ts":"2023-08-31T22:15:27Z","msg":"Reconciler error","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name":"cnpg-issue-resources","namespace":"test"},"namespace":"test","name":"cnpg-issue-resources","reconcileID":"ac13adfc-1c0e-4914-b3d5-e3bece9b4871","error":"Job.batch \"cnpg-issue-resources-1-initdb\" is invalid: [spec.template.spec.containers[0].resources.requests: Invalid value: \"256Mi\": must be less than or equal to memory limit, spec.template.spec.initContainers[0].resources.requests: Invalid value: \"256Mi\": must be less than or equal to memory limit]","stacktrace":"sigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).reconcileHandler\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:324\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).processNextWorkItem\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:265\nsigs.k8s.io/controller-runtime/pkg/internal/controller.(*Controller).Start.func2.2\n\tpkg/mod/sigs.k8s.io/[email protected]/pkg/internal/controller/controller.go:226"}
cnpg-cloudnative-pg-7dd9bf9949-r9694 manager {"level":"info","ts":"2023-08-31T22:15:27Z","msg":"Selected PVC is not ready yet, waiting for 1 second","controller":"cluster","controllerGroup":"postgresql.cnpg.io","controllerKind":"Cluster","Cluster":{"name":"cnpg-issue-resources","namespace":"test"},"namespace":"test","name":"cnpg-issue-resources","reconcileID":"4af56e5f-728c-472d-b4c3-89d313cc01e1","uuid":"e39f7e1b-484b-11ee-a5f3-72d6aa6f68c1","pvc":"cnpg-issue-resources-1","status":"initializing","instance":"cnpg-issue-resources-1"}

The final log message from above which states Selected PVC is not ready yet, waiting for 1 second will repeat indefinitely. The only realistic option is to delete the cluster. Fixing the error in the original YAML and applying it again leaves the cluster in an unready state permanently.

Activity

  1. phisco commented on Sep 1, 2023

    @phisco
    Contributor

    Hi, that would definitely be nice, however the only way I can see atm to do so would be to render generated resources and dry run apply them from the webhook, which is something we currently tried avoiding in order to not cause requests amplification. However, such errors should be definitely surfaced to the user both as events and via the Cluster status, isn't that the case?

  2. assigned and unassigned on Sep 1, 2023
  3. added 2 commits that reference this issue on Sep 5, 2023
    0f4edb2
    17da9ca
  4. added a commit that references this issue on Sep 6, 2023
    bdd0656
  5. added 2 commits that reference this issue on Sep 6, 2023
    790129c
    9fce5a3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions