Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Elasticsearch 7.0 support #44

Merged
merged 14 commits into from
May 14, 2019
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

This is an operator for running Elasticsearch in Kubernetes with focus on operational aspects, like safe draining and offering auto-scaling capabilities for Elasticsearch data nodes, rather than just abstracting manifest definitions.

## Compatibility

The ES-Operator has been tested with Elasticsearch 6.x and 7.0.

## How it works

The operator works by managing custom resources called `ElasticsearchDataSets` (EDS). They
Expand Down
33 changes: 24 additions & 9 deletions cmd/e2e/autoscale_test.go
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package main

import (
"strings"
"testing"

"github.com/cenk/backoff"
"github.com/stretchr/testify/require"
zv1 "github.com/zalando-incubator/es-operator/pkg/apis/zalando.org/v1"
)

func TestEDSCPUAutoscaleUP(t *testing.T) {
// we can can be tested on ES6 only.
func TestEDSCPUAutoscaleUP6(t *testing.T) {
t.Parallel()
edsName := "cpu-autoscale-up"
edsSpecFactory := NewTestEDSSpecFactory(edsName)
runTestEDSCPUAutoScaleUP(t, "6.7.1", "es6-config")
}

func runTestEDSCPUAutoScaleUP(t *testing.T, version, configMap string) {
edsName := "cpu-autoscale-up-" + strings.Replace(version, ".", "", -1)
edsSpecFactory := NewTestEDSSpecFactory(edsName, version, configMap)
edsSpecFactory.Scaling(&zv1.ElasticsearchDataSetScaling{
Enabled: true,
MinReplicas: 1,
Expand All @@ -29,12 +35,12 @@ func TestEDSCPUAutoscaleUP(t *testing.T) {
DiskUsagePercentScaledownWatermark: 0,
})
edsSpec := edsSpecFactory.Create()
edsSpec.Template.Spec = edsPodSpecCPULoadContainer(edsName)
edsSpec.Template.Spec = edsPodSpecCPULoadContainer(edsName, version, configMap)

err := createEDS(edsName, edsSpec)
require.NoError(t, err)

esClient, err := setupESClient("http://" + edsName + ":9200")
esClient, err := setupESClient("http://"+edsName+":9200", version)
require.NoError(t, err)
createIndex := func() error {
return esClient.CreateIndex(edsName, edsName, 1, 0)
Expand All @@ -47,10 +53,19 @@ func TestEDSCPUAutoscaleUP(t *testing.T) {
deleteEDS(edsName)
}

func TestEDSAutoscaleUPOnShardCount(t *testing.T) {
func TestEDSAutoscaleUPOnShardCount6(t *testing.T) {
t.Parallel()
edsName := "shard-autoscale-up"
edsSpecFactory := NewTestEDSSpecFactory(edsName)
runTestEDSAutoscaleUPOnShardCount(t, "6.7.1", "es6-config")
}

func TestEDSAutoscaleUPOnShardCount7(t *testing.T) {
t.Parallel()
runTestEDSAutoscaleUPOnShardCount(t, "7.0.1", "es7-config")
}

func runTestEDSAutoscaleUPOnShardCount(t *testing.T, version, configMap string) {
edsName := "shard-autoscale-up-" + strings.Replace(version, ".", "", -1)
edsSpecFactory := NewTestEDSSpecFactory(edsName, version, configMap)
edsSpecFactory.Scaling(&zv1.ElasticsearchDataSetScaling{
Enabled: true,
MinReplicas: 1,
Expand All @@ -72,7 +87,7 @@ func TestEDSAutoscaleUPOnShardCount(t *testing.T) {
err := createEDS(edsName, edsSpec)
require.NoError(t, err)

esClient, err := setupESClient("http://" + edsName + ":9200")
esClient, err := setupESClient("http://"+edsName+":9200", version)
require.NoError(t, err)
createIndex := func() error {
return esClient.CreateIndex(edsName, edsName, 2, 0)
Expand Down
36 changes: 24 additions & 12 deletions cmd/e2e/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import (
)

type TestEDSSpecFactory struct {
edsName string
replicas int32
scaling *zv1.ElasticsearchDataSetScaling
edsName string
replicas int32
scaling *zv1.ElasticsearchDataSetScaling
version string
configMap string
}

func NewTestEDSSpecFactory(edsName string) *TestEDSSpecFactory {
func NewTestEDSSpecFactory(edsName, version, configMap string) *TestEDSSpecFactory {
return &TestEDSSpecFactory{
edsName: edsName,
replicas: 1,
edsName: edsName,
version: version,
configMap: configMap,
replicas: 1,
}
}

Expand All @@ -46,15 +50,15 @@ func (f *TestEDSSpecFactory) Create() zv1.ElasticsearchDataSetSpec {
"component": "elasticsearch",
},
},
Spec: edsPodSpec(f.edsName),
Spec: edsPodSpec(f.edsName, f.version, f.configMap),
},
}

return result
}

func testEDSCreate(t *testing.T, edsName string) zv1.ElasticsearchDataSetSpec {
edsSpecFactory := NewTestEDSSpecFactory(edsName)
func testEDSCreate(t *testing.T, edsName, version, configMap string) zv1.ElasticsearchDataSetSpec {
edsSpecFactory := NewTestEDSSpecFactory(edsName, version, configMap)
edsSpec := edsSpecFactory.Create()

err := createEDS(edsName, edsSpec)
Expand Down Expand Up @@ -114,10 +118,18 @@ func mergeLabels(labelsSlice ...map[string]string) map[string]string {
return newLabels
}

func TestEDSCreateBasic(t *testing.T) {
func TestEDSCreateBasic6(t *testing.T) {
t.Parallel()
edsName := "basic"
edsSpec := testEDSCreate(t, edsName)
edsName := "basic6"
edsSpec := testEDSCreate(t, edsName, "6.7.1", "es6-config")
verifyEDS(t, edsName, edsSpec, edsSpec.Replicas)
deleteEDS(edsName)
}

func TestEDSCreateBasic7(t *testing.T) {
t.Parallel()
edsName := "basic7"
edsSpec := testEDSCreate(t, edsName, "7.0.1", "es7-config")
verifyEDS(t, edsName, edsSpec, edsSpec.Replicas)
deleteEDS(edsName)
}
13 changes: 11 additions & 2 deletions cmd/e2e/test_environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,17 @@ func requiredEnvar(envar string) string {
return namespace
}

func setupESClient(defaultServiceEndpoint string) (*operator.ESClient, error) {
serviceEndpoint := os.Getenv("ES_SERVICE_ENDPOINT")
func setupESClient(defaultServiceEndpoint, version string) (*operator.ESClient, error) {
var envSuffix string
if len(version) > 0 {
switch version[0] {
case '7':
envSuffix = "_ES7"
case '6':
envSuffix = "_ES6"
}
}
serviceEndpoint := os.Getenv("ES_SERVICE_ENDPOINT" + envSuffix)
if serviceEndpoint == "" {
serviceEndpoint = defaultServiceEndpoint
}
Expand Down
54 changes: 34 additions & 20 deletions cmd/e2e/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const (
)

var (
edsPodSpec = func(nodeGroup string) v1.PodSpec {
edsPodSpec = func(nodeGroup, version, configMap string) v1.PodSpec {
return v1.PodSpec{
ServiceAccountName: "operator",
InitContainers: []v1.Container{
Expand All @@ -43,13 +43,15 @@ var (
},
SecurityContext: &v1.SecurityContext{
Privileged: pbool(true),
RunAsUser: pint64(0),
},
},
},
Containers: []v1.Container{
{
Name: "elasticsearch",
Image: "docker.elastic.co/elasticsearch/elasticsearch-oss:6.6.1",
Name: "elasticsearch",
// gets replaced with desired version
Image: fmt.Sprintf("docker.elastic.co/elasticsearch/elasticsearch-oss:%s", version),
Ports: []v1.ContainerPort{
{
ContainerPort: 9200,
Expand All @@ -60,13 +62,9 @@ var (
},
Env: []v1.EnvVar{
{Name: "ES_JAVA_OPTS", Value: "-Xms256m -Xmx256m"},
{Name: "cluster.name", Value: "es-operator-e2e"},
{Name: "node.master", Value: "false"},
{Name: "node.data", Value: "true"},
{Name: "node.ingest", Value: "true"},
{Name: "network.host", Value: "0.0.0.0"},
{Name: "discovery.zen.minimum_master_nodes", Value: "1"},
{Name: "discovery.zen.ping.unicast.hosts", Value: "es-master"},
{Name: "node.attr.group", Value: nodeGroup},
},
Resources: v1.ResourceRequirements{
Expand All @@ -87,17 +85,17 @@ var (
Scheme: v1.URISchemeHTTP,
},
},
InitialDelaySeconds: 10,
TimeoutSeconds: 5,
PeriodSeconds: 10,
SuccessThreshold: 3,
FailureThreshold: 3,
},
VolumeMounts: []v1.VolumeMount{
{
Name: "data",
MountPath: "/usr/share/elasticsearch/data",
},
{
Name: "config",
MountPath: "/usr/share/elasticsearch/config/elasticsearch.yml",
SubPath: "elasticsearch.yml",
},
},
},
},
Expand All @@ -111,23 +109,39 @@ var (
},
},
},
{
Name: "config",
VolumeSource: v1.VolumeSource{
ConfigMap: &v1.ConfigMapVolumeSource{
LocalObjectReference: v1.LocalObjectReference{
Name: configMap,
},
Items: []v1.KeyToPath{
{
Key: "elasticsearch.yml",
Path: "elasticsearch.yml",
},
},
},
},
},
},
}
}
edsPodSpecCPULoadContainer = func(nodeGroup string) v1.PodSpec {
podSpec := edsPodSpec(nodeGroup)
edsPodSpecCPULoadContainer = func(nodeGroup, version, configMap string) v1.PodSpec {
podSpec := edsPodSpec(nodeGroup, version, configMap)
podSpec.Containers = append(podSpec.Containers, v1.Container{
Name: "stress-ng",
// https://hub.docker.com/r/alexeiled/stress-ng/
Image: "alexeiled/stress-ng",
Args: []string{"--cpu=1", "--cpu-load=10"},
Resources: v1.ResourceRequirements{
Limits: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("10Mi"),
v1.ResourceMemory: resource.MustParse("50Mi"),
v1.ResourceCPU: resource.MustParse("100m"),
},
Requests: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("10Mi"),
v1.ResourceMemory: resource.MustParse("50Mi"),
v1.ResourceCPU: resource.MustParse("100m"),
},
},
Expand Down Expand Up @@ -167,9 +181,9 @@ func (a *awaiter) await() error {
for {
retry, err := a.poll()
if err != nil {
a.t.Logf("%v", err)
if retry && time.Now().Before(deadline) {
a.t.Logf("%v", err)
time.Sleep(10 * time.Second)
time.Sleep(30 * time.Second)
continue
}
return err
Expand All @@ -188,6 +202,7 @@ func resourceCreated(t *testing.T, kind string, name string, k8sInterface interf
})
err := result[1].Interface()
if err != nil {
t.Logf("%v", err)
return apiErrors.IsNotFound(err.(error)), err.(error)
}
return false, nil
Expand Down Expand Up @@ -284,8 +299,7 @@ func createEDS(name string, spec zv1.ElasticsearchDataSetSpec) error {
Name: name,
Namespace: namespace,
Annotations: map[string]string{
"es-operator.zalando.org/operator": operatorId,
"es-operator.zalando.org/elasticsearch-endpoint": "http://es-operator-e2e:9200/",
"es-operator.zalando.org/operator": operatorId,
},
},
Spec: *myspec,
Expand Down
5 changes: 3 additions & 2 deletions cmd/e2e/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
func TestEDSUpgradingEDS(t *testing.T) {
t.Parallel()
edsName := "upgrade"
edsSpec := testEDSCreate(t, edsName)
edsSpec := testEDSCreate(t, edsName, "6.7.1", "es6-config")
eds := verifyEDS(t, edsName, edsSpec, edsSpec.Replicas)
eds.Spec.Template.Labels["new-label"] = "hello"
// this could become a test for a major version upgrade in the future.
eds.Spec.Template.Spec.Containers[0].Image = "docker.elastic.co/elasticsearch/elasticsearch-oss:6.7.2"

var err error
eds, err = waitForEDS(t, edsName)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: es-config
name: es6-config
data:
elasticsearch.yml: |
cluster.name: es-operator-e2e
cluster.name: es6-operator-e2e
network.host: "0.0.0.0"
bootstrap.memory_lock: false
discovery.zen.ping.unicast.hosts: es-master
discovery.zen.ping.unicast.hosts: es6-master
discovery.zen.minimum_master_nodes: 1
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: es-master
name: es6-master
spec:
clusterIP: None
publishNotReadyAddresses: true
selector:
application: es-master
application: es6
role: master
ports:
- name: transport
port: 9300
Expand Down
Loading