<p>I want to (temporarily) use localhost bound directories to persist application state of SonarQube. Below I describe how I achieved this in a self-hosted Kubernetes (1.11.3) cluster.</p>

<p>The problem I encounter is that despite everything working Kubernetes does not use the host path to persist the data (<code>/opt/sonarqube/postgresql</code>). Upon <code>docker inspect</code> of the SonarQube containers it uses the binds below.</p>

<p><strong>How can I use the host mounted path for the mounts?</strong></p>

<pre><code>        "Binds": [
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/volume-subpaths/sonarqube-pv-postgresql/sonarqube/0:/opt/sonarqube/conf",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/volumes/kubernetes.io~configmap/startup:/tmp-script/:ro",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/volume-subpaths/sonarqube-pv-postgresql/sonarqube/2:/opt/sonarqube/data",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/volume-subpaths/sonarqube-pv-postgresql/sonarqube/3:/opt/sonarqube/extensions",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/volumes/kubernetes.io~secret/default-token-zrjdj:/var/run/secrets/kubernetes.io/serviceaccount:ro",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/etc-hosts:/etc/hosts",
            "/var/lib/kubelet/pods/49666f05-dad0-11e8-95cd-666c474c0e54/containers/sonarqube/95053a5c:/dev/termination-log"
        ]
</code></pre>

<p><strong>Here is what I did to set up the application</strong></p>

<p>I created a <code>StorageClass</code> to create PVs that mount local paths:</p>

<pre><code>kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage-nowait
provisioner: kubernetes.io/no-provisioner
</code></pre>

<p>Then I created two PVs to be used with the <a href="https://github.com/helm/charts/tree/master/stable/sonarqube" rel="nofollow noreferrer">SonarQube helm chart</a> like this:</p>

<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: sonarqube-pv-postgresql
  labels:
    type: local
spec:
  capacity:
    storage: 20Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  hostPath:
    path: /opt/sonarqube/postgresql
    type: DirectoryOrCreate
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - myhost
</code></pre>

<p>I launched the SonarQube helm chart with this additional config to use the PVs I just created</p>

<pre><code>image:
  tag: 7.1

persistence:
  enabled: true
  storageClass: local-storage
  accessMode: ReadWriteOnce
  size: 10Gi

postgresql:
  persistence:
    enabled: true
    storageClass: local-storage
    accessMode: ReadWriteOnce
    size: 10Gi
</code></pre>

<p>If you see the docs <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#types-of-persistent-volumes" rel="noreferrer">here</a></p>

<blockquote>
  <ul>
  <li>HostPath (Single node testing only – local storage is not supported in any way and WILL NOT WORK in a multi-node cluster)</li>
  </ul>
</blockquote>

<p>Hence, that's probably why you are seeing it in a different place. I tried it myself and my PVC remains in pending state. So you can either use <code>local</code> like this:</p>

<pre><code>apiVersion: v1
kind: PersistentVolume
metadata:
  name: example-pv
  labels:
    vol=myvolume
spec:
  capacity:
    storage: 100Gi
  volumeMode: Filesystem
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: local-storage
  local:
    path: /mnt/disks/ssd1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - example-node
</code></pre>

<p>Then you have to create the corresponding PVC:</p>

<pre><code>kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 100Gi
  storageClassName: local-storage
  selector:
    matchLabels:
      vol: "myvolume"
</code></pre>

<p>Then in the pod spec:</p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    persistentVolumeClaim:
      claimName: myclaim
</code></pre>

<p>You can also use <code>hostPath</code> directly in the pod spec if you don't care about landing on any node and having different data in each node:</p>

<pre><code>apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: DirectoryOrCreate
</code></pre>
