<p>I am using <a href="https://hub.docker.com/r/payara/server-full" rel="nofollow noreferrer">payara/server-full</a> in Kubernetes. I want to add a persistent volume so that all configuration made to the Payara server via the Admin UI is perstisted after the pod is recreated, including uploaded .war files.</p>
<p>Right now my deployment looks like this:</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: 
spec:
  selector:
    matchLabels:
      app: myapp
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: payara/server-full
          imagePullPolicy: &quot;Always&quot;
          ports:
            - name: myapp-default
              containerPort: 8080
            - name: myapp-admin
          containerPort: 4848
</code></pre>
<ol>
<li>How to augment that yaml file to make use of a persistent volume?</li>
<li>Which path(s) within payara should be synced with the persistent volume so that Payara's configuration isn't lost after redeployment ?</li>
<li>Which additional yaml files do I need?</li>
</ol>

Viktor Stoitschev
<p>So after a longer conideration of the problem I realised I need to persist everything under <code>/opt/payara/appserver/glassfish/domains</code> for all configuration made via the Admin UI to be persisted. However if I simply start the pod with a volumeMount pointing to that path, i.e.</p>
<pre><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  selector:
    matchLabels:
      app: myapp
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  template:
    metadata:
      labels:
        app: myapp
    spec:
      volumes:
        - name: myapp-vol
          persistentVolumeClaim:
            claimName: myapp-rwo-pvc
      containers:
        - name: myapp
          image: payara/server-full
          imagePullPolicy: &quot;Always&quot;
          ports:
            - name: myapp-default
              containerPort: 8080
            - name: myapp-admin
          containerPort: 4848
          volumeMounts:
            - mountPath: &quot;/opt/payara/appserver/glassfish/domains&quot;
</code></pre>
<p>and</p>
<pre><code>apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myapp-rwo-pvc
  labels:
    app: dont-delete-autom
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
</code></pre>
<p>then the Payara server won't be able to start successfully, because Kubernetes will mount an empty persistent volume into that location. Payara needs however config files which are originally located within /opt/payara/appserver/glassfish/domains.</p>
<p>What I needed to do is to provision the volume with the data by default located in that folder. But how to do that when the only way to access the PV is to mount it into a pod?
Fist I scaled the above deployment to 0 with:</p>
<pre><code>kubectl scale --replicas=0 deployment/myapp
</code></pre>
<p>This deletes all pods accessing the persistent volume.</p>
<p>Then I created a &quot;provisioning&quot; pod which mounts the previously created persistent volume into /tmp.</p>
<pre><code>apiVersion: v1
kind: Pod
metadata:
  labels:
    app: myapp
  name: pv-provisioner
  namespace: default

spec:
  containers:
    - image: payara/server-full
      imagePullPolicy: Always
      name: pv-provisioner
      ports:
        - containerPort: 8080
          name: myapp-default
          protocol: TCP
        - containerPort: 4848
          name: myapp-admin
          protocol: TCP
      volumeMounts:
        - mountPath: &quot;/tmp&quot;
          name: myapp-vol
      resources:
        limits:
          cpu: &quot;2&quot;
          memory: 2Gi
        requests:
          cpu: 500m
          memory: 128Mi
  volumes:
    - name: myapp-vol
      persistentVolumeClaim:
        claimName: myapp-rwo-pvc 
</code></pre>
<p>Then I used the following commands to copy the necessary data first from the &quot;provisioning&quot; pod to a local folder /tmp and then back from /tmp to the persistent volume (previously mounted into pv-provisioner:/tmp). There is no option to copy directly from pod:/a to pod:/b</p>
<pre><code>kubectl cp pv-provisioner:/opt/payara/appserver/glassfish/domains/. tmp
kubectl cp tmp/. pv-provisioner:/tmp
</code></pre>
<p>As a result everything stored under /opt/payara/appserver/glassfish/domains/ in the original payara container was now copied into the persistent volume identified by the persistence volume claim &quot;myapp-rwo-pvc&quot;.</p>
<p>To finish it up I deleted the provisioning pod and scaled the deployment back up:</p>
<pre><code>kubectl delete pod pv-provisioner
kubectl scale --replicas=3 deployment/myapp
</code></pre>
<p>The payara server is now starting successfully and any configuration made via the Admin UI, including .war deployments is persisted, such that the payara pods can be killed any time and after the restart everything is as before.</p>
<p>Thanks for reading.</p>
