Change:
Context: NodeSwap feature gate was recently . Currently, as per , swap is only supported with cgroup v2 - cgroup v1 is no longer supported. For this reason, we decided to fail kubelet if NodeSwap feature gate is enabled and the node runs with cgroup v1. This would help prevent any surprises for the user by failing as soon as possible. This effort is being implemented in this PR: The problem: Currently, swap jobs are running with cgroup v1. Swap tests were in a way that they first check on which environment they're being run (e.g. which cgroup version? is NodeSwap FG enabled? Which swapBehavior is defined? etc) and then expect the right behavior to take place. With v1, the tests expect the containers to be defined without swap access. While the tests pass, they are much less valuable, since all they check is that swap is disabled for v1 workloads. The tests would be much more valuable if they would run with v2, therefore actually ensure that proper swap limitations are configured. In addition, is dependent on these changes, since as of now the jobs immediately fail with this PR since kubelet fails on an environment with cgroup v1 and swap enabled. What needs to change: [x] CRI-O swap related jobs should be defined to run with cgroup v2 (e.g. ) [x] containerd swap related jobs should be defined to run with cgroup v2 (e.g. ). Future work: In the future, we might consider introducing more jobs to check swap. Ideally, both and would be tested, perhaps by periodic jobs.
This issue is currently awaiting triage. If a SIG or subproject determines this is a relevant issue, they will accept it by applying the label and provide further guidance. The label can be by org members by writing in a comment. <detailsInstructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details
/sig node
/sig testing
/reopen
Reopened this issue. <detailsIn response to : /reopen Instructions for interacting with me using PR comments are available . If you have questions or suggestions related to my behavior, please file an issue against the repository. </details

Discussion:
} } <del> // Delete the PV. Fail test if delete fails. </del> <ins> // Delete the PV. Fail test if delete fails. If success the returned PV should // be nil, which prevents the AfterEach from attempting to delete it. </ins> func deletePersistentVolume(c *client.Client, pv *api.PersistentVolume) (*api.PersistentVolume, error) { if pv == nil { return nil, fmt.Errorf("PV to be deleted is nil") } <del> By("Deleting PersistentVolume") </del> framework.Logf("Deleting PersistentVolume %v", pv.Name) err := c.PersistentVolumes().Delete(pv.Name) if err != nil {

return nil, nil // success } <del> // Delete the PVC and wait for the PV to become Available again. // Validate that the PV has recycled (assumption here about reclaimPolicy). </del> <ins> // Delete the PVC and wait for the PV to become Available again. Validate that // the PV has recycled (assumption here about reclaimPolicy). Return the pv and // pvc to reflect that these resources have been retrieved again (Get). If the // delete is successful the returned pvc should be nil and the pv non-nil. // Note: the pv and pvc are returned back to the It() caller so that the //   AfterEach func can delete these objects if they are not nil. </ins> func deletePVCandValidatePV(c *client.Client, ns string, pvc *api.PersistentVolumeClaim, pv *api.PersistentVolume) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { <del> By("Deleting PersistentVolumeClaim to trigger PV Recycling") </del> framework.Logf("Deleting PersistentVolumeClaim %v to trigger PV Recycling", pvc.Name) err := c.PersistentVolumeClaims(ns).Delete(pvc.Name) if err != nil {

return pvc, nil } <del> // Create a PV and PVC based on the passed in nfs-server ip and namespace. // There are 4 combinations, 3 of which are supported here: //   1) prebind and create pvc first //   2) no prebind and create pvc first //   3) no prebind and create pv first // The case of prebinding and creating the pv first is not possible due to using a // *generated* name in the pvc, and thus not knowing the claim's name until after // it has been created. // **Note: this function complements makePersistentVolume() and fills in the remaining // name field in the pv's ClaimRef. func createPVandPVC(c *client.Client, serverIP, ns string, pvFirst, preBind bool) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { </del> <ins> // Create a PVC followed by the PV based on the passed in nfs-server ip and // namespace. If the "preBind" bool is true then pre-bind the PV to the PVC // via the PV's ClaimRef. Return the pv and pvc to reflect the created objects. // Note: the pv and pvc are returned back to the It() caller so that the //   AfterEach func can delete these objects if they are not nil. // Note: in the pre-bind case the real PVC name, which is generated, is not //   known until after the PVC is instantiated. This is why the pvc is created //   before the pv. func createPVCPV(c *client.Client, serverIP, ns string, preBind bool) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { </ins> var bindTo *api.PersistentVolumeClaim <del> var err error pvc := makePersistentVolumeClaim(ns) // pvc.Name not known yet </del> <ins> var preBindMsg string </ins> <del> bindTo = nil if preBind { // implies pvc *must* be created before the pv pvFirst = false </del> <ins> // make the pvc definition first pvc := makePersistentVolumeClaim(ns) if preBind { preBindMsg = " pre-bound" </ins> bindTo = pvc } <ins> // make the pv spec </ins> pv := makePersistentVolume(serverIP, bindTo) <del> if pvFirst { By("Creating the PV followed by the PVC") pv, err = createPV(c, pv) } else { By("Creating the PVC followed by the PV") pvc, err = createPVC(c, ns, pvc) } </del> <ins> By(fmt.Sprintf("Creating a PVC followed by a%s PV", preBindMsg)) // instantiate the pvc pvc, err := createPVC(c, ns, pvc) </ins> if err != nil { return nil, nil, err } <del> if pvFirst { pvc, err = createPVC(c, ns, pvc) if err != nil { return pv, nil, err } } else { // need to fill-in claimRef with pvc.Name </del> <ins> // instantiate the pvc, handle pre-binding by ClaimRef if needed if preBind { </ins> pv.Spec.ClaimRef.Name = pvc.Name <del> pv, err = createPV(c, pv) if err != nil { return nil, pvc, err } </del> <ins> } pv, err = createPV(c, pv) if err != nil { return nil, pvc, err } return pv, pvc, nil } // Create a PV followed by the PVC based on the passed in nfs-server ip and // namespace. If the "preBind" bool is true then pre-bind the PVC to the PV // via the PVC's VolumeName. Return the pv and pvc to reflect the created // objects. // Note: the pv and pvc are returned back to the It() caller so that the //   AfterEach func can delete these objects if they are not nil. // Note: in the pre-bind case the real PV name, which is generated, is not //   known until after the PV is instantiated. This is why the pv is created //   before the pvc. func createPVPVC(c *client.Client, serverIP, ns string, preBind bool) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { preBindMsg := "" if preBind { preBindMsg = " pre-bound" } By(fmt.Sprintf("Creating a PV followed by a%s PVC", preBindMsg)) // make the pv and pvc definitions pv := makePersistentVolume(serverIP, nil) pvc := makePersistentVolumeClaim(ns) // instantiate the pv pv, err := createPV(c, pv) if err != nil { return nil, nil, err } // instantiate the pvc, handle pre-binding by VolumeName if needed if preBind { pvc.Spec.VolumeName = pv.Name } pvc, err = createPVC(c, ns, pvc) if err != nil { return pv, nil, err </ins> } return pv, pvc, nil

} // Waits for the pv and pvc to be bound to each other, then checks that the pv's <del> // claimRef matches the pvc. Fails test on errors. </del> <ins> // claimRef matches the pvc. Fails test on errors. Return the pv and pvc to // reflect that these resources have been retrieved again (Get). // Note: the pv and pvc are returned back to the It() caller so that the //   AfterEach func can delete these objects if they are not nil. </ins> func waitAndValidatePVandPVC(c *client.Client, ns string, pv *api.PersistentVolume, pvc *api.PersistentVolumeClaim) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { var err error

return nil } <ins> // validate PV/PVC, create and verify writer pod, delete PVC and PV. Ensure // all of these steps were successful. Return the pv and pvc to reflect that // these resources have been retrieved again (Get). // Note: the pv and pvc are returned back to the It() caller so that the //   AfterEach func can delete these objects if they are not nil. func completeTest(f *framework.Framework, c *client.Client, ns string, pv *api.PersistentVolume, pvc *api.PersistentVolumeClaim) (*api.PersistentVolume, *api.PersistentVolumeClaim, error) { // 1. verify that the PV and PVC have binded correctly By("Validating the PV-PVC binding") pv, pvc, err := waitAndValidatePVandPVC(c, ns, pv, pvc) if err != nil { return pv, pvc, err } // 2. create the nfs writer pod, test if the write was successful, //    then delete the pod and verify that it was deleted By("Checking pod has write access to PersistentVolume") if err = createWaitAndDeletePod(f, c, ns, pvc.Name); err != nil { return pv, pvc, err } // 3. delete the PVC before deleting PV, wait for PV to be "Available" By("Deleting the PVC to invoke the recycler") pv, pvc, err = deletePVCandValidatePV(c, ns, pvc, pv) if err != nil { return pv, pvc, err } // 4. cleanup by deleting the pv By("Deleting the PV") if pv, err = deletePersistentVolume(c, pv); err != nil { return pv, pvc, err } return pv, pvc, nil } </ins> var _ = framework.KubeDescribe("PersistentVolumes", func() { // global vars for the It() tests below

NFSconfig = VolumeTestConfig{ namespace:   api.NamespaceDefault, prefix:      "nfs", <del> serverImage: "gcr.io/google_containers/volume-nfs:0.7", </del> <ins> serverImage: "gcr.io/google_containers/volume-nfs:0.6", </ins> serverPorts: []int{2049}, serverArgs:  []string{"-G", "777", "/exports"}, }

// Individual tests follow: // <del> // Create an nfs PV, a claim that matches the PV, a pod that contains the // claim. Verify that the PV and PVC bind correctly and that the pod can // write to the nfs volume. It("should create a PersistentVolume, Claim, and Pod that will test write access of the volume [Flaky]", func() { </del> <ins> // Create an nfs PV, then a claim that matches the PV, and a pod that // contains the claim. Verify that the PV and PVC bind correctly, and // that the pod can write to the nfs volume. It("should create a non-pre-bound PV and PVC: test write access [Flaky]", func() { </ins> <del> pv, pvc, err = createPVandPVC(c, serverIP, ns, true /*pv first*/, false) </del> <ins> pv, pvc, err = createPVPVC(c, serverIP, ns, false) </ins> if err != nil { framework.Failf("%v", err) } <del> pv, pvc, err = waitAndValidatePVandPVC(c, ns, pv, pvc) </del> <ins> // validate PV-PVC, create and verify writer pod, delete PVC // and PV pv, pvc, err = completeTest(f, c, ns, pv, pvc) </ins> if err != nil { framework.Failf("%v", err) } <ins> }) </ins> <del> By("Checking pod has write access to PersistentVolume") if err = createWaitAndDeletePod(f, c, ns, pvc.Name); err != nil { framework.Failf("%v", err) } </del> <ins> // Create a claim first, then a nfs PV that matches the claim, and a // pod that contains the claim. Verify that the PV and PVC bind // correctly, and that the pod can write to the nfs volume. It("create a PVC and non-pre-bound PV: test write access [Flaky]", func() { </ins> <del> // Delete the PVC before deleting PV, wait for PV to be Available pv, pvc, err = deletePVCandValidatePV(c, ns, pvc, pv) </del> <ins> pv, pvc, err = createPVCPV(c, serverIP, ns, false) </ins> if err != nil { framework.Failf("%v", err) } <del> // Last cleanup step is to delete the pv pv, err = deletePersistentVolume(c, pv) </del> <ins> // validate PV-PVC, create and verify writer pod, delete PVC // and PV pv, pvc, err = completeTest(f, c, ns, pv, pvc) </ins> if err != nil { framework.Failf("%v", err) } }) <del> // Create an nfs PV that is *pre-bound* to a claim. Create a pod that // contains the claim. Verify that the PV and PVC bind correctly and that // the pod can write to the nfs volume. It("should create a pre-bound PersistentVolume, Claim, and Pod that will test write access of the volume [Flaky]", func() { </del> <ins> // Create a claim first, then a pre-bound nfs PV that matches the claim, // and a pod that contains the claim. Verify that the PV and PVC bind // correctly, and that the pod can write to the nfs volume. It("create a PVC and a pre-bound PV: test write access [Flaky]", func() { </ins> <del> pv, pvc, err = createPVandPVC(c, serverIP, ns, false /*pvc first*/, true /*prebind*/) </del> <ins> pv, pvc, err = createPVCPV(c, serverIP, ns, true) </ins> if err != nil { framework.Failf("%v", err) } <del> pv, pvc, err = waitAndValidatePVandPVC(c, ns, pv, pvc) </del> <ins> // validate PV-PVC, create and verify writer pod, delete PVC // and PV pv, pvc, err = completeTest(f, c, ns, pv, pvc) </ins> if err != nil { framework.Failf("%v", err) } <ins> }) </ins> <del> // checkPod writes to the nfs volume By("Checking pod has write access to pre-bound PersistentVolume") // Instantiate pod, wait for it to exit, then delete it if err = createWaitAndDeletePod(f, c, ns, pvc.Name); err != nil { framework.Failf("%v", err) } </del> <ins> // Create a nfs PV first, then a pre-bound PVC that matches the PV, // and a pod that contains the claim. Verify that the PV and PVC bind // correctly, and that the pod can write to the nfs volume. It("create a PV and a pre-bound PVC: test write access [Flaky]", func() { </ins> <del> // Delete the PVC before deleting PV, wait for PV to be Available pv, pvc, err = deletePVCandValidatePV(c, ns, pvc, pv) </del> <ins> pv, pvc, err = createPVPVC(c, serverIP, ns, true) </ins> if err != nil { framework.Failf("%v", err) } <del> // Last cleanup step is to delete the pv pv, err = deletePersistentVolume(c, pv) </del> <ins> // validate PV-PVC, create and verify writer pod, delete PVC // and PV pv, pvc, err = completeTest(f, c, ns, pv, pvc) </ins> if err != nil { framework.Failf("%v", err) } }) }) <del> // Returns a PV definition based on the nfs server IP. If the PVC is not nil then the // PV is defined with a ClaimRef which includes the PVC's namespace. If the PVC is // nil then the PV is not defined with a ClaimRef. // **Note: the passed-in claim does not have a name until it is created (instantiated) // and thus the PV's ClaimRef cannot be completely filled-in in this func. Therefore, // the ClaimRef's name is added later in createPVandPVC(). </del> <ins> // Returns a PV definition based on the nfs server IP. If the PVC is not nil // then the PV is defined with a ClaimRef which includes the PVC's namespace. // If the PVC is nil then the PV is not defined with a ClaimRef. // Note: the passed-in claim does not have a name until it is created //   (instantiated) and thus the PV's ClaimRef cannot be completely filled-in in //   this func. Therefore, the ClaimRef's name is added later in //   createPVCPV. </ins> func makePersistentVolume(serverIP string, pvc *api.PersistentVolumeClaim) *api.PersistentVolume { // Specs are expected to match this test's PersistentVolumeClaim var claimRef *api.ObjectReference <del> claimRef = nil </del> if pvc != nil { claimRef = &api.ObjectReference{ Name:      pvc.Name,

} // Returns a PVC definition based on the namespace. <ins> // Note: if this PVC is intended to be pre-bound to a PV, whose name is not //   known until the PV is instantiated, then the func createPVPVC will add //   pvc.Spec.VolumeName to this claim. </ins> func makePersistentVolumeClaim(ns string) *api.PersistentVolumeClaim { // Specs are expected to match this test's PersistentVolume