Skip to content

Commit c68cc5f

Browse files
committed
nfs
1 parent 267b73a commit c68cc5f

2 files changed

Lines changed: 48 additions & 168 deletions

File tree

internal/controller/appruntime_controller.go

Lines changed: 28 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -308,133 +308,30 @@ func (r *AppRuntimeReconciler) createPod(ctx context.Context, appRuntime *enterp
308308
splunkHeadlessSvc := enterprise.GetSplunkServiceName(instType, parentName, true)
309309
splunkAddr := fmt.Sprintf("%s.%s.%s.svc.cluster.local", splunkPodName, splunkHeadlessSvc, nn.Namespace)
310310

311-
syncthingAPIKey := "syncthing-appruntime"
312-
313-
// Init script: generate certs, discover server device ID via REST API,
314-
// configure mutual peering, wait for initial sync to complete.
315-
// Uses Syncthing v1.18 CLI syntax (-flag= instead of --flag or subcommands).
316-
// Uses /rest/system/config endpoint (works across all Syncthing versions).
317-
syncthingInitCmd := fmt.Sprintf(`set -e
318-
319-
# Create var directory structure needed by the worker process
320-
mkdir -p /opt/splunk/var/log/splunk/ep \
321-
/opt/splunk/var/lib/splunk \
322-
/opt/splunk/var/run/splunk \
323-
/opt/splunk/var/spool
324-
325-
ST_HOME=/var/syncthing
326-
SERVER_ADDR="%s"
327-
SERVER_API="http://${SERVER_ADDR}:8384"
328-
API_KEY="%s"
329-
330-
mkdir -p "$ST_HOME"
331-
332-
# Generate local certs (v1.18 syntax)
333-
syncthing -generate="$ST_HOME"
334-
MY_DEVICE_ID=$(syncthing -home="$ST_HOME" -device-id)
335-
echo "Client device ID: $MY_DEVICE_ID"
336-
337-
# Wait for server API to be reachable and get its device ID
338-
echo "Waiting for Syncthing server at $SERVER_API..."
339-
SERVER_DEVICE_ID=""
340-
for i in $(seq 1 60); do
341-
SERVER_DEVICE_ID=$(curl -sf -H "X-API-Key: $API_KEY" "$SERVER_API/rest/system/status" 2>/dev/null | \
342-
python3 -c "import sys,json; print(json.load(sys.stdin)['myID'])" 2>/dev/null) && break
343-
SERVER_DEVICE_ID=""
344-
echo " attempt $i: server not ready, retrying in 3s..."
311+
nfsMountCmd := fmt.Sprintf(`set -e
312+
313+
NFS_SERVER="%s"
314+
315+
echo "Mounting NFS from $NFS_SERVER..."
316+
for i in $(seq 1 30); do
317+
mount -t nfs4 -o soft,timeo=50,retrans=2,nolock "$NFS_SERVER":/splunk-etc /opt/splunk/etc && \
318+
mount -t nfs4 -o soft,timeo=50,retrans=2,nolock "$NFS_SERVER":/splunk-var /opt/splunk/var && break
319+
echo "NFS mount attempt $i failed, retrying in 3s..."
320+
umount /opt/splunk/etc 2>/dev/null || true
345321
sleep 3
346322
done
347-
if [ -z "$SERVER_DEVICE_ID" ]; then
348-
echo "ERROR: could not reach Syncthing server after 60 attempts"
323+
324+
if ! mountpoint -q /opt/splunk/etc; then
325+
echo "ERROR: failed to mount NFS /etc after 30 attempts"
326+
exit 1
327+
fi
328+
if ! mountpoint -q /opt/splunk/var; then
329+
echo "ERROR: failed to mount NFS /var after 30 attempts"
349330
exit 1
350331
fi
351-
echo "Server device ID: $SERVER_DEVICE_ID"
352-
353-
# Write client config with server as peer
354-
cat > "$ST_HOME/config.xml" <<XMLEOF
355-
<configuration version="28">
356-
<folder id="splunk-etc" label="splunk-etc" path="/opt/splunk/etc" type="sendreceive" rescanIntervalS="3600" fsWatcherEnabled="true" fsWatcherDelayS="1">
357-
<filesystemType>basic</filesystemType>
358-
<device id="$MY_DEVICE_ID" introducedBy=""></device>
359-
<device id="$SERVER_DEVICE_ID" introducedBy=""></device>
360-
<minDiskFree unit="%%">0</minDiskFree>
361-
</folder>
362-
<device id="$MY_DEVICE_ID" name="client" compression="metadata">
363-
<address>dynamic</address>
364-
</device>
365-
<device id="$SERVER_DEVICE_ID" name="server" compression="metadata">
366-
<address>tcp://${SERVER_ADDR}:22000</address>
367-
</device>
368-
<gui enabled="true" tls="false" debugging="false">
369-
<address>0.0.0.0:8385</address>
370-
<apikey>$API_KEY</apikey>
371-
</gui>
372-
<options>
373-
<listenAddress>tcp://0.0.0.0:22001</listenAddress>
374-
<globalAnnounceEnabled>false</globalAnnounceEnabled>
375-
<localAnnounceEnabled>false</localAnnounceEnabled>
376-
<relaysEnabled>false</relaysEnabled>
377-
<natEnabled>false</natEnabled>
378-
<urAccepted>-1</urAccepted>
379-
<crashReportingEnabled>false</crashReportingEnabled>
380-
</options>
381-
</configuration>
382-
XMLEOF
383-
384-
# Add this client as a device on the server and share the folder with it.
385-
# Uses /rest/system/config (GET + POST entire config) which works on all versions.
386-
echo "Adding client device to server config..."
387-
SERVER_CFG=$(curl -sf -H "X-API-Key: $API_KEY" "$SERVER_API/rest/system/config")
388-
UPDATED_CFG=$(echo "$SERVER_CFG" | python3 -c "
389-
import sys, json
390-
cfg = json.load(sys.stdin)
391-
my_id = '$MY_DEVICE_ID'
392-
# Add client device if not present
393-
devs = cfg.get('devices', [])
394-
if not any(d['deviceID'] == my_id for d in devs):
395-
devs.append({'deviceID': my_id, 'name': 'client-$HOSTNAME', 'addresses': ['dynamic'], 'compression': 'metadata'})
396-
cfg['devices'] = devs
397-
# Add client device to the folder if not present
398-
for f in cfg.get('folders', []):
399-
if f['id'] == 'splunk-etc':
400-
fdevs = f.get('devices', [])
401-
if not any(d['deviceID'] == my_id for d in fdevs):
402-
fdevs.append({'deviceID': my_id, 'introducedBy': ''})
403-
f['devices'] = fdevs
404-
json.dump(cfg, sys.stdout)
405-
")
406-
curl -sf -X POST -H "X-API-Key: $API_KEY" -H "Content-Type: application/json" \
407-
"$SERVER_API/rest/system/config" \
408-
-d "$UPDATED_CFG"
409-
echo "Server config updated."
410-
411-
# Start syncthing in the background to perform initial sync (v1.18 syntax)
412-
syncthing -home="$ST_HOME" -no-browser -no-restart -verbose &
413-
ST_PID=$!
414-
415-
# Wait for initial sync to complete
416-
echo "Waiting for initial sync to complete..."
417-
for i in $(seq 1 120); do
418-
sleep 3
419-
RESULT=$(curl -sf -H "X-API-Key: $API_KEY" "http://127.0.0.1:8385/rest/db/completion?folder=splunk-etc&device=$SERVER_DEVICE_ID" 2>/dev/null) || continue
420-
COMPLETION=$(echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(f\"{d['completion']:.0f}\")" 2>/dev/null) || COMPLETION="0"
421-
NEED=$(echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['needBytes'])" 2>/dev/null) || NEED="-1"
422-
echo " sync progress: ${COMPLETION}%% (needBytes: $NEED)"
423-
if [ "$COMPLETION" = "100" ] && [ "$NEED" = "0" ]; then
424-
echo "Initial sync complete!"
425-
kill $ST_PID 2>/dev/null || true
426-
wait $ST_PID 2>/dev/null || true
427-
exit 0
428-
fi
429-
done
430-
echo "ERROR: initial sync did not complete in time"
431-
kill $ST_PID 2>/dev/null || true
432-
exit 1`, splunkAddr, syncthingAPIKey)
433332
434-
splunkVolumeMounts := []corev1.VolumeMount{
435-
{Name: "splunk-etc", MountPath: "/opt/splunk/etc"},
436-
{Name: "splunk-var", MountPath: "/opt/splunk/var"},
437-
}
333+
echo "NFS mounts established successfully"
334+
exec /usr/local/bin/entrypoint.sh`, splunkAddr)
438335

439336
privileged := true
440337
pod := &corev1.Pod{
@@ -458,24 +355,13 @@ exit 1`, splunkAddr, syncthingAPIKey)
458355
{Name: "splunk-bin", MountPath: "/mnt/splunk-bin"},
459356
},
460357
},
461-
{
462-
Name: "syncthing-init",
463-
Image: appRuntime.Spec.Image,
464-
ImagePullPolicy: corev1.PullIfNotPresent,
465-
Command: []string{"sh", "-c", syncthingInitCmd},
466-
VolumeMounts: append(splunkVolumeMounts,
467-
corev1.VolumeMount{Name: "syncthing-config", MountPath: "/var/syncthing"},
468-
),
469-
},
470358
},
471359
Containers: []corev1.Container{
472360
{
473361
Image: appRuntime.Spec.Image,
474362
Name: "appruntime",
475363
ImagePullPolicy: corev1.PullAlways,
476-
Command: []string{
477-
"/usr/local/bin/entrypoint.sh",
478-
},
364+
Command: []string{"sh", "-c", nfsMountCmd},
479365
Ports: []corev1.ContainerPort{
480366
{
481367
Name: "appruntime",
@@ -488,23 +374,16 @@ exit 1`, splunkAddr, syncthingAPIKey)
488374
Protocol: corev1.ProtocolTCP,
489375
},
490376
},
491-
VolumeMounts: append(splunkVolumeMounts,
492-
corev1.VolumeMount{Name: "splunk-lib", MountPath: "/opt/splunk/lib"},
493-
corev1.VolumeMount{Name: "splunk-bin", MountPath: "/opt/splunk/bin"},
494-
corev1.VolumeMount{Name: "containerd-data", MountPath: "/var/lib/containerd-nested"},
495-
corev1.VolumeMount{Name: "containerd-run", MountPath: "/run/containerd-nested"},
496-
),
377+
VolumeMounts: []corev1.VolumeMount{
378+
{Name: "splunk-etc", MountPath: "/opt/splunk/etc"},
379+
{Name: "splunk-var", MountPath: "/opt/splunk/var"},
380+
{Name: "splunk-lib", MountPath: "/opt/splunk/lib"},
381+
{Name: "splunk-bin", MountPath: "/opt/splunk/bin"},
382+
{Name: "containerd-data", MountPath: "/var/lib/containerd-nested"},
383+
{Name: "containerd-run", MountPath: "/run/containerd-nested"},
384+
},
497385
SecurityContext: &corev1.SecurityContext{Privileged: &privileged},
498386
},
499-
{
500-
Name: "syncthing-client",
501-
Image: appRuntime.Spec.Image,
502-
ImagePullPolicy: corev1.PullIfNotPresent,
503-
Command: []string{"syncthing", "-home=/var/syncthing", "-no-browser", "-no-restart", "-verbose"},
504-
VolumeMounts: append(splunkVolumeMounts,
505-
corev1.VolumeMount{Name: "syncthing-config", MountPath: "/var/syncthing"},
506-
),
507-
},
508387
},
509388
Volumes: []corev1.Volume{
510389
{
@@ -531,10 +410,6 @@ exit 1`, splunkAddr, syncthingAPIKey)
531410
Name: "containerd-run",
532411
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
533412
},
534-
{
535-
Name: "syncthing-config",
536-
VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}},
537-
},
538413
},
539414
},
540415
}

pkg/splunk/enterprise/configuration.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -244,8 +244,8 @@ func getSplunkService(ctx context.Context, cr splcommon.MetaObject, spec *enterp
244244
splcommon.AppendParentMeta(service.ObjectMeta.GetObjectMeta(), cr.GetObjectMeta())
245245

246246
if instanceType == SplunkDeployer || isHeadless {
247-
// required for SHC bootstrap process and for App Runtime Syncthing sync (which needs to
248-
// reach the syncthing-server sidecar before splunkd is fully ready)
247+
// required for SHC bootstrap process and for App Runtime NFS mount (which needs to
248+
// reach the nfs-server sidecar before splunkd is fully ready)
249249
service.Spec.PublishNotReadyAddresses = true
250250
}
251251

@@ -1173,25 +1173,20 @@ func updateSplunkPodTemplateWithConfig(ctx context.Context, client splcommon.Con
11731173
}
11741174
}
11751175

1176-
// Add Syncthing server sidecar for filesystem sync with App Runtime pods.
1176+
// Add NFS server sidecar for filesystem sharing with App Runtime pods.
11771177
// Appended AFTER the container loop above so its Env/Resources/SecurityContext are not overwritten.
1178-
syncthingServerImage := os.Getenv("RELATED_IMAGE_SYNCTHING_SERVER")
1179-
if syncthingServerImage == "" {
1180-
syncthingServerImage = "493245399694.dkr.ecr.us-west-2.amazonaws.com/appruntime/ecr-repo/syncthing-server:latest"
1178+
nfsServerImage := os.Getenv("RELATED_IMAGE_NFS_SERVER")
1179+
if nfsServerImage == "" {
1180+
nfsServerImage = "493245399694.dkr.ecr.us-west-2.amazonaws.com/appruntime/ecr-repo/nfs-server:latest"
11811181
}
11821182
podTemplateSpec.Spec.Containers = append(podTemplateSpec.Spec.Containers, corev1.Container{
1183-
Name: "syncthing-server",
1184-
Image: syncthingServerImage,
1183+
Name: "nfs-server",
1184+
Image: nfsServerImage,
11851185
ImagePullPolicy: corev1.PullAlways,
11861186
Ports: []corev1.ContainerPort{
11871187
{
1188-
Name: "st-sync",
1189-
ContainerPort: 22000,
1190-
Protocol: corev1.ProtocolTCP,
1191-
},
1192-
{
1193-
Name: "st-api",
1194-
ContainerPort: 8384,
1188+
Name: "nfs",
1189+
ContainerPort: 2049,
11951190
Protocol: corev1.ProtocolTCP,
11961191
},
11971192
},
@@ -1200,6 +1195,16 @@ func updateSplunkPodTemplateWithConfig(ctx context.Context, client splcommon.Con
12001195
Name: fmt.Sprintf(splcommon.PvcNamePrefix, splcommon.EtcVolumeStorage),
12011196
MountPath: fmt.Sprintf(splcommon.SplunkMountDirecPrefix, splcommon.EtcVolumeStorage),
12021197
},
1198+
{
1199+
Name: fmt.Sprintf(splcommon.PvcNamePrefix, splcommon.VarVolumeStorage),
1200+
MountPath: fmt.Sprintf(splcommon.SplunkMountDirecPrefix, splcommon.VarVolumeStorage),
1201+
},
1202+
},
1203+
SecurityContext: &corev1.SecurityContext{
1204+
Privileged: func() *bool { b := true; return &b }(),
1205+
RunAsUser: func() *int64 { uid := int64(0); return &uid }(),
1206+
RunAsGroup: func() *int64 { gid := int64(0); return &gid }(),
1207+
RunAsNonRoot: func() *bool { b := false; return &b }(),
12031208
},
12041209
Resources: corev1.ResourceRequirements{
12051210
Requests: corev1.ResourceList{

0 commit comments

Comments
 (0)