<p>I'm trying to create two deployments, one for Wordpress the other for MySQL which refer to two different Persistent Volumes.</p>

<p><strong>Sometimes</strong>, while deleting and recreating volumes and deployments, the MySQL deployment populates the Wordpress volume (ending up with a database in the <code>wordpress-volume</code> directory).</p>

<p>This is clearer when you do <code>kubectl get pv --namespace my-namespace</code>:</p>

<pre><code>mysql-volume       2Gi   RWO  Retain  Bound  flashart-it/wordpress-volume-claim   manual                   1h
wordpress-volume   2Gi   RWO  Retain  Bound  flashart-it/mysql-volume-claim       manual
</code></pre>

<p>.</p>

<p>I'm pretty sure the settings are ok. Please find the yaml file below.</p>

<h3>Persistent Volume Claims + Persistent Volumes</h3>

<pre><code>kind: PersistentVolume
apiVersion: v1
metadata:
  namespace: my-namespace
  name: mysql-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /path/to/mount/mysql-volume
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: my-namespace
  name: mysql-volume-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
kind: PersistentVolume
apiVersion: v1
metadata:
  namespace: my-namespace
  name: wordpress-volume
  labels:
    type: local
spec:
  storageClassName: manual
  capacity:
    storage: 2Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /path/to/mount/wordpress-volume
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: my-namespace
  name: wordpress-volume-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
</code></pre>

<h3>Deployments</h3>

<pre><code>kind: Deployment
apiVersion: apps/v1
metadata:
  name: wordpress
  namespace: my-namespace
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: frontend
  strategy:
    type: Recreate
  template:
    metadata:
      namespace: my-namespace
      labels:
        app: wordpress
        tier: frontend
    spec:
      containers:
      - image: wordpress:5.0-php7.1-apache
        name: wordpress
        env:
          # ...
        ports:
          # ...
        volumeMounts:
        - name: wordpress-volume
          mountPath: /var/www/html
      volumes:
      - name: wordpress-volume
        persistentVolumeClaim:
          claimName: wordpress-volume-claim
---
kind: Deployment
apiVersion: apps/v1
metadata:
  namespace: my-namespace
  name: wordpress-mysql
  labels:
    app: wordpress
spec:
  selector:
    matchLabels:
      app: wordpress
      tier: mysql
  strategy:
    type: Recreate
  template:
    metadata:
      namespace: my-namespace
      labels:
        app: wordpress
        tier: mysql
    spec:
      containers:
        - image: mysql:5.7
          name: mysql
          env:
            # ...
          ports:
            # ...
          volumeMounts:
            - name: mysql-volume
              mountPath: /var/lib/mysql
      volumes:
        - name: mysql-volume
          persistentVolumeClaim:
            claimName: mysql-volume-claim
</code></pre>

a.barbieri
<p>It's expected behavior in Kubernetes. PVC can bind to any available PV, given that storage  class is matched, access mode is matched, and storage size is sufficient. Names are not used to match PVC and PV.</p>

<p>A possible solution for your scenario is to use <a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#selector" rel="noreferrer">label selector</a> on PVC to filter qualified PV.</p>

<p>First, add a label to PV (in this case: app=mysql)</p>

<pre><code>kind: PersistentVolume
apiVersion: v1
metadata:
  name: mysql-volume
  labels:
    app: mysql
</code></pre>

<p>Then, add a label selector in PVC to filter PV.</p>

<pre><code>kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  namespace: my-namespace
  name: mysql-volume-claim
spec:
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  selector: 
    matchLabels: 
      app: mysql
</code></pre>
