From aa34a066f98b1e8492d641dcf7e85f4cd218e0ba Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Tue, 31 Jan 2023 19:04:23 +0530 Subject: [PATCH 01/16] Added postgres-operator Signed-off-by: MdSahil-oss --- .../addons/postgres-operator/README.md | 3 ++ .../addons/postgres-operator/metadata.yaml | 10 ++++ .../addons/postgres-operator/parameter.cue | 11 ++++ .../addons/postgres-operator/template.cue | 52 +++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 experimental/addons/postgres-operator/README.md create mode 100644 experimental/addons/postgres-operator/metadata.yaml create mode 100644 experimental/addons/postgres-operator/parameter.cue create mode 100644 experimental/addons/postgres-operator/template.cue diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md new file mode 100644 index 00000000..5eedb52f --- /dev/null +++ b/experimental/addons/postgres-operator/README.md @@ -0,0 +1,3 @@ +# postgres-operator + +This is an addon template. Check how to build your own addon: https://kubevela.net/docs/platform-engineers/addon/intro diff --git a/experimental/addons/postgres-operator/metadata.yaml b/experimental/addons/postgres-operator/metadata.yaml new file mode 100644 index 00000000..f90114ae --- /dev/null +++ b/experimental/addons/postgres-operator/metadata.yaml @@ -0,0 +1,10 @@ +name: postgres-operator +version: 1.0.0 +description: This addon adds postgres-operator to the kubevela to be used by across the application installed in kubevela. +icon: "" +url: "https://www.postgresql.org/" + +tags: +- postgres-operator + +invisible: false diff --git a/experimental/addons/postgres-operator/parameter.cue b/experimental/addons/postgres-operator/parameter.cue new file mode 100644 index 00000000..9ff20518 --- /dev/null +++ b/experimental/addons/postgres-operator/parameter.cue @@ -0,0 +1,11 @@ +// parameter.cue is used to store addon parameters. +// +// You can use these parameters in template.cue or in resources/ by 'parameter.myparam' +// +// For example, you can use parameters to allow the user to customize +// container images, ports, and etc. +parameter: { + // +usage=Custom parameter description + namespace: *"postgres-operator" | string + clusters?: [...string] +} diff --git a/experimental/addons/postgres-operator/template.cue b/experimental/addons/postgres-operator/template.cue new file mode 100644 index 00000000..491f0a0f --- /dev/null +++ b/experimental/addons/postgres-operator/template.cue @@ -0,0 +1,52 @@ +package main + +output: { + apiVersion: "core.oam.dev/v1beta1" + kind: "Application" + spec: { + components: [ + { + name: "ns-postgres-operator" + type: "k8s-objects" + properties: objects: [{ + kind: "Namespace" + apiVersion: "v1" + metadata: + name: "postgres-operator" + }] + }, + { + name: "postgres-operator" + type: "helm" + properties: { + repoType: "helm" + url: "https://opensource.zalando.com/postgres-operator/charts/postgres-operator" + chart: "postgres-operator-charts/postgres-operator" + version: "1.8.2" + } + }, + ] + policies: [ + { + type: "shared-resource" + name: "postgres-operator-ns" + properties: rules: [{ + selector: resourceTypes: ["Namespace"] + }] + }, + { + type: "topology" + name: "deploy-postgres-operator" + properties: { + namespace: parameter.namespace + if parameter.clusters != _|_ { + clusters: parameter.clusters + } + if parameter.clusters == _|_ { + clusterLabelSelector: {} + } + } + }, + ] + } +} From 45777908127407af68b170cb56bfabd4275081d2 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Wed, 1 Feb 2023 13:28:07 +0530 Subject: [PATCH 02/16] Updated helm chart version and chart name Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/template.cue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/experimental/addons/postgres-operator/template.cue b/experimental/addons/postgres-operator/template.cue index 491f0a0f..678e0e3d 100644 --- a/experimental/addons/postgres-operator/template.cue +++ b/experimental/addons/postgres-operator/template.cue @@ -21,8 +21,8 @@ output: { properties: { repoType: "helm" url: "https://opensource.zalando.com/postgres-operator/charts/postgres-operator" - chart: "postgres-operator-charts/postgres-operator" - version: "1.8.2" + chart: "postgres-operator" + version: "1.9.0" } }, ] From 0a4377e104cb7efbf8b215097b46ea01a4385c97 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Wed, 1 Feb 2023 13:46:47 +0530 Subject: [PATCH 03/16] made fluxcd as dependency Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/metadata.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/experimental/addons/postgres-operator/metadata.yaml b/experimental/addons/postgres-operator/metadata.yaml index f90114ae..ad87f6fd 100644 --- a/experimental/addons/postgres-operator/metadata.yaml +++ b/experimental/addons/postgres-operator/metadata.yaml @@ -8,3 +8,6 @@ tags: - postgres-operator invisible: false + +dependencies: + - name: fluxcd \ No newline at end of file From 902942500394bdb3ccb370f8e09418e59c6ba0cd Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Wed, 1 Feb 2023 14:03:39 +0530 Subject: [PATCH 04/16] Added additional line in metadata.yaml Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/addons/postgres-operator/metadata.yaml b/experimental/addons/postgres-operator/metadata.yaml index ad87f6fd..5cac4c1f 100644 --- a/experimental/addons/postgres-operator/metadata.yaml +++ b/experimental/addons/postgres-operator/metadata.yaml @@ -10,4 +10,4 @@ tags: invisible: false dependencies: - - name: fluxcd \ No newline at end of file + - name: fluxcd From 6235e1652dee828f41e2ca202f454d697167acda Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Wed, 1 Feb 2023 23:08:05 +0530 Subject: [PATCH 05/16] Added definition of postgres-operator Signed-off-by: MdSahil-oss --- .../definitions/postgres-cluster.cue | 181 ++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 experimental/addons/postgres-operator/definitions/postgres-cluster.cue diff --git a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue new file mode 100644 index 00000000..1b3b99c5 --- /dev/null +++ b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue @@ -0,0 +1,181 @@ +"postgres-cluster": { + alias: "" + annotations: {} + attributes: workload: type: "autodetects.core.oam.dev" + description: "postgres cluster component" + labels: {} + type: "component" +} + +template: { + output: { + apiVersion: "v1" + kind: "Secret" + metadata: { + name: context.name //"mongodb-secret" + namespace: "postgres-operator" //"default" + } + stringData: password: parameter.password //"abc123456" + type: "Opaque" + } + outputs: postgres: { + apiVersion: "acid.zalan.do/v1" + kind: "postgresql" + metadata: { + name: context.name //"mongodb" + namespace: context.namespace //"default" + } + spec: { + dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 + numberOfInstances: parameter.replicas //2 + teamId: parameter.teamId + postgresql: parameter.postgresql + databases: { + foo: "zalando" + } + preparedDatabases: { + bar: { + defaultUsers: true + extensions: { + pg_partman: "public" + pgcrypto: "public" + } + schemas: { + data: {} + history: { + defaultRoles: true + defaultUsers: false + } + } + } + } + users: { // Application/Robot users + zalando: ["superuser", "createdb"] + foo_user: [] + } + enableMasterLoadBalancer: parameter.enableMasterLoadBalancer + enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer + enableConnectionPooler: parameter.enableConnectionPooler + enableReplicaConnectionPooler: parameter.enableReplicaConnectionPooler + enableMasterPoolerLoadBalancer: parameter.enableMasterPoolerLoadBalancer + enableReplicaPoolerLoadBalancer: parameter.enableReplicaPoolerLoadBalancer + allowedSourceRanges: [ // load balancers' source ranges for both master and replica services + "127.0.0.1/32" + ] + volume: parameter.volume + additionalVolumes: [ + { + name: "empty" + mountPath: "/opt/empty" + targetContainers: [ + "all" + ] + volumeSource: { + emptyDir: {} + } + } + ] + enableShmVolume: parameter.enableShmVolume + resources: parameter.resources + patroni: parameter.patroni + ttl: parameter.ttl + loop_wait: parameter.loopWait + retry_timeout: parameter.retryTimeout + synchronous_mode: parameter.synchronousMode + synchronous_mode_strict: parameter.synchronousModeStrict + synchronous_node_count: parameter.synchronousNodeCount + maximum_lag_on_failover: 33554432 + initContainers: [ + { + name: "date" + image: "busybox" + command: [ "/bin/date" ] + } + ] + // Custom TLS certificate. Disabled unless tls.secretName has a value. + tls: parameter.tls + } + } + parameter: { + //+usage=configure postgresql. + postgresql: { + //+usage=the version of the postgresql to be used. + version: *"15" | string + parameters: { + // Expert section + shared_buffers: *"32MB" | string + max_connections: *"10" | string + log_statement: *"all" | string + } + } + //+usage=the size of the postgres cluster. + replicas: *2 | int + //+usage=set team Id. + teamId: *"acid" | string + //+usage=the image of the spilo. + image: *"ghcr.io/zalando/spilo-15:2.1-p9" | string + //+usage=configure volume. + volume: { + //+usage=the size of the volume used of postgres. + size: *"1Gi" | string + } + patroni: { + failsafe_mode: *false | bool + initdb: { + encoding: *"UTF8" | string + locale: *"en_US.UTF-8" | string + data-checksums: *"true" | string + } + } + //+usage=enable SHM volume if set true. + enableShmVolume: *true | bool + //+usage=enable master as load balancer if set true. + enableMasterLoadBalancer *false | bool + //+usage=enable replica as load balancer if set true. + enableReplicaLoadBalancer *false | bool + //+usage=enable/disable connection pooler deployment. + enableConnectionPooler *false | bool + //+usage=set to enable connection pooler for replica service. + enableReplicaConnectionPooler *false | bool + //+usage=set to enable master pooler as load balancer. + enableMasterPoolerLoadBalancer *false | bool + //+usage=set to enable replica pooler as load balancer. + enableReplicaPoolerLoadBalancer *false | bool + //+usage=set ttl(Time to live) by dedault it's 30 days. + ttl: *30 | int + //+usage=set loop wait time by dedault it's 10. + loopWait: *10 | int + //+usage=set retry timeout by dedault it's 10. + retryTimeout: *10 | int + //+usage=set to enable synchronous mode. + synchronousMode: *false | bool + //+usage=set to enable synchronous mode strictly. + synchronousModeStrict: *false | bool + //+usage=set how many nodes to be synchronized. + synchronousNodeCount: *1 | int + //+usage=configure resources. + resources: { + requests: { + cpu: *"10m" | string + memory: *"100Mi" | string + } + limits: { + cpu: *"500m" | string + memory: *"500Mi" | string + } + } + //+usage=configure custom TLS. + tls: { + //+usage=sets custom TLS secret name, It should correspond to a Kubernetes Secret resource to load. + secretName: *"" | string + //+usage=sets custom TLS certificate file. + certificateFile: *"tls.crt" | string + //+usage=sets custom TLS private key file. + privateKeyFile: *"tls.key" | string + //+usage=optionally configure Postgres with a CA certificate. + caFile: *"" | string + //+usage=optionally the ca.crt can come from this secret instead. + caSecretName: *"" | string + } + } +} From 8656296027600c8f5a962a7329576711a8fa715f Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 2 Feb 2023 16:16:13 +0530 Subject: [PATCH 06/16] removed redundant secret from the definition and some errors1 Signed-off-by: MdSahil-oss --- .../definitions/postgres-cluster.cue | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue index 1b3b99c5..c594f4ee 100644 --- a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue +++ b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue @@ -9,29 +9,19 @@ template: { output: { - apiVersion: "v1" - kind: "Secret" - metadata: { - name: context.name //"mongodb-secret" - namespace: "postgres-operator" //"default" - } - stringData: password: parameter.password //"abc123456" - type: "Opaque" - } - outputs: postgres: { - apiVersion: "acid.zalan.do/v1" kind: "postgresql" + apiVersion: "acid.zalan.do/v1" metadata: { - name: context.name //"mongodb" - namespace: context.namespace //"default" + name: context.name + // default namespace will be prod } spec: { dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 - numberOfInstances: parameter.replicas //2 + numberOfInstances: parameter.replicas //By default it's 2 teamId: parameter.teamId postgresql: parameter.postgresql databases: { - foo: "zalando" + foo: "zalando" // dbname: owner } preparedDatabases: { bar: { @@ -50,14 +40,14 @@ template: { } } users: { // Application/Robot users - zalando: ["superuser", "createdb"] - foo_user: [] + zalando: ["superuser", "createdb"] // database owner + foo_user: [] // role for application foo } enableMasterLoadBalancer: parameter.enableMasterLoadBalancer enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer enableConnectionPooler: parameter.enableConnectionPooler enableReplicaConnectionPooler: parameter.enableReplicaConnectionPooler - enableMasterPoolerLoadBalancer: parameter.enableMasterPoolerLoadBalancer + enableMasterPoolerLoadBalancer: parameter.enableReplicaConnectionPooler enableReplicaPoolerLoadBalancer: parameter.enableReplicaPoolerLoadBalancer allowedSourceRanges: [ // load balancers' source ranges for both master and replica services "127.0.0.1/32" @@ -119,28 +109,29 @@ template: { //+usage=the size of the volume used of postgres. size: *"1Gi" | string } + //+usage=configure patroni. patroni: { failsafe_mode: *false | bool initdb: { encoding: *"UTF8" | string locale: *"en_US.UTF-8" | string - data-checksums: *"true" | string + "data-checksums": *"true" | string } } //+usage=enable SHM volume if set true. enableShmVolume: *true | bool //+usage=enable master as load balancer if set true. - enableMasterLoadBalancer *false | bool + enableMasterLoadBalancer: *false | bool //+usage=enable replica as load balancer if set true. - enableReplicaLoadBalancer *false | bool + enableReplicaLoadBalancer: *false | bool //+usage=enable/disable connection pooler deployment. - enableConnectionPooler *false | bool + enableConnectionPooler: *false | bool //+usage=set to enable connection pooler for replica service. - enableReplicaConnectionPooler *false | bool + enableReplicaConnectionPooler: *false | bool //+usage=set to enable master pooler as load balancer. - enableMasterPoolerLoadBalancer *false | bool + enableMasterPoolerLoadBalancer: *false | bool //+usage=set to enable replica pooler as load balancer. - enableReplicaPoolerLoadBalancer *false | bool + enableReplicaPoolerLoadBalancer: *false | bool //+usage=set ttl(Time to live) by dedault it's 30 days. ttl: *30 | int //+usage=set loop wait time by dedault it's 10. From 5587915ed50fb5669733c764ea54309ce16471f1 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 2 Feb 2023 17:43:47 +0530 Subject: [PATCH 07/16] Made more attributes of postgres-operator as parameters Signed-off-by: MdSahil-oss --- .../definitions/postgres-cluster.cue | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue index c594f4ee..21753b15 100644 --- a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue +++ b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue @@ -13,36 +13,16 @@ template: { apiVersion: "acid.zalan.do/v1" metadata: { name: context.name - // default namespace will be prod + // default namespace will be "prod" } spec: { dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 numberOfInstances: parameter.replicas //By default it's 2 teamId: parameter.teamId postgresql: parameter.postgresql - databases: { - foo: "zalando" // dbname: owner - } - preparedDatabases: { - bar: { - defaultUsers: true - extensions: { - pg_partman: "public" - pgcrypto: "public" - } - schemas: { - data: {} - history: { - defaultRoles: true - defaultUsers: false - } - } - } - } - users: { // Application/Robot users - zalando: ["superuser", "createdb"] // database owner - foo_user: [] // role for application foo - } + databases: parameter.databases + preparedDatabases: parameter.preparedDatabases + users: parameter.users enableMasterLoadBalancer: parameter.enableMasterLoadBalancer enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer enableConnectionPooler: parameter.enableConnectionPooler @@ -109,6 +89,32 @@ template: { //+usage=the size of the volume used of postgres. size: *"1Gi" | string } + //+usage=define databases to be used. + databases: *{ + foo: "zalando" // dbname: owner + } | {...} + //+usage=configure created databases. + preparedDatabases: *{ + bar: { + defaultUsers: true + extensions: { + pg_partman: "public" + pgcrypto: "public" + } + schemas: { + data: {} + history: { + defaultRoles: true + defaultUsers: false + } + } + } + } | {...} + //+usage=configure users for the databases. + users: *{ + zalando: ["superuser", "createdb"] + foo_user: [] + } | {...} //+usage=configure patroni. patroni: { failsafe_mode: *false | bool From d5a2227330dded797be934304c40c3744333e86e Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 2 Feb 2023 19:50:18 +0530 Subject: [PATCH 08/16] Added postgres-operator exaple YAML in example folder Signed-off-by: MdSahil-oss --- examples/postgres-operator/demo.yaml | 66 ++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/postgres-operator/demo.yaml diff --git a/examples/postgres-operator/demo.yaml b/examples/postgres-operator/demo.yaml new file mode 100644 index 00000000..0be7be7f --- /dev/null +++ b/examples/postgres-operator/demo.yaml @@ -0,0 +1,66 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: postgres-operator-sample +spec: + components: + # This component is provided by postgres-operator addon. + # In this example, 3 redis instances(replicas) + # will be created. + - type: "postgres-cluster" + name: "postgres" + properties: + # You can increase/decrease this later to add/remove instances. + replicas: 3 # By default it's set to 2 + teamId: acid + image: "ghcr.io/zalando/spilo-15:2.1-p9" + volume: + size: 1Gi + databases: + foo: zalando + preparedDatabases: + bar: + defaultUsers: true + extensions: + pg_partman: public + pgcrypto: public + schemas: + data: {} + history: + defaultRoles: true + defaultUsers: false + users: + zalando: [superuser, createdb] + foo_user: [] + patroni: + failsafe_mode: false + initdb: + encoding: UTF8 + locale: en_US.UTF-8 + data-checksums: "true" + enableShmVolume: true + enableMasterLoadBalancer: false + enableReplicaLoadBalancer: false + enableConnectionPooler: false + enableReplicaConnectionPooler: false + enableMasterPoolerLoadBalancer: false + enableReplicaPoolerLoadBalancer: false + ttl: 30 + loopWait: 10 + retryTimeout: 10 + synchronousMode: false + synchronousModeStrict: false + synchronousNodeCount: 1 + resources: + requests: + cpu: 10m + memory: 100Mi + limits: + cpu: 500m + memory: 500Mi + tls: + secretName: "" + certificateFile: tls.crt + privateKeyFile: tls.key + caFile: "" + caSecretName: "" From 9691b8f2c7831ac811d340a30c2bfaf5e109028a Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 2 Feb 2023 22:04:27 +0530 Subject: [PATCH 09/16] Added README.md Signed-off-by: MdSahil-oss --- .../addons/postgres-operator/README.md | 77 +++++++++++++++++++ .../definitions/postgres-cluster.cue | 1 + 2 files changed, 78 insertions(+) diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index 5eedb52f..ad3c8c42 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -1,3 +1,80 @@ # postgres-operator This is an addon template. Check how to build your own addon: https://kubevela.net/docs/platform-engineers/addon/intro + +## Install + +Add experimental registry +``` +vela addon registry add experimental --type=helm --endpoint=https://addons.kubevela.net/experimental/ +``` + +Enable this addon +``` +vela addon enable postgres-operator +``` + +```shell +$ vela ls -A | grep postgres +vela-system addon-postgres-operator ns-postgres-operator k8s-objects running healthy +vela-system └─ postgres-operator helm running +healthy Fetch repository successfully, Create helm release +``` + +Disable this addon +``` +vela addon disable postgres-operator +``` + +## Use +## postgres-operator + +After you enable this addon, create a namespace `prod`: + +```shell +$ kubectl create namespace prod +``` + +Then apply this Application yaml to create a postgres cluster: + +```yaml +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: postgres-operator-sample +spec: + components: + - type: "postgres-cluster" + namespace: prod + name: postgres + properties: + replicas: 3 +``` + +```shell +$ kubectl get po -n prod -o wide +NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES +postgres-0 1/1 Running 0 2m30s 10.244.1.73 minikube +postgres-1 1/1 Running 0 2m20s 10.244.1.74 minikube +postgres-2 1/1 Running 0 105s 10.244.1.75 minikube +``` + +### Connect to PostgreSQL via psql + +With a port-forward on one of the database pods (e.g. the master) you can connect to the PostgreSQL database from your machine. Use labels to filter for the master pod of our test cluster. + +```shell +# get name of master pod of acid-minimal-cluster +export PGMASTER=$(kubectl get pods -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) + +# set up port forward +kubectl port-forward $PGMASTER 6432:5432 -n default +``` + +Open another CLI and connect to the database using e.g. the psql client. When connecting with a manifest role like foo_user user, read its password from the K8s secret which was generated when creating acid-minimal-cluster. As non-encrypted connections are rejected by default set SSL mode to require: + +```shell +export PGPASSWORD=$(kubectl get secret postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) +export PGSSLMODE=require +psql -U postgres -h localhost -p 6432 +``` diff --git a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue index 21753b15..9910d7d3 100644 --- a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue +++ b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue @@ -13,6 +13,7 @@ template: { apiVersion: "acid.zalan.do/v1" metadata: { name: context.name + namespace: context.namespace // default namespace will be "prod" } spec: { From d29932b94c83e731db5265f1778b500ec286a475 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 01:47:38 +0530 Subject: [PATCH 10/16] Added example Signed-off-by: MdSahil-oss --- .../demo-with-expose-trait.yaml | 17 + .../addons/postgres-operator/README.md | 8 +- .../definitions/postgres-cluster.cue | 348 +++++++++--------- .../definitions/traits/postgres-expose.cue | 37 ++ 4 files changed, 232 insertions(+), 178 deletions(-) create mode 100644 examples/postgres-operator/demo-with-expose-trait.yaml create mode 100644 experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue diff --git a/examples/postgres-operator/demo-with-expose-trait.yaml b/examples/postgres-operator/demo-with-expose-trait.yaml new file mode 100644 index 00000000..0954160c --- /dev/null +++ b/examples/postgres-operator/demo-with-expose-trait.yaml @@ -0,0 +1,17 @@ +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: postgres-operator-sample-with-postgres-expose-trait +spec: + components: + - type: "postgres-cluster" + name: "postgres" + namespace: "default" + properties: + replicas: 3 + traits: + - type: postgres-expose + properties: + type: NodePort + port: 5432 + targetPort: 5432 \ No newline at end of file diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index ad3c8c42..8c841ff5 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -65,16 +65,16 @@ With a port-forward on one of the database pods (e.g. the master) you can connec ```shell # get name of master pod of acid-minimal-cluster -export PGMASTER=$(kubectl get pods -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) +export PGMASTER=$(kubectl get pods -n prod -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) # set up port forward -kubectl port-forward $PGMASTER 6432:5432 -n default +kubectl port-forward $PGMASTER -n prod 5432:5432 -n default ``` Open another CLI and connect to the database using e.g. the psql client. When connecting with a manifest role like foo_user user, read its password from the K8s secret which was generated when creating acid-minimal-cluster. As non-encrypted connections are rejected by default set SSL mode to require: ```shell -export PGPASSWORD=$(kubectl get secret postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) +export PGPASSWORD=$(kubectl get secret -n prod postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) export PGSSLMODE=require -psql -U postgres -h localhost -p 6432 +psql -U postgres -h localhost -p 5432 ``` diff --git a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue index 9910d7d3..a33a0085 100644 --- a/experimental/addons/postgres-operator/definitions/postgres-cluster.cue +++ b/experimental/addons/postgres-operator/definitions/postgres-cluster.cue @@ -1,179 +1,179 @@ "postgres-cluster": { - alias: "" - annotations: {} - attributes: workload: type: "autodetects.core.oam.dev" - description: "postgres cluster component" - labels: {} - type: "component" + alias: "" + annotations: {} + attributes: workload: type: "autodetects.core.oam.dev" + description: "postgres cluster component" + labels: {} + type: "component" } template: { - output: { - kind: "postgresql" - apiVersion: "acid.zalan.do/v1" - metadata: { - name: context.name - namespace: context.namespace - // default namespace will be "prod" - } - spec: { - dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 - numberOfInstances: parameter.replicas //By default it's 2 - teamId: parameter.teamId - postgresql: parameter.postgresql - databases: parameter.databases - preparedDatabases: parameter.preparedDatabases - users: parameter.users - enableMasterLoadBalancer: parameter.enableMasterLoadBalancer - enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer - enableConnectionPooler: parameter.enableConnectionPooler - enableReplicaConnectionPooler: parameter.enableReplicaConnectionPooler - enableMasterPoolerLoadBalancer: parameter.enableReplicaConnectionPooler - enableReplicaPoolerLoadBalancer: parameter.enableReplicaPoolerLoadBalancer - allowedSourceRanges: [ // load balancers' source ranges for both master and replica services - "127.0.0.1/32" - ] - volume: parameter.volume - additionalVolumes: [ - { - name: "empty" - mountPath: "/opt/empty" - targetContainers: [ - "all" - ] - volumeSource: { - emptyDir: {} - } - } - ] - enableShmVolume: parameter.enableShmVolume - resources: parameter.resources - patroni: parameter.patroni - ttl: parameter.ttl - loop_wait: parameter.loopWait - retry_timeout: parameter.retryTimeout - synchronous_mode: parameter.synchronousMode - synchronous_mode_strict: parameter.synchronousModeStrict - synchronous_node_count: parameter.synchronousNodeCount - maximum_lag_on_failover: 33554432 - initContainers: [ - { - name: "date" - image: "busybox" - command: [ "/bin/date" ] - } - ] - // Custom TLS certificate. Disabled unless tls.secretName has a value. - tls: parameter.tls - } - } - parameter: { - //+usage=configure postgresql. - postgresql: { - //+usage=the version of the postgresql to be used. - version: *"15" | string - parameters: { - // Expert section - shared_buffers: *"32MB" | string - max_connections: *"10" | string - log_statement: *"all" | string - } - } - //+usage=the size of the postgres cluster. - replicas: *2 | int - //+usage=set team Id. - teamId: *"acid" | string - //+usage=the image of the spilo. - image: *"ghcr.io/zalando/spilo-15:2.1-p9" | string - //+usage=configure volume. - volume: { - //+usage=the size of the volume used of postgres. - size: *"1Gi" | string - } - //+usage=define databases to be used. - databases: *{ - foo: "zalando" // dbname: owner - } | {...} - //+usage=configure created databases. - preparedDatabases: *{ - bar: { - defaultUsers: true - extensions: { - pg_partman: "public" - pgcrypto: "public" - } - schemas: { - data: {} - history: { - defaultRoles: true - defaultUsers: false - } - } - } - } | {...} - //+usage=configure users for the databases. - users: *{ - zalando: ["superuser", "createdb"] - foo_user: [] - } | {...} - //+usage=configure patroni. - patroni: { - failsafe_mode: *false | bool - initdb: { - encoding: *"UTF8" | string - locale: *"en_US.UTF-8" | string - "data-checksums": *"true" | string - } - } - //+usage=enable SHM volume if set true. - enableShmVolume: *true | bool - //+usage=enable master as load balancer if set true. - enableMasterLoadBalancer: *false | bool - //+usage=enable replica as load balancer if set true. - enableReplicaLoadBalancer: *false | bool - //+usage=enable/disable connection pooler deployment. - enableConnectionPooler: *false | bool - //+usage=set to enable connection pooler for replica service. - enableReplicaConnectionPooler: *false | bool - //+usage=set to enable master pooler as load balancer. - enableMasterPoolerLoadBalancer: *false | bool - //+usage=set to enable replica pooler as load balancer. - enableReplicaPoolerLoadBalancer: *false | bool - //+usage=set ttl(Time to live) by dedault it's 30 days. - ttl: *30 | int - //+usage=set loop wait time by dedault it's 10. - loopWait: *10 | int - //+usage=set retry timeout by dedault it's 10. - retryTimeout: *10 | int - //+usage=set to enable synchronous mode. - synchronousMode: *false | bool - //+usage=set to enable synchronous mode strictly. - synchronousModeStrict: *false | bool - //+usage=set how many nodes to be synchronized. - synchronousNodeCount: *1 | int - //+usage=configure resources. - resources: { - requests: { - cpu: *"10m" | string - memory: *"100Mi" | string - } - limits: { - cpu: *"500m" | string - memory: *"500Mi" | string - } - } - //+usage=configure custom TLS. - tls: { - //+usage=sets custom TLS secret name, It should correspond to a Kubernetes Secret resource to load. - secretName: *"" | string - //+usage=sets custom TLS certificate file. - certificateFile: *"tls.crt" | string - //+usage=sets custom TLS private key file. - privateKeyFile: *"tls.key" | string - //+usage=optionally configure Postgres with a CA certificate. - caFile: *"" | string - //+usage=optionally the ca.crt can come from this secret instead. - caSecretName: *"" | string - } - } + output: { + kind: "postgresql" + apiVersion: "acid.zalan.do/v1" + metadata: { + name: context.name + namespace: context.namespace + // default namespace will be "prod" + } + spec: { + dockerImage: parameter.image //ghcr.io/zalando/spilo-15:2.1-p9 + numberOfInstances: parameter.replicas //By default it's 2 + teamId: parameter.teamId + postgresql: parameter.postgresql + databases: parameter.databases + preparedDatabases: parameter.preparedDatabases + users: parameter.users + enableMasterLoadBalancer: parameter.enableMasterLoadBalancer + enableReplicaLoadBalancer: parameter.enableReplicaLoadBalancer + enableConnectionPooler: parameter.enableConnectionPooler + enableReplicaConnectionPooler: parameter.enableReplicaConnectionPooler + enableMasterPoolerLoadBalancer: parameter.enableReplicaConnectionPooler + enableReplicaPoolerLoadBalancer: parameter.enableReplicaPoolerLoadBalancer + allowedSourceRanges: [ // load balancers' source ranges for both master and replica services + "127.0.0.1/32", + ] + volume: parameter.volume + additionalVolumes: [ + { + name: "empty" + mountPath: "/opt/empty" + targetContainers: [ + "all", + ] + volumeSource: { + emptyDir: {} + } + }, + ] + enableShmVolume: parameter.enableShmVolume + resources: parameter.resources + patroni: parameter.patroni + ttl: parameter.ttl + loop_wait: parameter.loopWait + retry_timeout: parameter.retryTimeout + synchronous_mode: parameter.synchronousMode + synchronous_mode_strict: parameter.synchronousModeStrict + synchronous_node_count: parameter.synchronousNodeCount + maximum_lag_on_failover: 33554432 + initContainers: [ + { + name: "date" + image: "busybox" + command: [ "/bin/date"] + }, + ] + // Custom TLS certificate. Disabled unless tls.secretName has a value. + tls: parameter.tls + } + } + parameter: { + //+usage=configure postgresql. + postgresql: { + //+usage=the version of the postgresql to be used. + version: *"15" | string + parameters: { + // Expert section + shared_buffers: *"32MB" | string + max_connections: *"10" | string + log_statement: *"all" | string + } + } + //+usage=the size of the postgres cluster. + replicas: *2 | int + //+usage=set team Id. + teamId: *"acid" | string + //+usage=the image of the spilo. + image: *"ghcr.io/zalando/spilo-15:2.1-p9" | string + //+usage=configure volume. + volume: { + //+usage=the size of the volume used of postgres. + size: *"1Gi" | string + } + //+usage=define databases to be used. + databases: *{ + foo: "zalando" // dbname: owner + } | {...} + //+usage=configure created databases. + preparedDatabases: *{ + bar: { + defaultUsers: true + extensions: { + pg_partman: "public" + pgcrypto: "public" + } + schemas: { + data: {} + history: { + defaultRoles: true + defaultUsers: false + } + } + } + } | {...} + //+usage=configure users for the databases. + users: *{ + zalando: ["superuser", "createdb"] + foo_user: [] + } | {...} + //+usage=configure patroni. + patroni: { + failsafe_mode: *false | bool + initdb: { + encoding: *"UTF8" | string + locale: *"en_US.UTF-8" | string + "data-checksums": *"true" | string + } + } + //+usage=enable SHM volume if set true. + enableShmVolume: *true | bool + //+usage=enable master as load balancer if set true. + enableMasterLoadBalancer: *false | bool + //+usage=enable replica as load balancer if set true. + enableReplicaLoadBalancer: *false | bool + //+usage=enable/disable connection pooler deployment. + enableConnectionPooler: *false | bool + //+usage=set to enable connection pooler for replica service. + enableReplicaConnectionPooler: *false | bool + //+usage=set to enable master pooler as load balancer. + enableMasterPoolerLoadBalancer: *false | bool + //+usage=set to enable replica pooler as load balancer. + enableReplicaPoolerLoadBalancer: *false | bool + //+usage=set ttl(Time to live) by dedault it's 30 days. + ttl: *30 | int + //+usage=set loop wait time by dedault it's 10. + loopWait: *10 | int + //+usage=set retry timeout by dedault it's 10. + retryTimeout: *10 | int + //+usage=set to enable synchronous mode. + synchronousMode: *false | bool + //+usage=set to enable synchronous mode strictly. + synchronousModeStrict: *false | bool + //+usage=set how many nodes to be synchronized. + synchronousNodeCount: *1 | int + //+usage=configure resources. + resources: { + requests: { + cpu: *"10m" | string + memory: *"100Mi" | string + } + limits: { + cpu: *"500m" | string + memory: *"500Mi" | string + } + } + //+usage=configure custom TLS. + tls: { + //+usage=sets custom TLS secret name, It should correspond to a Kubernetes Secret resource to load. + secretName: *"" | string + //+usage=sets custom TLS certificate file. + certificateFile: *"tls.crt" | string + //+usage=sets custom TLS private key file. + privateKeyFile: *"tls.key" | string + //+usage=optionally configure Postgres with a CA certificate. + caFile: *"" | string + //+usage=optionally the ca.crt can come from this secret instead. + caSecretName: *"" | string + } + } } diff --git a/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue b/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue new file mode 100644 index 00000000..79b99a26 --- /dev/null +++ b/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue @@ -0,0 +1,37 @@ +"postgres-expose": { + alias: "" + annotations: {} + attributes: { + workload: type: "autodetects.core.oam.dev" + } + description: "postgres expose trait" + labels: {} + type: "trait" +} + +template: { + outputs: expose: { + kind: "Service" + apiVersion: "v1" + spec: { + type: parameter.type + selector: { + "application": "spilo" + "cluster-name": "postgres" + "spilo-role": "master" + "team": "acid" + } + ports: [ + { + port: parameter.port + targetPort: parameter.targetPort + }, + ] + } + } + parameter: { + type: *"NodePort" | string + port: *5432 | int + targetPort: *5432 | int + } +} From 3ee1830b967323cdfedaf149fefde7add7c2853e Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 01:50:13 +0530 Subject: [PATCH 11/16] Updated Readme Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index 8c841ff5..79531fc1 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -68,7 +68,7 @@ With a port-forward on one of the database pods (e.g. the master) you can connec export PGMASTER=$(kubectl get pods -n prod -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) # set up port forward -kubectl port-forward $PGMASTER -n prod 5432:5432 -n default +kubectl port-forward $PGMASTER -n prod 5432:5432 -n prod ``` Open another CLI and connect to the database using e.g. the psql client. When connecting with a manifest role like foo_user user, read its password from the K8s secret which was generated when creating acid-minimal-cluster. As non-encrypted connections are rejected by default set SSL mode to require: From 7fd3f90c23ae7d4ac6b003c1d3d03e7117cad72f Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 01:58:44 +0530 Subject: [PATCH 12/16] Updated Readme Signed-off-by: MdSahil-oss --- .../addons/postgres-operator/README.md | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index 79531fc1..973a5c61 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -51,6 +51,28 @@ spec: replicas: 3 ``` +If you want to create a service to access Postgres, So apply below YAML: + +```yaml +apiVersion: core.oam.dev/v1beta1 +kind: Application +metadata: + name: postgres-operator-sample +spec: + components: + - type: "postgres-cluster" + name: "postgres" + namespace: "default" + properties: + replicas: 3 # By default it's set to 2. + traits: + - type: postgres-expose + properties: + type: NodePort # Change this field if you want diffrent type of service. + port: 5432 + targetPort: 5432 +``` + ```shell $ kubectl get po -n prod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES @@ -65,7 +87,7 @@ With a port-forward on one of the database pods (e.g. the master) you can connec ```shell # get name of master pod of acid-minimal-cluster -export PGMASTER=$(kubectl get pods -n prod -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) +$ export PGMASTER=$(kubectl get pods -n prod -o jsonpath={.items..metadata.name} -l application=spilo,cluster-name=postgres,spilo-role=master -n prod) # set up port forward kubectl port-forward $PGMASTER -n prod 5432:5432 -n prod @@ -74,7 +96,7 @@ kubectl port-forward $PGMASTER -n prod 5432:5432 -n prod Open another CLI and connect to the database using e.g. the psql client. When connecting with a manifest role like foo_user user, read its password from the K8s secret which was generated when creating acid-minimal-cluster. As non-encrypted connections are rejected by default set SSL mode to require: ```shell -export PGPASSWORD=$(kubectl get secret -n prod postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) -export PGSSLMODE=require +$ export PGPASSWORD=$(kubectl get secret -n prod postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) +$ export PGSSLMODE=require psql -U postgres -h localhost -p 5432 ``` From 566c5c7f83c0ada931c4a4b4f40cb36399f9e055 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 02:03:13 +0530 Subject: [PATCH 13/16] Updated example Signed-off-by: MdSahil-oss --- examples/postgres-operator/demo-with-expose-trait.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/postgres-operator/demo-with-expose-trait.yaml b/examples/postgres-operator/demo-with-expose-trait.yaml index 0954160c..c38ef900 100644 --- a/examples/postgres-operator/demo-with-expose-trait.yaml +++ b/examples/postgres-operator/demo-with-expose-trait.yaml @@ -14,4 +14,4 @@ spec: properties: type: NodePort port: 5432 - targetPort: 5432 \ No newline at end of file + targetPort: 5432 From b38ef6b0471fec95d4f015371715493a9d655008 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 13:40:29 +0530 Subject: [PATCH 14/16] Updated version Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/metadata.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/experimental/addons/postgres-operator/metadata.yaml b/experimental/addons/postgres-operator/metadata.yaml index 5cac4c1f..b4d54e7f 100644 --- a/experimental/addons/postgres-operator/metadata.yaml +++ b/experimental/addons/postgres-operator/metadata.yaml @@ -1,5 +1,5 @@ name: postgres-operator -version: 1.0.0 +version: 1.0.1 description: This addon adds postgres-operator to the kubevela to be used by across the application installed in kubevela. icon: "" url: "https://www.postgresql.org/" From a653f2f9565b6eff5c24ff6d7e9b4f04f9fca092 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Thu, 20 Apr 2023 18:25:08 +0530 Subject: [PATCH 15/16] Updated trait Signed-off-by: MdSahil-oss --- .../addons/postgres-operator/README.md | 2 +- .../definitions/traits/postgres-expose.cue | 67 +++++++++++++++---- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index 973a5c61..64b94405 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -98,5 +98,5 @@ Open another CLI and connect to the database using e.g. the psql client. When co ```shell $ export PGPASSWORD=$(kubectl get secret -n prod postgres.postgres.credentials.postgresql.acid.zalan.do -o 'jsonpath={.data.password}' | base64 -d) $ export PGSSLMODE=require -psql -U postgres -h localhost -p 5432 +$ psql -U postgres -h localhost -p 5432 ``` diff --git a/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue b/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue index 79b99a26..191323f6 100644 --- a/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue +++ b/experimental/addons/postgres-operator/definitions/traits/postgres-expose.cue @@ -10,28 +10,71 @@ } template: { - outputs: expose: { - kind: "Service" + outputs: service: { apiVersion: "v1" + kind: "Service" + metadata: annotations: parameter.annotations spec: { - type: parameter.type selector: { "application": "spilo" "cluster-name": "postgres" "spilo-role": "master" - "team": "acid" + "team": "acid" } - ports: [ - { - port: parameter.port - targetPort: parameter.targetPort + // compatible with the old way + if parameter["port"] != _|_ if parameter["ports"] == _|_ { + ports: [ + for p in parameter.port { + name: "port" + port: p + targetPort: p + }, + ] + } + if parameter["ports"] != _|_ { + ports: [ for v in parameter.ports { + port: v.port + targetPort: v.port + if v.name != _|_ { + name: v.name + } + if v.name == _|_ { + _name: "port" + name: *_name | string + if v.protocol != "TCP" { + name: _name + } + } + if v.nodePort != _|_ if parameter.type == "NodePort" { + nodePort: v.nodePort + } + if v.protocol != _|_ { + protocol: v.protocol + } }, - ] + ] + } + type: parameter.type } } parameter: { - type: *"NodePort" | string - port: *5432 | int - targetPort: *5432 | int + // +usage=Deprecated, the old way to specify the exposion ports + port?: [...int] + // +usage=Specify portsyou want customer traffic sent to + ports?: [...{ + // +usage=Number of port to expose on the pod's IP address + port: int + // +usage=Name of the port + name?: string + // +usage=Protocol for port. Must be UDP, TCP, or SCTP + protocol: *"TCP" | "UDP" | "SCTP" + // +usage=exposed node port. Only Valid when exposeType is NodePort + nodePort?: int + }] + // +usage=Specify the annotaions of the exposed service + annotations: [string]: string + matchLabels?: [string]: string + // +usage=Specify what kind of Service you want. options: "ClusterIP","NodePort","LoadBalancer","ExternalName" + type: *"ClusterIP" | "NodePort" | "LoadBalancer" | "ExternalName" } } From 8aad48ca7eab54d8e966f9943e9a6089ee8e1548 Mon Sep 17 00:00:00 2001 From: MdSahil-oss Date: Mon, 8 May 2023 17:58:27 +0530 Subject: [PATCH 16/16] Updated Readme Signed-off-by: MdSahil-oss --- experimental/addons/postgres-operator/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/experimental/addons/postgres-operator/README.md b/experimental/addons/postgres-operator/README.md index 64b94405..c3e4be7f 100644 --- a/experimental/addons/postgres-operator/README.md +++ b/experimental/addons/postgres-operator/README.md @@ -69,8 +69,7 @@ spec: - type: postgres-expose properties: type: NodePort # Change this field if you want diffrent type of service. - port: 5432 - targetPort: 5432 + port: [5432] ``` ```shell