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