Skip to content

Commit

Permalink
[Development][Add] Added support for keystore in elasticsearch (#44)
Browse files Browse the repository at this point in the history
* Added support for elastic keystore

Signed-off-by: iamabhishek-dubey <[email protected]>

* Added support for elastic keystore

Signed-off-by: iamabhishek-dubey <[email protected]>

* Added example for keystore

Signed-off-by: iamabhishek-dubey <[email protected]>

* Updated documentation for v0.4.0

Signed-off-by: iamabhishek-dubey <[email protected]>

Signed-off-by: iamabhishek-dubey <[email protected]>
  • Loading branch information
iamabhishek-dubey authored Sep 3, 2022
1 parent c1a2a62 commit d403e94
Show file tree
Hide file tree
Showing 17 changed files with 276 additions and 11 deletions.
11 changes: 6 additions & 5 deletions api/v1beta1/elasticsearch_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@ type ElasticsearchSpec struct {
Security *Security `json:"esSecurity,omitempty"`
// +kubebuilder:validation:default:={esMaster:{replicas: 3}}
// +kubebuilder:default:={storage:{accessModes: {ReadWriteOnce}, storageSize: "1Gi"},jvmMaxMemory: "1g", jvmMinMemory: "1g", replicas: 3}
ESMaster *NodeSpecificConfig `json:"esMaster,omitempty"`
ESData *NodeSpecificConfig `json:"esData,omitempty"`
ESIngestion *NodeSpecificConfig `json:"esIngestion,omitempty"`
ESClient *NodeSpecificConfig `json:"esClient,omitempty"`
ESPlugins *[]string `json:"esPlugins,omitempty"`
ESMaster *NodeSpecificConfig `json:"esMaster,omitempty"`
ESData *NodeSpecificConfig `json:"esData,omitempty"`
ESIngestion *NodeSpecificConfig `json:"esIngestion,omitempty"`
ESClient *NodeSpecificConfig `json:"esClient,omitempty"`
ESPlugins *[]string `json:"esPlugins,omitempty"`
ESKeystoreSecret *string `json:"esKeystoreSecret,omitempty"`
}

// NodeSpecificConfig defines the properties for elasticsearch nodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3630,6 +3630,8 @@ spec:
type: string
type: object
type: object
esKeystoreSecret:
type: string
esMaster:
default:
jvmMaxMemory: 1g
Expand Down
3 changes: 2 additions & 1 deletion docs/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ weight = 1
unsafe = true
[markup.highlight]
# See a complete list of available styles at https://xyproto.github.io/splash/docs/all.html
style = "rainbow_dash"
# style = "rainbow_dash"
style = "pygments"
# Uncomment if you want your chosen highlight style used for code blocks without a specified language
# guessSyntax = "true"

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Elasticsearch"
linkTitle: "Elasticsearch"
weight: 4
description: >
Advance configuration information for Elasticsearch
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
title: "Keystore Integration"
linkTitle: "Keystore Integration"
weight: 6
description: >
Keystore integration configuration for elasticsearch
---

## Keystore integation

Keystore is a recommended way of integrating different credentials like:- AWS, GCP, Azure and Slack, etc. to elasticsearch cluster. We simply need to create a Kubernetes secret and the operator can take care the integration of Kubernetes secret to elasticsearch keystore.

```shell
$ kubectl create secret generic slack-hook \
--from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asda'
```

or yaml file is also one of the way for creating the secret.

```yaml
---
apiVersion: v1
kind: Secret
metadata:
name: encryption-key
data:
xpack.notification.slack.account.monitoring.secure_url: aHR0cHM6Ly9ob29rcy5zbGFjay5jb20vc2VydmljZXMvYXNkYXNkYXNkL2FzZGFzZGFzL2FzZGFzZA==
# other secrets key value pairs can be defined here
type: Opaque
```
Then simply we can define the keystore secret name in CRD definition.
```yaml
---
apiVersion: logging.logging.opstreelabs.in/v1beta1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
esClusterName: "prod"
esVersion: "7.16.0"
esKeystoreSecret: encryption-key
```
Validation of keystore can be done using `elasticsearch-keystore` command.

```shell
$ kubectl exec -it elasticsearch-master-0 -n ot-operators -- ./bin/elasticsearch-keystore list
...
keystore.seed
xpack.notification.slack.account.monitoring.secure_url
```

## Helm Configuration

Keystore integration can also be done using helm chart of elasticsearch. We just need to define the keystore secret name in the values file of elasticsearch helm chart.

https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/elasticsearch/values.yaml#L9

```shell
$ helm upgrade elasticsearch ot-helm/elasticsearch --namespace ot-operators \
--set esMaster.storage.storageClass=do-block-storage \
--set esData.storage.storageClass=do-block-storage --install
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
title: "Plugins Management"
linkTitle: "Plugins Management"
weight: 5
description: >
Plugins related configuration for elasticsearch
---

## Plugins Installation

Plugins installation has been simplified using the Logging Operator. To install the plugins inside the elasticsearch, we just need to define the list of plugins inside the `esPlugins` section of elasticsearch CRD.

For example:-

```yaml
---
apiVersion: logging.logging.opstreelabs.in/v1beta1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
esClusterName: "prod"
esVersion: "7.16.0"
esPlugins: ["repository-s3"]
```
Validation of plugin installation can be done using `elasticsearch-plugin` or `curl` command.

```shell
$ kubectl exec -it elasticsearch-master-0 -n ot-operators -- ./bin/elasticsearch-plugin list
...
repository-s3
```

```shell
$ kubectl exec -it elasticsearch-master-0 -n ot-operators -- curl http://localhost:9200/_cat/plugins
...
elasticsearch-master-1 repository-s3 7.16.0
elasticsearch-master-2 repository-s3 7.16.0
elasticsearch-master-0 repository-s3 7.16.0
```

## Helm Configuration

Plugin installation can also be done using helm chart of elasticsearch. We just need to define the plugins list in the values file of elasticsearch helm chart.

https://github.com/OT-CONTAINER-KIT/helm-charts/blob/main/charts/elasticsearch/values.yaml#L8

```shell
$ helm upgrade elasticsearch ot-helm/elasticsearch --namespace ot-operators \
--set esMaster.storage.storageClass=do-block-storage \
--set esData.storage.storageClass=do-block-storage --install
```
7 changes: 7 additions & 0 deletions docs/content/en/docs/Advance Configuration/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
title: "Advance Configuration"
linkTitle: "Advance Configuration"
weight: 4
description: >
Advance configuration information for Logging Operator
---
18 changes: 18 additions & 0 deletions docs/content/en/docs/Configuration/elasticsearch-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The values.yaml file for Elasticsearch setup can be found [here](https://github.
|----------------------------------|-----------------|--------------------------------------------------------------------|
| clusterName | elastic-prod | Name of the elasticsearch cluster |
| esVersion | 7.17.0 | Major and minor version of elaticsearch |
| esPlugins | [] | Plugins list to install inside elasticsearch |
| esKeystoreSecret | - | Keystore secret to include in elasticsearch cluster |
| customConfiguration | {} | Additional configuration parameters for elasticsearch |
| esSecurity.enabled | true | To enabled the xpack security of elasticsearch |
| esMaster.replicas | 3 | Number of replicas for elasticsearch master node |
Expand Down Expand Up @@ -88,6 +90,22 @@ esClusterName: "prod"
esVersion: "7.16.0"
```

### esPlugins

`esPlugins` is a CRD parameter through which we can define the list of plugins that needs to install inside elasticsearch cluster.

```yaml
esPlugins: ["respository-s3", "repository-gcs"]
```

### esKeystoreSecret

`esKeystoreSecret` is a CRD parameter through which we can define the keystore related secret to include in elasticsearch cluster.

```yaml
esKeystoreSecret: keystore-secret
```

### esMaster

`esMaster` is a general configuration parameter for Elasticsearch CRD for defining the configuration of Elasticsearch Master node. This includes Kubernetes related configurations and Elasticsearch properties related configurations.
Expand Down
2 changes: 1 addition & 1 deletion docs/content/en/docs/Development/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ title: "Development"
linkTitle: "Development"
weight: 5
description: >
Development related information for MongoDB Operator
Development related information for Logging Operator
---
10 changes: 10 additions & 0 deletions docs/content/en/docs/Release History/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ description: >
Changelog version history for Logging Operator
---

### v0.4.0

**September 3, 2022**

**🏄 Features**

- Added elasticsearch 8.X version support
- Added plugin's installation support in elasticsearch
- Added keystore integration in elasticsearch

### v0.3.0

**July 4, 2022**
Expand Down
5 changes: 2 additions & 3 deletions docs/content/en/docs/Release History/_index.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
title: "Release History"
linkTitle: "Release History"
weight: 5
weight: 6
description: >
Release history information for MongoDB
Release history information for Logging Operator
---

2 changes: 1 addition & 1 deletion docs/content/en/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ menu:
weight: 20
---

All of Logging Operator documentation
All the Logging Operator documentation and examples.
9 changes: 9 additions & 0 deletions examples/elasticsearch/keystore/elasticsearch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: logging.logging.opstreelabs.in/v1beta1
kind: Elasticsearch
metadata:
name: elasticsearch
spec:
esClusterName: "prod"
esVersion: "7.16.0"
esKeystoreSecret: encryption-key
9 changes: 9 additions & 0 deletions examples/elasticsearch/keystore/keystore-secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
apiVersion: v1
data:
xpack.notification.slack.account.monitoring.secure_url: aHR0cHM6Ly9ob29rcy5zbGFjay5jb20vc2VydmljZXMvYXNkYXNkYXNkL2FzZGFzZGFzL2FzZGFzZA==
# other secrets key value pairs can be defined here
kind: Secret
metadata:
name: encryption-key
type: Opaque
28 changes: 28 additions & 0 deletions k8sgo/elasticsearch/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ func CreateElasticsearchStatefulSet(cr *loggingv1beta1.Elasticsearch, nodeConfig
if cr.Spec.ESPlugins != nil {
statefulsetParams.ESPlugins = cr.Spec.ESPlugins
}
if cr.Spec.ESKeystoreSecret != nil {
statefulsetParams.ESKeystoreSecret = cr.Spec.ESKeystoreSecret
}
statefulsetParams.ExtraVolumes = getVolumes(cr)

if nodeConfig != nil {
Expand Down Expand Up @@ -119,6 +122,13 @@ func getVolumeMounts(cr *loggingv1beta1.Elasticsearch, role string) *[]corev1.Vo
MountPath: "/usr/share/elasticsearch/plugins",
})
}
if cr.Spec.ESKeystoreSecret != nil {
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Name: "keystore-volume",
MountPath: "/usr/share/elasticsearch/config/elasticsearch.keystore",
SubPath: "elasticsearch.keystore",
})
}
return &volumeMounts
}

Expand All @@ -145,6 +155,24 @@ func getVolumes(cr *loggingv1beta1.Elasticsearch) *[]corev1.Volume {
},
})
}
if cr.Spec.ESKeystoreSecret != nil {
volume = append(volume, corev1.Volume{
Name: "keystore-volume",
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
}
if cr.Spec.ESKeystoreSecret != nil {
volume = append(volume, corev1.Volume{
Name: "keystore-secret",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: *cr.Spec.ESKeystoreSecret,
},
},
})
}
return &volume
}

Expand Down
31 changes: 31 additions & 0 deletions k8sgo/init_command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
Copyright 2022 Opstree Solutions.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package k8sgo

const keyStoreCommand = `set -euo pipefail
elasticsearch-keystore create
for i in /tmp/keystoreSecrets/*/*; do
key=$(basename $i)
echo "Adding file $i to keystore key $key"
elasticsearch-keystore add-file "$key" "$i"
done
# Add the bootstrap password since otherwise the Elasticsearch entrypoint tries to do this on startup
if [ ! -z ${ELASTIC_PASSWORD+x} ]; then
echo 'Adding env $ELASTIC_PASSWORD to keystore as key bootstrap.password'
echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x bootstrap.password
fi
cp -a /usr/share/elasticsearch/config/elasticsearch.keystore /tmp/keystore/`
25 changes: 25 additions & 0 deletions k8sgo/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package k8sgo

import (
"context"
"fmt"
"strings"

appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -46,6 +47,7 @@ type StatefulSetParameters struct {
SecurityContext *corev1.PodSecurityContext
ExtraVolumes *[]corev1.Volume
ESPlugins *[]string
ESKeystoreSecret *string
}

// PVCParameters is a struct to pass arguments for PVC
Expand Down Expand Up @@ -186,6 +188,9 @@ func generateStatefulSetDef(params StatefulSetParameters) *appsv1.StatefulSet {
if params.ESPlugins != nil {
statefulset.Spec.Template.Spec.InitContainers = append(statefulset.Spec.Template.Spec.InitContainers, getPluginInitContainers(params))
}
if params.ESKeystoreSecret != nil {
statefulset.Spec.Template.Spec.InitContainers = append(statefulset.Spec.Template.Spec.InitContainers, getKeystoreInitContainer(params))
}
if params.ExtraVolumes != nil {
statefulset.Spec.Template.Spec.Volumes = *params.ExtraVolumes
}
Expand Down Expand Up @@ -251,3 +256,23 @@ func getPluginInitContainers(params StatefulSetParameters) corev1.Container {
},
}
}

// getKeystoreInitContainer is a method to create init container for keystore
func getKeystoreInitContainer(params StatefulSetParameters) corev1.Container {
secretName := fmt.Sprintf("/tmp/keystoreSecrets/%s", *params.ESKeystoreSecret)
return corev1.Container{
Name: "keystore",
Image: params.ContainerParams.Image,
Command: []string{"bash", "-c", keyStoreCommand},
VolumeMounts: []corev1.VolumeMount{
{
Name: "keystore-volume",
MountPath: "/tmp/keystore",
},
{
Name: "keystore-secret",
MountPath: secretName,
},
},
}
}

0 comments on commit d403e94

Please sign in to comment.