Kubernetes can be deployed on multiple Cloud: AWS EC2, Google Cloud, OpenStack, etc. On most Clouds, Kubernetes hosts run on virtual machines. Since Cloud providers already have ways to provision storage volumes (mostly block store such as AWS EBS, GCE PD, and OpenStack Cinder), it makes sense for Kubernetes to call out the Cloud providers to provision storage, attach to the virtual machines, and let virtual machine make the volumes on the device table (mostly thanks to udev). Kubernetes then uses some built-in rules (i.e. searching /dev/disk/by-path) to find the volumes, make filesystem on it (if necessary), and mount the volume.
This process is roughly illustrated below. Note, currently the attach is initiated by kubelet. This function is going to move to k8s master (controller manager) later.
In this picture, it turns out the components involved are: Cloud providers, volume plugins, and kublet. I explained them a bit in my gist (for better formatting).