Unverified Commit 1c9d6f53 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #54018 from vmware/vSphereScaleTest

Automatic merge from submit-queue (batch tested with PRs 55301, 55319, 54018, 55322, 55125). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. E2E scale test for vSphere Cloud Provider Volume lifecycle operations This PR adds an E2E test for vSphere Cloud Provider which will create/attach/detach/detach the volumes at scale with multiple threads based on user configurable values for number of volumes, volumes per pod and number of threads. (Since this is a scale test, number of threads would be low. This is only used to speed up the operation) Test performs following tasks. 1. Create Storage Classes of 4 Categories (Default, SC with Non Default Datastore, SC with SPBM Policy, SC with VSAN Storage Capalibilies.) 2. Read VCP_SCALE_VOLUME_COUNT from System Environment. 3. Launch VCP_SCALE_INSTANCES go routines for creating VCP_SCALE_VOLUME_COUNT volumes. Each go routine is responsible for create/attach of VCP_SCALE_VOLUME_COUNT/VCP_SCALE_INSTANCES volumes. 4. Read VCP_SCALE_VOLUMES_PER_POD from System Environment. Each pod will be have VCP_SCALE_VOLUMES_PER_POD attached to it. 5. Once all the go routines are completed, we delete all the pods and volumes. Which issue this PR fixes fixes # vmware#291 ```release-note None ```
parents 62575414 0b3e28c8
...@@ -790,12 +790,12 @@ func deletePD(pdName string) error { ...@@ -790,12 +790,12 @@ func deletePD(pdName string) error {
// Returns a pod definition based on the namespace. The pod references the PVC's // Returns a pod definition based on the namespace. The pod references the PVC's
// name. // name.
func MakeWritePod(ns string, pvc *v1.PersistentVolumeClaim) *v1.Pod { func MakeWritePod(ns string, pvc *v1.PersistentVolumeClaim) *v1.Pod {
return MakePod(ns, []*v1.PersistentVolumeClaim{pvc}, true, "touch /mnt/volume1/SUCCESS && (id -G | grep -E '\\b777\\b')") return MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "touch /mnt/volume1/SUCCESS && (id -G | grep -E '\\b777\\b')")
} }
// Returns a pod definition based on the namespace. The pod references the PVC's // Returns a pod definition based on the namespace. The pod references the PVC's
// name. A slice of BASH commands can be supplied as args to be run by the pod // name. A slice of BASH commands can be supplied as args to be run by the pod
func MakePod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *v1.Pod { func MakePod(ns string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) *v1.Pod {
if len(command) == 0 { if len(command) == 0 {
command = "while true; do sleep 1; done" command = "while true; do sleep 1; done"
} }
...@@ -832,6 +832,9 @@ func MakePod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, ...@@ -832,6 +832,9 @@ func MakePod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool,
} }
podSpec.Spec.Containers[0].VolumeMounts = volumeMounts podSpec.Spec.Containers[0].VolumeMounts = volumeMounts
podSpec.Spec.Volumes = volumes podSpec.Spec.Volumes = volumes
if nodeSelector != nil {
podSpec.Spec.NodeSelector = nodeSelector
}
return podSpec return podSpec
} }
...@@ -886,9 +889,9 @@ func MakeSecPod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bo ...@@ -886,9 +889,9 @@ func MakeSecPod(ns string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bo
return podSpec return podSpec
} }
// create pod with given claims // CreatePod with given claims based on node selector
func CreatePod(client clientset.Interface, namespace string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) (*v1.Pod, error) { func CreatePod(client clientset.Interface, namespace string, nodeSelector map[string]string, pvclaims []*v1.PersistentVolumeClaim, isPrivileged bool, command string) (*v1.Pod, error) {
pod := MakePod(namespace, pvclaims, isPrivileged, command) pod := MakePod(namespace, nodeSelector, pvclaims, isPrivileged, command)
pod, err := client.CoreV1().Pods(namespace).Create(pod) pod, err := client.CoreV1().Pods(namespace).Create(pod)
if err != nil { if err != nil {
return nil, fmt.Errorf("pod Create API error: %v", err) return nil, fmt.Errorf("pod Create API error: %v", err)
...@@ -928,7 +931,7 @@ func CreateSecPod(client clientset.Interface, namespace string, pvclaims []*v1.P ...@@ -928,7 +931,7 @@ func CreateSecPod(client clientset.Interface, namespace string, pvclaims []*v1.P
// Define and create a pod with a mounted PV. Pod runs infinite loop until killed. // Define and create a pod with a mounted PV. Pod runs infinite loop until killed.
func CreateClientPod(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) (*v1.Pod, error) { func CreateClientPod(c clientset.Interface, ns string, pvc *v1.PersistentVolumeClaim) (*v1.Pod, error) {
return CreatePod(c, ns, []*v1.PersistentVolumeClaim{pvc}, true, "") return CreatePod(c, ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "")
} }
// wait until all pvcs phase set to bound // wait until all pvcs phase set to bound
......
...@@ -309,8 +309,8 @@ func PodsUseStaticPVsOrFail(f *framework.Framework, podCount int, image string) ...@@ -309,8 +309,8 @@ func PodsUseStaticPVsOrFail(f *framework.Framework, podCount int, image string)
By("Creating pods for each static PV") By("Creating pods for each static PV")
for _, config := range configs { for _, config := range configs {
podConfig := framework.MakePod(ns, []*v1.PersistentVolumeClaim{config.pvc}, false, "") podConfig := framework.MakePod(ns, nil, []*v1.PersistentVolumeClaim{config.pvc}, false, "")
config.pod, err = c.CoreV1().Pods(ns).Create(podConfig) config.pod, err = c.Core().Pods(ns).Create(podConfig)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
} }
......
...@@ -23,6 +23,7 @@ go_library( ...@@ -23,6 +23,7 @@ go_library(
"volume_metrics.go", "volume_metrics.go",
"volume_provisioning.go", "volume_provisioning.go",
"volumes.go", "volumes.go",
"vsphere_scale.go",
"vsphere_statefulsets.go", "vsphere_statefulsets.go",
"vsphere_stress.go", "vsphere_stress.go",
"vsphere_utils.go", "vsphere_utils.go",
......
...@@ -151,7 +151,7 @@ var _ = SIGDescribe("PersistentVolumes[Disruptive][Flaky]", func() { ...@@ -151,7 +151,7 @@ var _ = SIGDescribe("PersistentVolumes[Disruptive][Flaky]", func() {
framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv2, pvc2)) framework.ExpectNoError(framework.WaitOnPVandPVC(c, ns, pv2, pvc2))
By("Attaching both PVC's to a single pod") By("Attaching both PVC's to a single pod")
clientPod, err = framework.CreatePod(c, ns, []*v1.PersistentVolumeClaim{pvc1, pvc2}, true, "") clientPod, err = framework.CreatePod(c, ns, nil, []*v1.PersistentVolumeClaim{pvc1, pvc2}, true, "")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
}) })
...@@ -309,7 +309,7 @@ func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framew ...@@ -309,7 +309,7 @@ func initTestCase(f *framework.Framework, c clientset.Interface, pvConfig framew
} }
}() }()
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
pod := framework.MakePod(ns, []*v1.PersistentVolumeClaim{pvc}, true, "") pod := framework.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, "")
pod.Spec.NodeName = nodeName pod.Spec.NodeName = nodeName
framework.Logf("Creating NFS client pod.") framework.Logf("Creating NFS client pod.")
pod, err = c.CoreV1().Pods(ns).Create(pod) pod, err = c.CoreV1().Pods(ns).Create(pod)
......
...@@ -292,7 +292,7 @@ var _ = SIGDescribe("PersistentVolumes", func() { ...@@ -292,7 +292,7 @@ var _ = SIGDescribe("PersistentVolumes", func() {
// If a file is detected in /mnt, fail the pod and do not restart it. // If a file is detected in /mnt, fail the pod and do not restart it.
By("Verifying the mount has been cleaned.") By("Verifying the mount has been cleaned.")
mount := pod.Spec.Containers[0].VolumeMounts[0].MountPath mount := pod.Spec.Containers[0].VolumeMounts[0].MountPath
pod = framework.MakePod(ns, []*v1.PersistentVolumeClaim{pvc}, true, fmt.Sprintf("[ $(ls -A %s | wc -l) -eq 0 ] && exit 0 || exit 1", mount)) pod = framework.MakePod(ns, nil, []*v1.PersistentVolumeClaim{pvc}, true, fmt.Sprintf("[ $(ls -A %s | wc -l) -eq 0 ] && exit 0 || exit 1", mount))
pod, err = c.CoreV1().Pods(ns).Create(pod) pod, err = c.CoreV1().Pods(ns).Create(pod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
framework.ExpectNoError(framework.WaitForPodSuccessInNamespace(c, pod.Name, ns)) framework.ExpectNoError(framework.WaitForPodSuccessInNamespace(c, pod.Name, ns))
......
...@@ -87,7 +87,7 @@ var _ = SIGDescribe("[Serial] Volume metrics", func() { ...@@ -87,7 +87,7 @@ var _ = SIGDescribe("[Serial] Volume metrics", func() {
claims := []*v1.PersistentVolumeClaim{pvc} claims := []*v1.PersistentVolumeClaim{pvc}
pod := framework.MakePod(ns, claims, false, "") pod := framework.MakePod(ns, nil, claims, false, "")
pod, err = c.CoreV1().Pods(ns).Create(pod) pod, err = c.CoreV1().Pods(ns).Create(pod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
...@@ -115,7 +115,7 @@ var _ = SIGDescribe("[Serial] Volume metrics", func() { ...@@ -115,7 +115,7 @@ var _ = SIGDescribe("[Serial] Volume metrics", func() {
Expect(pvc).ToNot(Equal(nil)) Expect(pvc).ToNot(Equal(nil))
claims := []*v1.PersistentVolumeClaim{pvc} claims := []*v1.PersistentVolumeClaim{pvc}
pod := framework.MakePod(ns, claims, false, "") pod := framework.MakePod(ns, nil, claims, false, "")
pod, err = c.CoreV1().Pods(ns).Create(pod) pod, err = c.CoreV1().Pods(ns).Create(pod)
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
......
...@@ -18,6 +18,10 @@ package storage ...@@ -18,6 +18,10 @@ package storage
import ( import (
"fmt" "fmt"
"os"
"strconv"
"sync"
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
...@@ -28,9 +32,6 @@ import ( ...@@ -28,9 +32,6 @@ import (
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere" "k8s.io/kubernetes/pkg/cloudprovider/providers/vsphere"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"os"
"strconv"
"sync"
) )
/* /*
...@@ -45,13 +46,6 @@ import ( ...@@ -45,13 +46,6 @@ import (
*/ */
var _ = SIGDescribe("vsphere cloud provider stress [Feature:vsphere]", func() { var _ = SIGDescribe("vsphere cloud provider stress [Feature:vsphere]", func() {
f := framework.NewDefaultFramework("vcp-stress") f := framework.NewDefaultFramework("vcp-stress")
const (
volumesPerNode = 55
storageclass1 = "sc-default"
storageclass2 = "sc-vsan"
storageclass3 = "sc-spbm"
storageclass4 = "sc-user-specified-ds"
)
var ( var (
client clientset.Interface client clientset.Interface
namespace string namespace string
...@@ -159,7 +153,7 @@ func PerformVolumeLifeCycleInParallel(f *framework.Framework, client clientset.I ...@@ -159,7 +153,7 @@ func PerformVolumeLifeCycleInParallel(f *framework.Framework, client clientset.I
By(fmt.Sprintf("%v Creating Pod using the claim: %v", logPrefix, pvclaim.Name)) By(fmt.Sprintf("%v Creating Pod using the claim: %v", logPrefix, pvclaim.Name))
// Create pod to attach Volume to Node // Create pod to attach Volume to Node
pod, err := framework.CreatePod(client, namespace, pvclaims, false, "") pod, err := framework.CreatePod(client, namespace, nil, pvclaims, false, "")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By(fmt.Sprintf("%v Waiting for the Pod: %v to be in the running state", logPrefix, pod.Name)) By(fmt.Sprintf("%v Waiting for the Pod: %v to be in the running state", logPrefix, pod.Name))
......
...@@ -38,6 +38,14 @@ import ( ...@@ -38,6 +38,14 @@ import (
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
) )
const (
volumesPerNode = 55
storageclass1 = "sc-default"
storageclass2 = "sc-vsan"
storageclass3 = "sc-spbm"
storageclass4 = "sc-user-specified-ds"
)
// Sanity check for vSphere testing. Verify the persistent disk attached to the node. // Sanity check for vSphere testing. Verify the persistent disk attached to the node.
func verifyVSphereDiskAttached(vsp *vsphere.VSphere, volumePath string, nodeName types.NodeName) (bool, error) { func verifyVSphereDiskAttached(vsp *vsphere.VSphere, volumePath string, nodeName types.NodeName) (bool, error) {
var ( var (
...@@ -53,6 +61,46 @@ func verifyVSphereDiskAttached(vsp *vsphere.VSphere, volumePath string, nodeName ...@@ -53,6 +61,46 @@ func verifyVSphereDiskAttached(vsp *vsphere.VSphere, volumePath string, nodeName
return isAttached, err return isAttached, err
} }
// Wait until vsphere volumes are detached from the list of nodes or time out after 5 minutes
func waitForVSphereDisksToDetach(vsp *vsphere.VSphere, nodeVolumes map[k8stype.NodeName][]string) error {
var (
err error
disksAttached = true
detachTimeout = 5 * time.Minute
detachPollTime = 10 * time.Second
)
if vsp == nil {
vsp, err = vsphere.GetVSphere()
if err != nil {
return err
}
}
err = wait.Poll(detachPollTime, detachTimeout, func() (bool, error) {
attachedResult, err := vsp.DisksAreAttached(nodeVolumes)
if err != nil {
return false, err
}
for nodeName, nodeVolumes := range attachedResult {
for volumePath, attached := range nodeVolumes {
if attached {
framework.Logf("Waiting for volumes %q to detach from %q.", volumePath, string(nodeName))
return false, nil
}
}
}
disksAttached = false
framework.Logf("Volume are successfully detached from all the nodes: %+v", nodeVolumes)
return true, nil
})
if err != nil {
return err
}
if disksAttached {
return fmt.Errorf("Gave up waiting for volumes to detach after %v", detachTimeout)
}
return nil
}
// Wait until vsphere vmdk is deteched from the given node or time out after 5 minutes // Wait until vsphere vmdk is deteched from the given node or time out after 5 minutes
func waitForVSphereDiskToDetach(vsp *vsphere.VSphere, volumePath string, nodeName types.NodeName) error { func waitForVSphereDiskToDetach(vsp *vsphere.VSphere, volumePath string, nodeName types.NodeName) error {
var ( var (
......
...@@ -128,7 +128,7 @@ func invokeTestForInvalidFstype(f *framework.Framework, client clientset.Interfa ...@@ -128,7 +128,7 @@ func invokeTestForInvalidFstype(f *framework.Framework, client clientset.Interfa
var pvclaims []*v1.PersistentVolumeClaim var pvclaims []*v1.PersistentVolumeClaim
pvclaims = append(pvclaims, pvclaim) pvclaims = append(pvclaims, pvclaim)
// Create pod to attach Volume to Node // Create pod to attach Volume to Node
pod, err := framework.CreatePod(client, namespace, pvclaims, false, ExecCommand) pod, err := framework.CreatePod(client, namespace, nil, pvclaims, false, ExecCommand)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
eventList, err := client.CoreV1().Events(namespace).List(metav1.ListOptions{}) eventList, err := client.CoreV1().Events(namespace).List(metav1.ListOptions{})
...@@ -170,7 +170,7 @@ func createPodAndVerifyVolumeAccessible(client clientset.Interface, namespace st ...@@ -170,7 +170,7 @@ func createPodAndVerifyVolumeAccessible(client clientset.Interface, namespace st
pvclaims = append(pvclaims, pvclaim) pvclaims = append(pvclaims, pvclaim)
By("Creating pod to attach PV to the node") By("Creating pod to attach PV to the node")
// Create pod to attach Volume to Node // Create pod to attach Volume to Node
pod, err := framework.CreatePod(client, namespace, pvclaims, false, ExecCommand) pod, err := framework.CreatePod(client, namespace, nil, pvclaims, false, "")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
// Asserts: Right disk is attached to the pod // Asserts: Right disk is attached to the pod
......
...@@ -109,7 +109,7 @@ var _ = SIGDescribe("Volume Operations Storm [Feature:vsphere]", func() { ...@@ -109,7 +109,7 @@ var _ = SIGDescribe("Volume Operations Storm [Feature:vsphere]", func() {
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("Creating pod to attach PVs to the node") By("Creating pod to attach PVs to the node")
pod, err := framework.CreatePod(client, namespace, pvclaims, false, "") pod, err := framework.CreatePod(client, namespace, nil, pvclaims, false, "")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
By("Verify all volumes are accessible and available in the pod") By("Verify all volumes are accessible and available in the pod")
......
...@@ -292,7 +292,7 @@ func invokeValidPolicyTest(f *framework.Framework, client clientset.Interface, n ...@@ -292,7 +292,7 @@ func invokeValidPolicyTest(f *framework.Framework, client clientset.Interface, n
By("Creating pod to attach PV to the node") By("Creating pod to attach PV to the node")
// Create pod to attach Volume to Node // Create pod to attach Volume to Node
pod, err := framework.CreatePod(client, namespace, pvclaims, false, "") pod, err := framework.CreatePod(client, namespace, nil, pvclaims, false, "")
Expect(err).NotTo(HaveOccurred()) Expect(err).NotTo(HaveOccurred())
vsp, err := vsphere.GetVSphere() vsp, err := vsphere.GetVSphere()
......
...@@ -98,7 +98,7 @@ func (t *PersistentVolumeUpgradeTest) Teardown(f *framework.Framework) { ...@@ -98,7 +98,7 @@ func (t *PersistentVolumeUpgradeTest) Teardown(f *framework.Framework) {
// testPod creates a pod that consumes a pv and prints it out. The output is then verified. // testPod creates a pod that consumes a pv and prints it out. The output is then verified.
func (t *PersistentVolumeUpgradeTest) testPod(f *framework.Framework, cmd string) { func (t *PersistentVolumeUpgradeTest) testPod(f *framework.Framework, cmd string) {
pod := framework.MakePod(f.Namespace.Name, []*v1.PersistentVolumeClaim{t.pvc}, false, cmd) pod := framework.MakePod(f.Namespace.Name, nil, []*v1.PersistentVolumeClaim{t.pvc}, false, cmd)
expectedOutput := []string{pvTestData} expectedOutput := []string{pvTestData}
f.TestContainerOutput("pod consumes pv", pod, 0, expectedOutput) f.TestContainerOutput("pod consumes pv", pod, 0, expectedOutput)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment