add toggle to disable creation of CRD validation and document it
This commit is contained in:
parent
9e222bf90c
commit
c4889a3c82
|
|
@ -54,6 +54,7 @@ spec:
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
version: v1
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -364,7 +365,6 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
subPath:
|
subPath:
|
||||||
type: string
|
type: string
|
||||||
version: v1
|
|
||||||
---
|
---
|
||||||
apiVersion: apiextensions.k8s.io/v1beta1
|
apiVersion: apiextensions.k8s.io/v1beta1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
|
|
@ -409,6 +409,7 @@ spec:
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
version: v1
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -657,5 +658,4 @@ spec:
|
||||||
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
scalyr_server_url:
|
scalyr_server_url:
|
||||||
type: string
|
type: string
|
||||||
version: v1
|
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ configTarget: "OperatorConfigurationCRD"
|
||||||
|
|
||||||
# general top-level configuration parameters
|
# general top-level configuration parameters
|
||||||
configGeneral:
|
configGeneral:
|
||||||
|
# choose if deployment creates/updates CRDs with OpenAPIV3Validation
|
||||||
|
enable_crd_validation: true
|
||||||
# start any new database pod without limitations on shm memory
|
# start any new database pod without limitations on shm memory
|
||||||
enable_shm_volume: true
|
enable_shm_volume: true
|
||||||
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ configTarget: "ConfigMap"
|
||||||
|
|
||||||
# general configuration parameters
|
# general configuration parameters
|
||||||
configGeneral:
|
configGeneral:
|
||||||
|
# choose if deployment creates/updates CRDs with OpenAPIV3Validation
|
||||||
|
enable_crd_validation: "true"
|
||||||
# start any new database pod without limitations on shm memory
|
# start any new database pod without limitations on shm memory
|
||||||
enable_shm_volume: "true"
|
enable_shm_volume: "true"
|
||||||
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
# etcd connection string for Patroni. Empty uses K8s-native DCS.
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,30 @@
|
||||||
Learn how to configure and manage the Postgres Operator in your Kubernetes (K8s)
|
Learn how to configure and manage the Postgres Operator in your Kubernetes (K8s)
|
||||||
environment.
|
environment.
|
||||||
|
|
||||||
|
## CRD Validation
|
||||||
|
|
||||||
|
[CustomResourceDefinitions](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/#customresourcedefinitions)
|
||||||
|
will be registered with schema validation by default when the operator is
|
||||||
|
deployed. The `OperatorConfiguration` CRD will only get created if the
|
||||||
|
`POSTGRES_OPERATOR_CONFIGURATION_OBJECT` [environment variable](../manifests/postgres-operator.yaml#L36)
|
||||||
|
in the deployment yaml is set and not empty.
|
||||||
|
|
||||||
|
When submitting manifests of [`postgresql`](../manifests/postgresql.crd.yaml) or
|
||||||
|
[`OperatorConfiguration`](../manifests/operatorconfiguration.crd.yaml) custom
|
||||||
|
resources with kubectl, validation can be bypassed with `--validate=false`. The
|
||||||
|
operator can also be configured to not register CRDs with validation on `ADD` or
|
||||||
|
`UPDATE` events. Running instances are not affected when enabling the validation
|
||||||
|
afterwards unless the manifests is not changed then. Note, that the provided CRD
|
||||||
|
manifests contain the validation for users to understand what schema is
|
||||||
|
enforced.
|
||||||
|
|
||||||
|
Once the validation is enabled it can only be disabled manually by editing or
|
||||||
|
patching the CRD manifest:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}'
|
||||||
|
```
|
||||||
|
|
||||||
## Namespaces
|
## Namespaces
|
||||||
|
|
||||||
### Select the namespace to deploy to
|
### Select the namespace to deploy to
|
||||||
|
|
|
||||||
|
|
@ -119,15 +119,15 @@ kubectl get pod -l app.kubernetes.io/name=postgres-operator
|
||||||
kubectl create -f manifests/minimal-postgres-manifest.yaml
|
kubectl create -f manifests/minimal-postgres-manifest.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
After the cluster manifest is submitted the operator will create Service and
|
After the cluster manifest is submitted and passed the validation the operator
|
||||||
Endpoint resources and a StatefulSet which spins up new Pod(s) given the number
|
will create Service and Endpoint resources and a StatefulSet which spins up new
|
||||||
of instances specified in the manifest. All resources are named like the
|
Pod(s) given the number of instances specified in the manifest. All resources
|
||||||
cluster. The database pods can be identified by their number suffix, starting
|
are named like the cluster. The database pods can be identified by their number
|
||||||
from `-0`. They run the [Spilo](https://github.com/zalando/spilo) container
|
suffix, starting from `-0`. They run the [Spilo](https://github.com/zalando/spilo)
|
||||||
image by Zalando. As for the services and endpoints, there will be one for the
|
container image by Zalando. As for the services and endpoints, there will be one
|
||||||
master pod and another one for all the replicas (`-repl` suffix). Check if all
|
for the master pod and another one for all the replicas (`-repl` suffix). Check
|
||||||
components are coming up. Use the label `application=spilo` to filter and list
|
if all components are coming up. Use the label `application=spilo` to filter and
|
||||||
the label `spilo-role` to see who is currently the master.
|
list the label `spilo-role` to see who is currently the master.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# check the deployed cluster
|
# check the deployed cluster
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,11 @@ Variable names are underscore-separated words.
|
||||||
|
|
||||||
Those are top-level keys, containing both leaf keys and groups.
|
Those are top-level keys, containing both leaf keys and groups.
|
||||||
|
|
||||||
|
* **enable_crd_validation**
|
||||||
|
toggles if the operator will create or update CRDs with
|
||||||
|
[OpenAPI v3 schema validation](https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/#validation)
|
||||||
|
The default is `true`.
|
||||||
|
|
||||||
* **etcd_host**
|
* **etcd_host**
|
||||||
Etcd connection string for Patroni defined as `host:port`. Not required when
|
Etcd connection string for Patroni defined as `host:port`. Not required when
|
||||||
Patroni native Kubernetes support is used. The default is empty (use
|
Patroni native Kubernetes support is used. The default is empty (use
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ data:
|
||||||
# default_memory_request: 100Mi
|
# default_memory_request: 100Mi
|
||||||
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
||||||
# enable_admin_role_for_users: "true"
|
# enable_admin_role_for_users: "true"
|
||||||
|
# enable_crd_validation: "true"
|
||||||
# enable_database_access: "true"
|
# enable_database_access: "true"
|
||||||
enable_master_load_balancer: "false"
|
enable_master_load_balancer: "false"
|
||||||
# enable_pod_antiaffinity: "false"
|
# enable_pod_antiaffinity: "false"
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ spec:
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
version: v1
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -262,5 +263,3 @@ spec:
|
||||||
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
pattern: '^(\d+(e\d+)?|\d+(\.\d+)?(e\d+)?[EPTGMK]i?)$'
|
||||||
scalyr_server_url:
|
scalyr_server_url:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
version: v1
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ kind: OperatorConfiguration
|
||||||
metadata:
|
metadata:
|
||||||
name: postgresql-operator-default-configuration
|
name: postgresql-operator-default-configuration
|
||||||
configuration:
|
configuration:
|
||||||
|
# enable_crd_validation: true
|
||||||
etcd_host: ""
|
etcd_host: ""
|
||||||
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
docker_image: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
|
||||||
# enable_shm_volume: true
|
# enable_shm_volume: true
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ spec:
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
subresources:
|
subresources:
|
||||||
status: {}
|
status: {}
|
||||||
|
version: v1
|
||||||
validation:
|
validation:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
type: object
|
type: object
|
||||||
|
|
@ -324,5 +325,3 @@ spec:
|
||||||
type: string
|
type: string
|
||||||
subPath:
|
subPath:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
version: v1
|
|
||||||
|
|
|
||||||
|
|
@ -108,7 +108,8 @@ var min1 = 1.0
|
||||||
var minDisable = -1.0
|
var minDisable = -1.0
|
||||||
|
|
||||||
// PostgresCRDResourceValidation to check applied manifest parameters
|
// PostgresCRDResourceValidation to check applied manifest parameters
|
||||||
var PostgresCRDResourceValidation = apiextv1beta1.JSONSchemaProps{
|
var PostgresCRDResourceValidation = apiextv1beta1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Required: []string{"kind", "apiVersion", "spec"},
|
Required: []string{"kind", "apiVersion", "spec"},
|
||||||
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
|
@ -578,10 +579,12 @@ var PostgresCRDResourceValidation = apiextv1beta1.JSONSchemaProps{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// OperatorConfigCRDResourceValidation to check applied manifest parameters
|
// OperatorConfigCRDResourceValidation to check applied manifest parameters
|
||||||
var OperatorConfigCRDResourceValidation = apiextv1beta1.JSONSchemaProps{
|
var OperatorConfigCRDResourceValidation = apiextv1beta1.CustomResourceValidation{
|
||||||
|
OpenAPIV3Schema: &apiextv1beta1.JSONSchemaProps{
|
||||||
Type: "object",
|
Type: "object",
|
||||||
Required: []string{"kind", "apiVersion", "configuration"},
|
Required: []string{"kind", "apiVersion", "configuration"},
|
||||||
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
Properties: map[string]apiextv1beta1.JSONSchemaProps{
|
||||||
|
|
@ -975,9 +978,10 @@ var OperatorConfigCRDResourceValidation = apiextv1beta1.JSONSchemaProps{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition, validationSchema apiextv1beta1.JSONSchemaProps) *apiextv1beta1.CustomResourceDefinition {
|
func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomResourceColumnDefinition, validation apiextv1beta1.CustomResourceValidation) *apiextv1beta1.CustomResourceDefinition {
|
||||||
return &apiextv1beta1.CustomResourceDefinition{
|
return &apiextv1beta1.CustomResourceDefinition{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
|
|
@ -995,29 +999,39 @@ func buildCRD(name, kind, plural, short string, columns []apiextv1beta1.CustomRe
|
||||||
Status: &apiextv1beta1.CustomResourceSubresourceStatus{},
|
Status: &apiextv1beta1.CustomResourceSubresourceStatus{},
|
||||||
},
|
},
|
||||||
AdditionalPrinterColumns: columns,
|
AdditionalPrinterColumns: columns,
|
||||||
Validation: &apiextv1beta1.CustomResourceValidation{
|
Validation: &validation,
|
||||||
OpenAPIV3Schema: &validationSchema,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostgresCRD returns CustomResourceDefinition built from PostgresCRDResource
|
// PostgresCRD returns CustomResourceDefinition built from PostgresCRDResource
|
||||||
func PostgresCRD() *apiextv1beta1.CustomResourceDefinition {
|
func PostgresCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition {
|
||||||
|
postgresCRDvalidation := apiextv1beta1.CustomResourceValidation{}
|
||||||
|
|
||||||
|
if enableValidation != nil && *enableValidation {
|
||||||
|
postgresCRDvalidation = PostgresCRDResourceValidation
|
||||||
|
}
|
||||||
|
|
||||||
return buildCRD(PostgresCRDResouceName,
|
return buildCRD(PostgresCRDResouceName,
|
||||||
PostgresCRDResourceKind,
|
PostgresCRDResourceKind,
|
||||||
PostgresCRDResourcePlural,
|
PostgresCRDResourcePlural,
|
||||||
PostgresCRDResourceShort,
|
PostgresCRDResourceShort,
|
||||||
PostgresCRDResourceColumns,
|
PostgresCRDResourceColumns,
|
||||||
PostgresCRDResourceValidation)
|
postgresCRDvalidation)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource
|
// ConfigurationCRD returns CustomResourceDefinition built from OperatorConfigCRDResource
|
||||||
func ConfigurationCRD() *apiextv1beta1.CustomResourceDefinition {
|
func ConfigurationCRD(enableValidation *bool) *apiextv1beta1.CustomResourceDefinition {
|
||||||
|
opconfigCRDvalidation := apiextv1beta1.CustomResourceValidation{}
|
||||||
|
|
||||||
|
if enableValidation != nil && *enableValidation {
|
||||||
|
opconfigCRDvalidation = OperatorConfigCRDResourceValidation
|
||||||
|
}
|
||||||
|
|
||||||
return buildCRD(OperatorConfigCRDResourceName,
|
return buildCRD(OperatorConfigCRDResourceName,
|
||||||
OperatorConfigCRDResouceKind,
|
OperatorConfigCRDResouceKind,
|
||||||
OperatorConfigCRDResourcePlural,
|
OperatorConfigCRDResourcePlural,
|
||||||
OperatorConfigCRDResourceShort,
|
OperatorConfigCRDResourceShort,
|
||||||
OperatorConfigCRDResourceColumns,
|
OperatorConfigCRDResourceColumns,
|
||||||
OperatorConfigCRDResourceValidation)
|
opconfigCRDvalidation)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,7 @@ type ScalyrConfiguration struct {
|
||||||
|
|
||||||
// OperatorConfigurationData defines the operation config
|
// OperatorConfigurationData defines the operation config
|
||||||
type OperatorConfigurationData struct {
|
type OperatorConfigurationData struct {
|
||||||
|
EnableCRDValidation *bool `json:"enable_crd_validation,omitempty"`
|
||||||
EtcdHost string `json:"etcd_host,omitempty"`
|
EtcdHost string `json:"etcd_host,omitempty"`
|
||||||
DockerImage string `json:"docker_image,omitempty"`
|
DockerImage string `json:"docker_image,omitempty"`
|
||||||
Workers uint32 `json:"workers,omitempty"`
|
Workers uint32 `json:"workers,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
|
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
@ -240,7 +240,7 @@ func (c *Controller) initController() {
|
||||||
c.initClients()
|
c.initClients()
|
||||||
|
|
||||||
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
||||||
if err := c.createConfigurationCRD(); err != nil {
|
if err := c.createConfigurationCRD(c.opConfig.EnableCRDValidation); err != nil {
|
||||||
c.logger.Fatalf("could not register Operator Configuration CustomResourceDefinition: %v", err)
|
c.logger.Fatalf("could not register Operator Configuration CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
if cfg, err := c.readOperatorConfigurationFromCRD(spec.GetOperatorNamespace(), configObjectName); err != nil {
|
if cfg, err := c.readOperatorConfigurationFromCRD(spec.GetOperatorNamespace(), configObjectName); err != nil {
|
||||||
|
|
@ -256,7 +256,7 @@ func (c *Controller) initController() {
|
||||||
|
|
||||||
c.modifyConfigFromEnvironment()
|
c.modifyConfigFromEnvironment()
|
||||||
|
|
||||||
if err := c.createPostgresCRD(); err != nil {
|
if err := c.createPostgresCRD(c.opConfig.EnableCRDValidation); err != nil {
|
||||||
c.logger.Fatalf("could not register Postgres CustomResourceDefinition: %v", err)
|
c.logger.Fatalf("could not register Postgres CustomResourceDefinition: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result := &config.Config{}
|
result := &config.Config{}
|
||||||
|
|
||||||
// general config
|
// general config
|
||||||
|
result.EnableCRDValidation = fromCRD.EnableCRDValidation
|
||||||
result.EtcdHost = fromCRD.EtcdHost
|
result.EtcdHost = fromCRD.EtcdHost
|
||||||
result.DockerImage = fromCRD.DockerImage
|
result.DockerImage = fromCRD.DockerImage
|
||||||
result.Workers = fromCRD.Workers
|
result.Workers = fromCRD.Workers
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
|
@ -91,12 +91,12 @@ func (c *Controller) createOperatorCRD(crd *apiextv1beta1.CustomResourceDefiniti
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) createPostgresCRD() error {
|
func (c *Controller) createPostgresCRD(enableValidation *bool) error {
|
||||||
return c.createOperatorCRD(acidv1.PostgresCRD())
|
return c.createOperatorCRD(acidv1.PostgresCRD(enableValidation))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) createConfigurationCRD() error {
|
func (c *Controller) createConfigurationCRD(enableValidation *bool) error {
|
||||||
return c.createOperatorCRD(acidv1.ConfigurationCRD())
|
return c.createOperatorCRD(acidv1.ConfigurationCRD(enableValidation))
|
||||||
}
|
}
|
||||||
|
|
||||||
func readDecodedRole(s string) (*spec.PgUser, error) {
|
func readDecodedRole(s string) (*spec.PgUser, error) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type CRD struct {
|
||||||
ReadyWaitTimeout time.Duration `name:"ready_wait_timeout" default:"30s"`
|
ReadyWaitTimeout time.Duration `name:"ready_wait_timeout" default:"30s"`
|
||||||
ResyncPeriod time.Duration `name:"resync_period" default:"30m"`
|
ResyncPeriod time.Duration `name:"resync_period" default:"30m"`
|
||||||
RepairPeriod time.Duration `name:"repair_period" default:"5m"`
|
RepairPeriod time.Duration `name:"repair_period" default:"5m"`
|
||||||
|
EnableCRDValidation *bool `name:"enable_crd_validation" default:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resources describes kubernetes resource specific configuration parameters
|
// Resources describes kubernetes resource specific configuration parameters
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue