improve RBAC setup for postgres pods
changed the default name, updated helm chart and docs allow role to use privileged podsecurtitypolicies
This commit is contained in:
		
							parent
							
								
									702a194c41
								
							
						
					
					
						commit
						cb96454a56
					
				| 
						 | 
					@ -148,6 +148,8 @@ spec:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                pod_service_account_name:
 | 
					                pod_service_account_name:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
 | 
					                pod_service_account_role_definition:
 | 
				
			||||||
 | 
					                  type: string
 | 
				
			||||||
                pod_service_account_role_binding_definition:
 | 
					                pod_service_account_role_binding_definition:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                pod_terminate_grace_period:
 | 
					                pod_terminate_grace_period:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@ metadata:
 | 
				
			||||||
    app.kubernetes.io/managed-by: {{ .Release.Service }}
 | 
					    app.kubernetes.io/managed-by: {{ .Release.Service }}
 | 
				
			||||||
    app.kubernetes.io/instance: {{ .Release.Name }}
 | 
					    app.kubernetes.io/instance: {{ .Release.Name }}
 | 
				
			||||||
rules:
 | 
					rules:
 | 
				
			||||||
 | 
					# all verbs allowed for custom operator resources
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - acid.zalan.do
 | 
					  - acid.zalan.do
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -16,7 +17,15 @@ rules:
 | 
				
			||||||
  - postgresqls/status
 | 
					  - postgresqls/status
 | 
				
			||||||
  - operatorconfigurations
 | 
					  - operatorconfigurations
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - "*"
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - deletecollection
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					# to create or get/update CRDs when starting up
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - apiextensions.k8s.io
 | 
					  - apiextensions.k8s.io
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -26,12 +35,14 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
  - update
 | 
					  - update
 | 
				
			||||||
 | 
					# to read configuration from ConfigMaps
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - configmaps
 | 
					  - configmaps
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
 | 
					# to manage endpoints which are also used by Patroni
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -43,7 +54,9 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
  - watch  # needed if zalando-postgres-operator account is used for pods as well
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					# to CRUD secrets for database access
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -53,6 +66,7 @@ rules:
 | 
				
			||||||
  - update
 | 
					  - update
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
 | 
					# to check nodes for node readiness label
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -61,6 +75,7 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					  - watch
 | 
				
			||||||
 | 
					# to read or delete existing PVCs. Creation via StatefulSet
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -69,6 +84,7 @@ rules:
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
 | 
					 # to read existing PVs. Creation should be done via dynamic provisioning
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -77,6 +93,7 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - update  # only for resizing AWS volumes
 | 
					  - update  # only for resizing AWS volumes
 | 
				
			||||||
 | 
					# to watch Spilo pods and do rolling updates. Creation via StatefulSet
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -85,14 +102,17 @@ rules:
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					# to resize the filesystem in Spilo pods when increasing volume size
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - pods/exec
 | 
					  - pods/exec
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
 | 
					# to CRUD services to point to Postgres cluster instances
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -102,6 +122,7 @@ rules:
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					# to CRUD the StatefulSet which controls the Postgres cluster instances
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - apps
 | 
					  - apps
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -112,12 +133,26 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					# to CRUD cron jobs for logical backups
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - batch
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - cronjobs
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					# to get namespaces operator resources can run in
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - namespaces
 | 
					  - namespaces
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
 | 
					# to define PDBs. Update happens via delete/create
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - policy
 | 
					  - policy
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -126,6 +161,7 @@ rules:
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
 | 
					# to create ServiceAccounts in each namespace the operator watches
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					@ -133,30 +169,22 @@ rules:
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
 | 
					# to create roles and role bindings to the pod service account
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - "rbac.authorization.k8s.io"
 | 
					  - rbac.authorization.k8s.io
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - rolebindings
 | 
					  - rolebindings
 | 
				
			||||||
 | 
					  - roles
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
 | 
					# needed to grant to namespaced roles when pods run in privileged mode
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - "rbac.authorization.k8s.io"
 | 
					  - extensions
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - clusterroles
 | 
					  - podsecuritypolicies
 | 
				
			||||||
  verbs:
 | 
					 | 
				
			||||||
  - bind
 | 
					 | 
				
			||||||
  resourceNames:
 | 
					  resourceNames:
 | 
				
			||||||
  - {{ include "postgres-operator.serviceAccountName" . }}
 | 
					  - privileged
 | 
				
			||||||
- apiGroups:
 | 
					 | 
				
			||||||
  - batch
 | 
					 | 
				
			||||||
  resources:
 | 
					 | 
				
			||||||
  - cronjobs  # enables logical backups
 | 
					 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - create
 | 
					  - use
 | 
				
			||||||
  - delete
 | 
					 | 
				
			||||||
  - get
 | 
					 | 
				
			||||||
  - list
 | 
					 | 
				
			||||||
  - patch
 | 
					 | 
				
			||||||
  - update
 | 
					 | 
				
			||||||
{{ end }}
 | 
					{{ end }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,8 +14,6 @@ roleRef:
 | 
				
			||||||
  name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
					  name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
				
			||||||
subjects:
 | 
					subjects:
 | 
				
			||||||
- kind: ServiceAccount
 | 
					- kind: ServiceAccount
 | 
				
			||||||
# note: the cluster role binding needs to be defined
 | 
					 | 
				
			||||||
# for every namespace the operator service account lives in.
 | 
					 | 
				
			||||||
  name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
					  name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
				
			||||||
  namespace: {{ .Release.Namespace }}
 | 
					  namespace: {{ .Release.Namespace }}
 | 
				
			||||||
{{ end }}
 | 
					{{ end }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,6 @@ metadata:
 | 
				
			||||||
    app.kubernetes.io/managed-by: {{ .Release.Service }}
 | 
					    app.kubernetes.io/managed-by: {{ .Release.Service }}
 | 
				
			||||||
    app.kubernetes.io/instance: {{ .Release.Name }}
 | 
					    app.kubernetes.io/instance: {{ .Release.Name }}
 | 
				
			||||||
data:
 | 
					data:
 | 
				
			||||||
  pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
					 | 
				
			||||||
{{ toYaml .Values.configGeneral | indent 2 }}
 | 
					{{ toYaml .Values.configGeneral | indent 2 }}
 | 
				
			||||||
{{ toYaml .Values.configUsers | indent 2 }}
 | 
					{{ toYaml .Values.configUsers | indent 2 }}
 | 
				
			||||||
{{ toYaml .Values.configKubernetes | indent 2 }}
 | 
					{{ toYaml .Values.configKubernetes | indent 2 }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,7 +14,6 @@ configuration:
 | 
				
			||||||
{{ toYaml .Values.configUsers | indent 4 }}
 | 
					{{ toYaml .Values.configUsers | indent 4 }}
 | 
				
			||||||
  kubernetes:
 | 
					  kubernetes:
 | 
				
			||||||
    oauth_token_secret_name: {{ template "postgres-operator.fullname" . }}
 | 
					    oauth_token_secret_name: {{ template "postgres-operator.fullname" . }}
 | 
				
			||||||
    pod_service_account_name: {{ include "postgres-operator.serviceAccountName" . }}
 | 
					 | 
				
			||||||
{{ toYaml .Values.configKubernetes | indent 4 }}
 | 
					{{ toYaml .Values.configKubernetes | indent 4 }}
 | 
				
			||||||
  postgres_pod_resources:
 | 
					  postgres_pod_resources:
 | 
				
			||||||
{{ toYaml .Values.configPostgresPodResources | indent 4 }}
 | 
					{{ toYaml .Values.configPostgresPodResources | indent 4 }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,6 +100,17 @@ configKubernetes:
 | 
				
			||||||
  pod_management_policy: "ordered_ready"
 | 
					  pod_management_policy: "ordered_ready"
 | 
				
			||||||
  # label assigned to the Postgres pods (and services/endpoints)
 | 
					  # label assigned to the Postgres pods (and services/endpoints)
 | 
				
			||||||
  pod_role_label: spilo-role
 | 
					  pod_role_label: spilo-role
 | 
				
			||||||
 | 
					  # service account definition as JSON/YAML string to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  # pod_service_account_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # name of service account to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  pod_service_account_name: "postgres-pod"
 | 
				
			||||||
 | 
					  # role definition as JSON/YAML string to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  # pod_service_account_role_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # role binding definition as JSON/YAML string to be used by pod service account
 | 
				
			||||||
 | 
					  # pod_service_account_role_binding_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Postgres pods are terminated forcefully after this timeout
 | 
					  # Postgres pods are terminated forcefully after this timeout
 | 
				
			||||||
  pod_terminate_grace_period: 5m
 | 
					  pod_terminate_grace_period: 5m
 | 
				
			||||||
  # template for database user secrets generated by the operator
 | 
					  # template for database user secrets generated by the operator
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -93,6 +93,17 @@ configKubernetes:
 | 
				
			||||||
  pod_management_policy: "ordered_ready"
 | 
					  pod_management_policy: "ordered_ready"
 | 
				
			||||||
  # label assigned to the Postgres pods (and services/endpoints)
 | 
					  # label assigned to the Postgres pods (and services/endpoints)
 | 
				
			||||||
  pod_role_label: spilo-role
 | 
					  pod_role_label: spilo-role
 | 
				
			||||||
 | 
					  # service account definition as JSON/YAML string to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  # pod_service_account_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # name of service account to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  pod_service_account_name: "postgres-pod"
 | 
				
			||||||
 | 
					  # role definition as JSON/YAML string to be used by postgres cluster pods
 | 
				
			||||||
 | 
					  # pod_service_account_role_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # role binding definition as JSON/YAML string to be used by pod service account
 | 
				
			||||||
 | 
					  # pod_service_account_role_binding_definition: ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Postgres pods are terminated forcefully after this timeout
 | 
					  # Postgres pods are terminated forcefully after this timeout
 | 
				
			||||||
  pod_terminate_grace_period: 5m
 | 
					  pod_terminate_grace_period: 5m
 | 
				
			||||||
  # template for database user secrets generated by the operator
 | 
					  # template for database user secrets generated by the operator
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,12 @@ patching the CRD manifest:
 | 
				
			||||||
zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}'
 | 
					zk8 patch crd postgresqls.acid.zalan.do -p '{"spec":{"validation": null}}'
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Non-default cluster domain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If your cluster uses a DNS domain other than the default `cluster.local`, this
 | 
				
			||||||
 | 
					needs to be set in the operator configuration (`cluster_domain` variable). This
 | 
				
			||||||
 | 
					is used by the operator to connect to the clusters after creation.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Namespaces
 | 
					## Namespaces
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Select the namespace to deploy to
 | 
					### Select the namespace to deploy to
 | 
				
			||||||
| 
						 | 
					@ -89,30 +95,6 @@ lacks access rights to any of them (except K8s system namespaces like
 | 
				
			||||||
'list pods' execute at the cluster scope and fail at the first violation of
 | 
					'list pods' execute at the cluster scope and fail at the first violation of
 | 
				
			||||||
access rights.
 | 
					access rights.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The watched namespace also needs to have a (possibly different) service account
 | 
					 | 
				
			||||||
in the case database pods need to talk to the K8s API (e.g. when using
 | 
					 | 
				
			||||||
K8s-native configuration of Patroni). The operator checks that the
 | 
					 | 
				
			||||||
`pod_service_account_name` exists in the target namespace, and, if not, deploys
 | 
					 | 
				
			||||||
there the `pod_service_account_definition` from the operator
 | 
					 | 
				
			||||||
[`Config`](../pkg/util/config/config.go) with the default value of:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```yaml
 | 
					 | 
				
			||||||
apiVersion: v1
 | 
					 | 
				
			||||||
kind: ServiceAccount
 | 
					 | 
				
			||||||
metadata:
 | 
					 | 
				
			||||||
 name: operator
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
In this definition, the operator overwrites the account's name to match
 | 
					 | 
				
			||||||
`pod_service_account_name` and the `default` namespace to match the target
 | 
					 | 
				
			||||||
namespace. The operator performs **no** further syncing of this account.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Non-default cluster domain
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
If your cluster uses a DNS domain other than the default `cluster.local`, this
 | 
					 | 
				
			||||||
needs to be set in the operator configuration (`cluster_domain` variable). This
 | 
					 | 
				
			||||||
is used by the operator to connect to the clusters after creation.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Role-based access control for the operator
 | 
					## Role-based access control for the operator
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The manifest [`operator-service-account-rbac.yaml`](../manifests/operator-service-account-rbac.yaml)
 | 
					The manifest [`operator-service-account-rbac.yaml`](../manifests/operator-service-account-rbac.yaml)
 | 
				
			||||||
| 
						 | 
					@ -127,14 +109,19 @@ kubectl create -f manifests/postgres-operator.yaml
 | 
				
			||||||
kubectl create -f manifests/minimal-postgres-manifest.yaml
 | 
					kubectl create -f manifests/minimal-postgres-manifest.yaml
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Service account and cluster roles
 | 
					### Namespaced service account and roles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Note that the service account is named `zalando-postgres-operator`. You may have
 | 
					For each namespace the operator watches it creates (or reads) a service account
 | 
				
			||||||
to change the `service_account_name` in the operator ConfigMap and
 | 
					to be used by the Postgres Pods when a new cluster is deployed. This service
 | 
				
			||||||
`serviceAccountName` in the `postgres-operator` deployment appropriately. This
 | 
					account is bound to a namespaced Role via RoleBinding, which are also created
 | 
				
			||||||
is done intentionally to avoid breaking those setups that already work with the
 | 
					(or read) by the operator. The name and definitions of these resources can be
 | 
				
			||||||
default `operator` account. In the future the operator should ideally be run
 | 
					[configured](reference/operator_parameters.md#kubernetes-resources).
 | 
				
			||||||
under the `zalando-postgres-operator` service account.
 | 
					Note, that the operator performs **no** further syncing of them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Until v1.3.1, RoleBindings pointed to the operator ClusterRole by default. This
 | 
				
			||||||
 | 
					can still be configured but is not recommended as the Postgres Pods should only
 | 
				
			||||||
 | 
					run with the least privileges required for Patroni to work. By default, the
 | 
				
			||||||
 | 
					namespaced RBAC resources are named `postgres-pod`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Give K8s users access to create/list `postgresqls`
 | 
					### Give K8s users access to create/list `postgresqls`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,21 +152,29 @@ configuration they are grouped under the `kubernetes` key.
 | 
				
			||||||
  service account used by Patroni running on individual Pods to communicate
 | 
					  service account used by Patroni running on individual Pods to communicate
 | 
				
			||||||
  with the operator. Required even if native Kubernetes support in Patroni is
 | 
					  with the operator. Required even if native Kubernetes support in Patroni is
 | 
				
			||||||
  not used, because Patroni keeps pod labels in sync with the instance role.
 | 
					  not used, because Patroni keeps pod labels in sync with the instance role.
 | 
				
			||||||
  The default is `operator`.
 | 
					  The default is `postgres-pod`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* **pod_service_account_definition**
 | 
					* **pod_service_account_definition**
 | 
				
			||||||
  The operator tries to create the pod Service Account in the namespace that
 | 
					  on Postgres cluster creation the operator tries to create the service account
 | 
				
			||||||
  doesn't define such an account using the YAML definition provided by this
 | 
					  for the Postgres pods if it does not exist in the namespace. The internal
 | 
				
			||||||
  option. If not defined, a simple definition that contains only the name will
 | 
					  default service account definition (defines only the name) can be overwritten
 | 
				
			||||||
  be used. The default is empty.
 | 
					  with this parameter. Make sure to provide a valid YAML or JSON string. The
 | 
				
			||||||
 | 
					  default is empty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* **pod_service_account_role_definition**
 | 
				
			||||||
 | 
					  operator will try to create a role in the namespace to be used by pod service
 | 
				
			||||||
 | 
					  account. The internal default definition contains permissions to manage pods
 | 
				
			||||||
 | 
					  and endpoints necessary for Patroni to work. Therefore, when overwriting the
 | 
				
			||||||
 | 
					  definition with this parameter make sure to provide sufficient access rights
 | 
				
			||||||
 | 
					  in a valid YAML/JSON string. The default is empty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* **pod_service_account_role_binding_definition**
 | 
					* **pod_service_account_role_binding_definition**
 | 
				
			||||||
  This definition must bind pod service account to a role with permission
 | 
					  the created service account and role are referenced with a role binding. When
 | 
				
			||||||
  sufficient for the pods to start and for Patroni to access K8s endpoints;
 | 
					  overwriting its definition with this parameters using a valid YAML/JSON string
 | 
				
			||||||
  service account on its own lacks any such rights starting with K8s v1.8. If
 | 
					  check that the specified service account and role either exist in the K8s
 | 
				
			||||||
  not explicitly defined by the user, a simple definition that binds the
 | 
					  cluster or will be created by the operator. While it's possible to also
 | 
				
			||||||
  account to the operator's own 'zalando-postgres-operator' cluster role will
 | 
					  reference cluster roles, the binding itself can only be of kind `RoleBinding`,
 | 
				
			||||||
  be used. The default is empty.
 | 
					  not `ClusterRoleBinding`. The default is empty.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* **pod_terminate_grace_period**
 | 
					* **pod_terminate_grace_period**
 | 
				
			||||||
  Postgres pods are [terminated forcefully](https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods)
 | 
					  Postgres pods are [terminated forcefully](https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,10 @@ data:
 | 
				
			||||||
  pod_label_wait_timeout: 10m
 | 
					  pod_label_wait_timeout: 10m
 | 
				
			||||||
  pod_management_policy: "ordered_ready"
 | 
					  pod_management_policy: "ordered_ready"
 | 
				
			||||||
  pod_role_label: spilo-role
 | 
					  pod_role_label: spilo-role
 | 
				
			||||||
  pod_service_account_name: "zalando-postgres-operator"
 | 
					  # pod_service_account_definition: ""
 | 
				
			||||||
 | 
					  pod_service_account_name: "postgres-pod"
 | 
				
			||||||
 | 
					  # pod_service_account_role_definition: ""
 | 
				
			||||||
 | 
					  # pod_service_account_role_binding_definition: '{"apiVersion":"rbac.authorization.k8s.io/v1","kind":"RoleBinding","metadata":{"name":"postgres-pod"},"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind": "ClusterRole","name": "postgres-pod"},"subjects":[{"kind": "ServiceAccount","name": "postgres-pod"}]}'
 | 
				
			||||||
  pod_terminate_grace_period: 5m
 | 
					  pod_terminate_grace_period: 5m
 | 
				
			||||||
  # postgres_superuser_teams: "postgres_superusers"
 | 
					  # postgres_superuser_teams: "postgres_superusers"
 | 
				
			||||||
  # protected_role_names: "admin"
 | 
					  # protected_role_names: "admin"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,14 +1,14 @@
 | 
				
			||||||
apiVersion: v1
 | 
					apiVersion: v1
 | 
				
			||||||
kind: ServiceAccount
 | 
					kind: ServiceAccount
 | 
				
			||||||
metadata:
 | 
					metadata:
 | 
				
			||||||
  name: zalando-postgres-operator
 | 
					  name: postgres-operator
 | 
				
			||||||
  namespace: default
 | 
					  namespace: default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
apiVersion: rbac.authorization.k8s.io/v1
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
kind: ClusterRole
 | 
					kind: ClusterRole
 | 
				
			||||||
metadata:
 | 
					metadata:
 | 
				
			||||||
  name: zalando-postgres-operator
 | 
					  name: postgres-operator
 | 
				
			||||||
rules:
 | 
					rules:
 | 
				
			||||||
# all verbs allowed for custom operator resources
 | 
					# all verbs allowed for custom operator resources
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,14 @@ rules:
 | 
				
			||||||
  - postgresqls/status
 | 
					  - postgresqls/status
 | 
				
			||||||
  - operatorconfigurations
 | 
					  - operatorconfigurations
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - "*"
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - deletecollection
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
# to create or get/update CRDs when starting up
 | 
					# to create or get/update CRDs when starting up
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - apiextensions.k8s.io
 | 
					  - apiextensions.k8s.io
 | 
				
			||||||
| 
						 | 
					@ -48,7 +55,8 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
  - watch  # needed if zalando-postgres-operator account is used for pods as well
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
# to CRUD secrets for database access
 | 
					# to CRUD secrets for database access
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
| 
						 | 
					@ -95,8 +103,9 @@ rules:
 | 
				
			||||||
  - delete
 | 
					  - delete
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
# to resize the filesystem in Spilo pods when increasing volume size
 | 
					# to resize the filesystem in Spilo pods when increasing volume size
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
| 
						 | 
					@ -126,6 +135,18 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					# to CRUD cron jobs for logical backups
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - batch
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - cronjobs
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
# to get namespaces operator resources can run in
 | 
					# to get namespaces operator resources can run in
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
| 
						 | 
					@ -150,39 +171,35 @@ rules:
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
# to create role bindings to the operator service account
 | 
					# to create roles and role bindings to the pod service account
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - "rbac.authorization.k8s.io"
 | 
					  - rbac.authorization.k8s.io
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - rolebindings
 | 
					  - rolebindings
 | 
				
			||||||
 | 
					  - roles
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - create
 | 
					  - create
 | 
				
			||||||
# to CRUD cron jobs for logical backups
 | 
					# needed to grant to namespaced roles when pods run in privileged mode
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - batch
 | 
					  - extensions
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
  - cronjobs
 | 
					  - podsecuritypolicies
 | 
				
			||||||
 | 
					  resourceNames:
 | 
				
			||||||
 | 
					  - privileged
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - create
 | 
					  - use
 | 
				
			||||||
  - delete
 | 
					 | 
				
			||||||
  - get
 | 
					 | 
				
			||||||
  - list
 | 
					 | 
				
			||||||
  - patch
 | 
					 | 
				
			||||||
  - update
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
apiVersion: rbac.authorization.k8s.io/v1
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
kind: ClusterRoleBinding
 | 
					kind: ClusterRoleBinding
 | 
				
			||||||
metadata:
 | 
					metadata:
 | 
				
			||||||
  name: zalando-postgres-operator
 | 
					  name: postgres-operator
 | 
				
			||||||
roleRef:
 | 
					roleRef:
 | 
				
			||||||
  apiGroup: rbac.authorization.k8s.io
 | 
					  apiGroup: rbac.authorization.k8s.io
 | 
				
			||||||
  kind: ClusterRole
 | 
					  kind: ClusterRole
 | 
				
			||||||
  name: zalando-postgres-operator
 | 
					  name: postgres-operator
 | 
				
			||||||
subjects:
 | 
					subjects:
 | 
				
			||||||
- kind: ServiceAccount
 | 
					- kind: ServiceAccount
 | 
				
			||||||
# note: the cluster role binding needs to be defined
 | 
					  name: postgres-operator
 | 
				
			||||||
# for every namespace the operator service account lives in.
 | 
					 | 
				
			||||||
  name: zalando-postgres-operator
 | 
					 | 
				
			||||||
  namespace: default
 | 
					  namespace: default
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,6 +124,8 @@ spec:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                pod_service_account_name:
 | 
					                pod_service_account_name:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
 | 
					                pod_service_account_role_definition:
 | 
				
			||||||
 | 
					                  type: string
 | 
				
			||||||
                pod_service_account_role_binding_definition:
 | 
					                pod_service_account_role_binding_definition:
 | 
				
			||||||
                  type: string
 | 
					                  type: string
 | 
				
			||||||
                pod_terminate_grace_period:
 | 
					                pod_terminate_grace_period:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ spec:
 | 
				
			||||||
      labels:
 | 
					      labels:
 | 
				
			||||||
        name: postgres-operator
 | 
					        name: postgres-operator
 | 
				
			||||||
    spec:
 | 
					    spec:
 | 
				
			||||||
      serviceAccountName: zalando-postgres-operator
 | 
					      serviceAccountName: postgres-operator
 | 
				
			||||||
      containers:
 | 
					      containers:
 | 
				
			||||||
      - name: postgres-operator
 | 
					      - name: postgres-operator
 | 
				
			||||||
        image: registry.opensource.zalan.do/acid/postgres-operator:v1.3.1
 | 
					        image: registry.opensource.zalan.do/acid/postgres-operator:v1.3.1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,49 @@
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: ServiceAccount
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: postgres-pod
 | 
				
			||||||
 | 
					  namespace: default
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
 | 
					kind: ClusterRole
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: postgres-pod
 | 
				
			||||||
 | 
					rules:
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - ""
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - endpoints
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - deletecollection
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - ""
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - pods
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - ""
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - services
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - extensions
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - podsecuritypolicies
 | 
				
			||||||
 | 
					  resourceNames:
 | 
				
			||||||
 | 
					  - privileged
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - use
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,8 @@ configuration:
 | 
				
			||||||
    # pod_priority_class_name: ""
 | 
					    # pod_priority_class_name: ""
 | 
				
			||||||
    pod_role_label: spilo-role
 | 
					    pod_role_label: spilo-role
 | 
				
			||||||
    # pod_service_account_definition: ""
 | 
					    # pod_service_account_definition: ""
 | 
				
			||||||
    pod_service_account_name: zalando-postgres-operator
 | 
					    pod_service_account_name: postgres-pod
 | 
				
			||||||
 | 
					    # pod_service_account_role_definition: ""
 | 
				
			||||||
    # pod_service_account_role_binding_definition: ""
 | 
					    # pod_service_account_role_binding_definition: ""
 | 
				
			||||||
    pod_terminate_grace_period: 5m
 | 
					    pod_terminate_grace_period: 5m
 | 
				
			||||||
    secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}"
 | 
					    secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,14 @@ rules:
 | 
				
			||||||
  - postgresqls
 | 
					  - postgresqls
 | 
				
			||||||
  - postgresqls/status
 | 
					  - postgresqls/status
 | 
				
			||||||
  verbs:
 | 
					  verbs:
 | 
				
			||||||
  - "*"
 | 
					  - create
 | 
				
			||||||
 | 
					  - delete
 | 
				
			||||||
 | 
					  - deletecollection
 | 
				
			||||||
 | 
					  - get
 | 
				
			||||||
 | 
					  - list
 | 
				
			||||||
 | 
					  - patch
 | 
				
			||||||
 | 
					  - update
 | 
				
			||||||
 | 
					  - watch
 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
apiVersion: rbac.authorization.k8s.io/v1
 | 
					apiVersion: rbac.authorization.k8s.io/v1
 | 
				
			||||||
| 
						 | 
					@ -48,4 +55,3 @@ rules:
 | 
				
			||||||
  - get
 | 
					  - get
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					  - watch
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -771,6 +771,9 @@ var OperatorConfigCRDResourceValidation = apiextv1beta1.CustomResourceValidation
 | 
				
			||||||
							"pod_service_account_name": {
 | 
												"pod_service_account_name": {
 | 
				
			||||||
								Type: "string",
 | 
													Type: "string",
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
 | 
												"pod_service_account_role_definition": {
 | 
				
			||||||
 | 
													Type: "string",
 | 
				
			||||||
 | 
												},
 | 
				
			||||||
							"pod_service_account_role_binding_definition": {
 | 
												"pod_service_account_role_binding_definition": {
 | 
				
			||||||
								Type: "string",
 | 
													Type: "string",
 | 
				
			||||||
							},
 | 
												},
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@ type KubernetesMetaConfiguration struct {
 | 
				
			||||||
	PodServiceAccountName string `json:"pod_service_account_name,omitempty"`
 | 
						PodServiceAccountName string `json:"pod_service_account_name,omitempty"`
 | 
				
			||||||
	// TODO: change it to the proper json
 | 
						// TODO: change it to the proper json
 | 
				
			||||||
	PodServiceAccountDefinition            string                `json:"pod_service_account_definition,omitempty"`
 | 
						PodServiceAccountDefinition            string                `json:"pod_service_account_definition,omitempty"`
 | 
				
			||||||
 | 
						PodServiceAccountRoleDefinition        string                `json:"pod_service_account_role_definition,omitempty"`
 | 
				
			||||||
	PodServiceAccountRoleBindingDefinition string                `json:"pod_service_account_role_binding_definition,omitempty"`
 | 
						PodServiceAccountRoleBindingDefinition string                `json:"pod_service_account_role_binding_definition,omitempty"`
 | 
				
			||||||
	PodTerminateGracePeriod                Duration              `json:"pod_terminate_grace_period,omitempty"`
 | 
						PodTerminateGracePeriod                Duration              `json:"pod_terminate_grace_period,omitempty"`
 | 
				
			||||||
	SpiloPrivileged                        bool                  `json:"spilo_privileged,omitempty"`
 | 
						SpiloPrivileged                        bool                  `json:"spilo_privileged,omitempty"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@ type Config struct {
 | 
				
			||||||
	RestConfig                   *rest.Config
 | 
						RestConfig                   *rest.Config
 | 
				
			||||||
	InfrastructureRoles          map[string]spec.PgUser // inherited from the controller
 | 
						InfrastructureRoles          map[string]spec.PgUser // inherited from the controller
 | 
				
			||||||
	PodServiceAccount            *v1.ServiceAccount
 | 
						PodServiceAccount            *v1.ServiceAccount
 | 
				
			||||||
 | 
						PodServiceAccountRole        *rbacv1.Role
 | 
				
			||||||
	PodServiceAccountRoleBinding *rbacv1.RoleBinding
 | 
						PodServiceAccountRoleBinding *rbacv1.RoleBinding
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,7 @@ type Controller struct {
 | 
				
			||||||
	workerLogs map[uint32]ringlog.RingLogger
 | 
						workerLogs map[uint32]ringlog.RingLogger
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PodServiceAccount            *v1.ServiceAccount
 | 
						PodServiceAccount            *v1.ServiceAccount
 | 
				
			||||||
 | 
						PodServiceAccountRole        *rbacv1.Role
 | 
				
			||||||
	PodServiceAccountRoleBinding *rbacv1.RoleBinding
 | 
						PodServiceAccountRoleBinding *rbacv1.RoleBinding
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -161,10 +162,11 @@ func (c *Controller) initPodServiceAccount() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c.opConfig.PodServiceAccountDefinition == "" {
 | 
						if c.opConfig.PodServiceAccountDefinition == "" {
 | 
				
			||||||
		c.opConfig.PodServiceAccountDefinition = `
 | 
							c.opConfig.PodServiceAccountDefinition = `
 | 
				
			||||||
		{ "apiVersion": "v1",
 | 
							{
 | 
				
			||||||
 | 
								"apiVersion": "v1",
 | 
				
			||||||
			"kind": "ServiceAccount",
 | 
								"kind": "ServiceAccount",
 | 
				
			||||||
			"metadata": {
 | 
								"metadata": {
 | 
				
			||||||
				 "name": "operator"
 | 
									"name": "postgres-pod"
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}`
 | 
							}`
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -175,13 +177,13 @@ func (c *Controller) initPodServiceAccount() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case err != nil:
 | 
						case err != nil:
 | 
				
			||||||
		panic(fmt.Errorf("Unable to parse pod service account definition from the operator config map: %v", err))
 | 
							panic(fmt.Errorf("Unable to parse pod service account definition from the operator configuration: %v", err))
 | 
				
			||||||
	case groupVersionKind.Kind != "ServiceAccount":
 | 
						case groupVersionKind.Kind != "ServiceAccount":
 | 
				
			||||||
		panic(fmt.Errorf("pod service account definition in the operator config map defines another type of resource: %v", groupVersionKind.Kind))
 | 
							panic(fmt.Errorf("pod service account definition in the operator configuration defines another type of resource: %v", groupVersionKind.Kind))
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		c.PodServiceAccount = obj.(*v1.ServiceAccount)
 | 
							c.PodServiceAccount = obj.(*v1.ServiceAccount)
 | 
				
			||||||
		if c.PodServiceAccount.Name != c.opConfig.PodServiceAccountName {
 | 
							if c.PodServiceAccount.Name != c.opConfig.PodServiceAccountName {
 | 
				
			||||||
			c.logger.Warnf("in the operator config map, the pod service account name %v does not match the name %v given in the account definition; using the former for consistency", c.opConfig.PodServiceAccountName, c.PodServiceAccount.Name)
 | 
								c.logger.Warnf("in the operator configuration, the pod service account name %v does not match the name %v given in the account definition; using the former for consistency", c.opConfig.PodServiceAccountName, c.PodServiceAccount.Name)
 | 
				
			||||||
			c.PodServiceAccount.Name = c.opConfig.PodServiceAccountName
 | 
								c.PodServiceAccount.Name = c.opConfig.PodServiceAccountName
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		c.PodServiceAccount.Namespace = ""
 | 
							c.PodServiceAccount.Namespace = ""
 | 
				
			||||||
| 
						 | 
					@ -190,6 +192,100 @@ func (c *Controller) initPodServiceAccount() {
 | 
				
			||||||
	// actual service accounts are deployed at the time of Postgres/Spilo cluster creation
 | 
						// actual service accounts are deployed at the time of Postgres/Spilo cluster creation
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Controller) initRole() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// service account on its own lacks any rights starting with k8s v1.8
 | 
				
			||||||
 | 
						// operator binds it to the namespaced role with sufficient privileges
 | 
				
			||||||
 | 
						if c.opConfig.PodServiceAccountRoleDefinition == "" {
 | 
				
			||||||
 | 
							c.opConfig.PodServiceAccountRoleDefinition = fmt.Sprintf(`
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								"apiVersion": "rbac.authorization.k8s.io/v1",
 | 
				
			||||||
 | 
								"kind": "Role",
 | 
				
			||||||
 | 
								"metadata": {
 | 
				
			||||||
 | 
									"name": "%s"
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"rules": [
 | 
				
			||||||
 | 
							        {
 | 
				
			||||||
 | 
							            "apiGroups": [
 | 
				
			||||||
 | 
							                ""
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "resources": [
 | 
				
			||||||
 | 
							                "endpoints"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "verbs": [
 | 
				
			||||||
 | 
							                "create",
 | 
				
			||||||
 | 
							                "delete",
 | 
				
			||||||
 | 
							                "deletecollection",
 | 
				
			||||||
 | 
							                "get",
 | 
				
			||||||
 | 
							                "list",
 | 
				
			||||||
 | 
							                "patch",
 | 
				
			||||||
 | 
							                "update",
 | 
				
			||||||
 | 
							                "watch"
 | 
				
			||||||
 | 
							            ]
 | 
				
			||||||
 | 
							        },
 | 
				
			||||||
 | 
							        {
 | 
				
			||||||
 | 
							            "apiGroups": [
 | 
				
			||||||
 | 
							                ""
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "resources": [
 | 
				
			||||||
 | 
							                "pods"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "verbs": [
 | 
				
			||||||
 | 
							                "get",
 | 
				
			||||||
 | 
							                "list",
 | 
				
			||||||
 | 
							                "patch",
 | 
				
			||||||
 | 
							                "update",
 | 
				
			||||||
 | 
							                "watch"
 | 
				
			||||||
 | 
							            ]
 | 
				
			||||||
 | 
							        },
 | 
				
			||||||
 | 
							        {
 | 
				
			||||||
 | 
							            "apiGroups": [
 | 
				
			||||||
 | 
							                ""
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "resources": [
 | 
				
			||||||
 | 
							                "services"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "verbs": [
 | 
				
			||||||
 | 
							                "create"
 | 
				
			||||||
 | 
							            ]
 | 
				
			||||||
 | 
							        },
 | 
				
			||||||
 | 
							        {
 | 
				
			||||||
 | 
							            "apiGroups": [
 | 
				
			||||||
 | 
							                "extensions"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "resources": [
 | 
				
			||||||
 | 
							                "podsecuritypolicies"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "resourceNames": [
 | 
				
			||||||
 | 
							                "privileged"
 | 
				
			||||||
 | 
							            ],
 | 
				
			||||||
 | 
							            "verbs": [
 | 
				
			||||||
 | 
							                "use"
 | 
				
			||||||
 | 
							            ]
 | 
				
			||||||
 | 
							        }
 | 
				
			||||||
 | 
							    ]
 | 
				
			||||||
 | 
							}`, c.PodServiceAccount.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.logger.Info("Parse roles")
 | 
				
			||||||
 | 
						// re-uses k8s internal parsing. See k8s client-go issue #193 for explanation
 | 
				
			||||||
 | 
						decode := scheme.Codecs.UniversalDeserializer().Decode
 | 
				
			||||||
 | 
						obj, groupVersionKind, err := decode([]byte(c.opConfig.PodServiceAccountRoleDefinition), nil, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch {
 | 
				
			||||||
 | 
						case err != nil:
 | 
				
			||||||
 | 
							panic(fmt.Errorf("unable to parse the role definition from the operator configuration: %v", err))
 | 
				
			||||||
 | 
						case groupVersionKind.Kind != "Role":
 | 
				
			||||||
 | 
							panic(fmt.Errorf("role definition in the operator configuration defines another type of resource: %v", groupVersionKind.Kind))
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							c.PodServiceAccountRole = obj.(*rbacv1.Role)
 | 
				
			||||||
 | 
							c.PodServiceAccountRole.Namespace = ""
 | 
				
			||||||
 | 
							c.logger.Info("successfully parsed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// actual roles bindings are deployed at the time of Postgres/Spilo cluster creation
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Controller) initRoleBinding() {
 | 
					func (c *Controller) initRoleBinding() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// service account on its own lacks any rights starting with k8s v1.8
 | 
						// service account on its own lacks any rights starting with k8s v1.8
 | 
				
			||||||
| 
						 | 
					@ -205,7 +301,7 @@ func (c *Controller) initRoleBinding() {
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			"roleRef": {
 | 
								"roleRef": {
 | 
				
			||||||
				"apiGroup": "rbac.authorization.k8s.io",
 | 
									"apiGroup": "rbac.authorization.k8s.io",
 | 
				
			||||||
				"kind": "ClusterRole",
 | 
									"kind": "Role",
 | 
				
			||||||
				"name": "%s"
 | 
									"name": "%s"
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
			"subjects": [
 | 
								"subjects": [
 | 
				
			||||||
| 
						 | 
					@ -223,9 +319,9 @@ func (c *Controller) initRoleBinding() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch {
 | 
						switch {
 | 
				
			||||||
	case err != nil:
 | 
						case err != nil:
 | 
				
			||||||
		panic(fmt.Errorf("Unable to parse the definition of the role binding for the pod service account definition from the operator config map: %v", err))
 | 
							panic(fmt.Errorf("unable to parse the role binding definition from the operator configuration: %v", err))
 | 
				
			||||||
	case groupVersionKind.Kind != "RoleBinding":
 | 
						case groupVersionKind.Kind != "RoleBinding":
 | 
				
			||||||
		panic(fmt.Errorf("role binding definition in the operator config map defines another type of resource: %v", groupVersionKind.Kind))
 | 
							panic(fmt.Errorf("role binding definition in the operator configuration defines another type of resource: %v", groupVersionKind.Kind))
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		c.PodServiceAccountRoleBinding = obj.(*rbacv1.RoleBinding)
 | 
							c.PodServiceAccountRoleBinding = obj.(*rbacv1.RoleBinding)
 | 
				
			||||||
		c.PodServiceAccountRoleBinding.Namespace = ""
 | 
							c.PodServiceAccountRoleBinding.Namespace = ""
 | 
				
			||||||
| 
						 | 
					@ -253,6 +349,10 @@ func (c *Controller) initController() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.initPodServiceAccount()
 | 
						c.initPodServiceAccount()
 | 
				
			||||||
	c.initRoleBinding()
 | 
						c.initRoleBinding()
 | 
				
			||||||
 | 
						// init role only if binding references a role
 | 
				
			||||||
 | 
						if c.PodServiceAccountRoleBinding != nil && c.PodServiceAccountRoleBinding.RoleRef.Kind == "Role" {
 | 
				
			||||||
 | 
							c.initRole()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c.modifyConfigFromEnvironment()
 | 
						c.modifyConfigFromEnvironment()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
 | 
				
			||||||
	result.CustomPodAnnotations = fromCRD.Kubernetes.CustomPodAnnotations
 | 
						result.CustomPodAnnotations = fromCRD.Kubernetes.CustomPodAnnotations
 | 
				
			||||||
	result.PodServiceAccountName = fromCRD.Kubernetes.PodServiceAccountName
 | 
						result.PodServiceAccountName = fromCRD.Kubernetes.PodServiceAccountName
 | 
				
			||||||
	result.PodServiceAccountDefinition = fromCRD.Kubernetes.PodServiceAccountDefinition
 | 
						result.PodServiceAccountDefinition = fromCRD.Kubernetes.PodServiceAccountDefinition
 | 
				
			||||||
 | 
						result.PodServiceAccountRoleDefinition = fromCRD.Kubernetes.PodServiceAccountRoleDefinition
 | 
				
			||||||
	result.PodServiceAccountRoleBindingDefinition = fromCRD.Kubernetes.PodServiceAccountRoleBindingDefinition
 | 
						result.PodServiceAccountRoleBindingDefinition = fromCRD.Kubernetes.PodServiceAccountRoleBindingDefinition
 | 
				
			||||||
	result.PodEnvironmentConfigMap = fromCRD.Kubernetes.PodEnvironmentConfigMap
 | 
						result.PodEnvironmentConfigMap = fromCRD.Kubernetes.PodEnvironmentConfigMap
 | 
				
			||||||
	result.PodTerminateGracePeriod = time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod)
 | 
						result.PodTerminateGracePeriod = time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,23 +493,31 @@ func (c *Controller) postgresqlDelete(obj interface{}) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
  Ensures the pod service account and role bindings exists in a namespace
 | 
					  Ensures the pod service account, role and role bindings exists in a namespace
 | 
				
			||||||
  before a PG cluster is created there so that a user does not have to deploy
 | 
					  before a PG cluster is created there so that a user does not have to deploy
 | 
				
			||||||
  these credentials manually.  StatefulSets require the service account to
 | 
					  these credentials manually.  StatefulSets require the service account to
 | 
				
			||||||
  create pods; Patroni requires relevant RBAC bindings to access endpoints.
 | 
					  create pods; Patroni requires relevant RBAC bindings to access endpoints.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  The operator does not sync accounts/role bindings after creation.
 | 
					  The operator does not sync accounts/roles/role bindings after creation.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
func (c *Controller) submitRBACCredentials(event ClusterEvent) error {
 | 
					func (c *Controller) submitRBACCredentials(event ClusterEvent) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace := event.NewSpec.GetNamespace()
 | 
						namespace := event.NewSpec.GetNamespace()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.createPodServiceAccount(namespace); err != nil {
 | 
						if err := c.createPodServiceAccount(namespace); err != nil {
 | 
				
			||||||
		return fmt.Errorf("could not create pod service account %v : %v", c.opConfig.PodServiceAccountName, err)
 | 
							return fmt.Errorf("could not create pod service account %q : %v", c.opConfig.PodServiceAccountName, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// create role only if binding references a role
 | 
				
			||||||
 | 
						// if not role is empty and we rely on an existing cluster role
 | 
				
			||||||
 | 
						if c.PodServiceAccountRole != nil {
 | 
				
			||||||
 | 
							if err := c.createRole(namespace); err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("could not create role %q : %v", c.PodServiceAccountRole.Name, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.createRoleBindings(namespace); err != nil {
 | 
						if err := c.createRoleBindings(namespace); err != nil {
 | 
				
			||||||
		return fmt.Errorf("could not create role binding %v : %v", c.PodServiceAccountRoleBinding.Name, err)
 | 
							return fmt.Errorf("could not create role binding %q : %v", c.PodServiceAccountRoleBinding.Name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -517,19 +525,39 @@ func (c *Controller) submitRBACCredentials(event ClusterEvent) error {
 | 
				
			||||||
func (c *Controller) createPodServiceAccount(namespace string) error {
 | 
					func (c *Controller) createPodServiceAccount(namespace string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	podServiceAccountName := c.opConfig.PodServiceAccountName
 | 
						podServiceAccountName := c.opConfig.PodServiceAccountName
 | 
				
			||||||
	_, err := c.KubeClient.ServiceAccounts(namespace).Get(podServiceAccountName, metav1.GetOptions{})
 | 
					 | 
				
			||||||
	if k8sutil.ResourceNotFound(err) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		c.logger.Infof(fmt.Sprintf("creating pod service account in the namespace %v", namespace))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get a separate copy of service account
 | 
						// get a separate copy of service account
 | 
				
			||||||
	// to prevent a race condition when setting a namespace for many clusters
 | 
						// to prevent a race condition when setting a namespace for many clusters
 | 
				
			||||||
	sa := *c.PodServiceAccount
 | 
						sa := *c.PodServiceAccount
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := c.KubeClient.ServiceAccounts(namespace).Get(podServiceAccountName, metav1.GetOptions{})
 | 
				
			||||||
 | 
						if k8sutil.ResourceNotFound(err) {
 | 
				
			||||||
 | 
							c.logger.Infof(fmt.Sprintf("creating pod service account %q in the %q namespace", podServiceAccountName, namespace))
 | 
				
			||||||
		if _, err = c.KubeClient.ServiceAccounts(namespace).Create(&sa); err != nil {
 | 
							if _, err = c.KubeClient.ServiceAccounts(namespace).Create(&sa); err != nil {
 | 
				
			||||||
			return fmt.Errorf("cannot deploy the pod service account %v defined in the config map to the %v namespace: %v", podServiceAccountName, namespace, err)
 | 
								return fmt.Errorf("cannot deploy the pod service account %q defined in the configuration to the %q namespace: %v", podServiceAccountName, namespace, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.logger.Infof("successfully deployed the pod service account %q to the %q namespace", podServiceAccountName, namespace)
 | 
				
			||||||
 | 
						} else if k8sutil.ResourceAlreadyExists(err) {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		c.logger.Infof("successfully deployed the pod service account %v to the %v namespace", podServiceAccountName, namespace)
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Controller) createRole(namespace string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						podServiceAccountRoleName := c.PodServiceAccountRole.Name
 | 
				
			||||||
 | 
						// get a separate copy of the role
 | 
				
			||||||
 | 
						// to prevent a race condition when setting a namespace for many clusters
 | 
				
			||||||
 | 
						role := *c.PodServiceAccountRole
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := c.KubeClient.Roles(namespace).Get(podServiceAccountRoleName, metav1.GetOptions{})
 | 
				
			||||||
 | 
						if k8sutil.ResourceNotFound(err) {
 | 
				
			||||||
 | 
							c.logger.Infof("creating role %q in the %q namespace", podServiceAccountRoleName, namespace)
 | 
				
			||||||
 | 
							_, err = c.KubeClient.Roles(namespace).Create(&role)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("cannot create role %q in the %q namespace: %v", podServiceAccountRoleName, namespace, err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.logger.Infof("successfully deployed role %q to the %q namespace", podServiceAccountRoleName, namespace)
 | 
				
			||||||
	} else if k8sutil.ResourceAlreadyExists(err) {
 | 
						} else if k8sutil.ResourceAlreadyExists(err) {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -541,22 +569,18 @@ func (c *Controller) createRoleBindings(namespace string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	podServiceAccountName := c.opConfig.PodServiceAccountName
 | 
						podServiceAccountName := c.opConfig.PodServiceAccountName
 | 
				
			||||||
	podServiceAccountRoleBindingName := c.PodServiceAccountRoleBinding.Name
 | 
						podServiceAccountRoleBindingName := c.PodServiceAccountRoleBinding.Name
 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err := c.KubeClient.RoleBindings(namespace).Get(podServiceAccountRoleBindingName, metav1.GetOptions{})
 | 
					 | 
				
			||||||
	if k8sutil.ResourceNotFound(err) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		c.logger.Infof("Creating the role binding %v in the namespace %v", podServiceAccountRoleBindingName, namespace)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// get a separate copy of role binding
 | 
						// get a separate copy of role binding
 | 
				
			||||||
	// to prevent a race condition when setting a namespace for many clusters
 | 
						// to prevent a race condition when setting a namespace for many clusters
 | 
				
			||||||
	rb := *c.PodServiceAccountRoleBinding
 | 
						rb := *c.PodServiceAccountRoleBinding
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := c.KubeClient.RoleBindings(namespace).Get(podServiceAccountRoleBindingName, metav1.GetOptions{})
 | 
				
			||||||
 | 
						if k8sutil.ResourceNotFound(err) {
 | 
				
			||||||
 | 
							c.logger.Infof("creating the role binding %q in the %q namespace", podServiceAccountRoleBindingName, namespace)
 | 
				
			||||||
		_, err = c.KubeClient.RoleBindings(namespace).Create(&rb)
 | 
							_, err = c.KubeClient.RoleBindings(namespace).Create(&rb)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return fmt.Errorf("cannot bind the pod service account %q defined in the config map to the cluster role in the %q namespace: %v", podServiceAccountName, namespace, err)
 | 
								return fmt.Errorf("cannot bind the pod service account %q defined in the configuration to the cluster role in the %q namespace: %v", podServiceAccountName, namespace, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		c.logger.Infof("successfully deployed the role binding for the pod service account %q to the %q namespace", podServiceAccountName, namespace)
 | 
							c.logger.Infof("successfully deployed the role binding for the pod service account %q to the %q namespace", podServiceAccountName, namespace)
 | 
				
			||||||
 | 
					 | 
				
			||||||
	} else if k8sutil.ResourceAlreadyExists(err) {
 | 
						} else if k8sutil.ResourceAlreadyExists(err) {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,10 +95,10 @@ type Config struct {
 | 
				
			||||||
	EtcdHost              string            `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
 | 
						EtcdHost              string            `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
 | 
				
			||||||
	DockerImage           string            `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p16"`
 | 
						DockerImage           string            `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-cdp-12:1.6-p16"`
 | 
				
			||||||
	Sidecars              map[string]string `name:"sidecar_docker_images"`
 | 
						Sidecars              map[string]string `name:"sidecar_docker_images"`
 | 
				
			||||||
	// default name `operator` enables backward compatibility with the older ServiceAccountName field
 | 
						PodServiceAccountName string            `name:"pod_service_account_name" default:"postgres-pod"`
 | 
				
			||||||
	PodServiceAccountName string `name:"pod_service_account_name" default:"operator"`
 | 
					 | 
				
			||||||
	// value of this string must be valid JSON or YAML; see initPodServiceAccount
 | 
						// value of this string must be valid JSON or YAML; see initPodServiceAccount
 | 
				
			||||||
	PodServiceAccountDefinition            string            `name:"pod_service_account_definition" default:""`
 | 
						PodServiceAccountDefinition            string            `name:"pod_service_account_definition" default:""`
 | 
				
			||||||
 | 
						PodServiceAccountRoleDefinition        string            `name:"pod_service_account_role_definition" default:""`
 | 
				
			||||||
	PodServiceAccountRoleBindingDefinition string            `name:"pod_service_account_role_binding_definition" default:""`
 | 
						PodServiceAccountRoleBindingDefinition string            `name:"pod_service_account_role_binding_definition" default:""`
 | 
				
			||||||
	MasterPodMoveTimeout                   time.Duration     `name:"master_pod_move_timeout" default:"20m"`
 | 
						MasterPodMoveTimeout                   time.Duration     `name:"master_pod_move_timeout" default:"20m"`
 | 
				
			||||||
	DbHostedZone                           string            `name:"db_hosted_zone" default:"db.example.com"`
 | 
						DbHostedZone                           string            `name:"db_hosted_zone" default:"db.example.com"`
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ type KubernetesClient struct {
 | 
				
			||||||
	corev1.NamespacesGetter
 | 
						corev1.NamespacesGetter
 | 
				
			||||||
	corev1.ServiceAccountsGetter
 | 
						corev1.ServiceAccountsGetter
 | 
				
			||||||
	appsv1.StatefulSetsGetter
 | 
						appsv1.StatefulSetsGetter
 | 
				
			||||||
 | 
						rbacv1.RolesGetter
 | 
				
			||||||
	rbacv1.RoleBindingsGetter
 | 
						rbacv1.RoleBindingsGetter
 | 
				
			||||||
	policyv1beta1.PodDisruptionBudgetsGetter
 | 
						policyv1beta1.PodDisruptionBudgetsGetter
 | 
				
			||||||
	apiextbeta1.CustomResourceDefinitionsGetter
 | 
						apiextbeta1.CustomResourceDefinitionsGetter
 | 
				
			||||||
| 
						 | 
					@ -103,6 +104,7 @@ func NewFromConfig(cfg *rest.Config) (KubernetesClient, error) {
 | 
				
			||||||
	kubeClient.StatefulSetsGetter = client.AppsV1()
 | 
						kubeClient.StatefulSetsGetter = client.AppsV1()
 | 
				
			||||||
	kubeClient.PodDisruptionBudgetsGetter = client.PolicyV1beta1()
 | 
						kubeClient.PodDisruptionBudgetsGetter = client.PolicyV1beta1()
 | 
				
			||||||
	kubeClient.RESTClient = client.CoreV1().RESTClient()
 | 
						kubeClient.RESTClient = client.CoreV1().RESTClient()
 | 
				
			||||||
 | 
						kubeClient.RolesGetter = client.RbacV1()
 | 
				
			||||||
	kubeClient.RoleBindingsGetter = client.RbacV1()
 | 
						kubeClient.RoleBindingsGetter = client.RbacV1()
 | 
				
			||||||
	kubeClient.CronJobsGetter = client.BatchV1beta1()
 | 
						kubeClient.CronJobsGetter = client.BatchV1beta1()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue