Skip to content

Commit

Permalink
Set ES shards and replicas based on redundancy policy (#229)
Browse files Browse the repository at this point in the history
* Set shards and replicas based on redundancy policy

Signed-off-by: Pavol Loffay <ploffay@redhat.com>

* Add tests and deploy only client,data nodes in more than 3

Signed-off-by: Pavol Loffay <ploffay@redhat.com>

* Rename to expected

Signed-off-by: Pavol Loffay <ploffay@redhat.com>
  • Loading branch information
pavolloffay authored Feb 26, 2019
1 parent 0337cc9 commit ed9f1b2
Show file tree
Hide file tree
Showing 2 changed files with 205 additions and 43 deletions.
69 changes: 62 additions & 7 deletions pkg/storage/elasticsearch.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package storage

import (
"fmt"
"strings"

"k8s.io/api/core/v1"
Expand Down Expand Up @@ -49,6 +50,15 @@ func (ed *ElasticsearchDeployment) InjectStorageConfiguration(p *v1.PodSpec) {
"--es.server-urls="+elasticsearchUrl,
"--es.token-file="+k8sTokenFile,
"--es.tls.ca="+caPath)
if !containsPrefix("--es.num-shards", p.Containers[0].Args) {
// taken from https://github.com/openshift/cluster-logging-operator/blob/32b69e8bcf61a805e8f3c45c664a3c08d1ee62d5/vendor/github.com/openshift/elasticsearch-operator/pkg/k8shandler/configmaps.go#L38
// every ES node is a data node
p.Containers[0].Args = append(p.Containers[0].Args, fmt.Sprintf("--es.num-shards=%d", ed.Jaeger.Spec.Storage.Elasticsearch.NodeCount))
}
if !containsPrefix("--es.num-replicas", p.Containers[0].Args) {
p.Containers[0].Args = append(p.Containers[0].Args, fmt.Sprintf("--es.num-replicas=%d",
calculateReplicaShards(ed.Jaeger.Spec.Storage.Elasticsearch.RedundancyPolicy, int(ed.Jaeger.Spec.Storage.Elasticsearch.NodeCount))))
}
p.Containers[0].VolumeMounts = append(p.Containers[0].VolumeMounts, v1.VolumeMount{
Name: volumeName,
ReadOnly: true,
Expand Down Expand Up @@ -97,14 +107,59 @@ func (ed *ElasticsearchDeployment) createCr() *esv1alpha1.Elasticsearch {
Spec: esv1alpha1.ElasticsearchNodeSpec{
Resources: ed.Jaeger.Spec.Storage.Elasticsearch.Resources,
},
Nodes: []esv1alpha1.ElasticsearchNode{
{
NodeCount: ed.Jaeger.Spec.Storage.Elasticsearch.NodeCount,
Storage: ed.Jaeger.Spec.Storage.Elasticsearch.Storage,
NodeSelector: ed.Jaeger.Spec.Storage.Elasticsearch.NodeSelector,
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleClient, esv1alpha1.ElasticsearchRoleData, esv1alpha1.ElasticsearchRoleMaster},
},
Nodes: getNodes(ed.Jaeger.Spec.Storage.Elasticsearch),
},
}
}

func getNodes(es v1alpha1.ElasticsearchSpec) []esv1alpha1.ElasticsearchNode {
if es.NodeCount <= 3 {
return []esv1alpha1.ElasticsearchNode{
{
NodeCount: es.NodeCount,
Storage: es.Storage,
NodeSelector: es.NodeSelector,
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleClient, esv1alpha1.ElasticsearchRoleData, esv1alpha1.ElasticsearchRoleMaster},
},
}
}
return []esv1alpha1.ElasticsearchNode{
{
NodeCount: 3,
Storage: es.Storage,
NodeSelector: es.NodeSelector,
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleMaster},
},
{
NodeCount: es.NodeCount - 3,
Storage: es.Storage,
NodeSelector: es.NodeSelector,
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleClient, esv1alpha1.ElasticsearchRoleData},
},
}
}

// taken from https://github.com/openshift/cluster-logging-operator/blob/1ead6701c7c7af9c0578aa66597261079b2781d5/vendor/github.com/openshift/elasticsearch-operator/pkg/k8shandler/defaults.go#L33
func calculateReplicaShards(policyType esv1alpha1.RedundancyPolicyType, dataNodes int) int {
switch policyType {
case esv1alpha1.FullRedundancy:
return dataNodes - 1
case esv1alpha1.MultipleRedundancy:
return (dataNodes - 1) / 2
case esv1alpha1.SingleRedundancy:
return 1
case esv1alpha1.ZeroRedundancy:
return 0
default:
return 1
}
}

func containsPrefix(prefix string, arr []string) bool {
for _, a := range arr {
if strings.HasPrefix(a, prefix) {
return true
}
}
return false
}
179 changes: 143 additions & 36 deletions pkg/storage/elasticsearch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1"
esv1alpha1 "github.com/jaegertracing/jaeger-operator/pkg/storage/elasticsearch/v1alpha1"
)

func TestShouldDeployElasticsearch(t *testing.T) {
Expand All @@ -26,46 +27,152 @@ func TestShouldDeployElasticsearch(t *testing.T) {
}

func TestCreateElasticsearchCR(t *testing.T) {
trueVar := true
j := v1alpha1.NewJaeger("foo")
j.Namespace = "myproject"
es := &ElasticsearchDeployment{Jaeger: j}
cr := es.createCr()
assert.Equal(t, "myproject", cr.Namespace)
assert.Equal(t, "elasticsearch", cr.Name)
assert.Equal(t, []metav1.OwnerReference{{Name: "foo", Controller: &trueVar}}, cr.OwnerReferences)
tests := []struct {
jEsSpec v1alpha1.ElasticsearchSpec
esSpec esv1alpha1.ElasticsearchSpec
}{
{
jEsSpec: v1alpha1.ElasticsearchSpec{
NodeCount: 2,
RedundancyPolicy: esv1alpha1.FullRedundancy,
Storage: esv1alpha1.ElasticsearchStorageSpec{
StorageClassName: "floppydisk",
},
},
esSpec: esv1alpha1.ElasticsearchSpec{
ManagementState: esv1alpha1.ManagementStateManaged,
RedundancyPolicy: esv1alpha1.FullRedundancy,
Spec: esv1alpha1.ElasticsearchNodeSpec{},
Nodes: []esv1alpha1.ElasticsearchNode{
{
NodeCount: 2,
Storage: esv1alpha1.ElasticsearchStorageSpec{StorageClassName: "floppydisk"},
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleClient, esv1alpha1.ElasticsearchRoleData, esv1alpha1.ElasticsearchRoleMaster},
},
},
},
},
{
jEsSpec: v1alpha1.ElasticsearchSpec{
NodeCount: 5,
RedundancyPolicy: esv1alpha1.FullRedundancy,
Storage: esv1alpha1.ElasticsearchStorageSpec{
StorageClassName: "floppydisk",
},
},
esSpec: esv1alpha1.ElasticsearchSpec{
ManagementState: esv1alpha1.ManagementStateManaged,
RedundancyPolicy: esv1alpha1.FullRedundancy,
Spec: esv1alpha1.ElasticsearchNodeSpec{},
Nodes: []esv1alpha1.ElasticsearchNode{
{
NodeCount: 3,
Storage: esv1alpha1.ElasticsearchStorageSpec{StorageClassName: "floppydisk"},
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleMaster},
},
{
NodeCount: 2,
Storage: esv1alpha1.ElasticsearchStorageSpec{StorageClassName: "floppydisk"},
Roles: []esv1alpha1.ElasticsearchNodeRole{esv1alpha1.ElasticsearchRoleClient, esv1alpha1.ElasticsearchRoleData},
},
},
},
},
}
for _, test := range tests {
j := v1alpha1.NewJaeger("foo")
j.Namespace = "myproject"
j.Spec.Storage.Elasticsearch = test.jEsSpec
es := &ElasticsearchDeployment{Jaeger: j}
cr := es.createCr()
assert.Equal(t, "myproject", cr.Namespace)
assert.Equal(t, "elasticsearch", cr.Name)
trueVar := true
assert.Equal(t, []metav1.OwnerReference{{Name: "foo", Controller: &trueVar}}, cr.OwnerReferences)
assert.Equal(t, cr.Spec, test.esSpec)
}
}

func TestInject(t *testing.T) {
p := &v1.PodSpec{
Containers: []v1.Container{{
Args: []string{"foo"},
VolumeMounts: []v1.VolumeMount{{Name: "lol"}},
}},
}
es := &ElasticsearchDeployment{Jaeger: v1alpha1.NewJaeger("hoo")}
es.InjectStorageConfiguration(p)
expVolumes := []v1.Volume{{Name: "certs", VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "hoo-jaeger-elasticsearch",
tests := []struct {
pod *v1.PodSpec
expected *v1.PodSpec
}{
{pod: &v1.PodSpec{
Containers: []v1.Container{{
Args: []string{"foo"},
VolumeMounts: []v1.VolumeMount{{Name: "lol"}},
}},
},
}}}
assert.Equal(t, expVolumes, p.Volumes)
expContainers := []v1.Container{{
Args: []string{
"foo",
"--es.server-urls=https://elasticsearch:9200",
"--es.token-file=" + k8sTokenFile,
"--es.tls.ca=" + caPath,
expected: &v1.PodSpec{
Containers: []v1.Container{{
Args: []string{
"foo",
"--es.server-urls=" + elasticsearchUrl,
"--es.token-file=" + k8sTokenFile,
"--es.tls.ca=" + caPath,
"--es.num-shards=0",
"--es.num-replicas=1",
},
VolumeMounts: []v1.VolumeMount{
{Name: "lol"},
{Name: volumeName, ReadOnly: true, MountPath: volumeMountPath},
},
}},
Volumes: []v1.Volume{{Name: "certs", VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "hoo-jaeger-elasticsearch"}}},
}},
},
VolumeMounts: []v1.VolumeMount{
{Name: "lol"},
{
Name: volumeName,
ReadOnly: true,
MountPath: volumeMountPath,
},
{pod: &v1.PodSpec{
Containers: []v1.Container{{
Args: []string{"--es.num-shards=15"},
}},
},
expected: &v1.PodSpec{
Containers: []v1.Container{{
Args: []string{
"--es.num-shards=15",
"--es.server-urls=" + elasticsearchUrl,
"--es.token-file=" + k8sTokenFile,
"--es.tls.ca=" + caPath,
"--es.num-replicas=1",
},
VolumeMounts: []v1.VolumeMount{
{Name: volumeName, ReadOnly: true, MountPath: volumeMountPath},
},
}},
Volumes: []v1.Volume{{Name: "certs", VolumeSource: v1.VolumeSource{
Secret: &v1.SecretVolumeSource{
SecretName: "hoo-jaeger-elasticsearch"}}},
}},
},
}}
assert.Equal(t, expContainers, p.Containers)
}

for _, test := range tests {
es := &ElasticsearchDeployment{Jaeger: v1alpha1.NewJaeger("hoo")}
es.InjectStorageConfiguration(test.pod)
assert.Equal(t, test.expected, test.pod)
}

}

func TestCalculateReplicaShards(t *testing.T) {
tests := []struct {
dataNodes int
redType esv1alpha1.RedundancyPolicyType
shards int
}{
{redType: esv1alpha1.ZeroRedundancy, dataNodes: 1, shards: 0},
{redType: esv1alpha1.ZeroRedundancy, dataNodes: 1, shards: 0},
{redType: esv1alpha1.SingleRedundancy, dataNodes: 1, shards: 1},
{redType: esv1alpha1.SingleRedundancy, dataNodes: 20, shards: 1},
{redType: esv1alpha1.MultipleRedundancy, dataNodes: 1, shards: 0},
{redType: esv1alpha1.MultipleRedundancy, dataNodes: 20, shards: 9},
{redType: esv1alpha1.FullRedundancy, dataNodes: 1, shards: 0},
{redType: esv1alpha1.FullRedundancy, dataNodes: 20, shards: 19},
}
for _, test := range tests {
assert.Equal(t, test.shards, calculateReplicaShards(test.redType, test.dataNodes))
}
}

0 comments on commit ed9f1b2

Please sign in to comment.