urn:noticeable:projects:bYyIewUV308AvkMztxixSherlock changelogwww.sherlock.stanford.edu2024-02-08T00:29:40.623ZCopyright © SherlockNoticeablehttps://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/newspages/GtmOI32wuOUPBTrHaeki/01h55ta3gs1vmdhtqqtjmk7m4z-header-logo.pnghttps://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/newspages/GtmOI32wuOUPBTrHaeki/01h55ta3gs1vmdhtqqtjmk7m4z-header-logo.png#8c1515urn:noticeable:publications:VKxO5IXJlMStQurJnpwv2024-02-07T23:49:24.699Z2024-02-08T00:29:40.623ZSherlock goes full flashWhat could be more frustrating than anxiously waiting for your computing job to finish? Slow I/O that makes it take even longer is certainly high on the list. But not anymore! Fir, Sherlock’s scratch file system, has just undergone a major<p>What could be more frustrating than anxiously waiting for your computing job to finish? Slow I/O that makes it take even longer is certainly high on the list. But not anymore! <a href="https://news.sherlock.stanford.edu/publications/a-new-scratch?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Fir"><strong>Fir</strong></a><strong>,</strong> <strong>Sherlock’s scratch file system, has just undergone a major tech face-lift: it’s now</strong> <strong>a 10 PB all-flash storage system, providing an aggregate bandwidth of</strong> <strong>400 GB/sec</strong> (and &gt;800 kIOPS). Bringing Sherlock’s high-performance parallel scratch file system into the era of flash storage was not just a routine maintenance task, but a significant leap into the future of HPC and AI computing.</p><h2>But first, a little bit of context </h2><p>Traditionally, High-Performance Computing clusters face a challenge when dealing with modern, data-intensive applications. Existing HPC storage systems, long designed with spinning disks to provide efficient and parallel sequential read/write operations, often become bottlenecks for modern workloads generated by AI/ML or CryoEM applications. Those demand substantial data storage and processing capabilities, putting a strain on traditional systems.</p><p>So to accommodate those new needs and future evolution of the HPC I/O landscape, we at Stanford Research Computing, with the generous support of the <a href="https://doresearch.stanford.edu/who-we-are/office-vice-provost-and-dean-research?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Office of the Stanford VPDoR">Vice Provost and Dean of Research</a>, have been hard at work for over two years, revamping Sherlock's scratch with an all-flash system. </p><p>And it was not just a matter of taking delivery of a new turn-key system. As most things we do, it was done entirely in-house: from the original vendor-agnostic design, upgrade plan, budget requests, procurement, gradual in-place hardware replacement at the Stanford Research Computing Facility (SRCF), deployment and validation, performance benchmarks, to the final production stages, all of those steps were performed with minimum disruption for all Sherlock users.</p><h2>The technical details</h2><p>The <code>/scratch</code> file system on Sherlock is using <a href="https://wiki.lustre.org/?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Lustre">Lustre</a>, an open-source, parallel file system that supports many requirements of leadership class HPC environments. And as you probably know by now, Stanford Research Computing loves <a href="https://github.com/stanford-rc?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="open source">open source</a>! We actively contribute to the Lustre community and are a proud member of <a href="https://opensfs.org/?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="OpenSFS">OpenSFS</a>, a non-profit industry organization that supports vendor-neutral development and promotion of Lustre.</p><p>In Lustre, file metadata and data are stored separately, with Object Storage Servers (OSS) serving file data on the network. Each OSS pair and associated storage devices forms an I/O cell, and Sherlock's scratch has just bid farewell to its old HDD-based I/O cells. In their place, new flash-based I/O cells have taken the stage, each equipped with 96 x 15.35TB SSDs, delivering mind-blowing performance.</p><p>Sherlock’s <code>/scratch</code> has 8 I/O cells and the goal was to replace every one of them. Our new I/O cell has 2 OSS with Infiniband HDR at 200Gb/s (or 25GB/s) connected to 4 storage chassis, each with 24 x 15.35TB SSD (dual-attached 12Gb/s SAS), as pictured below:</p><p><span style="color: #000000;"></span></p><figure><img src="https://lh7-us.googleusercontent.com/gI-D9jEmQeMntz4clh3TNYF60Q6Xep5cMcwQqHL3TGX_9H7L0m_6MgjDlPfSQrUtSBsh5l9bVa8Nddamm4BHzsQwk1S5Q5s9Wq_i8wdGGcXXnOD5wW_kqTJDQXjdwGEb7VYN1gSNPHccCYBc9iEzgTM" alt="" height="284" loading="lazy" title="" width="562"></figure><br><br>Of course, you can’t just replace each individual rotating hard-drive with a SSD, there are some infrastructure changes required, and some reconfiguration needed. The upgrade, executed between January 2023 and January 2024, was a seamless transition. Old HDD-based I/O cells were gracefully retired, one by one, while flash-based ones progressively replaced them, gradually boosting performance for all Sherlock users throughout the year.<br><span style="color: #000000;"><figure><img src="https://lh7-us.googleusercontent.com/B7lwfOxhKxKc-kDeQZkZ63exdm99PnDvete7-03-wD3906KQ_BaUOAGpzuNRa1nrZ_UdcCz_XcPusFZGA60zH6xWSMR60WDz-C6q-qg2BetwYGf1Ytpevnr0Hg5cN9kVPnEVRkeRRfqJBXje3AvmAXo" alt="" height="332" loading="lazy" title="" width="472"></figure></span><br>All of those replacements happened while the file system was up and running, serving data to the thousands of computing jobs that run on Sherlock every day. Driven by our commitment to minimize disruptions to users, our top priority was to ensure uninterrupted access to data throughout the upgrade. Data migration is never fun, and we wanted to avoid having to ask users to manually transfer their files to a new, separate storage system. This is why we developed and <a href="https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commit;h=1121816c4a4e1bb2ef097c4a9802362181c43800&amp;utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="del_ost commit">contributed</a> a new feature in Lustre, which allowed us to seamlessly remove existing storage devices from the file system, before the new flash drives could be added. More technical details about the upgrade have been <a href="http://www.eofs.eu/wp-content/uploads/2024/02/2.5-stanfordrc_s_thiell.pdf?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="presentation slides">presented</a> during the <a href="https://www.eofs.eu/index.php/events/lad-22/?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="LAD'22">LAD’22</a> conference.<p></p><p><strong>Today, we are happy to announce that the upgrade is officially complete, and Sherlock stands proud with a whopping 9,824 TB of solid-state storage in production. No more spinning disks in sight!</strong></p><h2>Key benefits</h2><p>For users, the immediately visible benefits are quicker access to their files, faster data transfers, shorter job execution times for I/O intensive applications. More specifically, every key metric has been improved:</p><ul><li><p>IOPS: over <strong>100x</strong> (results may vary, see below)</p></li><li><p>Backend bandwidth: <strong>6x</strong> (128 GB/s to 768 GB/s)</p></li><li><p>Frontend bandwidth: <strong>2x</strong> (200 GB/s to 400 GB/s)</p></li><li><p>Usable volume: <strong>1.6x</strong> (6.1 PB to 9.8 PB)<br></p></li></ul><p>In terms of measured improvement, the graph below shows the impact of moving to full-flash storage for reading data from 1, 8 and 16 compute nodes, compared to the previous <code>/scratch</code> file system: </p><p><span style="color: #000000;"></span></p><figure><img src="https://lh7-us.googleusercontent.com/a1wBmS1DW--_SfmLz5iyYRChlTp8MSuE7VKNKinX2nBgzb6iRiNeiSqa5zuXQrTvN1YztMqTLBVPdc_gqA1lrqOpQh7ZA1FzsNdS4VToP_okzXIhbWdzS2rWtUD33joDAaFV4m7eSMQp6DB8se6PY_Y" alt="" height="387" loading="lazy" title="" width="624"></figure><p></p><p>And we even tried to replicate the I/O patterns of <a href="https://github.com/google-deepmind/alphafold?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-goes-full-flash&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VKxO5IXJlMStQurJnpwv&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="AlphaFold">AlphaFold</a>, a well-known AI model to predict protein structure, and the benefits are quite significant, with up to 125x speedups in some cases:</p><p><span style="color: #000000;"></span></p><figure><img src="https://lh7-us.googleusercontent.com/4qvJD4MDJwjdlyKLcE4F24ZaaqanbQHjS1CkxPVWvzBKHphgLLAfa0QoepWrbOYOtwLFnYLrwLHTyS1NatKDItsDI63mlC1mxhac6RSFKSHCLyiEOykLBnHw7ziqM5uQ0VTVmmLd5BPPJpNF6bNUN70" alt="" height="335" loading="lazy" title="" width="624"></figure><br><br>This upgrade is a major improvement that will benefit all Sherlock users, and Sherlock’s enhanced I/O capabilities will allow them to approach data-intensive tasks with unprecedented efficiency. We hope it will help support the ever-increasing computing needs of the Stanford research community, and enable even more breakthroughs and discoveries. <p></p><p>As usual, if you have any question or comment, please don’t hesitate to reach out to Research Computing at <a href="mailto:[email protected]" rel="noopener nofollow" target="_blank" title="[email protected]">[email protected]</a>. 🚀🔧<br><br></p>Stéphane Thiell & Kilian Cavalotti[email protected]urn:noticeable:publications:P3xY1hwDWMe8tR48vPEj2021-02-05T18:20:00Z2021-02-05T20:10:21.673ZTracking NFS problems down to the SFP levelWhen NFS problems turn out to be... not NFS problems at all.<blockquote><p><em>This is part of our </em><a href="https://news.sherlock.stanford.edu/labels/blog?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Sherlock blog series">technical blog series</a><em> about things that happen behind-the-scenes on Sherlock, and which are part of our ongoing effort to keep it up and running in the best possible conditions for our beloved users.</em></p></blockquote><p><strong>For quite a long time, we've been chasing down an annoying </strong><a href="https://en.wikipedia.org/wiki/Network_File_System?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="NFS"><strong>NFS</strong></a><strong> timeout issue that seemed to only affect </strong><a href="https://news.sherlock.stanford.edu/posts/sherlock-3-0-is-here?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Sherlock 3.0"><strong>Sherlock 3.0</strong></a><strong> nodes.</strong></p><p>That issue would impact both login and compute nodes, both NFSv4 user mounts (like <code><a href="https://www.sherlock.stanford.edu/docs/storage/filesystems/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage#home" rel="noopener nofollow" target="_blank" title="$HOME">$HOME</a></code> and <code><a href="https://www.sherlock.stanford.edu/docs/storage/filesystems/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage#group_home" rel="noopener nofollow" target="_blank" title="$GROUP_HOME">$GROUP_HOME</a></code>) and NFSv3 system-level mounts (like the one providing <a href="https://www.sherlock.stanford.edu/docs/software/list/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="software">software installations</a>), and occur at random times, on random nodes. It was not widespread enough to be causing real damage, but from time to time, a NFS mount would hang and block I/O for a job, or freeze a login session. When that happened, the node would still be able to ping all of the NFS servers' IP addresses, even remount the same NFS file system with the exact same options in another mount point, and no discernable network issue was apparent on the nodes. Sometimes, the stuck mounts would come back to life on their own, sometimes they would stay hanging forever.</p><h2>Is it load? Is it the kernel? Is it the CPU?</h2><p>It kind of looked like it could be correlated with <a href="https://en.wikipedia.org/wiki/Load_(computing)?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="load">load</a>, and mostly appear when multiple jobs were doing NFS I/O on a given node, but we never found conclusive proof that it was the case. The only distinguishable element was that the issue was only observed on Sherlock 3.0 nodes and never affected older Sherlock 1.0/2.0 nodes. So we started suspecting something about the kernel NFS client, maybe some oddity with AMD Rome CPUs: after all, they were all quite new, and the nodes had many more cores than the previous generation. So maybe they had more trouble handling the parallel operations, ended up with a deadlock or something.</p><p>But still, all the Sherlock nodes are using the same kernel, and only the Sherlock 3.0 nodes were affected, so it appeared unlikely to be a kernel issue. </p><h2>The NFS servers maybe?</h2><p>We then started looking at the NFS servers. Last December’s maintenance was actually an attempt at resolving those timeout issues, even though it proved fruitless in that aspect. We got in touch with vendor support to explore possible explanations, but nothing came out of it and our support case went nowhere. Plus, if the NFS servers were at fault, it would likely have affected all Sherlock nodes, not just a subset.</p><h2>It’s the NFS client parameters! Or is it?</h2><p>So back to the NFS client, we've started looking at the NFS client mount parameters. The <a href="https://www.google.com/search?q=nfs+timeout&amp;&amp;utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">petazillion web hits</a> about "nfs timeout" didn't really help in that matter, but in the process we found pretty interesting <a href="https://lore.kernel.org/linux-nfs/[email protected]/T/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">discussions</a> about read/write sizes and read-ahead. We tried tweaking all of those parameters left and right, deployed various configs on the compute nodes (A/B testing FTW!), but the timeout still happened.</p><h2>The lead</h2><p>In the end, what gave us a promising lead was an <a href="https://blog.noc.grnet.gr/2018/08/29/a-performance-story-how-a-faulty-qsfp-crippled-a-whole-ceph-cluster/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">article</a> found on the <a href="https://grnet.gr/en/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">GRNET</a> <a href="https://blog.noc.grnet.gr/?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">blog</a> that explain how the authors tracked down a defective <a href="https://en.wikipedia.org/wiki/Small_form-factor_pluggable_transceiver?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="QSFP">QSFP</a> that was causing issues in their <a href="https://en.wikipedia.org/wiki/Ceph_(software)?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="Ceph">Ceph</a> cluster. Well, it didn't take long to realize that there was a similar issue between those Sherlock nodes and the NFS servers. Packet loss was definitely involved.</p><p>The tricky part, as described in the blog post, is that the packet loss only manifested itself when using large <a href="https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">ICMP</a> packets, close to the <a href="https://en.wikipedia.org/wiki/Maximum_transmission_unit?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank">MTU</a> upper limit. When using regular packet size, no problem was apparent.</p><p>For instance, this regular ping didn't show any loss:</p><pre><code># ping -c 50 10.16.90.1 | grep loss 50 packets transmitted, 50 received, 0% packet loss, time 538ms</code></pre><p>But when cranking up the packet size:</p><pre><code># ping -s 8972 -c 50 10.16.90.1 | grep loss 50 packets transmitted, 36 received, 28% packet loss, time 539ms</code></pre><p>What was even funnier is that not all Sherlock 3.0 nodes were experiencing loss to the same NFS server nodes. For instance, from one client node , there was packet loss to just one of the NFS servers:</p><pre><code>client1# clush -Lw 10.16.90.[1-8] --worker=exec ping -s 8972 -M do -c 10 -q %h | grep loss 10.16.90.1: 10 packets transmitted, 10 received, 0% packet loss, time 195ms 10.16.90.2: 10 packets transmitted, 8 received, 20% packet loss, time 260ms 10.16.90.3: 10 packets transmitted, 10 received, 0% packet loss, time 193ms 10.16.90.4: 10 packets transmitted, 10 received, 0% packet loss, time 260ms 10.16.90.5: 10 packets transmitted, 10 received, 0% packet loss, time 200ms 10.16.90.6: 10 packets transmitted, 10 received, 0% packet loss, time 264ms 10.16.90.7: 10 packets transmitted, 10 received, 0% packet loss, time 196ms 10.16.90.8: 10 packets transmitted, 10 received, 0% packet loss, time 194ms</code></pre><p>But from another client, sitting right next to it, no loss to that server , but packets dropped to another one instead:</p><pre><code>client2# clush -Lw 10.16.90.[1-8] --worker=exec ping -s 8972 -M do -c 10 -q %h | grep loss 10.16.90.1: 10 packets transmitted, 8 received, 20% packet loss, time 190ms 10.16.90.2: 10 packets transmitted, 10 received, 0% packet loss, time 198ms 10.16.90.3: 10 packets transmitted, 10 received, 0% packet loss, time 210ms 10.16.90.4: 10 packets transmitted, 10 received, 0% packet loss, time 197ms 10.16.90.5: 10 packets transmitted, 10 received, 0% packet loss, time 196ms 10.16.90.6: 10 packets transmitted, 10 received, 0% packet loss, time 243ms 10.16.90.7: 10 packets transmitted, 10 received, 0% packet loss, time 201ms 10.16.90.8: 10 packets transmitted, 10 received, 0% packet loss, time 213ms</code></pre><h2>The link</h2><p>That all started to sound like a faulty stack link, or a a problem in one of the <a href="https://en.wikipedia.org/wiki/Link_aggregation?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage#Link_Aggregation_Control_Protocol" rel="noopener nofollow" target="_blank" title="LACP">LACP</a> links between the different switch stacks (Sherlock's and the NFS servers’). We didn't find anything obviously out-of-place in reviewing the switches configuration, so we went back to the switches’ documentation to try to understand how to check counters and identify bad links (which gave us the opportunity to mumble about documentation that is not in sync with actual commands, but that’s another topic...).</p><p>So we dumped the hardware counters for each link involved in the NFS connections, and on a switch, on the NFS client’s side, there was this:</p><pre><code>te1/45 Ingress FCSDrops : 0 te1/46 Ingress FCSDrops : 0 te2-45 Ingress FCSDrops : 0 te2-46 Ingress FCSDrops : 0 te3-45 Ingress FCSDrops : 0 te3-46 Ingress FCSDrops : 1064263014 te4-45 Ingress FCSDrops : 0 te4-46 Ingress FCSDrops : 0</code></pre><p>Something standing out, maybe?</p><p>In more details:</p><pre><code>#show interfaces te3/46 TenGigabitEthernet 3/46 is up, line protocol is up Port is part of Port-channel 98 [...] Input Statistics: 18533249104 packets, 35813681434965 bytes [...] 1064299255 CRC, 0 overrun, 0 discarded</code></pre><p>The CRC number indicates the number of CRC <em>failures</em>, packets which failed checksum validation. All the other ports on the switch were at 0. So clearly something was off with that port. </p><h2>The culprit: a faulty SFP!</h2><p>We decided to try to shut that port down (after all, it's just 1 port out of a 8-port LACP link), and immediately, all the packet loss disappeared.</p><p>So we replaced the the optical transceiver in that port, hoping that swapping that SFP would resolve the CRC failure problem. After re-enabling the link, the number of dropped packets seemed to have decreased. But not totally disappear…</p><h2>The <em>real</em> culprit: the <em>other</em> SFP</h2><p>Thinking a little more about it, since the errors were actually <strong>Ingress</strong> FCSDrops on the switch, it didn’t seem completely unreasonable to consider that those frames were received by the switch already corrupted, and thus, that they would have been mangled by either the transceiver on the other end of the link, or maybe in-flight by a damaged cable. So maybe we’ve been pointing fingers at a SFP, and maybe it was innocent… 😁<br><br>We checked the switch’s port on the NFS server’s side, and the checksum errors and drop counts were all at 0. We replaced that SFP anyway, just to see, and this time, bingo: no more CRC errors on the other side. </p><p>Which lead us to the following decision tree:</p><ul><li><p>if a port has RX/receiving/ingress errors, it’s probably <strong>not</strong> its fault, and the issue is most likely with its peer at the other end of the link,</p></li><li><p>if a port has TX/transmitting/egress errors, it’s probably the source of the problem,</p></li><li><p>if both ports at each end of a given link have errors, the cable is probably at fault.</p></li></ul><p>By the way, if you’re wondering, here’s what a SFP looks like:<br></p><figure><img src="https://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/publications/P3xY1hwDWMe8tR48vPEj/01h55ta3gs1drsabkq2fschedq-image.jpg" alt="" loading="lazy" title=""></figure><p></p><h1>TL;DR</h1><p><strong>We had seemingly random NFS timeout issues. They turned out to be caused by a defective SFP, that was eventually identified through the port error counter of the switch at the other end of the link.</strong></p><p>There's probably a lesson to be learned here, and we were almost disappointed that DNS was not involved (because <a href="https://isitdns.com?utm_source=noticeable&amp;utm_campaign=sherlock.tracking-nfs-problems-down-to-the-sfp-level&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.P3xY1hwDWMe8tR48vPEj&amp;utm_medium=newspage" rel="noopener nofollow" target="_blank" title="it's always DNS">it's always DNS</a>), but in the end, we were glad to finally find a rational explanation to those timeouts. And since that SFP replacement, not a single NFS timeout has been logged.<br><br></p>Kilian Cavalotti[email protected]urn:noticeable:publications:PPxLNPT4SMCJbp0ORhd72020-11-13T00:12:00.001Z2020-11-13T02:45:02.640ZSherlock factsEver wondered how many compute nodes is Sherlock made of? Or how many users are using it? Or how many Infiniband cables link it all together? Well, wonder no more: head to the Sherlock facts page and see for yourself! > hint: there are...<p>Ever wondered how many compute nodes is Sherlock made of? Or how many users are using it? Or how many Infiniband cables link it all together?</p> <p>Well, wonder no more: head to the <a href="https://www.sherlock.stanford.edu/docs/overview/tech/facts?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-facts&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.PPxLNPT4SMCJbp0ORhd7&amp;utm_medium=newspage" target="_blank" rel="noopener">Sherlock facts</a> page and see for yourself!</p> <blockquote> <p><em>hint</em>: there are <strong>a lot</strong> of cables :)</p> </blockquote> <p>And if you’re tired of seeing the some old specs from two years ago, we’ve updated the <a href="https://www.sherlock.stanford.edu/docs/overview/tech/specs?utm_source=noticeable&amp;utm_campaign=sherlock.sherlock-facts&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.PPxLNPT4SMCJbp0ORhd7&amp;utm_medium=newspage" target="_blank" rel="noopener">Sherlock tech specs</a> page too!</p> <p>To make sure those numbers never fall behind again and continue to offer an accurate representation of Sherlock’s resources, they will be automatically be updated each time something changes on the cluster.</p> <p>As usual, don’t hesitate to <a href="mailto:[email protected]" target="_blank" rel="noopener">reach out</a> if you have any question or comment!</p> Kilian Cavalotti[email protected]urn:noticeable:publications:VMnlU6zZGRceQom9u1Wh2019-12-03T23:30:00.001Z2019-12-04T21:49:36.010ZAdventures in storage_This is part of our blog series about behind-the-scenes things we do on a regular basis on Sherlock, to keep it up and running in the best possible conditions for our users. Now that Sherlock's old storage system has been retired, we...<blockquote> <p><em>This is part of our blog series about behind-the-scenes things we do on a regular basis on Sherlock, to keep it up and running in the best possible conditions for our users.<br> Now that <a href="https://news.sherlock.stanford.edu/posts/a-new-scratch-is-here?utm_source=noticeable&amp;utm_campaign=sherlock.adventures-in-storage&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VMnlU6zZGRceQom9u1Wh&amp;utm_medium=newspage" target="_blank" rel="noopener">Sherlock’s old storage system has been retired</a>, we can finally tell that story. It all happened in 2016.</em></p> </blockquote> <p>Or: <em>How we replaced more than 1 PB of hard drives, while continuing to serve files to unsuspecting users.</em></p> <p><strong>TL;DR:</strong> The parallel filesystem in <a href="//www.sherlock.stanford.edu" target="_blank" rel="noopener">Stanford’s largest HPC cluster</a> has been affected by frequent and repeated hard-drive failures since its early days. A defect was identified that affected all of the 360 disks used in 6 different disk arrays. A major swap operation was planned to replace the defective drives. Multiple hardware disasters piled up to make matters worse, but in the end, all of the initial disks were replaced, while retaining 1.5 PB of user data intact, and keeping the filesystem online the whole time.</p> <h2>History and context</h2> <p><em>Once upon a time, in a not so far away datacenter…</em></p> <p>We, <a href="srcc.stanford.edu" target="_blank" rel="noopener">Stanford Research Computing Center</a>, manage many high-performance computing and storage systems at Stanford. In 2013, in a effort to centralize resources and advance computational research, a new HPC cluster, <a href="//www.sherlock.stanford.edu" target="_blank" rel="noopener">Sherlock</a>, has been deployed. To provide best-in-class computing resources to all faculty and facilitate research in all fields, this campus-wide cluster features a high-performance, <a href="http://lustre.org?utm_source=noticeable&amp;utm_campaign=sherlock.adventures-in-storage&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VMnlU6zZGRceQom9u1Wh&amp;utm_medium=newspage" target="_blank" rel="noopener">Lustre</a>-based parallel filesystem.</p> <p>This filesystem, called <code>/scratch</code>, was designed to provide high-performance storage for temporary files during simulations. Initially made of three I/O cells, the filesystem had been designed to be easily expanded with more hardware as demand and utilization grew. Each I/O cell was comprised of:</p> <ul> <li>2x object storage servers,</li> <li>2x disk arrays, with: <ul> <li>dual RAID controllers,</li> <li>5 drawers of 12 disks each,</li> <li>60 4TB SAS disks total.</li> </ul></li> </ul> <p><img src="https://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/publications/VMnlU6zZGRceQom9u1Wh/01h55ta3gs0cjq7j0mcby72khd-image.jpg" alt="MD3260"></p> <p>Each disk array was configured with 6x 10-disk RAID6 LUNs, and every SAS path being redundant, the two OSS servers could act as a high-availability pair. This is a pretty common Lustre setup.</p> <p>Close to a petabyte in size, this filesystem quickly became the go-to solution for many researchers who didn’t really have any other option to store and compute against their often large data sets. Over time, the filesystem was expanded several times and eventually more than doubled in size:</p> <table> <thead> <tr><th></th><th style="text-align:right"># disk arrays</th><th style="text-align:right"># OSTs</th><th style="text-align:right"># disks</th><th style="text-align:right">size</th></tr> </thead> <tbody> <tr><td><strong>initially</strong></td><td style="text-align:right">6</td><td style="text-align:right">36</td><td style="text-align:right">360</td><td style="text-align:right">1.1 PB</td></tr> <tr><td><strong>ultimately</strong></td><td style="text-align:right">18</td><td style="text-align:right">108</td><td style="text-align:right">1080</td><td style="text-align:right">3.4 PB</td></tr> </tbody> </table> <p>As the filesystem grew, it ended up containing close to 380 million inodes (that is, filesystem entries, like files, directories or links). Please keep that in mind, turns out that’s an important factor for the following events.</p> <h2>The initial issue</h2> <p>All was fine and dandy in storage land, and we had our share of failing disks, as everybody. We were replacing them as they failed, sending them back to our vendor, and getting new ones in return. Datacenter business as usual.</p> <p>Except, a lot of disks were failing. Like, really <em>a lot</em>, as in one every other day.</p> <p>We eventually came to the conclusion that our system had been installed with a batch of disks with shorter-than-average lifespans. They were all from the same disk vendor, manufactured around the same date. But we didn’t worry too much.</p> <p>Until that day, where 2 disks failed within 3 hours of each other. In the same disk array. <strong>In. The. Same. <a href="https://en.wikipedia.org/wiki/Logical_unit_number?utm_source=noticeable&amp;utm_campaign=sherlock.adventures-in-storage&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.VMnlU6zZGRceQom9u1Wh&amp;utm_medium=newspage" target="_blank" rel="noopener">LUN</a>.</strong></p> <p>To give some context, <strong>one</strong> failed drive in a 10-disk RAID6 array is no big deal: data can be reconstructed from the 9 remaining physical disks without any problem. If by any chance one of those remaining disks suffers from a problem and data cannot be read from it, there are still enough redundancy to reconstruct the missing data and all is well.<img src="http://www.dcig.com/wp-content/uploads/images/Blog_RAID6.jpg" alt="RAID6 8+2"></p> <p>A single drive failure is handled quite transparently by the disk array:</p> <ul> <li>it emits an alert,</li> <li>you replace the failed disk,</li> <li>it detects the drive has been replaced,</li> <li>it starts rebuilding it from data and parity on the other disks of the LUN,</li> <li>about 24 hours later, you have a brand new LUN, all shiny and happy again.</li> </ul> <p>But <strong>two</strong> failed disks, on the other hand, that’s pretty much like a Russian roulette session: you may be lucky and pull it off, but there’s a good chance you won’t. While the LUN misses 2 disks, there is no redundancy left to reconstruct the data. Meaning that any read error on any of the remaining 8 disks will lead to data loss as the controller won’t be able to reconstruct anything. And worse, any bit flip during reads will go completely unnoticed, as there is no parity left to check the data. Which means that you can potentially be reconstructing completely random garbage on your drives.</p> <p>Given that, it didn’t take us long to pick up the phone and call our vendor.</p> <p>They confirmed our initial findings that in our initial set of 6 disk arrays, over the course of 2 years, we had already replaced about 60 disks out of 360. At a rate of 5-10 failures per month. Way higher than expected.</p> <p>The LUN rebuild eventually completed fine, without any problem, but that double-failure acted as a serious warning. So we stated thinking about ways to solve our problem. And that’s when the sticky cheese hit the fan…</p> <h3>When problems pile up</h3> <p>Three days after the double failure, we had an even more important hardware event: one drawer in another disk array misbehaved, reporting itself as degraded, and 6 disks failed in that same drawer over the course of a few minutes. A 7th disk was evicted a few hours later, and left 2 LUNs without any parity in that single array. Joy all over. In a few minutes, the situation we were dreading a few days earlier just happened twice in the same array. We were a disk away from loosing serious amounts of data (we’re talking 30TB per LUN). And as past experience proved, those disks were not of the most reliable kind…</p> <p>We got our vendor to dispatch a replacement drawer to us under the terms of our H+4 support contract. Except they didn’t have any replacement drawer in stock that they could get to us in 4 hours. So they overnight’d it and we got the replacement drawer the following day.</p> <p>We diligently replaced the drawer and rebuild started on those 7 drives in the disk array. Which, yes, means that one LUN was rebuilding without any redundancy. Like the one from the other disk array the week before. And as everyone probably guessed, things didn’t go that well the second time: that LUN stayed degraded, despite all the rebuild operations being done and all the physical disks state being "optimal". Turned out the interface and the internal controller state disagreed on the status of a drive. On our vendor’s suggestion, we replaced that drive, a new rebuild started, and then abruptly stopped mid-course: the state of the LUN was still "degraded".</p> <p>And then, we had the sensible yet completely foolish idea of calling vendor support on a week-end.</p> <p>Hilarity and data loss ensued.</p> <h3>Never trust your hardware vendor support on week-ends</h3> <p>We were in a situation were a LUN was degraded, and a recently failed drive had just failed to rebuild, yet was showing up as “optimal” in the management interface. The vendor support technician then had the brilliant idea of forcefully “reviving” that drive. Which had the immediate effect of putting back online a drive that had been partially reconstructed, <em>ie.</em> on which 100% of the data had to be considered bit waste.<br> And the LUN stayed in that state, serving ridiculously out-of-sync, inaccurate and pretty much random data to our Lustre OSS servers for about 15 minutes. Fifteen minutes. Nine hundred full-size seconds. A lot of bad things can (and did) happen in 900 seconds.</p> <p>Luckily, the Lustre filesystem quickly realized it was lied to, so it did the only sane thing to do, blocked all I/O and set that device read-only. Of course, some filesystem-level corruption happened during the process.</p> <p>We had to bring that storage target down and check it multiple time with <code>fsck</code> to restore its data structure consistency. About 1,500 corrupted entries where found, detached from the local filesystem map and stored in the <code>lost+found</code> directory. That means that all those 1,500 objects, which were previously part of files, where now orphaned from the filesystem, as it had no way of knowing what file the belonged too anymore. So it tossed them in <code>lost+found</code> as it couldn’t do much else with them.</p> <p>And on our cluster, users trying to access those files were kindly greeted with an error message, which, as error messages sometimes are, was unintuitively related to the matter at hand: <code>cannot allocate memory</code>.</p> <p>With (much better) support from our filesystem vendor, we were able to recover a vast majority of those 1,500 files, and re-attach them to the filesystem, where they originally were. For Lustre admins, the magic word here is <code>ll_recover_lost_found_objs</code>.</p> <p>So in the end, we “only” lost 29 files in the battle. We contacted each one of the owners to let them know about the tragic fate of their files, and most of them barely flinched, their typical response being: "Oh yeah, I know that’s temporary storage anyway, let me upload a new copy of that file from my local machine".</p> <p>We know, we’re blessed with terrific users.</p> <h2>The tablecloth trick</h2> <p>Now, this was just starters, we hadn’t really had a chance to tackle the real issue yet. We were merely absorbing the fallout of that initial drawer failure, but we hadn’t done anything to address the high failure rate of our disk drives.</p> <p>Our hardware vendor, well aware of the underlying reliability issue, as the same scenario happened other places too, kindly agreed to replace all of our remaining original disks. That is, about 300 of them:</p> <table> <thead> <tr><th style="text-align:right">disk array</th><th style="text-align:right">already HDDs</th><th style="text-align:right">total HDDs</th><th style="text-align:right">HDDs to replace</th></tr> </thead> <tbody> <tr><td style="text-align:right">DA00</td><td style="text-align:right">16</td><td style="text-align:right">60</td><td style="text-align:right">44</td></tr> <tr><td style="text-align:right">DA01</td><td style="text-align:right">15</td><td style="text-align:right">60</td><td style="text-align:right">45</td></tr> <tr><td style="text-align:right">DA02</td><td style="text-align:right">14</td><td style="text-align:right">60</td><td style="text-align:right">46</td></tr> <tr><td style="text-align:right">DA03</td><td style="text-align:right">13</td><td style="text-align:right">60</td><td style="text-align:right">47</td></tr> <tr><td style="text-align:right">DA04</td><td style="text-align:right">8</td><td style="text-align:right">60</td><td style="text-align:right">52</td></tr> <tr><td style="text-align:right">DA05</td><td style="text-align:right">15</td><td style="text-align:right">60</td><td style="text-align:right">45</td></tr> <tr><td style="text-align:right"><strong>total</strong></td><td style="text-align:right"><strong>81</strong></td><td style="text-align:right"><strong>360</strong></td><td style="text-align:right"><strong>279</strong></td></tr> </tbody> </table> <p>The strategy devised by that same vendor was:</p> <blockquote> <p>"We’ll send you a whole new disk array, filled with new disks, and you’ll replicate your existing data there".</p> </blockquote> <p>To which we replied:</p> <blockquote> <p>“Uh, sorry, that’s won’t work. You see, those arrays are part of a larger Lustre filesystem, we can’t really replicate data from one to another without a downtime. And we would need a downtime long enough to allow us to copy 240TB of data. Six times, 'cause you know, we have six arrays. Oh, and our users don’t like downtimes.”</p> </blockquote> <p>So we had to find another way.</p> <p>Our preference was to minimize manipulations on the filesystem and keep it online as much as possible during this big disk replacement operation. So we leaned toward the path of least resistance, and let the RAID controllers do what they do best: compute parities and write data. So we ended up removing each one of those bad disks, one at a time, replacing it with a new disk, and let the controller rebuild the LUN.</p> <p>Each rebuild operation took about 24 hours, so obviously, replacing ~300 disks one at a time wasn’t such a thrilling idea: assuming somebody would be around 24/7 to swap a new drive as soon as the previous one finished, that would make the whole operation last almost a full year. Not very practical.</p> <p>So we settled on doing them in batches, replacing one disk in each of the 36 LUNs in each batch. That would allow the RAID controllers to rebuild several LUNs in parallel, and cut the overall length of the operation. Instead of 300 sequential 24-hours rebuilds, we would only need 5 waves of disk replacements, which shouldn’t take more than a couple weeks total.</p> <p>Should we mention the fact that our adored vendor mentioned that, since we were using RAID6, if we wanted to speed things even more, we could potentially consider replacing two drives at a time in each LUN, but that they wouldn’t recommend it? Nah, right, we shouldn’t.</p> <h3>Remove the disks, keep the data</h3> <p>So they went away and shipped us new disks. That’s where the “tablecloth trick” analogy is fully realized: we were indeed removing disk drives from our filesystem, while keeping the data intact, and inserting new disks underneath to replace them. Which would really be like pulling the tablecloth, putting a new one in place, and keeping the dishes intact.</p> <p><img src="http://67.media.tumblr.com/8b26967a16e1cf8e193b02c86c29f2e0/tumblr_inline_o91qsbH6pq1raprkq_500.gif" alt="tablecloth"></p> <p>But you know, things never go as planned, and while we started replacing that first batch of disks, we realized that those unreliable drives? Well, they were really unreliable.</p> <h3>When things go south</h3> <p>No less than five additional disks failed during that same first wave of rebuilds. Four of them in the same array (<code>DA00</code>). To make things worse, in one of those LUNs, one additional disk failed during the rebuild and then, unreadable sectors were encountered on a 3rd disk. Which lead to data loss and a corrupted LUN.</p> <p>We contacted our vendor, which basically said: "LUN is lost, restore from backup". Ha ha! Of course, we have backups for a 3PB Lustre filesystem, and we can restore an individual OST without breaking complete havoc in the rest of the filesystem’s coherency. For some reason, our vendor support recommended to delete the LUN, recreate it, and let the Lustre file system re-populate data back. We are still trying to understand what they meant.</p> <p>On the bright side, they engaged our software vendor, to provide some more assistance at the filesystem level and devise a recovery strategy. We had one of our own rolling already, and it turned out it was about the same.</p> <h3>Relocating files</h3> <p>Since we still had access to the LUN, our approach was to migrate all the files out of that LUN as quickly as possible and relocate them on other OSTs in Lustre, re-initialize the LUN at the RAID level, and them reformat it and re-insert it in the filesystem. Or, more precisely:</p> <ol> <li>deactivate the OST on MDT to avoid new object creation,</li> <li>use <code>lfs_migrate</code> to relocate files out of that OST, using either Robinhood or the results of <code>lfs find</code> to identify files residing on that OST (the former can be out of date, the latter was quite slow),</li> <li>make sure the OST was empty (<code>lfs find</code> again),</li> <li>disable the OST on clients, so they didn’t use it anymore,</li> <li>reactivate the OST on the MDS to clear up orphaned objects (while the OST is disconnected from the MDT, file relocations are not synchronized to the OST, so objects are orphaned there and take up space unnecessarily),</li> <li>backup the OST configuration (so it could be recreated with the same parameters, including its index),</li> <li>reinitialize the LUN in the disk array, and retain its configuration (most importantly its WWID),</li> <li>reformat the OST with Lustre,</li> <li>restore the OST configuration (especially its index),</li> <li>reactivate the OST.</li> </ol> <p>What can go wrong in a 10-step procedure? Turns out, it kind of all stopped at step 1.</p> <h4>Making sure nobody writes files to a LUN anymore</h4> <p>In order to be able to migrate all the files from an OST, you need to make sure that nobody can write new files to it anymore. How could you empty an OST if new files keep being created on it?<br> There are several approaches to this, but it took us some tries to get it right where we wanted it to be.</p> <p>First, you can try to ‘deactivate’ the OST by making it read-only on the MDT. It means that users can still read the existing files on the OST, but the MDT won’t consider it for new file creations. Sounds great, except for one detail: when you do this, the OST is disconnected from the MDT, so inodes occupied by files that are being migrated are not reported as freed up to the MDT. The consequence is that the MDT still thinks that the inodes are in-use, and you end up in a de-synchronized state, with orphaned inodes on your OST. Not good.</p> <p>So you need, at some point, to reconnect your OST to the MDT. Except as soon as you do this, new files get created on it, and you need to deactivate the OST, migrate them again, and bam, new orphan inodes again. Back to square one.</p> <p>Another method is to mark the OST as "degraded", which is precisely designed to handle such cases: OST undergoing maintenance, or rebuilding RAIDs, during which period the OST shouldn’t be used to create new files. So, we went ahead and marked our OST as "degraded". Until we realized that files were still created on it. It turns out that this was because of some uneven usage in out OSTs (they were added to the filesystem over time, so they were not all filled at the same level): if there’s too much unbalanced utilization among OSTs, the Lustre QOS allocator will ignore the “degraded” flag on OSTs, and privilege trying to rebalance usage over obeying OST degradation flags.</p> <p>Our top-notch filesystem vendor support suggested an internal setting to set on the OST (<code>fail_loc=0x229</code>, don’t try this at home) to artificially mark the OST as "out-of-space", which would carry both benefits of leaving it connected to the MDT for inodes cleanup, and prevent new files creation there. Unfortunately, this setting had the unexpected side effect of making load spike on the MDS, practically rendering the whole filesystem unsuable.</p> <p>So we ended up deciding to temporarily sacrifice good load balancing across OSTs, and disabled the QOS allocator. This allowed us to mark our OST as "degraded", keep it connected to the MDT so inodes associated with migrated files would effectively be cleaned, while preventing new file creation. This worked great.</p> <p><img src="https://cloud.githubusercontent.com/assets/186807/17631228/14e610e8-6078-11e6-814d-f874d07ef1ff.png" alt="lfs_migrates"></p> <p>We let our migration complete, and at the end both OSTs were completely empty, devoid of any file.</p> <h3>Zombie LUN</h3> <p><em>Because any good story needs zombies.</em></p> <p>Once we had finished emptying our OSTs, we then needed to fix them at the RAID level. Because, remember, everything went to hell after multiple disk failures during a LUN rebuild. Meaning that in their current state, those two LUNs were unusable and had to be re-initialized. We had good hopes we would be able to do this from the disk array management tools. Unfortunately, our hardware vendor didn’t think it would be possible, and strongly recommended to destroy the LUN and to rebuild it with the same disks.</p> <p>The problem with that approach is that this would have generated a different identifier for our LUNs, meaning we would have had to change the configuration of our multipath layer, and more importantly, swap old WWIDs with the new ones in our Lustre management tool. Which is not supported.</p> <p>Thing is, we’re kind of stubborn. And we didn’t want to change WWIDs. So we looked for a way to re-initialize those LUNs in-place. Sure enough, failing multiple drives in the LUN rendered it inoperable. And nothing in the GUI seemed to be possible from there, besides "calling support for assistance". And you know, we tried that before, so no thanks we’ll pass.</p> <p>Finally, exploring the CLI options, we found one (<code>revive diskGroup</code>) that did exactly what we were looking for: after replacing the 2 defectives disks (which made the LUN fail), we revived it from the CLI, and it happily sprung to life again. With all its parameters intact, so from the servers point of view, it was like nothing ever happened.</p> <h3>Restore Lustre</h3> <p>So, all what was left to do, was to reformat the OSTs and restore their parameters we had backed up before failing and reviving the LUNs.</p> <h2>Wrap up</h2> <p>Everything was a smooth ride from there. While working on repairing our two failed OSTs, we were continuously replacing those ~300 defective hard drives, one at a time and monitoring the rebuilds processes. At any given time, we had something like 36 LUNs rebuilding (6 arrays, 6 LUNs each) to maximize the throughput.</p> <h3>Disk replacement</h3> <p>Our hardware vendor was sending us replacement drives in batches, and we’ve been replacing 1 disk in each LUN pretty much every day for about 3 weeks.<br> We built a tool to follow the replacements and select the next disks to replace (obviously placement was important as we didn’t want to remove multiple disks from the same LUN). The tool allowed to see the number of disks left to replace, the status of current rebuilds, and when possible, selected the next disks to replace by making them blink in the disk arrays.</p> <h3>The end</h3> <p>Just because that how lucky we are, another drawer failed during the last rounds of disk replacements. It took an extra few days to get a replacement on site and replace it. Fortunately, no unreadable sectors happened during the recovery.</p> <p>It took a few more days to clear out remaining drawers and controllers errors and to make sure that everything was stable and in running order. The official end of the operation was declared on May 17th, 2016, about 4 months after the initial double-disk failure.</p> <p>We definitely learned a lot in the process, way more that we could ever have dared to ask. And it was quite the adventure, the kind that we hope will not happen again. But considering all what happened, we’re very glad the damage was limited to a handful of files and didn’t have a much broader impact.</p> Kilian Cavalotti[email protected]urn:noticeable:publications:OYMZ9enkjo02jJ1V2vtK2019-12-03T23:30:00.001Z2019-12-04T19:28:02.638ZA newer, faster and better /scratchAs we just announced, Sherlock now features a brand new storage system for /scratch. But what was the old system, what does the new one look like, and how did the move happen? Read on to find out! The old Since its early days, Sherlock...<p>As <a href="https://news.sherlock.stanford.edu/posts/more-scratch-space-for-everyone?utm_source=noticeable&amp;utm_campaign=sherlock.a-new-scratch&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.OYMZ9enkjo02jJ1V2vtK&amp;utm_medium=newspage" target="_blank" rel="noopener">we just announced</a>, Sherlock now features a brand new storage system for <code>/scratch</code>. But what was the old system, what does the new one look like, and how did the move happen? Read on to find out!</p> <h2>The old</h2> <p>Since its early days, Sherlock ran its <code>/scratch</code> filesystem on a storage system that was donated by <a href="//www.intel.com" target="_blank" rel="noopener">Intel</a> and <a href="//www.dell.com" target="_blank" rel="noopener">Dell</a>.</p> <p>Dubbed <em><em>Regal</em></em>, it was one of the key components of the Sherlock cluster when we started it in early 2014, with an initial footprint of about 100 compute nodes. Its very existence allowed us to scale the cluster to more than 1,500 nodes today, almost entirely through Faculty and PIs contributions to its condominium model. That’s a 15x growth in 5 years, and adoption has been spectacular.</p> <p>Regal was initially just over 1PB when it’s been deployed in May 2013, which was quite substantial at the time. And similarly to the compute part of the cluster, its modular design allowed us to expand it to over 3PB with contributions from individual research groups.</p> <p>We had a number of adventures with that system, including a <a href="https://news.sherlock.stanford.edu/posts/adventures-in-storage?utm_source=noticeable&amp;utm_campaign=sherlock.a-new-scratch&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.OYMZ9enkjo02jJ1V2vtK&amp;utm_medium=newspage" target="_blank" rel="noopener">major scale disk replacement operation</a>, where we replaced about a petabyte of hard drives in production, while continuing to serve files to users ; or a literal drawer explosion in one of the disk arrays!</p> <p><img src="https://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/publications/OYMZ9enkjo02jJ1V2vtK/01h55ta3gsktzvgnjvd176d3yj-image.jpg" alt="kaboom"></p> <p>It’s been fun, and again, invaluable to our users.</p> <p>But time has come to retire it, and replace it with a newer, faster and better solution, to accommodate the ever-growing storage needs of Sherlock’s ever-growing community.</p> <h2>The new</h2> <p>This year, we stood up a completely new and separate <code>/scratch</code> filesystem for Sherlock.</p> <p>Nicknamed <em>Fir</em> (we like trees), this new storage system features:</p> <ul> <li>multiple metadata servers and faster metadata storage for better responsiveness with interactive operations,</li> <li>faster object storage servers,</li> <li>a faster backend interconnect, for lower latency operations across storage servers,</li> <li>more and faster storage routers to provide more bandwidth from Sherlock to <code>/scratch</code>,</li> <li>more space to share amongst all Sherlock users,</li> <li>a newer version of <a href="http://lustre.org?utm_source=noticeable&amp;utm_campaign=sherlock.a-new-scratch&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.OYMZ9enkjo02jJ1V2vtK&amp;utm_medium=newspage" target="_blank" rel="noopener">Lustre</a> which provides: <ul> <li>improved client performance,</li> <li>dynamic file striping to automatically adapt file layout and I/O performance to match a file’s size</li> <li>and <a href="http://wiki.lustre.org/Lustre_2.12.0_Changelog?utm_source=noticeable&amp;utm_campaign=sherlock.a-new-scratch&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.OYMZ9enkjo02jJ1V2vtK&amp;utm_medium=newspage" target="_blank" rel="noopener">much more</a>!</li> </ul></li> </ul> <p><img src="https://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/publications/OYMZ9enkjo02jJ1V2vtK/01h55ta3gs7981c7jwnsydp3eq-image.jpg" alt="new"></p> <p><img src="https://storage.noticeable.io/projects/bYyIewUV308AvkMztxix/publications/OYMZ9enkjo02jJ1V2vtK/01h55ta3gswz2f897qg6s6ha96-image.png" alt="logo-io500.png"> And not to brag, but Fir has been ranked #15 in the <a href="//www.vi4io.org/io500/list/19-11/10node" target="_blank" rel="noopener">IO-500 list of the fastest storage systems in the world</a>, in the 10-node challenge category, that was released at <a href="//sc19.supercomputing.org" target="_blank" rel="noopener">SC’19</a>. So yes, it’s decently fast.</p> <h2>The migration</h2> <p>Now, usually, when a new filesystem is made available on a computing system, there are two approaches:</p> <p>One is making the new system available under a new mount point (like <code>/scratch2</code>) and tell users: “here’s the new filesystem, the old one will go away soon, you have until next Monday to get your files there and update all your scripts.”<br> This usually results in a lot of I/O traffic going on at once from all the users rushing to copy their data to the new space, potential mistakes, confusion, and in the end, a lot of frustration, additional work and unnecessary stress on everyone. Not good.</p> <p>The other one is for sysadmins to copy all of the existing data from the old system to the new one in the background, in several passes, and then scheduled a (usually long) downtime to run a last synchronization pass and substitute the old filesystem by the new one under the same mount point (<code>/scratch</code>).<br> This also brings significant load on the filesystem while the synchronisation passes are running, taking I/O resources away from legitimate user jobs, it’s usually a very long process, and in the end it brings over old and abandoned files to the new storage system, wasting precious space. Not optimal either.</p> <p>So we decided to take another route, and devised a new scheme. We spent some time (and fun!) designing and developing a new kind of overlay layer, to bridge the gap between Regal and Fir, and to transparently migrate user data from one to the other.</p> <p>We (aptly) named this layer <code>migratefs</code> and open-sourced it at:<br> <a href="https://github.com/stanford-rc/fuse-migratefs?utm_source=noticeable&amp;utm_campaign=sherlock.a-new-scratch&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.OYMZ9enkjo02jJ1V2vtK&amp;utm_medium=newspage" target="_blank" rel="noopener">https://github.com/stanford-rc/fuse-migratefs</a>.</p> <p><img src="https://docs.google.com/drawings/d/e/2PACX-1vT0p9txFKOVS9GazuZFIfolJp0ksmlXNlb0MsjyR_F3rPNtdXEe3ho25lpW55sNKk_NHmc0WyErQnCA/pub?w=484&amp;h=195" alt="migratefs"></p> <p>The main idea of <code>migratefs</code> is to take advantage of user activity to:</p> <ol> <li>distribute the data transfer tasks across all of the cluster nodes, to reduce the overall migration time,</li> <li>only migrate data that is actively in use, and leave older files that are never accessed nor modified on the old storage system, resulting in a new storage system that only stores relevant data,</li> <li>migrate all the user data transparently, without any downtime.</li> </ol> <p>So over the last few months, all of the active user data on Regal has been seamlessly migrated to Fir, without users having to modify any of their job scripts, and all without a downtime.</p> <p>Which is why if you’re using <code>$SCRATCH</code> or <code>$GROUP_SCRATCH</code> today, you are actively using the new storage system, and all your active data is there already, ready to be used in your compute jobs.</p> <h2>Next steps</h2> <p>Now, Regal has been emptied of all of its data and has been retired. It’s currently being un-racked to make room for future Sherlock developments.And stay tuned, because… <em>epic</em> changes are coming!</p> Kilian Cavalotti[email protected]urn:noticeable:publications:IARfWlFT8IPjMRyh74t12019-12-03T23:30:00.001Z2019-12-03T23:33:14.769ZMore scratch space for everyone!Today, we're super excited to announce several major changes to the /scratch filesystem on Sherlock. What's /scratch already? /scratch is Sherlock's temporary, parallel and high-performance filesystem. It's available from all the...<p>Today, we’re super excited to announce several major changes to the <code>/scratch</code> filesystem on Sherlock.</p> <h2>What’s <code>/scratch</code> already?</h2> <p><code>/scratch</code> is Sherlock’s temporary, parallel and high-performance filesystem. It’s available from all the compute nodes in the cluster, and is aimed at storing temporary data, like raw job output, intermediate files, or unprocessed results.</p> <p>All the details about <code>/scratch</code> can be found in the Sherlock documentation, at <a href="https://www.sherlock.stanford.edu/docs/storage/filesystems/?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage#scratch" target="_blank" rel="noopener">https://www.sherlock.stanford.edu/docs/storage/filesystems/#scratch</a></p> <h2>A brand new storage system</h2> <p>So first of all, Sherlock’s <code>/scratch</code> now uses a brand new underlying storage system: it’s newer, faster and better that the old system in many ways that are described in much more details <a href="https://news.sherlock.stanford.edu/posts/a-new-scratch?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage" target="_blank" rel="noopener">in this other post</a>.</p> <p>But to sum it up, using newer and faster hardware, the new <code>/scratch</code> storage system is twice as large, dramatically accelerate small files access and metadata operations, and enables new filesystem features for better overall performance.</p> <p>If you’d like to take advantage of that new system and are wondering what you need to benefit from its improved performance, the answer is pretty simple: nothing! Your data is already there: if you’re using <code>$SCRATCH</code> or <code>$GROUP_SCRATCH</code> today, you don’t have to do anything, you’re already using the new storage system.</p> <p>How did that happen? You can read all about it in <a href="https://news.sherlock.stanford.edu/posts/a-new-scratch-is-here?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage" target="_blank" rel="noopener">that post I mentioned above</a>.</p> <h2>More space for everyone!</h2> <p>Now, some things don’t change, but others do. We’re really excited to announce that starting today, every user on Sherlock gets <del>twice</del> <del>thrice</del> 🎉✨ <strong>five times</strong>✨🎈 the amount of storage that was previously offered.</p> <p>Yep, that’s right, starting today, <strong>every user</strong> on Sherlock gets <strong>100TB</strong> in <code>$SCRATCH</code>. And because sharing is caring, <strong>each group</strong> gets an additional <strong>100TB</strong> to share data in <code>$GROUP_SCRATCH</code>.</p> <p>But wait, there’s more.</p> <p>Because we know ownership-based user and group quotas were confusing at times, we’re moving away from them and are adopting a new, directory-based quota system. That means that all the files that are under a given <code>$SCRATCH</code> directory, and only them, will be accounted for in the quota usage, no matter which user and group owns them. It will makes finding files that count towards a given quota much easier.</p> <p>Previously, with ownership-based accounting, a user with data in both her own <code>$SCRATCH</code> folder and in <code>$GROUP_SCRATCH</code> would see the sum of all those files’ size counted against both her user quota and the group quota. Plus, the group quota was <em>de facto</em> acting as a cap for all the users in the same group, which was penalizing for groups with more members.</p> <p>Now, data in a user’s <code>$SCRATCH</code> and <code>$GROUP_SCRATCH</code> are accounted for independently, and they’re cumulative. Meaning that no matter how many members a group counts, each user will be able to use the same amount of storage, and won’t be impacted by what others in the group use.</p> <p>Here what things looks like, more visually (and to scale!):<br> <img src="https://docs.google.com/drawings/d/e/2PACX-1vQrfxu9oTcz6Ilbta3X1BTF9fGMlQLul77ftTpbRFvwLGnrwhNlIjRUvqDcfYiSA80ARN6rtCkU1lFW/pub?w=1317&amp;h=881" alt="scratch quotas"></p> <ul> <li>before, individual ownership-based user quota (in blue) were limited by the overarching group quota (in purple).</li> <li>now, each user can use up to their quota limit, without being impacted by others, <em>and</em> an additional 100TB is available for the group to share data among group members.</li> </ul> <p>So not only individual quota values have been increased, but the change in quota type also means that the cumulative usable space in <code>/scratch</code> by each group will be much larger than before.</p> <h2>A new retention period</h2> <p>With that increase in space, we’re also updating the retention period on <code>/scratch</code> to 90 days. And because we don’t want to affect files that have been created less than 3 months ago, this change will not take effect immediately.</p> <p><strong>Starting Feb.3, 2020, all files stored in <code>/scratch</code> that have not been modified in the last 90 days will automatically be deleted from the filesystem.</strong></p> <p>This is in alignment with the vast majority of other computing centers, and a way to emphasize the temporary nature of the filesystem: <code>/scratch</code> is really designed to store temporary data, and provide high-performance throughput for parallel I/O.</p> <p>For long-term storage of research data, we always recommend using <a href="https://www.sherlock.stanford.edu/docs/storage/filesystems/?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage#oak" target="_blank" rel="noopener">Oak</a>, which is also directly available from all compute nodes on Sherlock (you’ll find all the details about Oak at <a href="https://oak-storage.stanford.edu?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage" target="_blank" rel="noopener">https://oak-storage.stanford.edu</a>). Data can freely be moved between <code>/scratch</code> and Oak at very high throughput rates. We can suggest optimized solutions for this, so please don’t hesitate to reach out if you have any question.</p> <h2>TL;DR</h2> <p>Today, we’re announcing:</p> <ol> <li>a brand new storage system for <code>/scratch</code> on Sherlock</li> <li>a quota increase to 100TB for each user in <code>$SCRATCH</code> and each group in <code>$GROUP_SCRATCH</code></li> <li>the move to directory-based quotas for easier accounting of space utilization, and for allowing each user to reach their <code>$SCRATCH</code> quota</li> <li>a new 90-day retention period for all files in <code>/scratch</code>, starting Feb. 3, 2020</li> </ol> <p>All those changes have been reflected in the documentation at <a href="https://www.sherlock.stanford.edu/docs/storage/filesystems/?utm_source=noticeable&amp;utm_campaign=sherlock.more-scratch-space-for-everyone&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.IARfWlFT8IPjMRyh74t1&amp;utm_medium=newspage" target="_blank" rel="noopener">https://www.sherlock.stanford.edu/docs/storage/filesystems/</a></p> <p>We hope those changes will enable more possibilities for computing on Sherlock, by allowing storage of larger datasets and running larger simulations.</p> <p>As usual, if you have any question or comment, please don’t hesitate to let us know at <a href="mailto:[email protected]" target="_blank" rel="noopener">[email protected]</a>.</p> Kilian Cavalotti[email protected]urn:noticeable:publications:axlbWNAaFoNduDkqnp5i2019-06-13T23:39:00.001Z2019-06-14T00:17:17.077ZEasier connection to Sherlock's DTNsWe know that easy access to data is essential, and that moving data around is a key part of every user's workflow on Sherlock. We also know that two-factor authentication (2FA) can sometimes get in the way, and hinder the ability to get...<p>We know that easy access to data is essential, and that moving data around is a key part of every user’s workflow on Sherlock. We also know that <a href="https://uit.stanford.edu/service/authentication/twostep?utm_source=noticeable&amp;utm_campaign=sherlock.easier-connection-to-sherlock-s-dt-ns&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.axlbWNAaFoNduDkqnp5i&amp;utm_medium=newspage" target="_blank" rel="noopener">two-factor authentication (2FA)</a> can sometimes get in the way, and hinder the ability to get work done.</p> <p>2FA is an important security measure and a definitive improvement over traditional authentication methods, that helps protect our data, identity and is becoming a part of our daily lives, even outside of Sherlock. But it doesn’t necessarily add the same protection value on <a href="https://www.sherlock.stanford.edu/docs/storage/data-transfer/?utm_source=noticeable&amp;utm_campaign=sherlock.easier-connection-to-sherlock-s-dt-ns&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.axlbWNAaFoNduDkqnp5i&amp;utm_medium=newspage#data-transfer-nodes-dtns" target="_blank" rel="noopener">Data Transfer Nodes (DTNs)</a>, which only allow file transfers and don’t offer interactive shells, than it does on login nodes.</p> <p>Additional authentication steps are sometimes also causing compatibility problems with some file transfer programs, which don’t support them.</p> <p>This is why we’re implementing changes, to make data transfers more seamless, easier, and more flexible.</p> <h2>Duo is not required on Sherlock DTNs anymore</h2> <p>Starting today, two-step authentication is not a requirement anymore to transfer files to/from Sherlock’s DTN.</p> <blockquote> <p><strong>Important</strong> Two-step authentication using Duo is still mandatory to connect to login nodes</p> </blockquote> <p>You can now connect to <code>dtn.sherlock.stanford.edu</code> either:</p> <ul> <li>interactively, using your SUNet ID and password,</li> <li>in a completely non-interactive way, using your Kerberos credentials (using <a href="https://www.sherlock.stanford.edu/docs/advanced-topics/connection/?utm_source=noticeable&amp;utm_campaign=sherlock.easier-connection-to-sherlock-s-dt-ns&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.axlbWNAaFoNduDkqnp5i&amp;utm_medium=newspage#gssapi" target="_blank" rel="noopener">GSSAPI</a>)</li> </ul> <p>An immediate benefit is that using <a href="https://www.sherlock.stanford.edu/docs/storage/data-transfer/?utm_source=noticeable&amp;utm_campaign=sherlock.easier-connection-to-sherlock-s-dt-ns&amp;utm_content=publication+link&amp;utm_id=bYyIewUV308AvkMztxix.GtmOI32wuOUPBTrHaeki.axlbWNAaFoNduDkqnp5i&amp;utm_medium=newspage#sshfs" target="_blank" rel="noopener">SSHFS</a> on Windows computers should be possible again.</p> <p>We hope this will help in making your data more easily accessible on Sherlock, and make more options available in terms of data transfer programs.</p> <p>As usual, don’t hesitate to get in touch at <a href="mailto:[email protected]" target="_blank" rel="noopener">[email protected]</a> if you have any question or suggestion.</p> Kilian Cavalotti[email protected]