Merge branch 'master' into default-db-roles

This commit is contained in:
Felix Kunde 2019-10-29 12:05:17 +01:00
commit e2bf0fdedf
14 changed files with 76 additions and 21 deletions

View File

@ -87,6 +87,12 @@ rules:
- list
- watch
- patch
- apiGroups:
- ""
resources:
- pods/exec
verbs:
- create
- apiGroups:
- ""
resources:

View File

@ -66,7 +66,7 @@ configKubernetes:
# list of labels that can be inherited from the cluster manifest
# inherited_labels:
# - application
# - app
# - environment
# timeout for successful migration of master pods from unschedulable node
# master_pod_move_timeout: 20m

View File

@ -62,7 +62,7 @@ configKubernetes:
# infrastructure_roles_secret_name: postgresql-infrastructure-roles
# 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
# master_pod_move_timeout: 20m

View File

@ -14,8 +14,9 @@ PG_BIN=$PG_DIR/$PG_VERSION/bin
DUMP_SIZE_COEFF=5
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
CLUSTER_NAME_LABEL=cluster-name
function estimate_size {
"$PG_BIN"/psql -tqAc "${ALL_DB_SIZE_QUERY}"
@ -48,33 +49,63 @@ function aws_upload {
function get_pods {
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 \
-H "Authorization: Bearer ${TOKEN}" | jq .items[].status.podIP -r
}
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 \
-H "Authorization: Bearer ${TOKEN}"
}
declare -a search_strategy=(
get_cluster_name_label
list_all_replica_pods_current_node
list_all_replica_pods_any_node
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 {
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 {
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 {
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)

View File

@ -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.
The PDB is only relaxed in two scenarios:
* 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`)
@ -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
to implement fine-controlled `NetworkPolicies`.
**postgres-operator ConfigMap**
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: postgres-operator
data:
inherited_labels: application,environment
...
```
**OperatorConfiguration**
```yaml
@ -375,7 +388,7 @@ manifest. Notes:
backup via `pg_dumpall` and upload of compressed and encrypted results to an S3
bucket; the default image ``registry.opensource.zalan.do/acid/logical-backup``
is the same image built with the Zalando-internal CI pipeline. `pg_dumpall`
requires a `superuser` access to a DB and runs on the replica when possible.
requires a `superuser` access to a DB and runs on the replica when possible.
2. Due to the [limitation of K8s cron jobs](https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/#cron-job-limitations)
it is highly advisable to set up additional monitoring for this feature; such

View File

@ -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
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
# 1) initialize helm

View File

@ -2,6 +2,8 @@ apiVersion: "acid.zalan.do/v1"
kind: postgresql
metadata:
name: acid-test-cluster
# labels:
# environment: demo
spec:
dockerImage: registry.opensource.zalan.do/acid/spilo-11:1.6-p1
initContainers:

View File

@ -31,7 +31,7 @@ data:
enable_teams_api: "false"
# etcd_host: ""
# infrastructure_roles_secret_name: postgresql-infrastructure-roles
# inherited_labels: ""
# inherited_labels: application,environment
# kube_iam_role: ""
# log_s3_bucket: ""
# logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup"

View File

@ -88,6 +88,12 @@ rules:
- list
- watch
- patch
- apiGroups:
- ""
resources:
- pods/exec
verbs:
- create
- apiGroups:
- ""
resources:

View File

@ -27,7 +27,7 @@ configuration:
# infrastructure_roles_secret_name: ""
# inherited_labels:
# - application
# - app
# - environment
# node_readiness_label: ""
oauth_token_secret_name: postgresql-operator
pdb_name_format: "postgres-{cluster}-pdb"

View File

@ -329,7 +329,7 @@ func (c *Cluster) deleteStatefulSet() error {
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)
}

View File

@ -30,7 +30,7 @@ func (c *Cluster) listPersistentVolumeClaims() ([]v1.PersistentVolumeClaim, erro
return pvcs.Items, nil
}
func (c *Cluster) deletePersistenVolumeClaims() error {
func (c *Cluster) deletePersistentVolumeClaims() error {
c.logger.Debugln("deleting PVCs")
pvcs, err := c.listPersistentVolumeClaims()
if err != nil {

View File

@ -58,7 +58,6 @@ type Controller struct {
PodServiceAccount *v1.ServiceAccount
PodServiceAccountRoleBinding *rbacv1beta1.RoleBinding
namespacesWithDefinedRBAC sync.Map
}
// NewController creates a new controller

View File

@ -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.
StatefulSets require the service account to create pods; Patroni requires relevant RBAC bindings to access endpoints.
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. 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.
*/
func (c *Controller) submitRBACCredentials(event ClusterEvent) error {
namespace := event.NewSpec.GetNamespace()
if _, ok := c.namespacesWithDefinedRBAC.Load(namespace); ok {
return nil
}
if err := c.createPodServiceAccount(namespace); err != nil {
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 {
return fmt.Errorf("could not create role binding %v : %v", c.PodServiceAccountRoleBinding.Name, err)
}
c.namespacesWithDefinedRBAC.Store(namespace, true)
return nil
}