Reorganized for new stable/waypoint versioning design.
This commit is contained in:
69
nfs/versions/v4/README.md
Normal file
69
nfs/versions/v4/README.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# NFS Client Provisioner
|
||||
|
||||
Provides shared NFS storage to the cluster by creating a StorageClass and PersistentVolume backed by an external NFS server. This is an infrastructure app — it has no pods or namespace, just cluster-scoped resources.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You need an NFS server already running and exporting a path. To set one up on a host:
|
||||
|
||||
```bash
|
||||
./setup-nfs-host.sh <host> <media-path>
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```bash
|
||||
./setup-nfs-host.sh box-01 /srv/nfs
|
||||
```
|
||||
|
||||
This SSHs into the host, installs `nfs-kernel-server`, and configures the export.
|
||||
|
||||
## Configuration
|
||||
|
||||
When added to an instance, the default config is merged into `config.yaml`:
|
||||
|
||||
```yaml
|
||||
apps:
|
||||
nfs:
|
||||
host: "192.168.1.100"
|
||||
mediaPath: "/mnt/storage/media"
|
||||
storageCapacity: "1Ti"
|
||||
```
|
||||
|
||||
Update `host` and `mediaPath` to match your NFS server before deploying.
|
||||
|
||||
## What Gets Deployed
|
||||
|
||||
- **StorageClass** (`nfs`) — allows PVCs to request NFS-backed storage
|
||||
- **PersistentVolume** (`nfs-media-pv`) — a cluster-wide volume pointing to the NFS export
|
||||
|
||||
No namespace, pods, or services are created.
|
||||
|
||||
## Scripts
|
||||
|
||||
- **check-nfs** — Verifies the NFS server is reachable, the export path exists, and checks whether the StorageClass and PersistentVolume are present in the cluster. Run from the app detail panel in the web UI.
|
||||
|
||||
## Usage
|
||||
|
||||
Applications can use NFS storage by setting `storageClassName: nfs` in their PVCs:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: media-pvc
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
storageClassName: nfs
|
||||
resources:
|
||||
requests:
|
||||
storage: 100Gi
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Cluster-wide access — any pod can mount the NFS share regardless of node placement
|
||||
- ReadWriteMany — multiple pods can simultaneously read and write
|
||||
- Configurable capacity — set PersistentVolume size via `storageCapacity`
|
||||
- Retain policy — data is preserved when volumes are released
|
||||
6
nfs/versions/v4/kustomization.yaml
Normal file
6
nfs/versions/v4/kustomization.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
|
||||
resources:
|
||||
- persistent-volume.yaml
|
||||
- storage-class.yaml
|
||||
9
nfs/versions/v4/manifest.yaml
Normal file
9
nfs/versions/v4/manifest.yaml
Normal file
@@ -0,0 +1,9 @@
|
||||
version: v4.0.18-3
|
||||
scripts:
|
||||
- name: check-nfs
|
||||
path: scripts/check-nfs.sh
|
||||
description: Verify NFS server is reachable and the export path is available
|
||||
defaultConfig:
|
||||
host: "192.168.1.100"
|
||||
mediaPath: "/mnt/storage/media"
|
||||
storageCapacity: "1Ti"
|
||||
23
nfs/versions/v4/persistent-volume.yaml
Normal file
23
nfs/versions/v4/persistent-volume.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: nfs-media-pv
|
||||
labels:
|
||||
storage: nfs-media
|
||||
spec:
|
||||
capacity:
|
||||
storage: {{ .storageCapacity }}
|
||||
accessModes:
|
||||
- ReadWriteMany
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
storageClassName: nfs
|
||||
nfs:
|
||||
server: {{ .host }}
|
||||
path: {{ .mediaPath }}
|
||||
mountOptions:
|
||||
- nfsvers=4.1
|
||||
- rsize=1048576
|
||||
- wsize=1048576
|
||||
- hard
|
||||
- intr
|
||||
- timeo=600
|
||||
79
nfs/versions/v4/scripts/check-nfs.sh
Executable file
79
nfs/versions/v4/scripts/check-nfs.sh
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
# Verify NFS server is reachable and the export path is available.
|
||||
# Run before or after deployment to validate NFS connectivity.
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
if [ -z "${WILD_INSTANCE}" ] || [ -z "${WILD_API_DATA_DIR}" ]; then
|
||||
echo "ERROR: WILD_INSTANCE and WILD_API_DATA_DIR must be set"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CONFIG_FILE="${WILD_API_DATA_DIR}/instances/${WILD_INSTANCE}/config.yaml"
|
||||
|
||||
NFS_HOST="$(yq '.apps.nfs.host' "${CONFIG_FILE}" 2>/dev/null | tr -d '"')"
|
||||
NFS_PATH="$(yq '.apps.nfs.mediaPath' "${CONFIG_FILE}" 2>/dev/null | tr -d '"')"
|
||||
|
||||
if [ -z "${NFS_HOST}" ] || [ "${NFS_HOST}" = "null" ]; then
|
||||
echo "ERROR: apps.nfs.host not set in config"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${NFS_PATH}" ] || [ "${NFS_PATH}" = "null" ]; then
|
||||
echo "ERROR: apps.nfs.mediaPath not set in config"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "NFS host: ${NFS_HOST}"
|
||||
echo "NFS path: ${NFS_PATH}"
|
||||
|
||||
# Resolve hostname to IP
|
||||
if [[ "${NFS_HOST}" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
NFS_IP="${NFS_HOST}"
|
||||
else
|
||||
NFS_IP=$(getent hosts "${NFS_HOST}" 2>/dev/null | awk '{print $1}' | head -n1 || true)
|
||||
if [ -z "${NFS_IP}" ]; then
|
||||
echo "ERROR: Cannot resolve hostname ${NFS_HOST}"
|
||||
exit 1
|
||||
fi
|
||||
echo "Resolved to: ${NFS_IP}"
|
||||
fi
|
||||
|
||||
# Check showmount
|
||||
if ! command -v showmount >/dev/null 2>&1; then
|
||||
echo "WARNING: showmount not available, skipping export check"
|
||||
else
|
||||
echo ""
|
||||
echo "Checking NFS exports..."
|
||||
if timeout 10 showmount -e "${NFS_IP}" >/dev/null 2>&1; then
|
||||
if showmount -e "${NFS_IP}" | grep -q "${NFS_PATH}"; then
|
||||
echo "OK: ${NFS_PATH} is exported"
|
||||
else
|
||||
echo "ERROR: ${NFS_PATH} not found in NFS exports:"
|
||||
showmount -e "${NFS_IP}"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "ERROR: Cannot reach NFS server at ${NFS_IP}:2049"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check k8s resources if KUBECONFIG is available
|
||||
if [ -n "${KUBECONFIG}" ]; then
|
||||
echo ""
|
||||
echo "Checking Kubernetes resources..."
|
||||
if kubectl get storageclass nfs >/dev/null 2>&1; then
|
||||
echo "OK: StorageClass 'nfs' exists"
|
||||
else
|
||||
echo "WARNING: StorageClass 'nfs' not found (deploy NFS first)"
|
||||
fi
|
||||
if kubectl get pv nfs-media-pv >/dev/null 2>&1; then
|
||||
echo "OK: PersistentVolume 'nfs-media-pv' exists"
|
||||
kubectl get pv nfs-media-pv --no-headers
|
||||
else
|
||||
echo "WARNING: PersistentVolume 'nfs-media-pv' not found (deploy NFS first)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "NFS check complete."
|
||||
306
nfs/versions/v4/setup-nfs-host.sh
Executable file
306
nfs/versions/v4/setup-nfs-host.sh
Executable file
@@ -0,0 +1,306 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
set -o pipefail
|
||||
|
||||
# Navigate to script directory
|
||||
SCRIPT_PATH="$(realpath "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
|
||||
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
|
||||
usage() {
|
||||
echo "Usage: setup-nfs-host.sh [server] [media-path] [options]"
|
||||
echo ""
|
||||
echo "Set up NFS server on the specified host."
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " setup-nfs-host.sh box-01 /data/media"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " -e, --export-options Set the NFS export options"
|
||||
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-e|--export-options)
|
||||
if [[ -z "$2" ]]; then
|
||||
echo "Error: --export-options requires a value"
|
||||
exit 1
|
||||
else
|
||||
NFS_EXPORT_OPTIONS="$2"
|
||||
fi
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "Unknown option $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
# First non-option argument is server
|
||||
if [[ -z "$NFS_HOST" ]]; then
|
||||
export NFS_HOST="$1"
|
||||
# Second non-option argument is media path
|
||||
elif [[ -z "$NFS_MEDIA_PATH" ]]; then
|
||||
export NFS_MEDIA_PATH="$1"
|
||||
else
|
||||
echo "Too many arguments"
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "Setting up NFS server on this host..."
|
||||
|
||||
# Check if required NFS variables are configured
|
||||
if [[ -z "${NFS_HOST}" ]]; then
|
||||
echo "NFS_HOST not set. Please set NFS_HOST=<hostname> in your environment"
|
||||
echo "Example: export NFS_HOST=box-01"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure NFS_MEDIA_PATH is explicitly set
|
||||
if [[ -z "${NFS_MEDIA_PATH}" ]]; then
|
||||
echo "Error: NFS_MEDIA_PATH not set. Please set it in your environment"
|
||||
echo "Example: export NFS_MEDIA_PATH=/data/media"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set default for NFS_EXPORT_OPTIONS if not already set
|
||||
if [[ -z "${NFS_EXPORT_OPTIONS}" ]]; then
|
||||
export NFS_EXPORT_OPTIONS="*(rw,sync,no_subtree_check,no_root_squash)"
|
||||
echo "Using default NFS_EXPORT_OPTIONS: ${NFS_EXPORT_OPTIONS}"
|
||||
fi
|
||||
|
||||
echo "Target NFS host: ${NFS_HOST}"
|
||||
echo "Media path: ${NFS_MEDIA_PATH}"
|
||||
echo "Export options: ${NFS_EXPORT_OPTIONS}"
|
||||
|
||||
# Function to check if we're running on the correct host
|
||||
check_host() {
|
||||
local current_hostname=$(hostname)
|
||||
if [[ "${current_hostname}" != "${NFS_HOST}" ]]; then
|
||||
echo "Warning: Current host (${current_hostname}) differs from NFS_HOST (${NFS_HOST})"
|
||||
echo "This script should be run on ${NFS_HOST}"
|
||||
read -p "Continue anyway? (y/N): " -n 1 -r
|
||||
echo
|
||||
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to install NFS server and SMB/CIFS
|
||||
install_nfs_server() {
|
||||
echo "Installing NFS server and SMB/CIFS packages..."
|
||||
|
||||
# Detect package manager and install NFS server + Samba
|
||||
if command -v apt-get >/dev/null 2>&1; then
|
||||
# Debian/Ubuntu
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y nfs-kernel-server nfs-common samba samba-common-bin
|
||||
elif command -v yum >/dev/null 2>&1; then
|
||||
# RHEL/CentOS
|
||||
sudo yum install -y nfs-utils samba samba-client
|
||||
elif command -v dnf >/dev/null 2>&1; then
|
||||
# Fedora
|
||||
sudo dnf install -y nfs-utils samba samba-client
|
||||
else
|
||||
echo "Error: Unable to detect package manager. Please install NFS server and Samba manually."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to create media directory
|
||||
create_media_directory() {
|
||||
echo "Creating media directory: ${NFS_MEDIA_PATH}"
|
||||
|
||||
# Create directory if it doesn't exist
|
||||
sudo mkdir -p "${NFS_MEDIA_PATH}"
|
||||
|
||||
# Set appropriate permissions
|
||||
# Using 755 for directory, allowing read/execute for all, write for owner
|
||||
sudo chmod 755 "${NFS_MEDIA_PATH}"
|
||||
|
||||
echo "Media directory created with appropriate permissions"
|
||||
echo "Directory info:"
|
||||
ls -la "${NFS_MEDIA_PATH}/"
|
||||
}
|
||||
|
||||
# Function to configure NFS exports
|
||||
configure_nfs_exports() {
|
||||
echo "Configuring NFS exports..."
|
||||
|
||||
local export_line="${NFS_MEDIA_PATH} ${NFS_EXPORT_OPTIONS}"
|
||||
local exports_file="/etc/exports"
|
||||
|
||||
# Backup existing exports file
|
||||
sudo cp "${exports_file}" "${exports_file}.backup.$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
|
||||
|
||||
# Check if export already exists
|
||||
if sudo grep -q "^${NFS_MEDIA_PATH}" "${exports_file}" 2>/dev/null; then
|
||||
echo "Export for ${NFS_MEDIA_PATH} already exists, updating..."
|
||||
sudo sed -i "s|^${NFS_MEDIA_PATH}.*|${export_line}|" "${exports_file}"
|
||||
else
|
||||
echo "Adding new export for ${NFS_MEDIA_PATH}..."
|
||||
echo "${export_line}" | sudo tee -a "${exports_file}"
|
||||
fi
|
||||
|
||||
# Export the filesystems
|
||||
sudo exportfs -rav
|
||||
|
||||
echo "NFS exports configured:"
|
||||
sudo exportfs -v
|
||||
}
|
||||
|
||||
# Function to start and enable NFS services
|
||||
start_nfs_services() {
|
||||
echo "Starting NFS services..."
|
||||
|
||||
# Start and enable NFS server
|
||||
sudo systemctl enable nfs-server
|
||||
sudo systemctl start nfs-server
|
||||
|
||||
# Also enable related services
|
||||
sudo systemctl enable rpcbind
|
||||
sudo systemctl start rpcbind
|
||||
|
||||
echo "NFS services started and enabled"
|
||||
|
||||
# Show service status
|
||||
sudo systemctl status nfs-server --no-pager --lines=5
|
||||
}
|
||||
|
||||
# Function to configure SMB/CIFS sharing
|
||||
configure_smb_sharing() {
|
||||
echo "Configuring SMB/CIFS sharing..."
|
||||
|
||||
local smb_config="/etc/samba/smb.conf"
|
||||
local share_name="media"
|
||||
|
||||
# Backup existing config
|
||||
sudo cp "${smb_config}" "${smb_config}.backup.$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
|
||||
|
||||
# Check if share already exists
|
||||
if sudo grep -q "^\[${share_name}\]" "${smb_config}" 2>/dev/null; then
|
||||
echo "SMB share '${share_name}' already exists, updating..."
|
||||
# Remove existing share section
|
||||
sudo sed -i "/^\[${share_name}\]/,/^\[/{ /^\[${share_name}\]/d; /^\[/!d; }" "${smb_config}"
|
||||
fi
|
||||
|
||||
# Add media share configuration
|
||||
cat << EOF | sudo tee -a "${smb_config}"
|
||||
|
||||
[${share_name}]
|
||||
comment = Media files for Wild Cloud
|
||||
path = ${NFS_MEDIA_PATH}
|
||||
browseable = yes
|
||||
read only = no
|
||||
guest ok = yes
|
||||
create mask = 0664
|
||||
directory mask = 0775
|
||||
force user = $(whoami)
|
||||
force group = $(whoami)
|
||||
EOF
|
||||
|
||||
echo "SMB share configuration added"
|
||||
|
||||
# Test configuration
|
||||
if sudo testparm -s >/dev/null 2>&1; then
|
||||
echo "✓ SMB configuration is valid"
|
||||
else
|
||||
echo "✗ SMB configuration has errors"
|
||||
sudo testparm
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to start SMB services
|
||||
start_smb_services() {
|
||||
echo "Starting SMB services..."
|
||||
|
||||
# Enable and start Samba services
|
||||
sudo systemctl enable smbd
|
||||
sudo systemctl start smbd
|
||||
sudo systemctl enable nmbd
|
||||
sudo systemctl start nmbd
|
||||
|
||||
echo "SMB services started and enabled"
|
||||
|
||||
# Show service status
|
||||
sudo systemctl status smbd --no-pager --lines=3
|
||||
}
|
||||
|
||||
# Function to test NFS setup
|
||||
test_nfs_setup() {
|
||||
echo "Testing NFS setup..."
|
||||
|
||||
# Test if NFS is responding
|
||||
if command -v showmount >/dev/null 2>&1; then
|
||||
echo "Available NFS exports:"
|
||||
showmount -e localhost || echo "Warning: showmount failed, but NFS may still be working"
|
||||
fi
|
||||
|
||||
# Check if the export directory is accessible
|
||||
if [[ -d "${NFS_MEDIA_PATH}" ]]; then
|
||||
echo "✓ Media directory exists and is accessible"
|
||||
else
|
||||
echo "✗ Media directory not accessible"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to show usage instructions
|
||||
show_usage_instructions() {
|
||||
echo
|
||||
echo "=== NFS/SMB Host Setup Complete ==="
|
||||
echo
|
||||
echo "NFS and SMB servers are now running on this host with media directory: ${NFS_MEDIA_PATH}"
|
||||
echo
|
||||
echo "Access methods:"
|
||||
echo "1. NFS (for Kubernetes): Use setup-nfs-k8s.sh to register with cluster"
|
||||
echo "2. SMB/CIFS (for Windows): \\\\${NFS_HOST}\\media"
|
||||
echo
|
||||
echo "To add media files:"
|
||||
echo "- Copy directly to: ${NFS_MEDIA_PATH}"
|
||||
echo "- Or mount SMB share from Windows and copy there"
|
||||
echo
|
||||
echo "Windows SMB mount:"
|
||||
echo "- Open File Explorer"
|
||||
echo "- Map network drive to: \\\\${NFS_HOST}\\media"
|
||||
echo "- Or use: \\\\$(hostname -I | awk '{print $1}')\\media"
|
||||
echo
|
||||
echo "To verify services:"
|
||||
echo "- NFS: showmount -e ${NFS_HOST}"
|
||||
echo "- SMB: smbclient -L ${NFS_HOST} -N"
|
||||
echo "- Status: systemctl status nfs-server smbd"
|
||||
echo
|
||||
echo "Current NFS exports:"
|
||||
sudo exportfs -v
|
||||
echo
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
check_host
|
||||
install_nfs_server
|
||||
create_media_directory
|
||||
configure_nfs_exports
|
||||
start_nfs_services
|
||||
configure_smb_sharing
|
||||
start_smb_services
|
||||
test_nfs_setup
|
||||
show_usage_instructions
|
||||
}
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
10
nfs/versions/v4/storage-class.yaml
Normal file
10
nfs/versions/v4/storage-class.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: storage.k8s.io/v1
|
||||
kind: StorageClass
|
||||
metadata:
|
||||
name: nfs
|
||||
provisioner: nfs
|
||||
parameters:
|
||||
server: {{ .host }}
|
||||
path: {{ .mediaPath }}
|
||||
reclaimPolicy: Retain
|
||||
allowVolumeExpansion: true
|
||||
Reference in New Issue
Block a user