title: Is volume bound or not?
body: <p>I am trying to make a mysql instant save on persistent volume, using minikube. PVCs get generated from a volumeClaimTemplate inside a statefulset. I created a few PVs (named pv-volume, pv-volume2, pv-volume3...) and the following storageclass:</p>
  <pre><code>apiVersion: storage.k8s.io/v1
  kind: StorageClass
  metadata:
    name: local-storage
  provisioner: kubernetes.io/no-provisioner
  volumeBindingMode: WaitForFirstConsumer
  </code></pre>
  <p>Now, when I start the statefulset first I get the error <code>0/1 nodes are available: 1 node(s) didn't find available persistent volumes to bind.</code> but right after that <code> Successfully assigned default/mysql-0 to minikube</code>
  What should I think? From the volumes I see that those are bound to the pods.
  For completeness, here is the whole statefulset (its basically the one from the <a href="https://kubernetes.io/docs/tasks/run-application/run-replicated-stateful-application/" rel="nofollow noreferrer">k8 guide</a> with changes only to the template part):</p>
  <pre><code>apiVersion: apps/v1
  kind: StatefulSet
  metadata:
    name: mysql
  spec:
    selector:
      matchLabels:
        app: mysql
    serviceName: mysql
    replicas: 3
    template:
      metadata:
        labels:
          app: mysql
      spec:
        initContainers:
        - name: init-mysql
          image: mysql:5.7
          command:
          - bash
          - &quot;-c&quot;
          - |
            set -ex
            # Generate mysql server-id from pod ordinal index.
            [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
            ordinal=${BASH_REMATCH[1]}
            echo [mysqld] &gt; /mnt/conf.d/server-id.cnf
            # Add an offset to avoid reserved server-id=0 value.
            echo server-id=$((100 + $ordinal)) &gt;&gt; /mnt/conf.d/server-id.cnf
            # Copy appropriate conf.d files from config-map to emptyDir.
            if [[ $ordinal -eq 0 ]]; then
              cp /mnt/config-map/primary.cnf /mnt/conf.d/
            else
              cp /mnt/config-map/replica.cnf /mnt/conf.d/
            fi
          volumeMounts:
          - name: conf
            mountPath: /mnt/conf.d
          - name: config-map
            mountPath: /mnt/config-map
        - name: clone-mysql
          image: gcr.io/google-samples/xtrabackup:1.0
          command:
          - bash
          - &quot;-c&quot;
          - |
            set -ex
            # Skip the clone if data already exists.
            [[ -d /var/lib/mysql/mysql ]] &amp;&amp; exit 0
            # Skip the clone on primary (ordinal index 0).
            [[ `hostname` =~ -([0-9]+)$ ]] || exit 1
            ordinal=${BASH_REMATCH[1]}
            [[ $ordinal -eq 0 ]] &amp;&amp; exit 0
            # Clone data from previous peer.
            ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
            # Prepare the backup.
            xtrabackup --prepare --target-dir=/var/lib/mysql
          volumeMounts:
          - name: data
            mountPath: /var/lib/mysql
            subPath: mysql
          - name: conf
            mountPath: /etc/mysql/conf.d
        containers:
        - name: mysql
          image: mysql:5.7
          env:
          - name: MYSQL_ALLOW_EMPTY_PASSWORD
            value: &quot;1&quot;
          ports:
          - name: mysql
            containerPort: 3306
          volumeMounts:
          - name: data
            mountPath: /var/lib/mysql
            subPath: mysql
          - name: conf
            mountPath: /etc/mysql/conf.d
          resources:
            requests:
              cpu: 500m
              memory: 1Gi
          livenessProbe:
            exec:
              command: [&quot;mysqladmin&quot;, &quot;ping&quot;]
            initialDelaySeconds: 30
            periodSeconds: 10
            timeoutSeconds: 5
          readinessProbe:
            exec:
              # Check we can execute queries over TCP (skip-networking is off).
              command: [&quot;mysql&quot;, &quot;-h&quot;, &quot;127.0.0.1&quot;, &quot;-e&quot;, &quot;SELECT 1&quot;]
            initialDelaySeconds: 5
            periodSeconds: 2
            timeoutSeconds: 1
        - name: xtrabackup
          image: gcr.io/google-samples/xtrabackup:1.0
          ports:
          - name: xtrabackup
            containerPort: 3307
          command:
          - bash
          - &quot;-c&quot;
          - |
            set -ex
            cd /var/lib/mysql
  
            # Determine binlog position of cloned data, if any.
            if [[ -f xtrabackup_slave_info &amp;&amp; &quot;x$(&lt;xtrabackup_slave_info)&quot; != &quot;x&quot; ]]; then
              # XtraBackup already generated a partial &quot;CHANGE MASTER TO&quot; query
              # because we're cloning from an existing replica. (Need to remove the tailing semicolon!)
              cat xtrabackup_slave_info | sed -E 's/;$//g' &gt; change_master_to.sql.in
              # Ignore xtrabackup_binlog_info in this case (it's useless).
              rm -f xtrabackup_slave_info xtrabackup_binlog_info
            elif [[ -f xtrabackup_binlog_info ]]; then
              # We're cloning directly from primary. Parse binlog position.
              [[ `cat xtrabackup_binlog_info` =~ ^(.*?)[[:space:]]+(.*?)$ ]] || exit 1
              rm -f xtrabackup_binlog_info xtrabackup_slave_info
              echo &quot;CHANGE MASTER TO MASTER_LOG_FILE='${BASH_REMATCH[1]}',\
                    MASTER_LOG_POS=${BASH_REMATCH[2]}&quot; &gt; change_master_to.sql.in
            fi
  
            # Check if we need to complete a clone by starting replication.
            if [[ -f change_master_to.sql.in ]]; then
              echo &quot;Waiting for mysqld to be ready (accepting connections)&quot;
              until mysql -h 127.0.0.1 -e &quot;SELECT 1&quot;; do sleep 1; done
  
              echo &quot;Initializing replication from clone position&quot;
              mysql -h 127.0.0.1 \
                    -e &quot;$(&lt;change_master_to.sql.in), \
                            MASTER_HOST='mysql-0.mysql', \
                            MASTER_USER='root', \
                            MASTER_PASSWORD='', \
                            MASTER_CONNECT_RETRY=10; \
                          START SLAVE;&quot; || exit 1
              # In case of container restart, attempt this at-most-once.
              mv change_master_to.sql.in change_master_to.sql.orig
            fi
  
            # Start a server to send backups when requested by peers.
            exec ncat --listen --keep-open --send-only --max-conns=1 3307 -c \
              &quot;xtrabackup --backup --slave-info --stream=xbstream --host=127.0.0.1 --user=root&quot;
          volumeMounts:
          - name: data
            mountPath: /var/lib/mysql
            subPath: mysql
          - name: conf
            mountPath: /etc/mysql/conf.d
          resources:
            requests:
              cpu: 100m
              memory: 100Mi
        volumes:
        - name: conf
          emptyDir: {}
        - name: config-map
          configMap:
            name: mysql
        - name: mysql-initdb
          configMap:
            name: mysql-initdb-config
    volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ &quot;ReadWriteOnce&quot; ]
        storageClassName: &quot;local-storage&quot;
        resources:
          requests:
            storage: 1Gi
  </code></pre>
  <h1>UPDATE</h1>
  <p>In order to provide more context, here is the declaration of my &quot;local-storage&quot; storageclass:</p>
  <pre><code>apiVersion: storage.k8s.io/v1
  kind: StorageClass
  metadata:
    name: local-storage
  provisioner: kubernetes.io/no-provisioner
  volumeBindingMode: WaitForFirstConsumer
  </code></pre>
  <p>And here is how I create volumes</p>
  <pre><code>apiVersion: v1
  kind: PersistentVolume
  metadata:
    name: pv-volume
  spec:
    storageClassName: local-storage
    accessModes:
      - ReadWriteOnce
    capacity:
      storage: 1Gi
    hostPath:
      path: /data/
  </code></pre>
  <p>I made a few of those volumes, changing just the names, since I have to statically allocate them. In fact, this is the output of <code>kubectl get pv</code></p>
  <pre><code>NAME         CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                  STORAGECLASS    REASON   AGE
  pv-volume    1Gi        RWO            Retain           Bound       default/data-mysql-0   local-storage            79s
  pv-volume2   1Gi        RWO            Retain           Bound       default/data-mysql-1   local-storage            79s
  pv-volume3   1Gi        RWO            Retain           Available                          local-storage            78s
  pv-volume4   1Gi        RWO            Retain           Available                          local-storage            78s
  pv-volume5   1Gi        RWO            Retain           Available                          local-storage            78s
  </code></pre>
  <p>And this is the output of <code>kubectl get pvc</code>, where it sees like the binding has succeeded for both mysql replicas.</p>
  <pre><code>NAME           STATUS   VOLUME       CAPACITY   ACCESS MODES   STORAGECLASS    AGE
  data-mysql-0   Bound    pv-volume    1Gi        RWO            local-storage   2m11s
  data-mysql-1   Bound    pv-volume2   1Gi        RWO            local-storage   61s
  </code></pre>