@@ -5,13 +5,15 @@ import (
55
66 "k8s.io/apimachinery/pkg/labels"
77 "k8s.io/apimachinery/pkg/types"
8+ "k8s.io/component-helpers/storage/volume"
89 "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
910 "sigs.k8s.io/controller-runtime/pkg/manager"
1011 "sigs.k8s.io/controller-runtime/pkg/predicate"
1112 "sigs.k8s.io/controller-runtime/pkg/reconcile"
1213
1314 v1 "k8s.io/api/core/v1"
1415 apierrors "k8s.io/apimachinery/pkg/api/errors"
16+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1517 ctrl "sigs.k8s.io/controller-runtime"
1618 ctrlruntimeclient "sigs.k8s.io/controller-runtime/pkg/client"
1719
@@ -22,6 +24,7 @@ import (
2224const (
2325 pvcControllerName = "pvc-syncer-controller"
2426 pvcFinalizerName = "pvc.k3k.io/finalizer"
27+ pseudoPVLabel = "pod.k3k.io/pseudoPV"
2528)
2629
2730type PVCReconciler struct {
@@ -105,6 +108,12 @@ func (r *PVCReconciler) Reconcile(ctx context.Context, req reconcile.Request) (r
105108 if err := r .HostClient .Delete (ctx , syncedPVC ); err != nil && ! apierrors .IsNotFound (err ) {
106109 return reconcile.Result {}, err
107110 }
111+
112+ // delete the synced virtual PV
113+ if err := r .VirtualClient .Delete (ctx , newPersistentVolume (& virtPVC )); err != nil && ! apierrors .IsNotFound (err ) {
114+ return reconcile.Result {}, err
115+ }
116+
108117 // remove the finalizer after cleaning up the synced pvc
109118 if controllerutil .RemoveFinalizer (& virtPVC , pvcFinalizerName ) {
110119 if err := r .VirtualClient .Update (ctx , & virtPVC ); err != nil {
@@ -127,7 +136,13 @@ func (r *PVCReconciler) Reconcile(ctx context.Context, req reconcile.Request) (r
127136
128137 // note that we dont need to update the PVC on the host cluster, only syncing the PVC to allow being
129138 // handled by the host cluster.
130- return reconcile.Result {}, ctrlruntimeclient .IgnoreAlreadyExists (r .HostClient .Create (ctx , syncedPVC ))
139+ if err := r .HostClient .Create (ctx , syncedPVC ); err != nil && ! apierrors .IsAlreadyExists (err ) {
140+ return reconcile.Result {}, err
141+ }
142+
143+ // Creating a virtual PV to bound the existing PVC in the virtual cluster - needed for scheduling of
144+ // the consumer pods
145+ return reconcile.Result {}, r .createVirtualPersistentVolume (ctx , virtPVC )
131146}
132147
133148func (r * PVCReconciler ) pvc (obj * v1.PersistentVolumeClaim ) * v1.PersistentVolumeClaim {
@@ -136,3 +151,82 @@ func (r *PVCReconciler) pvc(obj *v1.PersistentVolumeClaim) *v1.PersistentVolumeC
136151
137152 return hostPVC
138153}
154+
155+ func (r * PVCReconciler ) createVirtualPersistentVolume (ctx context.Context , pvc v1.PersistentVolumeClaim ) error {
156+ log := ctrl .LoggerFrom (ctx )
157+ log .V (1 ).Info ("Creating virtual PersistentVolume" )
158+
159+ pv := newPersistentVolume (& pvc )
160+
161+ if err := r .VirtualClient .Create (ctx , pv ); err != nil && ! apierrors .IsAlreadyExists (err ) {
162+ return err
163+ }
164+
165+ orig := pv .DeepCopy ()
166+ pv .Status = v1.PersistentVolumeStatus {
167+ Phase : v1 .VolumeBound ,
168+ }
169+
170+ if err := r .VirtualClient .Status ().Patch (ctx , pv , ctrlruntimeclient .MergeFrom (orig )); err != nil {
171+ return err
172+ }
173+
174+ log .V (1 ).Info ("Patch the status of PersistentVolumeClaim to Bound" )
175+
176+ pvcPatch := pvc .DeepCopy ()
177+ if pvcPatch .Annotations == nil {
178+ pvcPatch .Annotations = make (map [string ]string )
179+ }
180+
181+ pvcPatch .Annotations [volume .AnnBoundByController ] = "yes"
182+ pvcPatch .Annotations [volume .AnnBindCompleted ] = "yes"
183+ pvcPatch .Status .Phase = v1 .ClaimBound
184+ pvcPatch .Status .AccessModes = pvcPatch .Spec .AccessModes
185+
186+ return r .VirtualClient .Status ().Update (ctx , pvcPatch )
187+ }
188+
189+ func newPersistentVolume (obj * v1.PersistentVolumeClaim ) * v1.PersistentVolume {
190+ var storageClass string
191+
192+ if obj .Spec .StorageClassName != nil {
193+ storageClass = * obj .Spec .StorageClassName
194+ }
195+
196+ return & v1.PersistentVolume {
197+ ObjectMeta : metav1.ObjectMeta {
198+ Name : obj .Name ,
199+ Labels : map [string ]string {
200+ pseudoPVLabel : "true" ,
201+ },
202+ Annotations : map [string ]string {
203+ volume .AnnBoundByController : "true" ,
204+ volume .AnnDynamicallyProvisioned : "k3k-kubelet" ,
205+ },
206+ },
207+ TypeMeta : metav1.TypeMeta {
208+ Kind : "PersistentVolume" ,
209+ APIVersion : "v1" ,
210+ },
211+ Spec : v1.PersistentVolumeSpec {
212+ PersistentVolumeSource : v1.PersistentVolumeSource {
213+ FlexVolume : & v1.FlexPersistentVolumeSource {
214+ Driver : "pseudopv" ,
215+ },
216+ },
217+ StorageClassName : storageClass ,
218+ VolumeMode : obj .Spec .VolumeMode ,
219+ PersistentVolumeReclaimPolicy : v1 .PersistentVolumeReclaimDelete ,
220+ AccessModes : obj .Spec .AccessModes ,
221+ Capacity : obj .Spec .Resources .Requests ,
222+ ClaimRef : & v1.ObjectReference {
223+ APIVersion : obj .APIVersion ,
224+ UID : obj .UID ,
225+ ResourceVersion : obj .ResourceVersion ,
226+ Kind : obj .Kind ,
227+ Namespace : obj .Namespace ,
228+ Name : obj .Name ,
229+ },
230+ },
231+ }
232+ }
0 commit comments