[{"data":1,"prerenderedAt":1197},["Reactive",2],{"/blog/migrating-kubernetes-pvcs-from-csi-proxmox-to-csi-cephfs":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"categories":11,"body":14,"_type":1192,"_id":1193,"_source":1194,"_file":1195,"_extension":1196},"/blog/migrating-kubernetes-pvcs-from-csi-proxmox-to-csi-cephfs","blog",false,"","Migrating Kubernetes PVCs from csi-proxmox to csi-cephfs","My journey moving from Proxmox VMs to CephFS as my k8s primary data storage.","2025-04-16T00:00:00.000Z",[12,13],"Kubernetes","Proxmox",{"type":15,"children":16,"toc":1180},"root",[17,41,46,93,113,132,139,144,180,192,197,203,208,263,268,274,295,302,307,493,499,504,921,926,949,954,978,983,989,1018,1024,1029,1048,1053,1059,1064,1073,1078,1097,1102,1107,1113,1132,1137,1142,1174],{"type":18,"tag":19,"props":20,"children":21},"element","p",{},[22,25,39],{"type":23,"value":24},"text","For a while now, I’ve been using ",{"type":18,"tag":26,"props":27,"children":31},"a",{"href":28,"rel":29},"https://github.com/sergelogvinov/proxmox-csi-plugin",[30],"nofollow",[32],{"type":18,"tag":33,"props":34,"children":36},"code",{"className":35},[],[37],{"type":23,"value":38},"csi-proxmox",{"type":23,"value":40}," to provision Kubernetes PersistentVolumeClaims (PVCs) using virtual disks on my Proxmox nodes. It’s a solid setup for basic storage needs—especially if you're already deep in the Proxmox ecosystem, but I wanted more flexibility as my homelab grew.",{"type":18,"tag":19,"props":42,"children":43},{},[44],{"type":23,"value":45},"Specifically, I was looking for a way to:",{"type":18,"tag":47,"props":48,"children":49},"ul",{},[50,64,81],{"type":18,"tag":51,"props":52,"children":53},"li",{},[54,56,62],{"type":23,"value":55},"Support ",{"type":18,"tag":57,"props":58,"children":59},"strong",{},[60],{"type":23,"value":61},"multi-node",{"type":23,"value":63}," read/write volumes",{"type":18,"tag":51,"props":65,"children":66},{},[67,69,74,76],{"type":23,"value":68},"Improve ",{"type":18,"tag":57,"props":70,"children":71},{},[72],{"type":23,"value":73},"resilience",{"type":23,"value":75}," and ",{"type":18,"tag":57,"props":77,"children":78},{},[79],{"type":23,"value":80},"availability",{"type":18,"tag":51,"props":82,"children":83},{},[84,86,91],{"type":23,"value":85},"Simplify ",{"type":18,"tag":57,"props":87,"children":88},{},[89],{"type":23,"value":90},"storage management",{"type":23,"value":92}," with a shared backend",{"type":18,"tag":19,"props":94,"children":95},{},[96,98,103,105,111],{"type":23,"value":97},"That’s when I started experimenting with ",{"type":18,"tag":57,"props":99,"children":100},{},[101],{"type":23,"value":102},"CephFS",{"type":23,"value":104},". After getting it working inside my Proxmox cluster, I integrated it with Kubernetes using the ",{"type":18,"tag":33,"props":106,"children":108},{"className":107},[],[109],{"type":23,"value":110},"csi-cephfs",{"type":23,"value":112}," driver, and now I’m gradually migrating my workloads over to it. I am starting off with a single node cluster (I know, I know. This is not the best way to handle it.), but it's getting me started on the process and I'll be moving towards a real quorum soon!",{"type":18,"tag":19,"props":114,"children":115},{},[116,118,123,125,130],{"type":23,"value":117},"Let me walk you through what that looks like, with a real example of how I migrated data from a ",{"type":18,"tag":33,"props":119,"children":121},{"className":120},[],[122],{"type":23,"value":38},{"type":23,"value":124}," volume to a ",{"type":18,"tag":33,"props":126,"children":128},{"className":127},[],[129],{"type":23,"value":110},{"type":23,"value":131}," volume using a simple pod-based approach.",{"type":18,"tag":133,"props":134,"children":136},"h2",{"id":135},"why-im-migrating-to-cephfs",[137],{"type":23,"value":138},"Why I'm Migrating to CephFS",{"type":18,"tag":19,"props":140,"children":141},{},[142],{"type":23,"value":143},"Here's a quick overview of why I’m moving my PVCs to CephFS:",{"type":18,"tag":47,"props":145,"children":146},{},[147,159,170,175],{"type":18,"tag":51,"props":148,"children":149},{},[150,152,157],{"type":23,"value":151},"✅ ",{"type":18,"tag":57,"props":153,"children":154},{},[155],{"type":23,"value":156},"ReadWriteMany (RWX)",{"type":23,"value":158}," support — pods across nodes can share the same volume",{"type":18,"tag":51,"props":160,"children":161},{},[162,163,168],{"type":23,"value":151},{"type":18,"tag":57,"props":164,"children":165},{},[166],{"type":23,"value":167},"Backups and snapshots",{"type":23,"value":169}," are easier to manage with Ceph",{"type":18,"tag":51,"props":171,"children":172},{},[173],{"type":23,"value":174},"✅ No more VM disk sprawl tied to specific nodes",{"type":18,"tag":51,"props":176,"children":177},{},[178],{"type":23,"value":179},"✅ Ceph already runs inside Proxmox, so no extra infra required",{"type":18,"tag":19,"props":181,"children":182},{},[183,185,190],{"type":23,"value":184},"That being said, most of my workloads (especially StatefulSets) still had PVCs tied to the old ",{"type":18,"tag":33,"props":186,"children":188},{"className":187},[],[189],{"type":23,"value":38},{"type":23,"value":191}," StorageClass.",{"type":18,"tag":19,"props":193,"children":194},{},[195],{"type":23,"value":196},"I needed a way to safely migrate that data.",{"type":18,"tag":133,"props":198,"children":200},{"id":199},"the-migration-process",[201],{"type":23,"value":202},"The Migration Process",{"type":18,"tag":19,"props":204,"children":205},{},[206],{"type":23,"value":207},"Here’s the overall flow I followed for each PVC migration:",{"type":18,"tag":209,"props":210,"children":211},"ol",{},[212,222,240,253,258],{"type":18,"tag":51,"props":213,"children":214},{},[215,217],{"type":23,"value":216},"Create a ",{"type":18,"tag":57,"props":218,"children":219},{},[220],{"type":23,"value":221},"new CephFS-based PVC",{"type":18,"tag":51,"props":223,"children":224},{},[225,227,232,233,238],{"type":23,"value":226},"Launch a pod that mounts both the ",{"type":18,"tag":57,"props":228,"children":229},{},[230],{"type":23,"value":231},"old",{"type":23,"value":75},{"type":18,"tag":57,"props":234,"children":235},{},[236],{"type":23,"value":237},"new",{"type":23,"value":239}," PVCs",{"type":18,"tag":51,"props":241,"children":242},{},[243,245,251],{"type":23,"value":244},"Use ",{"type":18,"tag":33,"props":246,"children":248},{"className":247},[],[249],{"type":23,"value":250},"rsync",{"type":23,"value":252}," inside the pod to copy the data",{"type":18,"tag":51,"props":254,"children":255},{},[256],{"type":23,"value":257},"Update the application to point to the new PVC",{"type":18,"tag":51,"props":259,"children":260},{},[261],{"type":23,"value":262},"Clean up the old storage resources",{"type":18,"tag":19,"props":264,"children":265},{},[266],{"type":23,"value":267},"Let’s break that down with a real example.",{"type":18,"tag":133,"props":269,"children":271},{"id":270},"example-migrating-my-tautulli-pvc",[272],{"type":23,"value":273},"Example: Migrating My Tautulli PVC",{"type":18,"tag":19,"props":275,"children":276},{},[277,279,286,288,293],{"type":23,"value":278},"I have the ",{"type":18,"tag":26,"props":280,"children":283},{"href":281,"rel":282},"https://github.com/Tautulli/Tautulli",[30],[284],{"type":23,"value":285},"Tautulli",{"type":23,"value":287}," app running in Kubernetes, and its persistent data was on a ",{"type":18,"tag":33,"props":289,"children":291},{"className":290},[],[292],{"type":23,"value":38},{"type":23,"value":294}," backed PVC. I wanted to move this to CephFS without losing anything or dealing with complicated downtime.",{"type":18,"tag":296,"props":297,"children":299},"h3",{"id":298},"step-1-create-a-new-pvc-for-cephfs",[300],{"type":23,"value":301},"Step 1: Create a New PVC for CephFS",{"type":18,"tag":19,"props":303,"children":304},{},[305],{"type":23,"value":306},"First, I created a new PVC using my CephFS-backed StorageClass. Here's a sample YAML:",{"type":18,"tag":308,"props":309,"children":313},"pre",{"className":310,"code":311,"language":312,"meta":7,"style":7},"language-yaml shiki shiki-themes material-theme-lighter material-theme-palenight","apiVersion: v1\nkind: PersistentVolumeClaim\nmetadata:\n  name: tautulli-cephfs\nspec:\n  accessModes:\n    - ReadWriteMany\n  resources:\n    requests:\n      storage: 5Gi\n  storageClassName: csi-cephfs-sc\n","yaml",[314],{"type":18,"tag":33,"props":315,"children":316},{"__ignoreMap":7},[317,341,359,373,391,404,417,431,444,457,475],{"type":18,"tag":318,"props":319,"children":322},"span",{"class":320,"line":321},"line",1,[323,329,335],{"type":18,"tag":318,"props":324,"children":326},{"style":325},"--shiki-default:#E53935;--shiki-dark:#F07178",[327],{"type":23,"value":328},"apiVersion",{"type":18,"tag":318,"props":330,"children":332},{"style":331},"--shiki-default:#39ADB5;--shiki-dark:#89DDFF",[333],{"type":23,"value":334},":",{"type":18,"tag":318,"props":336,"children":338},{"style":337},"--shiki-default:#91B859;--shiki-dark:#C3E88D",[339],{"type":23,"value":340}," v1\n",{"type":18,"tag":318,"props":342,"children":344},{"class":320,"line":343},2,[345,350,354],{"type":18,"tag":318,"props":346,"children":347},{"style":325},[348],{"type":23,"value":349},"kind",{"type":18,"tag":318,"props":351,"children":352},{"style":331},[353],{"type":23,"value":334},{"type":18,"tag":318,"props":355,"children":356},{"style":337},[357],{"type":23,"value":358}," PersistentVolumeClaim\n",{"type":18,"tag":318,"props":360,"children":362},{"class":320,"line":361},3,[363,368],{"type":18,"tag":318,"props":364,"children":365},{"style":325},[366],{"type":23,"value":367},"metadata",{"type":18,"tag":318,"props":369,"children":370},{"style":331},[371],{"type":23,"value":372},":\n",{"type":18,"tag":318,"props":374,"children":376},{"class":320,"line":375},4,[377,382,386],{"type":18,"tag":318,"props":378,"children":379},{"style":325},[380],{"type":23,"value":381},"  name",{"type":18,"tag":318,"props":383,"children":384},{"style":331},[385],{"type":23,"value":334},{"type":18,"tag":318,"props":387,"children":388},{"style":337},[389],{"type":23,"value":390}," tautulli-cephfs\n",{"type":18,"tag":318,"props":392,"children":394},{"class":320,"line":393},5,[395,400],{"type":18,"tag":318,"props":396,"children":397},{"style":325},[398],{"type":23,"value":399},"spec",{"type":18,"tag":318,"props":401,"children":402},{"style":331},[403],{"type":23,"value":372},{"type":18,"tag":318,"props":405,"children":407},{"class":320,"line":406},6,[408,413],{"type":18,"tag":318,"props":409,"children":410},{"style":325},[411],{"type":23,"value":412},"  accessModes",{"type":18,"tag":318,"props":414,"children":415},{"style":331},[416],{"type":23,"value":372},{"type":18,"tag":318,"props":418,"children":420},{"class":320,"line":419},7,[421,426],{"type":18,"tag":318,"props":422,"children":423},{"style":331},[424],{"type":23,"value":425},"    -",{"type":18,"tag":318,"props":427,"children":428},{"style":337},[429],{"type":23,"value":430}," ReadWriteMany\n",{"type":18,"tag":318,"props":432,"children":434},{"class":320,"line":433},8,[435,440],{"type":18,"tag":318,"props":436,"children":437},{"style":325},[438],{"type":23,"value":439},"  resources",{"type":18,"tag":318,"props":441,"children":442},{"style":331},[443],{"type":23,"value":372},{"type":18,"tag":318,"props":445,"children":447},{"class":320,"line":446},9,[448,453],{"type":18,"tag":318,"props":449,"children":450},{"style":325},[451],{"type":23,"value":452},"    requests",{"type":18,"tag":318,"props":454,"children":455},{"style":331},[456],{"type":23,"value":372},{"type":18,"tag":318,"props":458,"children":460},{"class":320,"line":459},10,[461,466,470],{"type":18,"tag":318,"props":462,"children":463},{"style":325},[464],{"type":23,"value":465},"      storage",{"type":18,"tag":318,"props":467,"children":468},{"style":331},[469],{"type":23,"value":334},{"type":18,"tag":318,"props":471,"children":472},{"style":337},[473],{"type":23,"value":474}," 5Gi\n",{"type":18,"tag":318,"props":476,"children":478},{"class":320,"line":477},11,[479,484,488],{"type":18,"tag":318,"props":480,"children":481},{"style":325},[482],{"type":23,"value":483},"  storageClassName",{"type":18,"tag":318,"props":485,"children":486},{"style":331},[487],{"type":23,"value":334},{"type":18,"tag":318,"props":489,"children":490},{"style":337},[491],{"type":23,"value":492}," csi-cephfs-sc\n",{"type":18,"tag":296,"props":494,"children":496},{"id":495},"step-2-launch-a-migration-pod",[497],{"type":23,"value":498},"Step 2: Launch a Migration Pod",{"type":18,"tag":19,"props":500,"children":501},{},[502],{"type":23,"value":503},"To copy data between PVCs, I created a pod that mounts both volumes and gives me an interactive shell:",{"type":18,"tag":308,"props":505,"children":507},{"className":310,"code":506,"language":312,"meta":7,"style":7},"apiVersion: v1\nkind: Pod\nmetadata:\n  name: pvc-migrator\nspec:\n  containers:\n    - name: migrator\n      image: ubuntu:22.04\n      command: [\"/bin/bash\", \"-c\", \"sleep infinity\"]\n      volumeMounts:\n        - name: old-pvc\n          mountPath: /mnt/old\n        - name: new-pvc\n          mountPath: /mnt/new\n  volumes:\n    - name: old-pvc\n      persistentVolumeClaim:\n        claimName: tautulli-data\n    - name: new-pvc\n      persistentVolumeClaim:\n        claimName: tautulli-cephfs\n  restartPolicy: Never\n",[508],{"type":18,"tag":33,"props":509,"children":510},{"__ignoreMap":7},[511,526,542,553,569,580,592,613,630,702,714,735,753,774,791,804,824,837,855,875,887,903],{"type":18,"tag":318,"props":512,"children":513},{"class":320,"line":321},[514,518,522],{"type":18,"tag":318,"props":515,"children":516},{"style":325},[517],{"type":23,"value":328},{"type":18,"tag":318,"props":519,"children":520},{"style":331},[521],{"type":23,"value":334},{"type":18,"tag":318,"props":523,"children":524},{"style":337},[525],{"type":23,"value":340},{"type":18,"tag":318,"props":527,"children":528},{"class":320,"line":343},[529,533,537],{"type":18,"tag":318,"props":530,"children":531},{"style":325},[532],{"type":23,"value":349},{"type":18,"tag":318,"props":534,"children":535},{"style":331},[536],{"type":23,"value":334},{"type":18,"tag":318,"props":538,"children":539},{"style":337},[540],{"type":23,"value":541}," Pod\n",{"type":18,"tag":318,"props":543,"children":544},{"class":320,"line":361},[545,549],{"type":18,"tag":318,"props":546,"children":547},{"style":325},[548],{"type":23,"value":367},{"type":18,"tag":318,"props":550,"children":551},{"style":331},[552],{"type":23,"value":372},{"type":18,"tag":318,"props":554,"children":555},{"class":320,"line":375},[556,560,564],{"type":18,"tag":318,"props":557,"children":558},{"style":325},[559],{"type":23,"value":381},{"type":18,"tag":318,"props":561,"children":562},{"style":331},[563],{"type":23,"value":334},{"type":18,"tag":318,"props":565,"children":566},{"style":337},[567],{"type":23,"value":568}," pvc-migrator\n",{"type":18,"tag":318,"props":570,"children":571},{"class":320,"line":393},[572,576],{"type":18,"tag":318,"props":573,"children":574},{"style":325},[575],{"type":23,"value":399},{"type":18,"tag":318,"props":577,"children":578},{"style":331},[579],{"type":23,"value":372},{"type":18,"tag":318,"props":581,"children":582},{"class":320,"line":406},[583,588],{"type":18,"tag":318,"props":584,"children":585},{"style":325},[586],{"type":23,"value":587},"  containers",{"type":18,"tag":318,"props":589,"children":590},{"style":331},[591],{"type":23,"value":372},{"type":18,"tag":318,"props":593,"children":594},{"class":320,"line":419},[595,599,604,608],{"type":18,"tag":318,"props":596,"children":597},{"style":331},[598],{"type":23,"value":425},{"type":18,"tag":318,"props":600,"children":601},{"style":325},[602],{"type":23,"value":603}," name",{"type":18,"tag":318,"props":605,"children":606},{"style":331},[607],{"type":23,"value":334},{"type":18,"tag":318,"props":609,"children":610},{"style":337},[611],{"type":23,"value":612}," migrator\n",{"type":18,"tag":318,"props":614,"children":615},{"class":320,"line":433},[616,621,625],{"type":18,"tag":318,"props":617,"children":618},{"style":325},[619],{"type":23,"value":620},"      image",{"type":18,"tag":318,"props":622,"children":623},{"style":331},[624],{"type":23,"value":334},{"type":18,"tag":318,"props":626,"children":627},{"style":337},[628],{"type":23,"value":629}," ubuntu:22.04\n",{"type":18,"tag":318,"props":631,"children":632},{"class":320,"line":446},[633,638,642,647,652,657,661,666,671,676,680,684,688,693,697],{"type":18,"tag":318,"props":634,"children":635},{"style":325},[636],{"type":23,"value":637},"      command",{"type":18,"tag":318,"props":639,"children":640},{"style":331},[641],{"type":23,"value":334},{"type":18,"tag":318,"props":643,"children":644},{"style":331},[645],{"type":23,"value":646}," [",{"type":18,"tag":318,"props":648,"children":649},{"style":331},[650],{"type":23,"value":651},"\"",{"type":18,"tag":318,"props":653,"children":654},{"style":337},[655],{"type":23,"value":656},"/bin/bash",{"type":18,"tag":318,"props":658,"children":659},{"style":331},[660],{"type":23,"value":651},{"type":18,"tag":318,"props":662,"children":663},{"style":331},[664],{"type":23,"value":665},",",{"type":18,"tag":318,"props":667,"children":668},{"style":331},[669],{"type":23,"value":670}," \"",{"type":18,"tag":318,"props":672,"children":673},{"style":337},[674],{"type":23,"value":675},"-c",{"type":18,"tag":318,"props":677,"children":678},{"style":331},[679],{"type":23,"value":651},{"type":18,"tag":318,"props":681,"children":682},{"style":331},[683],{"type":23,"value":665},{"type":18,"tag":318,"props":685,"children":686},{"style":331},[687],{"type":23,"value":670},{"type":18,"tag":318,"props":689,"children":690},{"style":337},[691],{"type":23,"value":692},"sleep infinity",{"type":18,"tag":318,"props":694,"children":695},{"style":331},[696],{"type":23,"value":651},{"type":18,"tag":318,"props":698,"children":699},{"style":331},[700],{"type":23,"value":701},"]\n",{"type":18,"tag":318,"props":703,"children":704},{"class":320,"line":459},[705,710],{"type":18,"tag":318,"props":706,"children":707},{"style":325},[708],{"type":23,"value":709},"      volumeMounts",{"type":18,"tag":318,"props":711,"children":712},{"style":331},[713],{"type":23,"value":372},{"type":18,"tag":318,"props":715,"children":716},{"class":320,"line":477},[717,722,726,730],{"type":18,"tag":318,"props":718,"children":719},{"style":331},[720],{"type":23,"value":721},"        -",{"type":18,"tag":318,"props":723,"children":724},{"style":325},[725],{"type":23,"value":603},{"type":18,"tag":318,"props":727,"children":728},{"style":331},[729],{"type":23,"value":334},{"type":18,"tag":318,"props":731,"children":732},{"style":337},[733],{"type":23,"value":734}," old-pvc\n",{"type":18,"tag":318,"props":736,"children":738},{"class":320,"line":737},12,[739,744,748],{"type":18,"tag":318,"props":740,"children":741},{"style":325},[742],{"type":23,"value":743},"          mountPath",{"type":18,"tag":318,"props":745,"children":746},{"style":331},[747],{"type":23,"value":334},{"type":18,"tag":318,"props":749,"children":750},{"style":337},[751],{"type":23,"value":752}," /mnt/old\n",{"type":18,"tag":318,"props":754,"children":756},{"class":320,"line":755},13,[757,761,765,769],{"type":18,"tag":318,"props":758,"children":759},{"style":331},[760],{"type":23,"value":721},{"type":18,"tag":318,"props":762,"children":763},{"style":325},[764],{"type":23,"value":603},{"type":18,"tag":318,"props":766,"children":767},{"style":331},[768],{"type":23,"value":334},{"type":18,"tag":318,"props":770,"children":771},{"style":337},[772],{"type":23,"value":773}," new-pvc\n",{"type":18,"tag":318,"props":775,"children":777},{"class":320,"line":776},14,[778,782,786],{"type":18,"tag":318,"props":779,"children":780},{"style":325},[781],{"type":23,"value":743},{"type":18,"tag":318,"props":783,"children":784},{"style":331},[785],{"type":23,"value":334},{"type":18,"tag":318,"props":787,"children":788},{"style":337},[789],{"type":23,"value":790}," /mnt/new\n",{"type":18,"tag":318,"props":792,"children":794},{"class":320,"line":793},15,[795,800],{"type":18,"tag":318,"props":796,"children":797},{"style":325},[798],{"type":23,"value":799},"  volumes",{"type":18,"tag":318,"props":801,"children":802},{"style":331},[803],{"type":23,"value":372},{"type":18,"tag":318,"props":805,"children":807},{"class":320,"line":806},16,[808,812,816,820],{"type":18,"tag":318,"props":809,"children":810},{"style":331},[811],{"type":23,"value":425},{"type":18,"tag":318,"props":813,"children":814},{"style":325},[815],{"type":23,"value":603},{"type":18,"tag":318,"props":817,"children":818},{"style":331},[819],{"type":23,"value":334},{"type":18,"tag":318,"props":821,"children":822},{"style":337},[823],{"type":23,"value":734},{"type":18,"tag":318,"props":825,"children":827},{"class":320,"line":826},17,[828,833],{"type":18,"tag":318,"props":829,"children":830},{"style":325},[831],{"type":23,"value":832},"      persistentVolumeClaim",{"type":18,"tag":318,"props":834,"children":835},{"style":331},[836],{"type":23,"value":372},{"type":18,"tag":318,"props":838,"children":840},{"class":320,"line":839},18,[841,846,850],{"type":18,"tag":318,"props":842,"children":843},{"style":325},[844],{"type":23,"value":845},"        claimName",{"type":18,"tag":318,"props":847,"children":848},{"style":331},[849],{"type":23,"value":334},{"type":18,"tag":318,"props":851,"children":852},{"style":337},[853],{"type":23,"value":854}," tautulli-data\n",{"type":18,"tag":318,"props":856,"children":858},{"class":320,"line":857},19,[859,863,867,871],{"type":18,"tag":318,"props":860,"children":861},{"style":331},[862],{"type":23,"value":425},{"type":18,"tag":318,"props":864,"children":865},{"style":325},[866],{"type":23,"value":603},{"type":18,"tag":318,"props":868,"children":869},{"style":331},[870],{"type":23,"value":334},{"type":18,"tag":318,"props":872,"children":873},{"style":337},[874],{"type":23,"value":773},{"type":18,"tag":318,"props":876,"children":878},{"class":320,"line":877},20,[879,883],{"type":18,"tag":318,"props":880,"children":881},{"style":325},[882],{"type":23,"value":832},{"type":18,"tag":318,"props":884,"children":885},{"style":331},[886],{"type":23,"value":372},{"type":18,"tag":318,"props":888,"children":890},{"class":320,"line":889},21,[891,895,899],{"type":18,"tag":318,"props":892,"children":893},{"style":325},[894],{"type":23,"value":845},{"type":18,"tag":318,"props":896,"children":897},{"style":331},[898],{"type":23,"value":334},{"type":18,"tag":318,"props":900,"children":901},{"style":337},[902],{"type":23,"value":390},{"type":18,"tag":318,"props":904,"children":906},{"class":320,"line":905},22,[907,912,916],{"type":18,"tag":318,"props":908,"children":909},{"style":325},[910],{"type":23,"value":911},"  restartPolicy",{"type":18,"tag":318,"props":913,"children":914},{"style":331},[915],{"type":23,"value":334},{"type":18,"tag":318,"props":917,"children":918},{"style":337},[919],{"type":23,"value":920}," Never\n",{"type":18,"tag":19,"props":922,"children":923},{},[924],{"type":23,"value":925},"Then I connected to it:",{"type":18,"tag":308,"props":927,"children":931},{"className":928,"code":929,"language":930,"meta":7,"style":7},"language-bash shiki shiki-themes material-theme-lighter material-theme-palenight","kubectl exec -it pvc-migrator -- bash\n","bash",[932],{"type":18,"tag":33,"props":933,"children":934},{"__ignoreMap":7},[935],{"type":18,"tag":318,"props":936,"children":937},{"class":320,"line":321},[938,944],{"type":18,"tag":318,"props":939,"children":941},{"style":940},"--shiki-default:#E2931D;--shiki-dark:#FFCB6B",[942],{"type":23,"value":943},"kubectl",{"type":18,"tag":318,"props":945,"children":946},{"style":337},[947],{"type":23,"value":948}," exec -it pvc-migrator -- bash\n",{"type":18,"tag":19,"props":950,"children":951},{},[952],{"type":23,"value":953},"And inside the container, I ran:",{"type":18,"tag":308,"props":955,"children":957},{"className":928,"code":956,"language":930,"meta":7,"style":7},"rsync -a /mnt/old/ /mnt/new/\n",[958],{"type":18,"tag":33,"props":959,"children":960},{"__ignoreMap":7},[961],{"type":18,"tag":318,"props":962,"children":963},{"class":320,"line":321},[964,968,973],{"type":18,"tag":318,"props":965,"children":966},{"style":940},[967],{"type":23,"value":250},{"type":18,"tag":318,"props":969,"children":970},{"style":337},[971],{"type":23,"value":972}," -a",{"type":18,"tag":318,"props":974,"children":975},{"style":337},[976],{"type":23,"value":977}," /mnt/old/ /mnt/new/\n",{"type":18,"tag":19,"props":979,"children":980},{},[981],{"type":23,"value":982},"This preserved file permissions, symlinks, and ownership during the migration.",{"type":18,"tag":296,"props":984,"children":986},{"id":985},"step-3-point-tautulli-to-the-new-pvc",[987],{"type":23,"value":988},"Step 3: Point Tautulli to the New PVC",{"type":18,"tag":19,"props":990,"children":991},{},[992,994,1000,1002,1008,1010,1016],{"type":23,"value":993},"After confirming the data was in place, I updated the Deployment to use ",{"type":18,"tag":33,"props":995,"children":997},{"className":996},[],[998],{"type":23,"value":999},"tautulli-cephfs",{"type":23,"value":1001}," instead of ",{"type":18,"tag":33,"props":1003,"children":1005},{"className":1004},[],[1006],{"type":23,"value":1007},"tautulli-data",{"type":23,"value":1009},". In my case, this meant updating the ",{"type":18,"tag":33,"props":1011,"children":1013},{"className":1012},[],[1014],{"type":23,"value":1015},"persistence.volumeClaimName",{"type":23,"value":1017}," inside my Helm values and pushing that change through ArgoCD.",{"type":18,"tag":296,"props":1019,"children":1021},{"id":1020},"step-4-cleanup",[1022],{"type":23,"value":1023},"Step 4: Cleanup",{"type":18,"tag":19,"props":1025,"children":1026},{},[1027],{"type":23,"value":1028},"Once I verified everything was working as expected, I deleted the migration pod:",{"type":18,"tag":308,"props":1030,"children":1032},{"className":928,"code":1031,"language":930,"meta":7,"style":7},"kubectl delete pod pvc-migrator\n",[1033],{"type":18,"tag":33,"props":1034,"children":1035},{"__ignoreMap":7},[1036],{"type":18,"tag":318,"props":1037,"children":1038},{"class":320,"line":321},[1039,1043],{"type":18,"tag":318,"props":1040,"children":1041},{"style":940},[1042],{"type":23,"value":943},{"type":18,"tag":318,"props":1044,"children":1045},{"style":337},[1046],{"type":23,"value":1047}," delete pod pvc-migrator\n",{"type":18,"tag":19,"props":1049,"children":1050},{},[1051],{"type":23,"value":1052},"Then I cleaned up the old PVC and its corresponding Proxmox disk.",{"type":18,"tag":133,"props":1054,"children":1056},{"id":1055},"a-gotcha-volume-already-bound-to-a-different-claim",[1057],{"type":23,"value":1058},"A Gotcha: “Volume already bound to a different claim”",{"type":18,"tag":19,"props":1060,"children":1061},{},[1062],{"type":23,"value":1063},"At one point, I accidentally deleted a PVC without deleting its associated PV. When I tried to recreate it, I got this error:",{"type":18,"tag":1065,"props":1066,"children":1067},"blockquote",{},[1068],{"type":18,"tag":19,"props":1069,"children":1070},{},[1071],{"type":23,"value":1072},"volume \"pv-tautulli\" already bound to a different claim",{"type":18,"tag":19,"props":1074,"children":1075},{},[1076],{"type":23,"value":1077},"The fix: manually edit the PV and update the UID for the claim to the UID on the PVC, like so:",{"type":18,"tag":308,"props":1079,"children":1081},{"className":928,"code":1080,"language":930,"meta":7,"style":7},"kubectl edit pv pv-tautulli\n",[1082],{"type":18,"tag":33,"props":1083,"children":1084},{"__ignoreMap":7},[1085],{"type":18,"tag":318,"props":1086,"children":1087},{"class":320,"line":321},[1088,1092],{"type":18,"tag":318,"props":1089,"children":1090},{"style":940},[1091],{"type":23,"value":943},{"type":18,"tag":318,"props":1093,"children":1094},{"style":337},[1095],{"type":23,"value":1096}," edit pv pv-tautulli\n",{"type":18,"tag":19,"props":1098,"children":1099},{},[1100],{"type":23,"value":1101},"Then delete or reapply your PVC. Problem solved.",{"type":18,"tag":19,"props":1103,"children":1104},{},[1105],{"type":23,"value":1106},"The only small thing I'll note here that was different for me - instead of applying and deleting the pods manually, I continued to push them through git and used ArgoCD to sync the changes. I did this mostly for historical purposes and so I could remember how I did the full process and in what order, but either process works great for this purpose.",{"type":18,"tag":133,"props":1108,"children":1110},{"id":1109},"conclusion",[1111],{"type":23,"value":1112},"Conclusion",{"type":18,"tag":19,"props":1114,"children":1115},{},[1116,1118,1123,1125,1130],{"type":23,"value":1117},"Migrating from ",{"type":18,"tag":33,"props":1119,"children":1121},{"className":1120},[],[1122],{"type":23,"value":38},{"type":23,"value":1124}," to ",{"type":18,"tag":33,"props":1126,"children":1128},{"className":1127},[],[1129],{"type":23,"value":110},{"type":23,"value":1131}," has been a surprisingly smooth process once I nailed down this pattern. Using a simple data-copy pod made it safe and predictable, and CephFS has been a huge upgrade in flexibility.",{"type":18,"tag":19,"props":1133,"children":1134},{},[1135],{"type":23,"value":1136},"I still have a few more workloads to migrate, but so far I’m really happy with how this is turning out.",{"type":18,"tag":19,"props":1138,"children":1139},{},[1140],{"type":23,"value":1141},"If you’re managing your own Proxmox + Kubernetes setup and want more modern storage workflows, I definitely recommend giving CephFS a look.",{"type":18,"tag":19,"props":1143,"children":1144},{},[1145,1147,1154,1156,1163,1165,1172],{"type":23,"value":1146},"You can follow my ongoing homelab experiments on ",{"type":18,"tag":26,"props":1148,"children":1151},{"href":1149,"rel":1150},"https://github.com/calebsmithdev",[30],[1152],{"type":23,"value":1153},"GitHub",{"type":23,"value":1155},", or keep an eye on ",{"type":18,"tag":26,"props":1157,"children":1160},{"href":1158,"rel":1159},"https://github.com/calebsmithdev/personal-site-nuxt",[30],[1161],{"type":23,"value":1162},"my blog repo",{"type":23,"value":1164}," for future updates. I'm publishing all my blog posts in Markdown using ",{"type":18,"tag":26,"props":1166,"children":1169},{"href":1167,"rel":1168},"https://content.nuxt.com/",[30],[1170],{"type":23,"value":1171},"Nuxt Content",{"type":23,"value":1173},", so feel free to browse the source as well.",{"type":18,"tag":1175,"props":1176,"children":1177},"style",{},[1178],{"type":23,"value":1179},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":7,"searchDepth":343,"depth":343,"links":1181},[1182,1183,1184,1190,1191],{"id":135,"depth":343,"text":138},{"id":199,"depth":343,"text":202},{"id":270,"depth":343,"text":273,"children":1185},[1186,1187,1188,1189],{"id":298,"depth":361,"text":301},{"id":495,"depth":361,"text":498},{"id":985,"depth":361,"text":988},{"id":1020,"depth":361,"text":1023},{"id":1055,"depth":343,"text":1058},{"id":1109,"depth":343,"text":1112},"markdown","content:blog:migrating-kubernetes-pvcs-from-csi-proxmox-to-csi-cephfs.md","content","blog/migrating-kubernetes-pvcs-from-csi-proxmox-to-csi-cephfs.md","md",1784603432889]