Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,29 @@ spec:
name:
description: Name to use for the volume. Required.
type: string
nfs:
description: NFS object to use to populate the volume
properties:
path:
description: |-
path that is exported by the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
readOnly:
description: |-
readOnly here will force the NFS export to be mounted with read-only permissions.
Defaults to false.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: boolean
server:
description: |-
server is the hostname or IP address of the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
required:
- path
- server
type: object
path:
description: Path in the container to mount the volume at.
Required.
Expand Down Expand Up @@ -1705,6 +1728,11 @@ spec:
- name
- path
type: object
x-kubernetes-validations:
- message: exactly one of secret, configMap, emptyDir, csi,
projected, nfs must be set
rule: (has(self.secret)?1:0)+(has(self.configMap)?1:0)+(has(self.emptyDir)?1:0)+(has(self.csi)?1:0)+(has(self.projected)?1:0)+(has(self.nfs)?1:0)
== 1
type: array
affinity:
description: Affinity is a group of affinity scheduling rules.
Expand Down Expand Up @@ -3557,6 +3585,29 @@ spec:
name:
description: Name to use for the volume. Required.
type: string
nfs:
description: NFS object to use to populate the volume
properties:
path:
description: |-
path that is exported by the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
readOnly:
description: |-
readOnly here will force the NFS export to be mounted with read-only permissions.
Defaults to false.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: boolean
server:
description: |-
server is the hostname or IP address of the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
required:
- path
- server
type: object
path:
description: Path in the container to mount the volume at.
Required.
Expand Down Expand Up @@ -3979,6 +4030,11 @@ spec:
- name
- path
type: object
x-kubernetes-validations:
- message: exactly one of secret, configMap, emptyDir, csi,
projected, nfs must be set
rule: (has(self.secret)?1:0)+(has(self.configMap)?1:0)+(has(self.emptyDir)?1:0)+(has(self.csi)?1:0)+(has(self.projected)?1:0)+(has(self.nfs)?1:0)
== 1
type: array
annotations:
additionalProperties:
Expand Down
40 changes: 40 additions & 0 deletions docs/userguide/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,12 @@ spec:
sources:
- serviceAccountToken:
path: "token"
- name: nfs-volume
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
readOnly: false # Optional, defaults to false
dashboards:
additionalVolumes:
- name: example-secret
Expand All @@ -765,6 +771,40 @@ spec:
secretName: secret-name
```

#### NFS Volume Support

NFS volumes can be mounted directly into OpenSearch pods without requiring external provisioners or CSI drivers. This is particularly useful for snapshot repositories stored on NFS shares. To configure an NFS volume, specify the `nfs` field with the required `server` and `path` parameters:

```yaml
spec:
general:
additionalVolumes:
- name: nfs-backups
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
readOnly: false # Optional, defaults to false
```

This can be combined with snapshot repository configuration:

```yaml
spec:
general:
additionalVolumes:
- name: nfs-backups
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
snapshotRepositories:
- name: nfs-repository
type: fs
settings:
location: /mnt/backups/opensearch
```

The defined volumes are added to all pods of the opensearch cluster. It is currently not possible to define them per nodepool.

### Adding environment variables to pods
Expand Down
3 changes: 3 additions & 0 deletions opensearch-operator/api/v1/opensearch_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ type ImageSpec struct {
ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"`
}

// +kubebuilder:validation:XValidation:rule="(has(self.secret)?1:0)+(has(self.configMap)?1:0)+(has(self.emptyDir)?1:0)+(has(self.csi)?1:0)+(has(self.projected)?1:0)+(has(self.nfs)?1:0) == 1",message="exactly one of secret, configMap, emptyDir, csi, projected, nfs must be set"
type AdditionalVolume struct {
// Name to use for the volume. Required.
Name string `json:"name"`
Expand All @@ -303,6 +304,8 @@ type AdditionalVolume struct {
CSI *corev1.CSIVolumeSource `json:"csi,omitempty"`
// Projected object to use to populate the volume
Projected *corev1.ProjectedVolumeSource `json:"projected,omitempty"`
// NFS object to use to populate the volume
NFS *corev1.NFSVolumeSource `json:"nfs,omitempty"`
// Whether to restart the pods on content change
RestartPods bool `json:"restartPods,omitempty"`
}
Expand Down
5 changes: 5 additions & 0 deletions opensearch-operator/api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,29 @@ spec:
name:
description: Name to use for the volume. Required.
type: string
nfs:
description: NFS object to use to populate the volume
properties:
path:
description: |-
path that is exported by the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
readOnly:
description: |-
readOnly here will force the NFS export to be mounted with read-only permissions.
Defaults to false.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: boolean
server:
description: |-
server is the hostname or IP address of the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
required:
- path
- server
type: object
path:
description: Path in the container to mount the volume at.
Required.
Expand Down Expand Up @@ -1705,6 +1728,11 @@ spec:
- name
- path
type: object
x-kubernetes-validations:
- message: exactly one of secret, configMap, emptyDir, csi,
projected, nfs must be set
rule: (has(self.secret)?1:0)+(has(self.configMap)?1:0)+(has(self.emptyDir)?1:0)+(has(self.csi)?1:0)+(has(self.projected)?1:0)+(has(self.nfs)?1:0)
== 1
type: array
affinity:
description: Affinity is a group of affinity scheduling rules.
Expand Down Expand Up @@ -3557,6 +3585,29 @@ spec:
name:
description: Name to use for the volume. Required.
type: string
nfs:
description: NFS object to use to populate the volume
properties:
path:
description: |-
path that is exported by the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
readOnly:
description: |-
readOnly here will force the NFS export to be mounted with read-only permissions.
Defaults to false.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: boolean
server:
description: |-
server is the hostname or IP address of the NFS server.
More info: https://kubernetes.io/docs/concepts/storage/volumes#nfs
type: string
required:
- path
- server
type: object
path:
description: Path in the container to mount the volume at.
Required.
Expand Down Expand Up @@ -3979,6 +4030,11 @@ spec:
- name
- path
type: object
x-kubernetes-validations:
- message: exactly one of secret, configMap, emptyDir, csi,
projected, nfs must be set
rule: (has(self.secret)?1:0)+(has(self.configMap)?1:0)+(has(self.emptyDir)?1:0)+(has(self.csi)?1:0)+(has(self.projected)?1:0)+(has(self.nfs)?1:0)
== 1
type: array
annotations:
additionalProperties:
Expand Down
10 changes: 9 additions & 1 deletion opensearch-operator/pkg/reconcilers/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,21 @@ func CreateAdditionalVolumes(
},
})
}
if volumeConfig.NFS != nil {
retVolumes = append(retVolumes, corev1.Volume{
Name: volumeConfig.Name,
VolumeSource: corev1.VolumeSource{
NFS: volumeConfig.NFS,
},
})
}
if volumeConfig.RestartPods {
namesIndex[volumeConfig.Name] = i
names = append(names, volumeConfig.Name)
}

subPath := ""
// SubPaths are only supported for ConfigMaps, Secrets and CSI volumes
// SubPaths are only supported for ConfigMaps, Secrets, CSI and Projected volumes
if volumeConfig.ConfigMap != nil || volumeConfig.Secret != nil || volumeConfig.CSI != nil || volumeConfig.Projected != nil {
subPath = strings.TrimSpace(volumeConfig.SubPath)
}
Expand Down
19 changes: 19 additions & 0 deletions opensearch-operator/pkg/reconcilers/util/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,4 +200,23 @@ var _ = Describe("Additional volumes", func() {
Expect(volumeMount[0].SubPath).To(BeEmpty())
})
})

When("NFS volume is added", func() {
It("Should have NFSVolumeSource fields and mount readOnly", func() {
volumeConfigs[0].NFS = &v1.NFSVolumeSource{
Server: "10.0.0.1",
Path: "/export/path",
ReadOnly: true,
}

volume, volumeMount, _, _ := CreateAdditionalVolumes(mockClient, namespace, volumeConfigs)
Expect(volume[0].NFS.Server).To(Equal("10.0.0.1"))
Expect(volume[0].NFS.Path).To(Equal("/export/path"))
Expect(volume[0].NFS.ReadOnly).To(BeTrue())
Expect(volumeMount[0].MountPath).To(Equal("myPath/a/b"))
Expect(volumeMount[0].ReadOnly).To(BeTrue())
Expect(volumeMount[0].SubPath).To(BeEmpty())

})
})
})