Merge branch 'master' into default-db-roles
This commit is contained in:
		
						commit
						e2bf0fdedf
					
				| 
						 | 
					@ -87,6 +87,12 @@ rules:
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					  - watch
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - ""
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - pods/exec
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,7 +66,7 @@ configKubernetes:
 | 
				
			||||||
  # list of labels that can be inherited from the cluster manifest
 | 
					  # list of labels that can be inherited from the cluster manifest
 | 
				
			||||||
  # inherited_labels:
 | 
					  # inherited_labels:
 | 
				
			||||||
  # - application
 | 
					  # - application
 | 
				
			||||||
  # - app
 | 
					  # - environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # timeout for successful migration of master pods from unschedulable node
 | 
					  # timeout for successful migration of master pods from unschedulable node
 | 
				
			||||||
  # master_pod_move_timeout: 20m
 | 
					  # master_pod_move_timeout: 20m
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ configKubernetes:
 | 
				
			||||||
  # infrastructure_roles_secret_name: postgresql-infrastructure-roles
 | 
					  # infrastructure_roles_secret_name: postgresql-infrastructure-roles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # list of labels that can be inherited from the cluster manifest
 | 
					  # list of labels that can be inherited from the cluster manifest
 | 
				
			||||||
  # inherited_labels: ""
 | 
					  # inherited_labels: application,environment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # timeout for successful migration of master pods from unschedulable node
 | 
					  # timeout for successful migration of master pods from unschedulable node
 | 
				
			||||||
  # master_pod_move_timeout: 20m
 | 
					  # master_pod_move_timeout: 20m
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -14,8 +14,9 @@ PG_BIN=$PG_DIR/$PG_VERSION/bin
 | 
				
			||||||
DUMP_SIZE_COEFF=5
 | 
					DUMP_SIZE_COEFF=5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
 | 
					TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
 | 
				
			||||||
K8S_API_URL=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT/api/v1
 | 
					K8S_API_URL=https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
 | 
				
			||||||
CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
 | 
					CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
 | 
				
			||||||
 | 
					CLUSTER_NAME_LABEL=cluster-name
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function estimate_size {
 | 
					function estimate_size {
 | 
				
			||||||
    "$PG_BIN"/psql -tqAc "${ALL_DB_SIZE_QUERY}"
 | 
					    "$PG_BIN"/psql -tqAc "${ALL_DB_SIZE_QUERY}"
 | 
				
			||||||
| 
						 | 
					@ -48,33 +49,63 @@ function aws_upload {
 | 
				
			||||||
function get_pods {
 | 
					function get_pods {
 | 
				
			||||||
    declare -r SELECTOR="$1"
 | 
					    declare -r SELECTOR="$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    curl "${K8S_API_URL}/namespaces/${POD_NAMESPACE}/pods?$SELECTOR"        \
 | 
					    curl "${K8S_API_URL}/api/v1/namespaces/${POD_NAMESPACE}/pods?$SELECTOR"        \
 | 
				
			||||||
        --cacert $CERT                          \
 | 
					        --cacert $CERT                          \
 | 
				
			||||||
        -H "Authorization: Bearer ${TOKEN}" | jq .items[].status.podIP -r
 | 
					        -H "Authorization: Bearer ${TOKEN}" | jq .items[].status.podIP -r
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function get_current_pod {
 | 
					function get_current_pod {
 | 
				
			||||||
    curl "${K8S_API_URL}/namespaces/${POD_NAMESPACE}/pods?fieldSelector=metadata.name%3D${HOSTNAME}" \
 | 
					    curl "${K8S_API_URL}/api/v1/namespaces/${POD_NAMESPACE}/pods?fieldSelector=metadata.name%3D${HOSTNAME}" \
 | 
				
			||||||
        --cacert $CERT   \
 | 
					        --cacert $CERT   \
 | 
				
			||||||
        -H "Authorization: Bearer ${TOKEN}"
 | 
					        -H "Authorization: Bearer ${TOKEN}"
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
declare -a search_strategy=(
 | 
					declare -a search_strategy=(
 | 
				
			||||||
 | 
					    get_cluster_name_label
 | 
				
			||||||
    list_all_replica_pods_current_node
 | 
					    list_all_replica_pods_current_node
 | 
				
			||||||
    list_all_replica_pods_any_node
 | 
					    list_all_replica_pods_any_node
 | 
				
			||||||
    get_master_pod
 | 
					    get_master_pod
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function get_config_resource() {
 | 
				
			||||||
 | 
					    curl "${K8S_API_URL}/apis/apps/v1/namespaces/default/deployments/postgres-operator" \
 | 
				
			||||||
 | 
					        --cacert $CERT   \
 | 
				
			||||||
 | 
					        -H "Authorization: Bearer ${TOKEN}" | jq '.spec.template.spec.containers[0].env[] | select(.name == "$1") | .value'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function get_cluster_name_label {
 | 
				
			||||||
 | 
					    local config
 | 
				
			||||||
 | 
					    local clustername
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    config=$(get_config_resource "CONFIG_MAP_NAME")
 | 
				
			||||||
 | 
					    if [ -n "$config" ]; then
 | 
				
			||||||
 | 
					        clustername=$(curl "${K8S_API_URL}/api/v1/namespaces/default/configmaps/${config}" \
 | 
				
			||||||
 | 
					                            --cacert $CERT   \
 | 
				
			||||||
 | 
					                            -H "Authorization: Bearer ${TOKEN}" | jq '.data.cluster_name_label')
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        config=$(get_config_resource "POSTGRES_OPERATOR_CONFIGURATION_OBJECT")
 | 
				
			||||||
 | 
					        if [ -n "$config" ]; then
 | 
				
			||||||
 | 
					            clustername=$(curl "${K8S_API_URL}/apis/acid.zalan.do/v1/namespaces/default/operatorconfigurations/${config}" \
 | 
				
			||||||
 | 
					                                --cacert $CERT   \
 | 
				
			||||||
 | 
					                                -H "Authorization: Bearer ${TOKEN}" | jq '.configuration.kubernetes.cluster_name_label')
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if [ -n "$clustername" ]; then
 | 
				
			||||||
 | 
					        CLUSTER_NAME_LABEL=${clustername}
 | 
				
			||||||
 | 
					    fi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function list_all_replica_pods_current_node {
 | 
					function list_all_replica_pods_current_node {
 | 
				
			||||||
    get_pods "labelSelector=version%3D${SCOPE},spilo-role%3Dreplica&fieldSelector=spec.nodeName%3D${CURRENT_NODENAME}" | head -n 1
 | 
					    get_pods "labelSelector=${CLUSTER_NAME_LABEL}%3D${SCOPE},spilo-role%3Dreplica&fieldSelector=spec.nodeName%3D${CURRENT_NODENAME}" | head -n 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function list_all_replica_pods_any_node {
 | 
					function list_all_replica_pods_any_node {
 | 
				
			||||||
    get_pods "labelSelector=version%3D${SCOPE},spilo-role%3Dreplica" | head -n 1
 | 
					    get_pods "labelSelector=${CLUSTER_NAME_LABEL}%3D${SCOPE},spilo-role%3Dreplica" | head -n 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function get_master_pod {
 | 
					function get_master_pod {
 | 
				
			||||||
    get_pods "labelSelector=version%3D${SCOPE},spilo-role%3Dmaster" | head -n 1
 | 
					    get_pods "labelSelector=${CLUSTER_NAME_LABEL}%3D${SCOPE},spilo-role%3Dmaster" | head -n 1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CURRENT_NODENAME=$(get_current_pod | jq .items[].spec.nodeName --raw-output)
 | 
					CURRENT_NODENAME=$(get_current_pod | jq .items[].spec.nodeName --raw-output)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,7 @@ parameter of the PDB is set to `1` which prevents killing masters in single-node
 | 
				
			||||||
clusters and/or the last remaining running instance in a multi-node cluster.
 | 
					clusters and/or the last remaining running instance in a multi-node cluster.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The PDB is only relaxed in two scenarios:
 | 
					The PDB is only relaxed in two scenarios:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* If a cluster is scaled down to `0` instances (e.g. for draining nodes)
 | 
					* If a cluster is scaled down to `0` instances (e.g. for draining nodes)
 | 
				
			||||||
* If the PDB is disabled in the configuration (`enable_pod_disruption_budget`)
 | 
					* If the PDB is disabled in the configuration (`enable_pod_disruption_budget`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,6 +201,18 @@ Postgres cluster, in order to identify its child objects. The typical use case
 | 
				
			||||||
is to add labels that identifies the `Pods` created by the operator, in order
 | 
					is to add labels that identifies the `Pods` created by the operator, in order
 | 
				
			||||||
to implement fine-controlled `NetworkPolicies`.
 | 
					to implement fine-controlled `NetworkPolicies`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**postgres-operator ConfigMap**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```yaml
 | 
				
			||||||
 | 
					apiVersion: v1
 | 
				
			||||||
 | 
					kind: ConfigMap
 | 
				
			||||||
 | 
					metadata:
 | 
				
			||||||
 | 
					  name: postgres-operator
 | 
				
			||||||
 | 
					data:
 | 
				
			||||||
 | 
					  inherited_labels: application,environment
 | 
				
			||||||
 | 
					  ...
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**OperatorConfiguration**
 | 
					**OperatorConfiguration**
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```yaml
 | 
					```yaml
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ is prepended to the operator resource's names.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Use `--name zalando` to match with the default service account name as older
 | 
					Use `--name zalando` to match with the default service account name as older
 | 
				
			||||||
operator versions do not support custom names for service accounts. To use
 | 
					operator versions do not support custom names for service accounts. To use
 | 
				
			||||||
CRD-based configuration you need to specify the [values-crd yaml file](../charts/values-crd.yaml).
 | 
					CRD-based configuration you need to specify the [values-crd yaml file](../charts/postgres-operator/values-crd.yaml).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```bash
 | 
					```bash
 | 
				
			||||||
# 1) initialize helm
 | 
					# 1) initialize helm
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,8 @@ apiVersion: "acid.zalan.do/v1"
 | 
				
			||||||
kind: postgresql
 | 
					kind: postgresql
 | 
				
			||||||
metadata:
 | 
					metadata:
 | 
				
			||||||
  name: acid-test-cluster
 | 
					  name: acid-test-cluster
 | 
				
			||||||
 | 
					#  labels:
 | 
				
			||||||
 | 
					#    environment: demo
 | 
				
			||||||
spec:
 | 
					spec:
 | 
				
			||||||
  dockerImage: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
 | 
					  dockerImage: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
 | 
				
			||||||
  initContainers:
 | 
					  initContainers:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ data:
 | 
				
			||||||
  enable_teams_api: "false"
 | 
					  enable_teams_api: "false"
 | 
				
			||||||
  # etcd_host: ""
 | 
					  # etcd_host: ""
 | 
				
			||||||
  # infrastructure_roles_secret_name: postgresql-infrastructure-roles
 | 
					  # infrastructure_roles_secret_name: postgresql-infrastructure-roles
 | 
				
			||||||
  # inherited_labels: ""
 | 
					  # inherited_labels: application,environment
 | 
				
			||||||
  # kube_iam_role: ""
 | 
					  # kube_iam_role: ""
 | 
				
			||||||
  # log_s3_bucket: ""
 | 
					  # log_s3_bucket: ""
 | 
				
			||||||
  # logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
 | 
					  # logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -88,6 +88,12 @@ rules:
 | 
				
			||||||
  - list
 | 
					  - list
 | 
				
			||||||
  - watch
 | 
					  - watch
 | 
				
			||||||
  - patch
 | 
					  - patch
 | 
				
			||||||
 | 
					- apiGroups:
 | 
				
			||||||
 | 
					  - ""
 | 
				
			||||||
 | 
					  resources:
 | 
				
			||||||
 | 
					  - pods/exec
 | 
				
			||||||
 | 
					  verbs:
 | 
				
			||||||
 | 
					  - create
 | 
				
			||||||
- apiGroups:
 | 
					- apiGroups:
 | 
				
			||||||
  - ""
 | 
					  - ""
 | 
				
			||||||
  resources:
 | 
					  resources:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@ configuration:
 | 
				
			||||||
    # infrastructure_roles_secret_name: ""
 | 
					    # infrastructure_roles_secret_name: ""
 | 
				
			||||||
    # inherited_labels:
 | 
					    # inherited_labels:
 | 
				
			||||||
    # - application
 | 
					    # - application
 | 
				
			||||||
    # - app
 | 
					    # - environment
 | 
				
			||||||
    # node_readiness_label: ""
 | 
					    # node_readiness_label: ""
 | 
				
			||||||
    oauth_token_secret_name: postgresql-operator
 | 
					    oauth_token_secret_name: postgresql-operator
 | 
				
			||||||
    pdb_name_format: "postgres-{cluster}-pdb"
 | 
					    pdb_name_format: "postgres-{cluster}-pdb"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,7 +329,7 @@ func (c *Cluster) deleteStatefulSet() error {
 | 
				
			||||||
		return fmt.Errorf("could not delete pods: %v", err)
 | 
							return fmt.Errorf("could not delete pods: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := c.deletePersistenVolumeClaims(); err != nil {
 | 
						if err := c.deletePersistentVolumeClaims(); err != nil {
 | 
				
			||||||
		return fmt.Errorf("could not delete PersistentVolumeClaims: %v", err)
 | 
							return fmt.Errorf("could not delete PersistentVolumeClaims: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,7 @@ func (c *Cluster) listPersistentVolumeClaims() ([]v1.PersistentVolumeClaim, erro
 | 
				
			||||||
	return pvcs.Items, nil
 | 
						return pvcs.Items, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *Cluster) deletePersistenVolumeClaims() error {
 | 
					func (c *Cluster) deletePersistentVolumeClaims() error {
 | 
				
			||||||
	c.logger.Debugln("deleting PVCs")
 | 
						c.logger.Debugln("deleting PVCs")
 | 
				
			||||||
	pvcs, err := c.listPersistentVolumeClaims()
 | 
						pvcs, err := c.listPersistentVolumeClaims()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,6 @@ type Controller struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	PodServiceAccount            *v1.ServiceAccount
 | 
						PodServiceAccount            *v1.ServiceAccount
 | 
				
			||||||
	PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding
 | 
						PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding
 | 
				
			||||||
	namespacesWithDefinedRBAC    sync.Map
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewController creates a new controller
 | 
					// NewController creates a new controller
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -493,17 +493,16 @@ func (c *Controller) postgresqlDelete(obj interface{}) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
  Ensures the pod service account and role bindings exists in a namespace before a PG cluster is created there so that a user does not have to deploy these credentials manually.
 | 
					  Ensures the pod service account and role bindings exists in a namespace
 | 
				
			||||||
  StatefulSets require the service account to create pods; Patroni requires relevant RBAC bindings to access endpoints.
 | 
					  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
 | 
				
			||||||
 | 
					  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/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 _, ok := c.namespacesWithDefinedRBAC.Load(namespace); ok {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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 %v : %v", c.opConfig.PodServiceAccountName, err)
 | 
				
			||||||
| 
						 | 
					@ -512,7 +511,6 @@ func (c *Controller) submitRBACCredentials(event ClusterEvent) error {
 | 
				
			||||||
	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 %v : %v", c.PodServiceAccountRoleBinding.Name, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c.namespacesWithDefinedRBAC.Store(namespace, true)
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue