Skip to content

Commit

Permalink
docs(administration): add opensearch configuration documentation (rea…
Browse files Browse the repository at this point in the history
  • Loading branch information
jlemesh committed Sep 6, 2024
1 parent 3668003 commit f9225a9
Showing 1 changed file with 223 additions and 0 deletions.
223 changes: 223 additions & 0 deletions docs/administration/configuration/configuring-opensearch/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# Configuring OpenSearch

OpenSearch with FluentBit is required for live job logs functionality. It is deployed using [OpenSearch Helm chart](https://github.com/opensearch-project/helm-charts) as REANA Helm chart dependency and should be enabled by changing `opensearch.enabled` value to `true`. Configuration can be passed to the chart by putting it under `opensearch` field in REANA Helm chart.

Example Helm command to add live logs to an existing REANA deployment (check [Authentication/authorization section](index.md#authenticationauthorization) on how to create password hashes):

```bash
helm upgrade reana reanahub/reana --wait \
--set opensearch.customSecurityConfig.internalUsers.reana.hash='$So$mE$reAnAPaSswoRDhASh' \
--set opensearch.customSecurityConfig.internalUsers.fluentbit.hash='$So$fLUenTmE$PaSswoRDhASh' \
--set fluent-bit.outputConfig.httpPasswd='FluentBitUserPassword' \
--set components.reana_workflow_controller.environment.REANA_OPENSEARCH_ENABLED=true \
--set components.reana_workflow_controller.environment.REANA_OPENSEARCH_PASSWORD='ReanaUserPassword'
--set opensearch.enabled=true \
--set fluent-bit.enabled=true
```

[External OpenSearch service](index.md#external-opensearch-service) can be used instead (recommended).

## Number of instances

Only one OpenSearch instance is deployed by default. To add more instances, each of these instances needs to have its own `PersistentVolumeClaim` and `PersistentVolume` as each instance writes to a data directory with the same name but different contents - this will not work with `reana-shared-persistent-volume` or `reana-infrastructure-persistent-volume`. OpenSearch Helm chart uses `volumeClaimTemplates` to create a separate volume for each instance. It is possible to use `volumeClaimTemplates` with the `StorageClass` of choice (see [Multiple volumes with custom storage class](index.md#multiple-volumes-with-custom-storage-class)).

Change Helm chart vlaues to configure 3 OpenSearch instances:

```yaml
opensearch:
<...>
singleNode: false
replicas: 3
<...>
```

OpenSearch allows deploying nodes of different types, e. g. `master` and `data`. Current Helm setup does not allow it, and each node has all possible roles, see [default Helm chart roles value](https://github.com/opensearch-project/helm-charts/blob/4253842c1e4d3ac6d4aee294e905c1f20469adc2/charts/opensearch/values.yaml#L16-L20).

## Persistent storage

There are multiple ways to configure persistent strage for OpenSearch.

### Host path

This is the simplest method, but not usable for production, see [Configuring storage volumes](../configuring-storage-volumes/index.md#hostpath).

OpenSearch for REANA is configured with `hostPath` by default, you should change it to one of the configurations below.

### Shared/infrastructure volume

To use shared or infrastructure volume, change `opensearch.extraVolumes` parameter in REANA `values.yaml` file:

```yaml
opensearch:
<...>
extraVolumes:
- name: reana-opensearch-volume
persistentVolumeClaim:
claimName: reana-shared-persistent-volume # or reana-infrastructure-persistent-volume
readOnly: false
<...>
```

Bear in mind that this only works with one OpenSearch node. To deploy multiple nodes, see [Multiple volumes with custom storage class](index.md#multiple-volumes-with-custom-storage-class).

### Multiple volumes with custom storage class

To deploy [multiple OpenSearch nodes](./index.md#number-of-instances), persistence configuration provided by OpenSearch chart should be used. It employs [`volumeClaimTemplates`](https://github.com/opensearch-project/helm-charts/blob/4253842c1e4d3ac6d4aee294e905c1f20469adc2/charts/opensearch/templates/statefulset.yaml#L27-L53) to create a separate `PersistentVolume` and `PersistentVolumeClaim` for each OpenSearch instance. You need to provide the name of your `StorageClass`, which you should have created as described in [NFS](../configuring-storage-volumes/index.md#nfs) or [CephFS](../configuring-storage-volumes/index.md#cephfs) configuration docs. The name of the `StorageClass` should be `reana-shared-volume-storage-class` or `reana-infrastructure-volume-storage-class`:

```yaml
opensearch:
<...>
persistence:
enabled: true
storageClass: "reana-shared-volume-storage-class" # or reana-infrastructure-volume-storage-class
<...>
extraVolumes: []
extraVolumeMounts: []
```
Additionally, you can configure persistence `size`, `annotations` and other attributes, see [docs](https://github.com/opensearch-project/helm-charts/tree/main/charts/opensearch).

Alternatively, `PersistentVolume` and `PersistentVolumeClaim` can be created for each node manually. `PersistentVolumeClaim` should be named as `<clusterName|nameOverride|fullnameOverride>-<nodeGroup>-<clusterName|nameOverride|fullnameOverride>-<nodeGroup>-<N>`, where `N` is a number of an OpenSearch node. The name of each node is either `clusterName-nodeGroup-X`, or `nameOverride-nodeGroup-X` if a `nameOverride` is specified, or `fullnameOverride-X` if a `fullnameOverride` is specified. By default it is `opensearch-cluster-master-0`, `opensearch-cluster-master-1`, etc., hence `PersistentVolumeClaim` names should be `opensearch-cluster-master-opensearch-cluster-master-0`, `opensearch-cluster-master-opensearch-cluster-master-1`, etc. `volumeClaimTemplates` will pick the existing volumes by their names and will not create new ones.

## TLS

OpenSearch uses TLS certificates for communication between nodes (not possible to turn off if using security features, even when only one OpenSearch node is deployed) and for REST API HTTPS (can be disabled). By default both internode communication and REST API use TLS. REST API HTTPS has to be enabled in order to use Basic Authentication for users as in this case username and password in plain text are sent to the server, hence without TLS credentials risk being exposed. You can read more on TLS configuration in [Opensearch documentation](https://opensearch.org/docs/latest/security/configuration/tls).

By default TLS certificates for OpenSearch nodes are generated automatically by a Helm function, similar to how it is done for [Ingress](../configuring-tls-certificates/index.md#default-self-signed-certificate). In production deployments, it is recommended to supply your own certificates by putting them in a secret and mounting to an OpenSearch pod (in `opensearch.secretMounts`).

!!! warning
Add the subject to both CN and SANs of an OpenSearch certificate, otherwise `opensearch-py` client will be unable to verify the hostname.

When certificates change, OpenSearch has to be manually restarted or have dynamic certificate reload as described in the [documentation](https://opensearch.org/docs/latest/security/access-control/api/#reload-transport-certificates). If root CA has changed, services that connect to OpenSearch should also be restarted.

To use custom TLS certificates, change `opensearch.tls.generate` to `false` and manually create a secret with TLS certificates, which should have the following structure:

```yaml
apiVersion: v1
kind: Secret
metadata:
name: reana-opensearch-tls-secret
namespace: <reana opensearch namespace>
type: kubernetes.io/tls
stringData:
ca.crt: |
<root CA public key>
tls.crt: |
<internode public key>
tls.key: |
<internode private key>
admin.crt: |
<admin public key>
admin.key: |
<admin private key>
```

Common name (CN) of each certificate is used in `opensearch.yml` configuration and by default should be `reana.io` (CA), `opensearch-cluster-master.default.svc.cluster.local` (internode) and `opensearch-admin.reana.io` (admin). If you generate the certificates with different common names, you should change `opensearch.yml` values `plugins.security.nodes_dn` and `plugins.security.admin_dn` accordingly (via `opensearch.tls.cert.cn` and `opensearch.tls.admin.cn` Helm chart values).

Admin TLS certificates provide superadmin permissions and are stored in the same secret - there is no `admin` user, hence Basic Authentication credentials are not needed when making requests. Helm generated admin certificates can be used while making REST API requests requiring superadmin permissions (e. g. TLS certificates reload), but not while executing `securityconfig.sh` script.

### Certificate renewal

Helm generated certificate validity in days can be configured via `opensearch.tls.ca.ttl`, `opensearch.tls.cert.ttl` and `opensearch.tls.admin.ttl`. At some point the certificates will have to be renewed whether they are Helm generated or custom.

Certificates can be updated on OpenSearch pod restart or using hot reload without OpenSearch pod restart.

OpenSearch restart takes up to several minutes, hence without hot reload there is a bigger chance of losing some job logs data. If you put REANA in maintenance mode and stopped all jobs, restart method is sufficient.

TLS certificate hot reload is enabled in the chart configuration and allows updating TLS certificates without restarting OpenSearch instance, see [OpenSearch docs](https://opensearch.org/docs/latest/security/configuration/tls/#hot-reloading-tls-certificates).

Certificate renewal steps:

1. Take note what certificates are currently used:

```bash
kubectl exec statefulset/opensearch-cluster-master -- cat ./config/certs/tls.crt
```

1. Update the certificates. Either:

- Delete the secret and upgrade Helm to generate new one:

```bash
kubectl delete secret reana-opensearch-tls-secret
helm upgrade <...>
```

- Or edit it by adding your new custom certificates:

```bash
kubectl edit secret reana-opensearch-tls-secret
```

1. Wait until new secret is mounted into the pods:

```bash
sleep 60
```

1. Check that certificates have changed:

```bash
kubectl exec statefulset/opensearch-cluster-master -- cat ./config/certs/tls.crt
```

1. Load new OpenSearch certificates. Either:

- Restart OpenSearch:

```bash
kubectl rollout restart statefulset opensearch-cluster-master
```

- Hot reload certificates:

```bash
kubectl port-forward service/opensearch-cluster-master 9200:9200
curl --cacert ca.crt --cert admin.crt --key admin.key \
--insecure -XPUT https://localhost:9200/_plugins/_security/api/ssl/transport/reloadcerts
curl --cacert ca.crt --cert admin.crt --key admin.key \
--insecure -XPUT https://localhost:9200/_plugins/_security/api/ssl/http/reloadcerts
```

1. Restart related services if root CA has changed. There might be errors related to TLS until the services are restarted. You probably will lose some logs if there are running workflows or jobs as it can take up to several minutes to restart the services:

```bash
kubectl rollout restart daemonset reana-fluent-bit
kubectl rollout restart deployment reana-workflow-controller
```

## Authentication/authorization

REANA Helm chart configures system users using configuration files in OpenSearch `config/opensearch-security` folder. You can change security configuration by overriding `opensearch.customSecurityConfig` value which creates `internal_users.yaml`, `roles.yaml` and `roles_mapping.yaml` files. This configuration is loaded only once when OpenSearch is first deployed.

!!! warning
Subsequent changes to OpenSearch security configuration files will not take effect unless you run `securityadmin.sh` script, which can also delete users that were created via REST API. Read the [documentation on Opensearch security configuration](https://opensearch.org/docs/latest/security/configuration/security-admin/) before attempting to make changes.
To run `securityadmin.sh` script, you will need [custom admin certificates in PKCS#8 format](https://opensearch.org/docs/latest/security/configuration/generate-certificates/#generate-an-admin-certificate) - it will not work with Helm generated certificates.

By default two users are configured - `reana` and `fluentbit`. Their passwords need to be prepared by first spinning up OpenSearch instance in development environment, connecting to a pod and [running `plugins/opensearch-security/tools/hash.sh` script](https://opensearch.org/docs/latest/security/configuration/yaml/#internal_usersyml):

```bash
kubectl exec statefulset/opensearch-cluster-master -- ./plugins/opensearch-security/tools/hash.sh -p <somepassword>
```

The generated hashes for the passwords should be supplied to Helm with `--set opensearch.customSecurityConfig.internalUsers.reana.hash='$So$Me$pASsWOrD.HasH' --set opensearch.customSecurityConfig.internalUsers.fluentbit.hash='$So$Me$pASsWOrD.HasH'` options.

## External OpenSearch service

Using external OpenSearch service is recommended.

1. Create `reana` and `fluentbit` users in your OpenSearch service. Their passwords will have to be supplied to Helm via `components.reana_workflow_controller.environment.REANA_OPENSEARCH_PASSWORD` and `fluent-bit.outputConfig.httpPasswd` respectively.

1. Create `reana-opensearch-tls-secret` as described in [TLS](index.md#tls) but only add `ca.crt` field that contains root CA of the OpenSearch certificates.

1. Run:

```bash
helm install reana reanahub/reana --wait \
--set fluent-bit.outputConfig.httpPasswd='FluentBitUserPassword' \
--set fluent-bit.enabled=true \
--set components.reana_workflow_controller.environment.REANA_OPENSEARCH_ENABLED=true \
--set components.reana_workflow_controller.environment.REANA_OPENSEARCH_PASSWORD='ReanaUserPassword' \
--set components.reana_workflow_controller.environment.REANA_OPENSEARCH_HOST='your.opensearch.host'
```

0 comments on commit f9225a9

Please sign in to comment.