Skip to content

Commit d11b23b

Browse files
stangsdudoladov
authored andcommitted
Add inherited_labels (zalando#459)
* add support for inherited_labels Signed-off-by: Stephane Tang <[email protected]> * update docs with inherited_labels Signed-off-by: Stephane Tang <[email protected]>
1 parent f2dddb0 commit d11b23b

File tree

10 files changed

+108
-22
lines changed

10 files changed

+108
-22
lines changed

docs/administrator.md

+51
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,57 @@ data:
146146
...
147147
```
148148

149+
### Add cluster-specific labels
150+
151+
In some cases, you might want to add `labels` that are specific to a given
152+
postgres cluster, in order to identify its child objects.
153+
The typical use case is to add labels that identifies the `Pods` created by the
154+
operator, in order to implement fine-controlled `NetworkPolicies`.
155+
156+
**OperatorConfiguration**
157+
158+
```yaml
159+
apiVersion: "acid.zalan.do/v1"
160+
kind: OperatorConfiguration
161+
metadata:
162+
name: postgresql-operator-configuration
163+
configuration:
164+
kubernetes:
165+
inherited_labels:
166+
- application
167+
- environment
168+
...
169+
```
170+
171+
**cluster manifest**
172+
173+
```yaml
174+
apiVersion: "acid.zalan.do/v1"
175+
kind: postgresql
176+
metadata:
177+
name: demo-cluster
178+
labels:
179+
application: my-app
180+
environment: demo
181+
spec:
182+
...
183+
```
184+
185+
**network policy**
186+
187+
```yaml
188+
kind: NetworkPolicy
189+
apiVersion: networking.k8s.io/v1
190+
metadata:
191+
name: netpol-example
192+
spec:
193+
podSelector:
194+
matchLabels:
195+
application: my-app
196+
environment: demo
197+
...
198+
```
199+
149200
## Custom Pod Environment Variables
150201

151202
It is possible to configure a ConfigMap which is used by the Postgres pods as

docs/reference/cluster_manifest.md

+13-5
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,15 @@ Those parameters are grouped under the `metadata` top-level key.
3333
services, secrets) for the cluster. Changing it after the cluster creation
3434
results in deploying or updating a completely separate cluster in the target
3535
namespace. Optional (if present, should match the namespace where the
36-
manifest is applied).
36+
manifest is applied).
37+
38+
* **labels**
39+
if labels are matching one of the `inherited_labels` [configured in the
40+
operator parameters](operator_parameters.md#kubernetes-resources),
41+
they will automatically be added to all the objects (StatefulSet, Service,
42+
Endpoints, etc.) that are created by the operator.
43+
Labels that are set here but not listed as `inherited_labels` in the operator
44+
parameters are ignored.
3745

3846
## Top-level parameters
3947

@@ -89,7 +97,7 @@ Those are parameters grouped directly under the `spec` key in the manifest.
8997
examples](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/)
9098
for details on tolerations and possible values of those keys. When set, this
9199
value overrides the `pod_toleration` setting from the operator. Optional.
92-
100+
93101
* **podPriorityClassName**
94102
a name of the [priority
95103
class](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass)
@@ -135,7 +143,7 @@ explanation of `ttl` and `loop_wait` parameters.
135143
a map of key-value pairs describing initdb parameters. For `data-checksum`,
136144
`debug`, `no-locale`, `noclean`, `nosync` and `sync-only` parameters use
137145
`true` as the value if you want to set them. Changes to this option do not
138-
affect the already initialized clusters. Optional.
146+
affect the already initialized clusters. Optional.
139147

140148
* **pg_hba**
141149
list of custom `pg_hba` lines to replace default ones. Note that the default
@@ -215,7 +223,7 @@ under the `clone` top-level key and do not affect the already running cluster.
215223
different namespaces) , the operator uses UID in the S3 bucket name in order
216224
to guarantee uniqueness. Has no effect when cloning from the running
217225
clusters. Optional.
218-
226+
219227
* **timestamp**
220228
the timestamp up to which the recovery should proceed. The operator always
221229
configures non-inclusive recovery target, stopping right before the given
@@ -235,7 +243,7 @@ properties of the persistent storage that stores postgres data.
235243
the name of the Kubernetes storage class to draw the persistent volume from.
236244
See [Kubernetes
237245
documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/)
238-
for the details on storage classes. Optional.
246+
for the details on storage classes. Optional.
239247

240248
### Sidecar definitions
241249

docs/reference/operator_parameters.md

+14-6
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ configuration.
1212

1313
* CRD-based configuration. The configuration is stored in a custom YAML
1414
manifest. The manifest is an instance of the custom resource definition (CRD) called
15-
`OperatorConfiguration`. The operator registers this CRD
15+
`OperatorConfiguration`. The operator registers this CRD
1616
during the start and uses it for configuration if the [operator deployment manifest ](https://github.com/zalando-incubator/postgres-operator/blob/master/manifests/postgres-operator.yaml#L21) sets the `POSTGRES_OPERATOR_CONFIGURATION_OBJECT` env variable to a non-empty value. The variable should point to the
1717
`postgresql-operator-configuration` object in the operator's namespace.
1818

1919
The CRD-based configuration is a regular YAML
20-
document; non-scalar keys are simply represented in the usual YAML way.
20+
document; non-scalar keys are simply represented in the usual YAML way.
2121
There are no default values built-in in the operator, each parameter that is
2222
not supplied in the configuration receives an empty value. In order to
2323
create your own configuration just copy the [default
@@ -172,6 +172,14 @@ configuration they are grouped under the `kubernetes` key.
172172
list of `name:value` pairs for additional labels assigned to the cluster
173173
objects. The default is `application:spilo`.
174174

175+
* **inherited_labels**
176+
list of labels that can be inherited from the cluster manifest, and added to
177+
each child objects (`StatefulSet`, `Pod`, `Service` and `Endpoints`) created by
178+
the opertor.
179+
Typical use case is to dynamically pass labels that are specific to a given
180+
postgres cluster, in order to implement `NetworkPolicy`.
181+
The default is empty.
182+
175183
* **cluster_name_label**
176184
name of the label assigned to Kubernetes objects created by the operator that
177185
indicates which cluster a given object belongs to. The default is
@@ -198,13 +206,13 @@ configuration they are grouped under the `kubernetes` key.
198206
All variables from that ConfigMap are injected to the pod's environment, on
199207
conflicts they are overridden by the environment variables generated by the
200208
operator. The default is empty.
201-
209+
202210
* **pod_priority_class_name**
203211
a name of the [priority
204212
class](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass)
205213
that should be assigned to the Postgres pods. The priority class itself must be defined in advance.
206214
Default is empty (use the default priority class).
207-
215+
208216

209217
## Kubernetes resource requests
210218

@@ -350,7 +358,7 @@ Options to aid debugging of the operator itself. Grouped under the `debug` key.
350358
boolean parameter that toggles the functionality of the operator that require
351359
access to the postgres database, i.e. creating databases and users. The default
352360
is `true`.
353-
361+
354362
## Automatic creation of human users in the database
355363

356364
Options to automate creation of human users with the aid of the teams API
@@ -448,4 +456,4 @@ scalyr sidecar. In the CRD-based configuration they are grouped under the
448456
Memory limit value for the Scalyr sidecar. The default is `1Gi`.
449457

450458

451-
For the configmap operator configuration, the [default parameter values](https://github.com/zalando-incubator/postgres-operator/blob/master/pkg/util/config/config.go#L14) mentioned here are likely to be overwritten in your local operator installation via your local version of the operator configmap. In the case you use the operator CRD, all the CRD defaults are provided in the [operator's default configuration manifest](https://github.com/zalando-incubator/postgres-operator/blob/master/manifests/postgresql-operator-default-configuration.yaml)
459+
For the configmap operator configuration, the [default parameter values](https://github.com/zalando-incubator/postgres-operator/blob/master/pkg/util/config/config.go#L14) mentioned here are likely to be overwritten in your local operator installation via your local version of the operator configmap. In the case you use the operator CRD, all the CRD defaults are provided in the [operator's default configuration manifest](https://github.com/zalando-incubator/postgres-operator/blob/master/manifests/postgresql-operator-default-configuration.yaml)

manifests/postgresql-operator-default-configuration.yaml

+7-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,11 @@ configuration:
2525
pod_role_label: spilo-role
2626
cluster_labels:
2727
application: spilo
28+
# inherited_labels:
29+
# - application
30+
# - app
2831
cluster_name_label: cluster-name
29-
# watched_namespace:""
32+
# watched_namespace:""
3033
# node_readiness_label: ""
3134
# toleration: {}
3235
# infrastructure_roles_secret_name: ""
@@ -53,7 +56,7 @@ configuration:
5356
replica_dns_name_format: "{cluster}-repl.{team}.{hostedzone}"
5457
aws_or_gcp:
5558
# db_hosted_zone: ""
56-
# wal_s3_bucket: ""
59+
# wal_s3_bucket: ""
5760
# log_s3_bucket: ""
5861
# kube_iam_role: ""
5962
aws_region: eu-central-1
@@ -62,13 +65,13 @@ configuration:
6265
enable_database_access: true
6366
teams_api:
6467
enable_teams_api: false
65-
team_api_role_configuration:
68+
team_api_role_configuration:
6669
log_statement: all
6770
enable_team_superuser: false
6871
team_admin_role: admin
6972
pam_role_name: zalandos
7073
# pam_configuration: ""
71-
protected_role_names:
74+
protected_role_names:
7275
- admin
7376
# teams_api_url: ""
7477
# postgres_superuser_teams: "postgres_superusers"

pkg/apis/acid.zalan.do/v1/operator_configuration_type.go

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ type KubernetesMetaConfiguration struct {
5252
InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"`
5353
PodRoleLabel string `json:"pod_role_label,omitempty"`
5454
ClusterLabels map[string]string `json:"cluster_labels,omitempty"`
55+
InheritedLabels []string `json:"inherited_labels,omitempty"`
5556
ClusterNameLabel string `json:"cluster_name_label,omitempty"`
5657
NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"`
5758
// TODO: use a proper toleration structure?

pkg/cluster/k8sres.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ func (c *Cluster) generateService(role PostgresRole, spec *acidv1.PostgresSpec)
10731073
}
10741074

10751075
if role == Replica {
1076-
serviceSpec.Selector = c.roleLabelsSet(role)
1076+
serviceSpec.Selector = c.roleLabelsSet(false, role)
10771077
}
10781078

10791079
var annotations map[string]string
@@ -1113,7 +1113,7 @@ func (c *Cluster) generateService(role PostgresRole, spec *acidv1.PostgresSpec)
11131113
ObjectMeta: metav1.ObjectMeta{
11141114
Name: c.serviceName(role),
11151115
Namespace: c.Namespace,
1116-
Labels: c.roleLabelsSet(role),
1116+
Labels: c.roleLabelsSet(true, role),
11171117
Annotations: annotations,
11181118
},
11191119
Spec: serviceSpec,
@@ -1127,7 +1127,7 @@ func (c *Cluster) generateEndpoint(role PostgresRole, subsets []v1.EndpointSubse
11271127
ObjectMeta: metav1.ObjectMeta{
11281128
Name: c.endpointName(role),
11291129
Namespace: c.Namespace,
1130-
Labels: c.roleLabelsSet(role),
1130+
Labels: c.roleLabelsSet(true, role),
11311131
},
11321132
}
11331133
if len(subsets) > 0 {
@@ -1191,7 +1191,7 @@ func (c *Cluster) generatePodDisruptionBudget() *policybeta1.PodDisruptionBudget
11911191
Spec: policybeta1.PodDisruptionBudgetSpec{
11921192
MinAvailable: &minAvailable,
11931193
Selector: &metav1.LabelSelector{
1194-
MatchLabels: c.roleLabelsSet(Master),
1194+
MatchLabels: c.roleLabelsSet(false, Master),
11951195
},
11961196
},
11971197
}

pkg/cluster/pod.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func (c *Cluster) listPods() ([]v1.Pod, error) {
2727

2828
func (c *Cluster) getRolePods(role PostgresRole) ([]v1.Pod, error) {
2929
listOptions := metav1.ListOptions{
30-
LabelSelector: c.roleLabelsSet(role).String(),
30+
LabelSelector: c.roleLabelsSet(false, role).String(),
3131
}
3232

3333
pods, err := c.KubeClient.Pods(c.Namespace).List(listOptions)

pkg/cluster/util.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,19 @@ func (c *Cluster) labelsSet(shouldAddExtraLabels bool) labels.Set {
389389
if shouldAddExtraLabels {
390390
// enables filtering resources owned by a team
391391
lbls["team"] = c.Postgresql.Spec.TeamID
392+
393+
// allow to inherit certain labels from the 'postgres' object
394+
if spec, err := c.GetSpec(); err == nil {
395+
for k, v := range spec.ObjectMeta.Labels {
396+
for _, match := range c.OpConfig.InheritedLabels {
397+
if k == match {
398+
lbls[k] = v
399+
}
400+
}
401+
}
402+
} else {
403+
c.logger.Warningf("could not get the list of InheritedLabels for cluster %q: %v", c.Name, err)
404+
}
392405
}
393406

394407
return labels.Set(lbls)
@@ -398,8 +411,8 @@ func (c *Cluster) labelsSelector() *metav1.LabelSelector {
398411
return &metav1.LabelSelector{MatchLabels: c.labelsSet(false), MatchExpressions: nil}
399412
}
400413

401-
func (c *Cluster) roleLabelsSet(role PostgresRole) labels.Set {
402-
lbls := c.labelsSet(false)
414+
func (c *Cluster) roleLabelsSet(shouldAddExtraLabels bool, role PostgresRole) labels.Set {
415+
lbls := c.labelsSet(shouldAddExtraLabels)
403416
lbls[c.OpConfig.PodRoleLabel] = string(role)
404417
return lbls
405418
}

pkg/controller/operator_config.go

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
4848
result.InfrastructureRolesSecretName = fromCRD.Kubernetes.InfrastructureRolesSecretName
4949
result.PodRoleLabel = fromCRD.Kubernetes.PodRoleLabel
5050
result.ClusterLabels = fromCRD.Kubernetes.ClusterLabels
51+
result.InheritedLabels = fromCRD.Kubernetes.InheritedLabels
5152
result.ClusterNameLabel = fromCRD.Kubernetes.ClusterNameLabel
5253
result.NodeReadinessLabel = fromCRD.Kubernetes.NodeReadinessLabel
5354
result.PodPriorityClassName = fromCRD.Kubernetes.PodPriorityClassName

pkg/util/config/config.go

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type Resources struct {
2727
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
2828
PodPriorityClassName string `name:"pod_priority_class_name"`
2929
ClusterLabels map[string]string `name:"cluster_labels" default:"application:spilo"`
30+
InheritedLabels []string `name:"inherited_labels" default:""`
3031
ClusterNameLabel string `name:"cluster_name_label" default:"cluster-name"`
3132
PodRoleLabel string `name:"pod_role_label" default:"spilo-role"`
3233
PodToleration map[string]string `name:"toleration" default:""`

0 commit comments

Comments
 (0)