Skip to content

Commit

Permalink
Merge pull request #1028 from nkvoll/use-pvcs-by-default
Browse files Browse the repository at this point in the history
Use persistent storage by default for ES data
  • Loading branch information
nkvoll authored Jun 10, 2019
2 parents 0a760c9 + 19f1517 commit 817db81
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 30 deletions.
46 changes: 46 additions & 0 deletions operators/pkg/controller/common/defaults/pvc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package defaults

import v1 "k8s.io/api/core/v1"

// AppendDefaultPVCs appends defaults PVCs to a set of existing ones.
//
// The default PVC is not appended if:
// - a Volume with the same .Name is found in podSpec.Volumes, and that volume is not a PVC volume
// - a PVC with the same .Metadata.Name is found in existing.
func AppendDefaultPVCs(
existing []v1.PersistentVolumeClaim,
podSpec v1.PodSpec,
defaults ...v1.PersistentVolumeClaim,
) []v1.PersistentVolumeClaim {
// create a set of volume names that are not PVC-volumes for efficient testing
nonPVCvolumes := map[string]struct{}{}

for _, volume := range podSpec.Volumes {
if volume.PersistentVolumeClaim == nil {
// this volume is not a PVC
nonPVCvolumes[volume.Name] = struct{}{}
}
}

defaults:
for _, defaultPVC := range defaults {
for _, existingPVC := range existing {
if existingPVC.Name == defaultPVC.Name {
// a PVC with that name already exists, skip.
continue defaults
}
if _, isNonPVCVolume := nonPVCvolumes[defaultPVC.Name]; isNonPVCVolume {
// the corresponding volume is not a PVC
continue defaults
}
}

existing = append(existing, defaultPVC)
}

return existing
}
124 changes: 124 additions & 0 deletions operators/pkg/controller/common/defaults/pvc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
// or more contributor license agreements. Licensed under the Elastic License;
// you may not use this file except in compliance with the Elastic License.

package defaults

import (
"reflect"
"testing"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestAppendDefaultPVCs(t *testing.T) {
foo := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
}
bar := v1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "bar",
},
}

strRef := func(s string) *string {
return &s
}

type args struct {
existing []v1.PersistentVolumeClaim
podSpec v1.PodSpec
defaults []v1.PersistentVolumeClaim
}
tests := []struct {
name string
args args
want []v1.PersistentVolumeClaim
}{
{
name: "append new pvcs",
args: args{
existing: []v1.PersistentVolumeClaim{foo},
defaults: []v1.PersistentVolumeClaim{bar},
},
want: []v1.PersistentVolumeClaim{foo, bar},
},
{
name: "do not overwrite or duplicate existing",
args: args{
existing: []v1.PersistentVolumeClaim{foo},
defaults: []v1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: v1.PersistentVolumeClaimSpec{
StorageClassName: strRef("custom"),
},
},
},
},
want: []v1.PersistentVolumeClaim{foo},
},
{
name: "not add a default pvc if a non-pvc volume with the same name exists",
args: args{
existing: []v1.PersistentVolumeClaim{foo},
podSpec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: bar.Name,
VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}},
},
},
},
defaults: []v1.PersistentVolumeClaim{bar},
},
want: []v1.PersistentVolumeClaim{foo},
},
{
name: "add a default pvc if a pvcvolume with the same name exists",
args: args{
existing: []v1.PersistentVolumeClaim{foo},
podSpec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: bar.Name,
VolumeSource: v1.VolumeSource{
PersistentVolumeClaim: &v1.PersistentVolumeClaimVolumeSource{},
},
},
},
},
defaults: []v1.PersistentVolumeClaim{bar},
},
want: []v1.PersistentVolumeClaim{foo, bar},
},
{
name: "add a default pvc if a non-pvc volume with a different name exists",
args: args{
existing: []v1.PersistentVolumeClaim{foo},
podSpec: v1.PodSpec{
Volumes: []v1.Volume{
{
Name: "not" + bar.Name,
VolumeSource: v1.VolumeSource{EmptyDir: &v1.EmptyDirVolumeSource{}},
},
},
},
defaults: []v1.PersistentVolumeClaim{bar},
},
want: []v1.PersistentVolumeClaim{foo, bar},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := AppendDefaultPVCs(tt.args.existing, tt.args.podSpec, tt.args.defaults...); !reflect.DeepEqual(got, tt.want) {
t.Errorf("AppendDefaultPVCs() = %v, want %v", got, tt.want)
}
})
}
}
5 changes: 3 additions & 2 deletions operators/pkg/controller/elasticsearch/driver/pods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"testing"

"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/label"
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand All @@ -28,7 +29,7 @@ func Test_newPVCFromTemplate(t *testing.T) {
args: args{
claimTemplate: corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-data",
Name: volume.ElasticsearchDataVolumeName,
},
},
pod: &corev1.Pod{
Expand All @@ -43,7 +44,7 @@ func Test_newPVCFromTemplate(t *testing.T) {
},
want: &corev1.PersistentVolumeClaim{
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-sample-es-6bw9qkw77k-elasticsearch-data",
Name: "elasticsearch-sample-es-6bw9qkw77k-" + volume.ElasticsearchDataVolumeName,
Labels: map[string]string{
"l1": "v1",
"l2": "v2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ import (
// Volumes that are shared between the prepare-fs init container and the ES container
var (
DataSharedVolume = SharedVolume{
Name: "elasticsearch-data",
Name: volume.ElasticsearchDataVolumeName,
InitContainerMountPath: "/usr/share/elasticsearch/data",
EsContainerMountPath: "/usr/share/elasticsearch/data",
}

LogsSharedVolume = SharedVolume{
Name: "elasticsearch-logs",
Name: volume.ElasticsearchLogsVolumeName,
InitContainerMountPath: "/usr/share/elasticsearch/logs",
EsContainerMountPath: "/usr/share/elasticsearch/logs",
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/name"
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/pod"
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/reconcile"
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -317,14 +318,18 @@ func Test_PodMatchesSpec(t *testing.T) {
{
name: "Pod has a PVC with an empty VolumeMode",
args: args{
pod: withPVCs(ESPodWithConfig(defaultImage, defaultCPULimit), "elasticsearch-data", "elasticsearch-sample-es-7gnc85w7ll-elasticsearch-data"),
pod: withPVCs(
ESPodWithConfig(defaultImage, defaultCPULimit),
volume.ElasticsearchDataVolumeName,
"elasticsearch-sample-es-7gnc85w7ll-"+volume.ElasticsearchDataVolumeName,
),
spec: pod.PodSpecContext{
PodSpec: ESPodSpecContext(defaultImage, defaultCPULimit).PodSpec,
NodeSpec: v1alpha1.NodeSpec{
VolumeClaimTemplates: []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-data",
Name: volume.ElasticsearchDataVolumeName,
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeMode: nil,
Expand All @@ -336,7 +341,9 @@ func Test_PodMatchesSpec(t *testing.T) {
state: reconcile.ResourcesState{
PVCs: []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{Name: "elasticsearch-sample-es-7gnc85w7ll-elasticsearch-data"},
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-sample-es-7gnc85w7ll-" + volume.ElasticsearchDataVolumeName,
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeMode: &fs,
},
Expand All @@ -350,14 +357,18 @@ func Test_PodMatchesSpec(t *testing.T) {
{
name: "Pod has a PVC with a VolumeMode set to something else than default setting",
args: args{
pod: withPVCs(ESPodWithConfig(defaultImage, defaultCPULimit), "elasticsearch-data", "elasticsearch-sample-es-7gnc85w7ll-elasticsearch-data"),
pod: withPVCs(
ESPodWithConfig(defaultImage, defaultCPULimit),
volume.ElasticsearchDataVolumeName,
"elasticsearch-sample-es-7gnc85w7ll-"+volume.ElasticsearchDataVolumeName,
),
spec: pod.PodSpecContext{
PodSpec: ESPodSpecContext(defaultImage, defaultCPULimit).PodSpec,
NodeSpec: v1alpha1.NodeSpec{
VolumeClaimTemplates: []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-data",
Name: volume.ElasticsearchDataVolumeName,
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeMode: &block,
Expand All @@ -369,7 +380,9 @@ func Test_PodMatchesSpec(t *testing.T) {
state: reconcile.ResourcesState{
PVCs: []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{Name: "elasticsearch-sample-es-7gnc85w7ll-elasticsearch-data"},
ObjectMeta: metav1.ObjectMeta{
Name: "elasticsearch-sample-es-7gnc85w7ll-" + volume.ElasticsearchDataVolumeName,
},
Spec: corev1.PersistentVolumeClaimSpec{
VolumeMode: &block,
},
Expand Down
25 changes: 22 additions & 3 deletions operators/pkg/controller/elasticsearch/pod/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import (
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/settings"
"github.com/elastic/cloud-on-k8s/operators/pkg/controller/elasticsearch/volume"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
Expand All @@ -31,6 +32,25 @@ var (
{Name: "transport", ContainerPort: network.TransportPort, Protocol: corev1.ProtocolTCP},
{Name: "process-manager", ContainerPort: processmanager.DefaultPort, Protocol: corev1.ProtocolTCP},
}

// DefaultVolumeClaimTemplates is the default volume claim templates for Elasticsearch pods
DefaultVolumeClaimTemplates = []corev1.PersistentVolumeClaim{
{
ObjectMeta: metav1.ObjectMeta{
Name: volume.ElasticsearchDataVolumeName,
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{
corev1.ReadWriteOnce,
},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse("1Gi"),
},
},
},
},
}
)

// DefaultAffinity returns the default affinity for pods in a cluster.
Expand All @@ -43,7 +63,7 @@ func DefaultAffinity(esName string) *corev1.Affinity {
Weight: 100,
PodAffinityTerm: corev1.PodAffinityTerm{
TopologyKey: "kubernetes.io/hostname",
LabelSelector: &v1.LabelSelector{
LabelSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
label.ClusterNameLabelName: esName,
},
Expand Down Expand Up @@ -97,7 +117,6 @@ type NewPodSpecParams struct {
ESConfigVolume volume.SecretVolume
// UsersSecretVolume is the volume that contains x-pack configuration (users, users_roles)
UsersSecretVolume volume.SecretVolume

// ProbeUser is the user that should be used for the readiness probes.
ProbeUser client.UserAuth
// KeystoreUser is the user that should be used for reloading the credentials.
Expand Down
Loading

0 comments on commit 817db81

Please sign in to comment.