Add inherited_labels (#459)
* add support for inherited_labels Signed-off-by: Stephane Tang <hi@stang.sh> * update docs with inherited_labels Signed-off-by: Stephane Tang <hi@stang.sh>
This commit is contained in:
parent
f2dddb0f2b
commit
d11b23bd71
|
|
@ -146,6 +146,57 @@ data:
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Add cluster-specific labels
|
||||||
|
|
||||||
|
In some cases, you might want to add `labels` that are specific to a given
|
||||||
|
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`.
|
||||||
|
|
||||||
|
**OperatorConfiguration**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "acid.zalan.do/v1"
|
||||||
|
kind: OperatorConfiguration
|
||||||
|
metadata:
|
||||||
|
name: postgresql-operator-configuration
|
||||||
|
configuration:
|
||||||
|
kubernetes:
|
||||||
|
inherited_labels:
|
||||||
|
- application
|
||||||
|
- environment
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
**cluster manifest**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "acid.zalan.do/v1"
|
||||||
|
kind: postgresql
|
||||||
|
metadata:
|
||||||
|
name: demo-cluster
|
||||||
|
labels:
|
||||||
|
application: my-app
|
||||||
|
environment: demo
|
||||||
|
spec:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
**network policy**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: NetworkPolicy
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
metadata:
|
||||||
|
name: netpol-example
|
||||||
|
spec:
|
||||||
|
podSelector:
|
||||||
|
matchLabels:
|
||||||
|
application: my-app
|
||||||
|
environment: demo
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
## Custom Pod Environment Variables
|
## Custom Pod Environment Variables
|
||||||
|
|
||||||
It is possible to configure a ConfigMap which is used by the Postgres pods as
|
It is possible to configure a ConfigMap which is used by the Postgres pods as
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,14 @@ Those parameters are grouped under the `metadata` top-level key.
|
||||||
namespace. Optional (if present, should match the namespace where the
|
namespace. Optional (if present, should match the namespace where the
|
||||||
manifest is applied).
|
manifest is applied).
|
||||||
|
|
||||||
|
* **labels**
|
||||||
|
if labels are matching one of the `inherited_labels` [configured in the
|
||||||
|
operator parameters](operator_parameters.md#kubernetes-resources),
|
||||||
|
they will automatically be added to all the objects (StatefulSet, Service,
|
||||||
|
Endpoints, etc.) that are created by the operator.
|
||||||
|
Labels that are set here but not listed as `inherited_labels` in the operator
|
||||||
|
parameters are ignored.
|
||||||
|
|
||||||
## Top-level parameters
|
## Top-level parameters
|
||||||
|
|
||||||
Those are parameters grouped directly under the `spec` key in the manifest.
|
Those are parameters grouped directly under the `spec` key in the manifest.
|
||||||
|
|
|
||||||
|
|
@ -172,6 +172,14 @@ configuration they are grouped under the `kubernetes` key.
|
||||||
list of `name:value` pairs for additional labels assigned to the cluster
|
list of `name:value` pairs for additional labels assigned to the cluster
|
||||||
objects. The default is `application:spilo`.
|
objects. The default is `application:spilo`.
|
||||||
|
|
||||||
|
* **inherited_labels**
|
||||||
|
list of labels that can be inherited from the cluster manifest, and added to
|
||||||
|
each child objects (`StatefulSet`, `Pod`, `Service` and `Endpoints`) created by
|
||||||
|
the opertor.
|
||||||
|
Typical use case is to dynamically pass labels that are specific to a given
|
||||||
|
postgres cluster, in order to implement `NetworkPolicy`.
|
||||||
|
The default is empty.
|
||||||
|
|
||||||
* **cluster_name_label**
|
* **cluster_name_label**
|
||||||
name of the label assigned to Kubernetes objects created by the operator that
|
name of the label assigned to Kubernetes objects created by the operator that
|
||||||
indicates which cluster a given object belongs to. The default is
|
indicates which cluster a given object belongs to. The default is
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ configuration:
|
||||||
pod_role_label: spilo-role
|
pod_role_label: spilo-role
|
||||||
cluster_labels:
|
cluster_labels:
|
||||||
application: spilo
|
application: spilo
|
||||||
|
# inherited_labels:
|
||||||
|
# - application
|
||||||
|
# - app
|
||||||
cluster_name_label: cluster-name
|
cluster_name_label: cluster-name
|
||||||
# watched_namespace:""
|
# watched_namespace:""
|
||||||
# node_readiness_label: ""
|
# node_readiness_label: ""
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ type KubernetesMetaConfiguration struct {
|
||||||
InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"`
|
InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"`
|
||||||
PodRoleLabel string `json:"pod_role_label,omitempty"`
|
PodRoleLabel string `json:"pod_role_label,omitempty"`
|
||||||
ClusterLabels map[string]string `json:"cluster_labels,omitempty"`
|
ClusterLabels map[string]string `json:"cluster_labels,omitempty"`
|
||||||
|
InheritedLabels []string `json:"inherited_labels,omitempty"`
|
||||||
ClusterNameLabel string `json:"cluster_name_label,omitempty"`
|
ClusterNameLabel string `json:"cluster_name_label,omitempty"`
|
||||||
NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"`
|
NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"`
|
||||||
// TODO: use a proper toleration structure?
|
// TODO: use a proper toleration structure?
|
||||||
|
|
|
||||||
|
|
@ -1073,7 +1073,7 @@ func (c *Cluster) generateService(role PostgresRole, spec *acidv1.PostgresSpec)
|
||||||
}
|
}
|
||||||
|
|
||||||
if role == Replica {
|
if role == Replica {
|
||||||
serviceSpec.Selector = c.roleLabelsSet(role)
|
serviceSpec.Selector = c.roleLabelsSet(false, role)
|
||||||
}
|
}
|
||||||
|
|
||||||
var annotations map[string]string
|
var annotations map[string]string
|
||||||
|
|
@ -1113,7 +1113,7 @@ func (c *Cluster) generateService(role PostgresRole, spec *acidv1.PostgresSpec)
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: c.serviceName(role),
|
Name: c.serviceName(role),
|
||||||
Namespace: c.Namespace,
|
Namespace: c.Namespace,
|
||||||
Labels: c.roleLabelsSet(role),
|
Labels: c.roleLabelsSet(true, role),
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
},
|
},
|
||||||
Spec: serviceSpec,
|
Spec: serviceSpec,
|
||||||
|
|
@ -1127,7 +1127,7 @@ func (c *Cluster) generateEndpoint(role PostgresRole, subsets []v1.EndpointSubse
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: c.endpointName(role),
|
Name: c.endpointName(role),
|
||||||
Namespace: c.Namespace,
|
Namespace: c.Namespace,
|
||||||
Labels: c.roleLabelsSet(role),
|
Labels: c.roleLabelsSet(true, role),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
if len(subsets) > 0 {
|
if len(subsets) > 0 {
|
||||||
|
|
@ -1191,7 +1191,7 @@ func (c *Cluster) generatePodDisruptionBudget() *policybeta1.PodDisruptionBudget
|
||||||
Spec: policybeta1.PodDisruptionBudgetSpec{
|
Spec: policybeta1.PodDisruptionBudgetSpec{
|
||||||
MinAvailable: &minAvailable,
|
MinAvailable: &minAvailable,
|
||||||
Selector: &metav1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: c.roleLabelsSet(Master),
|
MatchLabels: c.roleLabelsSet(false, Master),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func (c *Cluster) listPods() ([]v1.Pod, error) {
|
||||||
|
|
||||||
func (c *Cluster) getRolePods(role PostgresRole) ([]v1.Pod, error) {
|
func (c *Cluster) getRolePods(role PostgresRole) ([]v1.Pod, error) {
|
||||||
listOptions := metav1.ListOptions{
|
listOptions := metav1.ListOptions{
|
||||||
LabelSelector: c.roleLabelsSet(role).String(),
|
LabelSelector: c.roleLabelsSet(false, role).String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
pods, err := c.KubeClient.Pods(c.Namespace).List(listOptions)
|
pods, err := c.KubeClient.Pods(c.Namespace).List(listOptions)
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,19 @@ func (c *Cluster) labelsSet(shouldAddExtraLabels bool) labels.Set {
|
||||||
if shouldAddExtraLabels {
|
if shouldAddExtraLabels {
|
||||||
// enables filtering resources owned by a team
|
// enables filtering resources owned by a team
|
||||||
lbls["team"] = c.Postgresql.Spec.TeamID
|
lbls["team"] = c.Postgresql.Spec.TeamID
|
||||||
|
|
||||||
|
// allow to inherit certain labels from the 'postgres' object
|
||||||
|
if spec, err := c.GetSpec(); err == nil {
|
||||||
|
for k, v := range spec.ObjectMeta.Labels {
|
||||||
|
for _, match := range c.OpConfig.InheritedLabels {
|
||||||
|
if k == match {
|
||||||
|
lbls[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.logger.Warningf("could not get the list of InheritedLabels for cluster %q: %v", c.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return labels.Set(lbls)
|
return labels.Set(lbls)
|
||||||
|
|
@ -398,8 +411,8 @@ func (c *Cluster) labelsSelector() *metav1.LabelSelector {
|
||||||
return &metav1.LabelSelector{MatchLabels: c.labelsSet(false), MatchExpressions: nil}
|
return &metav1.LabelSelector{MatchLabels: c.labelsSet(false), MatchExpressions: nil}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) roleLabelsSet(role PostgresRole) labels.Set {
|
func (c *Cluster) roleLabelsSet(shouldAddExtraLabels bool, role PostgresRole) labels.Set {
|
||||||
lbls := c.labelsSet(false)
|
lbls := c.labelsSet(shouldAddExtraLabels)
|
||||||
lbls[c.OpConfig.PodRoleLabel] = string(role)
|
lbls[c.OpConfig.PodRoleLabel] = string(role)
|
||||||
return lbls
|
return lbls
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
||||||
result.InfrastructureRolesSecretName = fromCRD.Kubernetes.InfrastructureRolesSecretName
|
result.InfrastructureRolesSecretName = fromCRD.Kubernetes.InfrastructureRolesSecretName
|
||||||
result.PodRoleLabel = fromCRD.Kubernetes.PodRoleLabel
|
result.PodRoleLabel = fromCRD.Kubernetes.PodRoleLabel
|
||||||
result.ClusterLabels = fromCRD.Kubernetes.ClusterLabels
|
result.ClusterLabels = fromCRD.Kubernetes.ClusterLabels
|
||||||
|
result.InheritedLabels = fromCRD.Kubernetes.InheritedLabels
|
||||||
result.ClusterNameLabel = fromCRD.Kubernetes.ClusterNameLabel
|
result.ClusterNameLabel = fromCRD.Kubernetes.ClusterNameLabel
|
||||||
result.NodeReadinessLabel = fromCRD.Kubernetes.NodeReadinessLabel
|
result.NodeReadinessLabel = fromCRD.Kubernetes.NodeReadinessLabel
|
||||||
result.PodPriorityClassName = fromCRD.Kubernetes.PodPriorityClassName
|
result.PodPriorityClassName = fromCRD.Kubernetes.PodPriorityClassName
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ type Resources struct {
|
||||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||||
PodPriorityClassName string `name:"pod_priority_class_name"`
|
PodPriorityClassName string `name:"pod_priority_class_name"`
|
||||||
ClusterLabels map[string]string `name:"cluster_labels" default:"application:spilo"`
|
ClusterLabels map[string]string `name:"cluster_labels" default:"application:spilo"`
|
||||||
|
InheritedLabels []string `name:"inherited_labels" default:""`
|
||||||
ClusterNameLabel string `name:"cluster_name_label" default:"cluster-name"`
|
ClusterNameLabel string `name:"cluster_name_label" default:"cluster-name"`
|
||||||
PodRoleLabel string `name:"pod_role_label" default:"spilo-role"`
|
PodRoleLabel string `name:"pod_role_label" default:"spilo-role"`
|
||||||
PodToleration map[string]string `name:"toleration" default:""`
|
PodToleration map[string]string `name:"toleration" default:""`
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue