diff --git a/api/v1beta1/elasticsearch_types.go b/api/v1beta1/elasticsearch_types.go index be14392..bcfd520 100644 --- a/api/v1beta1/elasticsearch_types.go +++ b/api/v1beta1/elasticsearch_types.go @@ -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 diff --git a/config/crd/bases/logging.logging.opstreelabs.in_elasticsearches.yaml b/config/crd/bases/logging.logging.opstreelabs.in_elasticsearches.yaml index 2ce404c..6d70ee1 100644 --- a/config/crd/bases/logging.logging.opstreelabs.in_elasticsearches.yaml +++ b/config/crd/bases/logging.logging.opstreelabs.in_elasticsearches.yaml @@ -3630,6 +3630,8 @@ spec: type: string type: object type: object + esKeystoreSecret: + type: string esMaster: default: jvmMaxMemory: 1g diff --git a/docs/config.toml b/docs/config.toml index 2f97189..4cc9f1a 100644 --- a/docs/config.toml +++ b/docs/config.toml @@ -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" diff --git a/docs/content/en/docs/Advance Configuration/Elasticsearch/_index.md b/docs/content/en/docs/Advance Configuration/Elasticsearch/_index.md new file mode 100644 index 0000000..1f004c2 --- /dev/null +++ b/docs/content/en/docs/Advance Configuration/Elasticsearch/_index.md @@ -0,0 +1,7 @@ +--- +title: "Elasticsearch" +linkTitle: "Elasticsearch" +weight: 4 +description: > + Advance configuration information for Elasticsearch +--- diff --git a/docs/content/en/docs/Advance Configuration/Elasticsearch/keystore.md b/docs/content/en/docs/Advance Configuration/Elasticsearch/keystore.md new file mode 100644 index 0000000..c0ae42f --- /dev/null +++ b/docs/content/en/docs/Advance Configuration/Elasticsearch/keystore.md @@ -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 +``` diff --git a/docs/content/en/docs/Advance Configuration/Elasticsearch/plugins.md b/docs/content/en/docs/Advance Configuration/Elasticsearch/plugins.md new file mode 100644 index 0000000..a4d9630 --- /dev/null +++ b/docs/content/en/docs/Advance Configuration/Elasticsearch/plugins.md @@ -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 +``` diff --git a/docs/content/en/docs/Advance Configuration/_index.md b/docs/content/en/docs/Advance Configuration/_index.md new file mode 100644 index 0000000..4dcef23 --- /dev/null +++ b/docs/content/en/docs/Advance Configuration/_index.md @@ -0,0 +1,7 @@ +--- +title: "Advance Configuration" +linkTitle: "Advance Configuration" +weight: 4 +description: > + Advance configuration information for Logging Operator +--- diff --git a/docs/content/en/docs/Configuration/elasticsearch-config.md b/docs/content/en/docs/Configuration/elasticsearch-config.md index f67826d..5ef048b 100644 --- a/docs/content/en/docs/Configuration/elasticsearch-config.md +++ b/docs/content/en/docs/Configuration/elasticsearch-config.md @@ -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 | @@ -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. diff --git a/docs/content/en/docs/Development/_index.md b/docs/content/en/docs/Development/_index.md index a2bc558..d9b7ab5 100644 --- a/docs/content/en/docs/Development/_index.md +++ b/docs/content/en/docs/Development/_index.md @@ -3,5 +3,5 @@ title: "Development" linkTitle: "Development" weight: 5 description: > - Development related information for MongoDB Operator + Development related information for Logging Operator --- diff --git a/docs/content/en/docs/Release History/CHANGELOG.md b/docs/content/en/docs/Release History/CHANGELOG.md index c2ce71d..f771bb9 100644 --- a/docs/content/en/docs/Release History/CHANGELOG.md +++ b/docs/content/en/docs/Release History/CHANGELOG.md @@ -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** diff --git a/docs/content/en/docs/Release History/_index.md b/docs/content/en/docs/Release History/_index.md index be6dabe..40a29f0 100644 --- a/docs/content/en/docs/Release History/_index.md +++ b/docs/content/en/docs/Release History/_index.md @@ -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 --- - diff --git a/docs/content/en/docs/_index.md b/docs/content/en/docs/_index.md index d0ebfb1..e30390a 100755 --- a/docs/content/en/docs/_index.md +++ b/docs/content/en/docs/_index.md @@ -8,4 +8,4 @@ menu: weight: 20 --- -All of Logging Operator documentation +All the Logging Operator documentation and examples. diff --git a/examples/elasticsearch/keystore/elasticsearch.yaml b/examples/elasticsearch/keystore/elasticsearch.yaml new file mode 100644 index 0000000..d8edea9 --- /dev/null +++ b/examples/elasticsearch/keystore/elasticsearch.yaml @@ -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 diff --git a/examples/elasticsearch/keystore/keystore-secret.yaml b/examples/elasticsearch/keystore/keystore-secret.yaml new file mode 100644 index 0000000..7e264ae --- /dev/null +++ b/examples/elasticsearch/keystore/keystore-secret.yaml @@ -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 diff --git a/k8sgo/elasticsearch/statefulset.go b/k8sgo/elasticsearch/statefulset.go index 46b5647..7aa9b18 100644 --- a/k8sgo/elasticsearch/statefulset.go +++ b/k8sgo/elasticsearch/statefulset.go @@ -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 { @@ -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 } @@ -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 } diff --git a/k8sgo/init_command.go b/k8sgo/init_command.go new file mode 100644 index 0000000..5650b3f --- /dev/null +++ b/k8sgo/init_command.go @@ -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/` diff --git a/k8sgo/statefulset.go b/k8sgo/statefulset.go index 9d494d2..f41f323 100644 --- a/k8sgo/statefulset.go +++ b/k8sgo/statefulset.go @@ -18,6 +18,7 @@ package k8sgo import ( "context" + "fmt" "strings" appsv1 "k8s.io/api/apps/v1" @@ -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 @@ -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 } @@ -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, + }, + }, + } +}