add pdb configuration toggle
This commit is contained in:
commit
b8453e6075
|
|
@ -114,6 +114,7 @@ configKubernetesCRD:
|
|||
cluster_name_label: cluster-name
|
||||
enable_pod_antiaffinity: false
|
||||
pod_antiaffinity_topology_key: "kubernetes.io/hostname"
|
||||
enable_pod_disruption_budget: true
|
||||
secret_name_template: "{username}.{cluster}.credentials.{tprkind}.{tprgroup}"
|
||||
# inherited_labels:
|
||||
# - application
|
||||
|
|
@ -161,7 +162,7 @@ serviceAccount:
|
|||
# The name of the ServiceAccount to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
# When relying solely on the OperatorConfiguration CRD, set this value to "operator"
|
||||
# Otherwise, the operator tries to use the "default" service account which is forbidden
|
||||
# Otherwise, the operator tries to use the "default" service account which is forbidden
|
||||
name: ""
|
||||
|
||||
priorityClassName: ""
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ configuration:
|
|||
pod_management_policy: "ordered_ready"
|
||||
enable_pod_antiaffinity: false
|
||||
pod_antiaffinity_topology_key: "kubernetes.io/hostname"
|
||||
enable_pod_disruption_budget: true
|
||||
postgres_pod_resources:
|
||||
default_cpu_request: 100m
|
||||
default_memory_request: 100Mi
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ type KubernetesMetaConfiguration struct {
|
|||
EnablePodAntiAffinity bool `json:"enable_pod_antiaffinity,omitempty"`
|
||||
PodAntiAffinityTopologyKey string `json:"pod_antiaffinity_topology_key,omitempty"`
|
||||
PodManagementPolicy string `json:"pod_management_policy,omitempty"`
|
||||
EnablePodDisruptionBudget bool `json:"enable_pod_disruption_budget,omitempty"`
|
||||
}
|
||||
|
||||
// PostgresPodResourcesDefaults defines the spec of default resources
|
||||
|
|
|
|||
|
|
@ -1274,6 +1274,11 @@ func (c *Cluster) generateCloneEnvironment(description *acidv1.CloneDescription)
|
|||
func (c *Cluster) generatePodDisruptionBudget() *policybeta1.PodDisruptionBudget {
|
||||
minAvailable := intstr.FromInt(1)
|
||||
|
||||
// Is PodDisruptionBudget is disabled or if there is no master, set the budget to 0.
|
||||
if (c.OpConfig.EnablePodDisruptionBudget != nil && !*c.OpConfig.EnablePodDisruptionBudget) || c.Spec.NumberOfInstances <= 0 {
|
||||
minAvailable = intstr.FromInt(0)
|
||||
}
|
||||
|
||||
return &policybeta1.PodDisruptionBudget{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: c.podDisruptionBudgetName(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"testing"
|
||||
|
|
@ -9,6 +11,10 @@ import (
|
|||
"github.com/zalando/postgres-operator/pkg/util/config"
|
||||
"github.com/zalando/postgres-operator/pkg/util/constants"
|
||||
"github.com/zalando/postgres-operator/pkg/util/k8sutil"
|
||||
|
||||
policyv1beta1 "k8s.io/api/policy/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
func True() *bool {
|
||||
|
|
@ -21,6 +27,11 @@ func False() *bool {
|
|||
return &b
|
||||
}
|
||||
|
||||
func toIntStr(val int) *intstr.IntOrString {
|
||||
b := intstr.FromInt(val)
|
||||
return &b
|
||||
}
|
||||
|
||||
func TestGenerateSpiloJSONConfiguration(t *testing.T) {
|
||||
var cluster = New(
|
||||
Config{
|
||||
|
|
@ -143,6 +154,113 @@ func TestCreateLoadBalancerLogic(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGeneratePodDisruptionBudget(t *testing.T) {
|
||||
tests := []struct {
|
||||
c *Cluster
|
||||
out policyv1beta1.PodDisruptionBudget
|
||||
}{
|
||||
// With multiple instances.
|
||||
{
|
||||
New(
|
||||
Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb"}},
|
||||
k8sutil.KubernetesClient{},
|
||||
acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"},
|
||||
Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}},
|
||||
logger),
|
||||
policyv1beta1.PodDisruptionBudget{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "postgres-myapp-database-pdb",
|
||||
Namespace: "myapp",
|
||||
Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"},
|
||||
},
|
||||
Spec: policyv1beta1.PodDisruptionBudgetSpec{
|
||||
MinAvailable: toIntStr(1),
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// With zero instances.
|
||||
{
|
||||
New(
|
||||
Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb"}},
|
||||
k8sutil.KubernetesClient{},
|
||||
acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"},
|
||||
Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 0}},
|
||||
logger),
|
||||
policyv1beta1.PodDisruptionBudget{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "postgres-myapp-database-pdb",
|
||||
Namespace: "myapp",
|
||||
Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"},
|
||||
},
|
||||
Spec: policyv1beta1.PodDisruptionBudgetSpec{
|
||||
MinAvailable: toIntStr(0),
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// With PodDisruptionBudget disabled.
|
||||
{
|
||||
New(
|
||||
Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-pdb", EnablePodDisruptionBudget: False()}},
|
||||
k8sutil.KubernetesClient{},
|
||||
acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"},
|
||||
Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}},
|
||||
logger),
|
||||
policyv1beta1.PodDisruptionBudget{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "postgres-myapp-database-pdb",
|
||||
Namespace: "myapp",
|
||||
Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"},
|
||||
},
|
||||
Spec: policyv1beta1.PodDisruptionBudgetSpec{
|
||||
MinAvailable: toIntStr(0),
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// With non-default PDBNameFormat and PodDisruptionBudget explicitly enabled.
|
||||
{
|
||||
New(
|
||||
Config{OpConfig: config.Config{Resources: config.Resources{ClusterNameLabel: "cluster-name", PodRoleLabel: "spilo-role"}, PDBNameFormat: "postgres-{cluster}-databass-budget", EnablePodDisruptionBudget: True()}},
|
||||
k8sutil.KubernetesClient{},
|
||||
acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "myapp-database", Namespace: "myapp"},
|
||||
Spec: acidv1.PostgresSpec{TeamID: "myapp", NumberOfInstances: 3}},
|
||||
logger),
|
||||
policyv1beta1.PodDisruptionBudget{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "postgres-myapp-database-databass-budget",
|
||||
Namespace: "myapp",
|
||||
Labels: map[string]string{"team": "myapp", "cluster-name": "myapp-database"},
|
||||
},
|
||||
Spec: policyv1beta1.PodDisruptionBudgetSpec{
|
||||
MinAvailable: toIntStr(1),
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"spilo-role": "master", "cluster-name": "myapp-database"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
result := tt.c.generatePodDisruptionBudget()
|
||||
if !reflect.DeepEqual(*result, tt.out) {
|
||||
t.Errorf("Expected PodDisruptionBudget: %#v, got %#v", tt.out, *result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShmVolume(t *testing.T) {
|
||||
testName := "TestShmVolume"
|
||||
tests := []struct {
|
||||
|
|
@ -269,6 +387,5 @@ func TestCloneEnv(t *testing.T) {
|
|||
t.Errorf("%s %s: Expected env value %s, have %s instead",
|
||||
testName, tt.subTest, tt.env.Value, env.Value)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
|||
result.PodServiceAccountRoleBindingDefinition = fromCRD.Kubernetes.PodServiceAccountRoleBindingDefinition
|
||||
result.PodEnvironmentConfigMap = fromCRD.Kubernetes.PodEnvironmentConfigMap
|
||||
result.PodTerminateGracePeriod = time.Duration(fromCRD.Kubernetes.PodTerminateGracePeriod)
|
||||
result.EnablePodDisruptionBudget = fromCRD.Kubernetes.EnablePodDisruptionBudget
|
||||
result.SpiloPrivileged = fromCRD.Kubernetes.SpiloPrivileged
|
||||
result.SpiloFSGroup = fromCRD.Kubernetes.SpiloFSGroup
|
||||
result.ClusterDomain = fromCRD.Kubernetes.ClusterDomain
|
||||
|
|
|
|||
|
|
@ -110,20 +110,21 @@ type Config struct {
|
|||
EnablePodAntiAffinity bool `name:"enable_pod_antiaffinity" default:"false"`
|
||||
PodAntiAffinityTopologyKey string `name:"pod_antiaffinity_topology_key" default:"kubernetes.io/hostname"`
|
||||
// deprecated and kept for backward compatibility
|
||||
EnableLoadBalancer *bool `name:"enable_load_balancer"`
|
||||
MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
||||
ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
||||
PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
||||
Workers uint32 `name:"workers" default:"4"`
|
||||
APIPort int `name:"api_port" default:"8080"`
|
||||
RingLogLines int `name:"ring_log_lines" default:"100"`
|
||||
ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"`
|
||||
TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"`
|
||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||
PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"`
|
||||
ProtectedRoles []string `name:"protected_role_names" default:"admin"`
|
||||
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
|
||||
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" defaults:"false"`
|
||||
EnableLoadBalancer *bool `name:"enable_load_balancer"`
|
||||
MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
||||
ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
||||
PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
||||
Workers uint32 `name:"workers" default:"4"`
|
||||
APIPort int `name:"api_port" default:"8080"`
|
||||
RingLogLines int `name:"ring_log_lines" default:"100"`
|
||||
ClusterHistoryEntries int `name:"cluster_history_entries" default:"1000"`
|
||||
TeamAPIRoleConfiguration map[string]string `name:"team_api_role_configuration" default:"log_statement:all"`
|
||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||
PodManagementPolicy string `name:"pod_management_policy" default:"ordered_ready"`
|
||||
EnablePodDisruptionBudget *bool `name:"enable_pod_disruption_budget" default:"true"`
|
||||
ProtectedRoles []string `name:"protected_role_names" default:"admin"`
|
||||
PostgresSuperuserTeams []string `name:"postgres_superuser_teams" default:""`
|
||||
SetMemoryRequestToLimit bool `name:"set_memory_request_to_limit" default:"false"`
|
||||
}
|
||||
|
||||
// MustMarshal marshals the config or panics
|
||||
|
|
|
|||
Loading…
Reference in New Issue