2 điểm bởi GN⁺ 2024-03-13 | 1 bình luận | Chia sẻ qua WhatsApp
  • Thay vì thiết lập lại laptop mới từ đầu, tác giả expose toàn bộ ổ đĩa của laptop cũ qua NVMe over TCP rồi sao chép nguyên trạng qua mạng
  • Môi trường cũ dùng mã hóa toàn bộ ổ đĩa và ổ 512GB; laptop mới có NVMe 1TB nên sau khi sao chép cần mở rộng phân vùng, LUKS và BTRFS
  • Việc xuất ổ đĩa không dùng systemd-storagetm.service; thay vào đó khởi động cả hai laptop bằng GRML rescue CD và cấu hình bằng nvmet-tcp cùng /sys/kernel/config/nvmet
  • Quá trình sao chép thực tế dùng dd; do laptop mới không có cổng Ethernet nên chỉ dùng WiFi, kết quả sao chép 512GB mất khoảng 7 giờ 30 phút, tốc độ khoảng 18–20MB/s
  • Sau khi sao chép, tác giả điều chỉnh để dùng toàn bộ 1TB thông qua parted, growpart, cryptsetup resize và BTRFS resize, gần như tiếp tục sử dụng nguyên môi trường laptop cũ

Xuất ổ đĩa cũ qua NVMe over TCP

  • Để không phải lặp lại quy trình thiết lập laptop mới, theo đề xuất của đồng nghiệp, tác giả chọn cách sao chép toàn bộ ổ đĩa của laptop cũ

  • Trước khi bắt đầu có hai trở ngại

    • Không có dụng cụ để mở laptop cũ và kết nối ổ đĩa mới qua USB
    • Laptop cũ dùng mã hóa toàn bộ ổ đĩa và ổ 512GB, còn laptop mới có NVMe 1TB nên cần thay đổi kích thước LUKS
  • Luồng công việc gồm ba bước: expose ổ đĩa, sao chép và mở rộng dung lượng

    • Xuất ổ đĩa từ laptop cũ bằng nvmet-tcp
    • Sao chép ổ đĩa đó trên laptop mới
    • Mở rộng phân vùng ra toàn bộ 1TB
    • Thay đổi kích thước LUKS
    • Cuối cùng, thay đổi kích thước ổ root BTRFS
  • Dùng GRML thay cho systemd-storagetm.service

    • Cách dễ nhất có thể là dùng systemd-storagetm.service
    • Có thể gọi nó bằng cách chỉ định rd.systemd.unit=storage-target-mode.target để boot vào storage-target-mode.target
    • Tuy nhiên cách này yêu cầu đưa các dịch vụ mạng vào ảnh dracut initrd, và trong chế độ đó việc cấu hình WiFi khá phiền phức, nên tác giả bỏ qua
    • Thay vào đó, tác giả boot cả hai laptop bằng GRML rescue CD, rồi trên laptop cũ xuất ổ NVMe bằng module nvmet-tcp của Linux
    modprobe nvmet-tcp
    cd /sys/kernel/config/nvmet
    mkdir ports/0
    cd ports/0
    echo "ipv4" > addr_adrfam
    echo 0.0.0.0 > addr_traaddr
    echo 4420 > addr_trsvcid
    echo tcp > addr_trtype
    cd /sys/kernel/config/nvmet/subsystems
    mkdir testnqn
    echo 1 >testnqn/allow_any_host
    mkdir testnqn/namespaces/1
    cd testnqn
    
    
    # replace the device name with the disk you want to export
    echo "/dev/nvme0n1" > namespaces/1/device_path
    echo 1 > namespaces/1/enable
    ln -s "../../subsystems/testnqn" /sys/kernel/config/nvmet/ports/0/subsystems/testnqn
    
    • Với cấu hình này, thiết bị đích được expose dưới dạng NVMe over TCP
    • Trên laptop mới, tìm kiếm và kết nối tới thiết bị đã xuất
    nvme discover -t tcp -a <ip> -s 4420
    nvme connectl-all -t tcp -a <> -s 4420
    
    • Sau đó có thể kiểm tra thiết bị được kết nối trên laptop mới bằng nvme list và tiến hành sao chép ổ đĩa

Sao chép ổ đĩa và thay đổi kích thước

  • Sao chép 512GB bằng dd

    • Việc sao chép ổ root được thực hiện bằng lệnh dd
    • Do laptop mới không có cổng Ethernet nên chỉ dùng WiFi, việc sao chép toàn bộ 512GB mất khoảng 7 giờ 30 phút
    • Tốc độ truyền khoảng 18–20MB/s
    • Các lựa chọn khác là tạo sẵn phân vùng và hệ thống tệp ban đầu rồi dùng rsync để sao chép ổ root, hoặc dùng cơ chế truyền hệ thống tệp của chính BTRFS
    dd if=/dev/nvme2n1 of=/dev/nvme0n1 status=progress bs=40M
    
  • Mở rộng phân vùng, LUKS và BTRFS

    • parted phát hiện bảng phân vùng không khớp với kích thước ổ đĩa, sau khi hỏi xác nhận đã tự động sửa
    • Để mở rộng phân vùng thứ hai, tác giả cài cloud-guest-utils và dùng growpart
    growpart /dev/nvem0n1 p2
    
    • Ở bước tiếp theo, dùng cryptsetup để tăng kích thước container LUKS
    cryptsetup luksOpen /dev/nvme0n1p2 ENC
    cryptsetup resize ENC
    
    • Sau khi boot lại từ ổ đĩa và xác nhận hoạt động bình thường, tác giả đăng nhập rồi thay đổi kích thước hệ thống tệp BTRFS
    • Với BTRFS, hệ thống phải được mount để thay đổi kích thước, nên không thể thử trong trạng thái live boot
    btfs fielsystem resize max /
    
    • Kết quả là trên laptop mới, tác giả có được môi trường như thể vẫn đang dùng tiếp laptop cũ
    • Thông thường cần khoảng 1–2 tuần để hoàn toàn thích nghi với laptop mới, nhưng cách này đã rút ngắn thời gian đó
    • Ngoài ra, tác giả cũng học được cách xuất ổ đĩa qua NVMe over TCP

1 bình luận

 
GN⁺ 2024-03-13
Ý kiến trên Hacker News
  • Trong kịch bản của tác giả, rốt cuộc chỉ thực hiện sao chép khối tuần tự bằng dd(1), nên gần như không có lợi ích gì khi dùng NVMe/TCP. Lệnh phức tạp có thể được thay bằng netcat đơn giản
    Laptop đích: $ nc -l -p 1234 | dd of=/dev/nvme0nX bs=1M
    Laptop nguồn: $ nc x.x.x.x 1234
    dd ở phía đích dùng để buffer thao tác ghi nhằm làm nhanh và hiệu quả hơn. Nếu thêm gzip/gunzip ở nguồn/đích thì sẽ nhanh hơn nhiều khi đĩa chưa đầy và có nhiều khối 0. Cá nhân tôi thích nhất cách này khi tạo image PC qua mạng và đã làm nhiều lần
    Trên GigE, nén thường trở thành nút thắt cổ chai, nên nên truyền --fast cho gzip; tốt hơn nữa là dùng lz4/unlz4 thay cho gzip/gunzip thì sẽ nhanh hơn. Trước đây khi image một laptop Windows mới có NVMe 1TB qua GigE, mất khoảng 20 phút, và vì dung lượng trống được nén gần như về 0 nên image kết quả chỉ 20GB. Thường tôi sao lưu image lz4 đó, rồi vài năm sau khi đem tặng laptop thì khôi phục bằng unlz4 | dd, rất tiện
    Tuy nhiên tôi không biết đến module kernel Linux nvme-tcp, ngày nào cũng học được điều mới. Cái này có vẻ hữu ích hơn cho việc mount filesystem trên NVMe từ xa, thay vì truy cập thô bằng dd
    Ngoài ra, kích thước pipe buffer tối đa của Linux là 64kB, nên về mặt kỹ thuật tham số dd bs=X không cần lớn hơn mức đó. Dù vậy bs=1M không gây hại và sẽ gom các lần đọc 64kB cho đến khi đủ 1MB, đồng thời cũng phòng khi kích thước pipe tăng trong tương lai. Một số phiên bản netcat có tùy chọn kích thước khối I/O nên không cần dd bs=X, nhưng netcat trên đĩa cứu hộ thường là phiên bản không có tùy chọn đó

    • Pipe buffer của Linux có thể tăng lên, và theo tôi biết giá trị tối đa mặc định thường khoảng 1MB. Làm từ dòng lệnh hơi rắc rối, nhưng có ví dụ triển khai khả thi tại https://unix.stackexchange.com/a/328364
    • Dù hơi lộn xộn, nếu dùng pv thay cho dd ở cả hai phía thì không phải lo chỉ định kích thước khối phù hợp, và còn có biểu đồ tiến độ đẹp mắt
    • Khoảng 9 năm trước tôi từng đi tư vấn cho một công ty bị hack nội bộ; một đồng sáng lập bất mãn đã thiết lập kiểu dead man’s switch để sao chép 20MB đầu của mọi đĩa vào một bucket nào đó rồi ghi đè bằng 0. Để khôi phục dữ liệu, tôi phải dựng lại bảng phân vùng bằng testdisk, nhưng trước đó không muốn động vào các đĩa đã hỏng, nên đã sao chép khoảng 40TB bằng đĩa flash cứu hộ, netcat và ổ đĩa
      Một số máy chủ có toàn bộ khe RAID vật lý đều đã đầy nên cũng không dùng được khe đĩa dự phòng; đại khái tôi dùng dd if=/dev/sdc bs=xxx | gzip | nc -l -p 8888 và lệnh ngược lại ở phía bên kia. Bất ngờ là nó chạy tốt. Một điểm cần chú ý là thử khớp tổ hợp dd bs với kích thước sector, vì kích thước phù hợp ảnh hưởng lớn đến thông lượng của dd
    • Cách dùng dd này có thể gây hư hỏng. Để tránh bị cắt khối, cần iflag=fullblock, và dù có thể là thói quen mù quáng, conv=sync cũng không gây hại. Cá nhân tôi thích đơn giản là nc -l -p 1234 > /dev/nvme0nX
    • Có lẽ phần lớn mạng cục bộ không nhanh hơn tốc độ truyền của SSD. Dù vậy, tôi tò mò liệu có tồn tại công cụ sao chép thiết bị khối I/O đồng thời cho những người có môi trường như vậy không
      Nếu đưa pv vào pipeline thì có thể xem thời gian hoàn tất dự kiến, nhưng có thể ảnh hưởng đôi chút đến hiệu năng
  • Cảm ơn AWS/Annapurna/Nitro/Lightbits đã đưa NVMe-over-TCP vào Linux
    https://www.techtarget.com/searchstorage/news/252459311/Ligh...
    “Liên minh NVM Express đã phê chuẩn NVMe/TCP làm tầng truyền tải binding vào tháng 11/2018. Tiêu chuẩn này phát triển từ nền tảng mã do đội ngũ kỹ thuật Lightbits ban đầu gửi lên NVM Express.”
    https://www.lightbitslabs.com/blog/linux-distributions-nvme-...
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin...

  • Trông rườm rà hơn nhiều so với cách bên dưới: nbdkit file /dev/nvme0n1, nbdcopy nbd://otherlaptop localfile

    • Cách này thực sự tốt hơn nhiều, vì nbdcopy có thể xử lý file thưa, có thể đặt số kết nối và số luồng theo số core, có thể ép flush trước khi kết thúc và cũng bật được thanh tiến độ. Nếu là ổ chưa mã hóa thì cũng hỗ trợ TLS
  • Gần đây tôi phải cài xubuntu trên một laptop mới. Trước đây tôi thường clone, nhưng lần này muốn sắp xếp lại một số cấu hình
    Việc truyền 10Gb/s bằng cáp USB-C thật sự hữu ích, vì lựa chọn khác chỉ còn WiFi
    Cắm hai máy tính vào nhau là một mạng tạm thời được hình thành, rồi chỉ cần chuyển bằng rsync. Nhìn thì có vẻ đường truyền đã bão hòa, nên dùng giao thức khác cũng không có nhiều ý nghĩa. Tất nhiên học cái mới là tốt, nhưng có thể không phải vào lúc đang clone laptop

    • Tôi tò mò không biết nó có chạy ngay không. Lần cuối tôi thử kết nối trực tiếp không phải Ethernet là từ thập niên 90, nên hỏi nghiêm túc đấy
    • Tôi cũng đã thử, nhưng để mạng hoạt động thì phải mua cáp Thunderbolt 4 giá trên 30 đô. Chỉ cáp USB3-C thông thường là không đủ
      Bản thân việc truyền thì cực nhanh, chuyển 1TB chỉ trong vài phút. Lần này không dùng mã hóa nên đơn giản hơn nhiều
    • Tôi tò mò là bạn đã boot bằng live disk rồi chuyển toàn bộ filesystem, hay cài hệ thống cơ bản trước rồi chỉ chuyển file
  • Tôi không hiểu vì sao lại không pipe btrfs qua mạng. Trước tiên tạo snapshot btrfs, rồi làm btrfs send => nc => network => nc => btrfs receive thì chỉ các block đang được dùng mới được truyền

    • Ngay khi thấy dùng btrfs, tôi cũng nghĩ đến điều đó đầu tiên. Tôi luôn dùng btrfs send/receive qua SSH và nó chạy rất tốt. Có lẽ cũng có thể dễ dàng dựng SSH server trong phiên live GRML
      Tuy nhiên có một điểm cần lưu ý. Trong btrfs không thể gửi snapshot theo cách đệ quy, nên nếu có nhiều snapshot đệ quy thì việc mirror cùng cấu trúc sang đĩa mới tương đối khó. Điều đó có thể xảy ra với Docker/LXD/Incus. Tôi thích btrfs, nhưng send/receive đệ quy là phần ZFS làm tốt hơn
  • Gần đây tôi phải sao chép khoảng 200GB file qua WiFi. Tôi dùng rsync để khi kết nối lỗi không phải bắt đầu lại từ đầu, và để không mất dữ liệu, nhưng mất ít nhất 6 giờ. Không biết có cách nào tốt hơn không
    Và tôi cũng tò mò cách dùng dd mang lại bảo đảm gì. Có phải so sánh md5 của block device kết quả không?

    • Chuyển 200GB qua WiFi trong 6 giờ thì thông lượng không ấn tượng lắm đối với truyền nội bộ. Có lẽ nên dùng cáp Ethernet
      WiFi có nhiều nguyên nhân gây nghẽn hiệu năng hơn hẳn. Chỉ cần nối ít nhất một thiết bị với router bằng cáp, còn thiết bị kia để không dây, cũng đã giúp khá nhiều
    • Nếu file rất nhiều và nhỏ, nhiều khả năng nút thắt là việc rsync chỉ truyền từng file một. Có thể chia danh sách file bằng xargs/parallel để chạy nhiều instance rsync, hoặc dùng thứ như rclone vốn hỗ trợ truyền song song
    • 6 giờ tương đương khoảng 10MB/s, nên rất có thể đã có thể làm nhanh hơn nhiều. Không biết bạn có nén bằng -z không. Nếu dùng được Ethernet thì trên phần lớn thiết bị có thể gần 100MB/s, tức khoảng 35 phút
    • Nếu phương thức truyền của rsync là SSH thì thường chính nó là nút thắt. OpenSSH trước đây từng có các giới hạn hiệu năng kỳ lạ, và có thời phải dùng một bản vá ít người biết để обход qua. Nếu CPU không phải nút thắt, bật nén cũng có ích
    • WiFi chia sẻ môi trường truyền là không khí với mọi thiết bị không dây khác. Khi phát hiện va chạm, nó dừng lại rồi chờ một khoảng thời gian ngẫu nhiên
      “Trong mạng máy tính, đa truy cập cảm nhận sóng mang tránh va chạm (CSMA/CA) là một phương thức đa truy cập mạng sử dụng cảm nhận sóng mang, nhưng cố tránh va chạm bằng cách chỉ bắt đầu truyền sau khi kênh được phát hiện là ‘rỗi’. Khi truyền, nút gửi toàn bộ dữ liệu gói
      Điều này đặc biệt quan trọng trong mạng không dây, nơi không thể dùng CSMA/CD, cơ chế phát hiện va chạm, vì bộ phát không dây khiến bộ thu bị mất nhạy và gần như tắt trong lúc truyền gói
      CSMA/CA kém tin cậy do vấn đề nút ẩn
      CSMA/CA là một giao thức hoạt động ở tầng liên kết dữ liệu.”
      https://en.wikipedia.org/wiki/Carrier-sense_multiple_access_...
  • Cách tiếp cận này hẳn có ưu điểm, nhưng trước đây khi chuyển laptop, tôi chạy trình cài đặt ở cả hai bên rồi kết hợp dd với nc. Theo trí nhớ thì tôi còn thêm gzip để truyền các vùng null lớn nhanh hơn
    Nếu laptop mới không có cổng Ethernet, cách hacky của tôi có thể đã nhanh hơn một chút nhờ nén. Vì với một liên kết mạng tốc độ cao, hẳn nó vẫn chưa chạm tới giới hạn mà nén bổ sung gây ra

    • Nếu đang mã hóa toàn bộ đĩa, trừ khi đã chỉ thị cho LUKS cho TRIM đi qua, thì với cách tác giả mô tả, về cơ bản bạn chỉ nhận được dữ liệu ngẫu nhiên
  • Cứ dùng Clonezilla là được mà? Nó chỉ sao chép các block dữ liệu thực sự và cũng có thể tự động chỉnh kích thước phân vùng. Tôi luôn làm như vậy
    Tất nhiên thường thì tôi tháo đĩa NVMe khỏi laptop rồi cắm vào dock tốc độ cao

    • Clonezilla rất tuyệt. Nó chỉ có một việc phải làm và thường thành công ngay lần đầu. Chỉ có điều phàn nàn duy nhất là vì đường cong học ban đầu nên phải mày mò thử nhiều thứ
      Vẫn chưa đến mức có thể hoàn toàn tin tưởng rồi bỏ mặc. Backup không giống với backup cộng restore, nên nên thử nghiệm. Clonezilla cũng có thể gặp vấn đề khi tạo lại phân vùng trên một đĩa rất khác so với bản gốc
  • Đã hàng chục năm rồi tôi không thực sự “cài” hệ điều hành lên desktop hay laptop; tôi luôn sao chép file rồi chỉ chỉnh những phần cần thiết. Thường thì tôi nhân dịp này tạo filesystem mới rồi chuyển file bằng rsync, để cập nhật các tham số như loại filesystem hay kích thước block, mã hóa, v.v.
    Dù vậy, nếu là kiểu người lên kế hoạch trước, có lẽ một cách khai báo hơn như NixOS, nơi chỉ sao chép cấu hình còn phần còn lại tự động cài lại, sẽ tốt hơn

  • Nếu kết nối trực tiếp các thiết bị bằng WiFi mà không qua AP trung gian, có lẽ có thể tăng gấp đôi tốc độ truyền. Trong tình huống này thì đáng để thử