Trong nhiều tình huống, việc di chuyển dữ liệu và yêu cầu vận hành từ một máy chủ này sang máy chủ khác là cần thiết. Điều này có thể xảy ra khi bạn triển khai giải pháp tại một trung tâm dữ liệu mới, nâng cấp lên một máy chủ mạnh hơn, hoặc chuyển sang phần cứng mới hoặc nhà cung cấp VPS khác.
Dù lý do di chuyển là gì, có rất nhiều yếu tố quan trọng cần được xem xét để đảm bảo quá trình diễn ra suôn sẻ. Để đạt được cấu hình hệ thống tương đương về chức năng, việc sử dụng các công cụ quản lý cấu hình như Chef, Puppet hay Ansible là vô cùng quan trọng. Việc không chỉ chuyển dữ liệu mà còn cấu hình lại các dịch vụ để hoạt động chính xác trên máy chủ mới sẽ giúp hệ thống duy trì hiệu suất và tính ổn định như trước.
Lưu ý: Trong các triển khai hiện đại, bạn nên luôn sử dụng hệ thống quản lý cấu hình bất cứ khi nào có thể, cho dù đó là các node Kubernetes ngắn hạn hay các dịch vụ hệ thống kết hợp với phần mềm container hóa. Hướng dẫn này sẽ hữu ích chủ yếu trong những trường hợp không thể áp dụng tự động hóa, khi các dịch vụ cần được liệt kê và di chuyển thủ công.
Trong hướng dẫn này, bạn sẽ được xem qua cách chuẩn bị hệ thống nguồn và hệ thống đích cho việc di chuyển. Điều này bao gồm thiết lập giao tiếp giữa hai máy qua SSH Keys và khảo sát các thành phần cần được chuyển giao. Bạn sẽ bắt đầu quá trình di chuyển thực sự trong bài viết tiếp theo của loạt bài này.
Bước 1 – Tạo bản sao lưu
Bước đầu tiên khi thực hiện bất kỳ hành động có thể gây thay đổi dữ liệu là tạo bản sao lưu mới. Bạn không muốn rơi vào tình huống lệnh nào đó làm hỏng hệ thống sản xuất hiện tại trước khi máy chủ thay thế được khởi động.
Có rất nhiều cách để sao lưu máy chủ của bạn. Lựa chọn của bạn sẽ phụ thuộc vào các tùy chọn phù hợp với tình huống và cách làm quen của bạn với phương pháp đó.
Nếu bạn có quyền truy cập vào phần cứng vật lý và có không gian để sao lưu (ổ đĩa, USB, v.v.), bạn có thể sao chép đĩa bằng bất kỳ giải pháp backup image nào có sẵn. Trên các máy chủ đám mây, tương đương chức năng của việc này là tạo một snapshot hoặc image thông qua giao diện điều khiển.
Khi đã hoàn tất sao lưu, bạn đã sẵn sàng tiến hành các bước tiếp theo. Trong phần còn lại của hướng dẫn, bạn sẽ cần chạy nhiều lệnh với quyền root, hoặc sử dụng sudo.
Bước 2 – Thu thập thông tin về hệ thống nguồn
Trước khi bắt đầu di chuyển, bạn nên cấu hình hệ thống đích sao cho phù hợp với hệ thống nguồn.
Bạn sẽ muốn cấu hình càng giống càng tốt giữa máy chủ hiện tại và máy chủ mà bạn định di chuyển đến. Có thể bạn sẽ muốn nâng cấp máy chủ hiện tại trước khi chuyển sang hệ thống đích mới, sau đó tạo thêm một bộ bản sao lưu mới. Điều quan trọng là đảm bảo rằng cả hai máy khởi đầu đều có cấu hình tương đồng càng nhiều càng tốt khi bắt đầu quá trình di chuyển.
Hầu hết thông tin cần thiết để quyết định hệ thống máy chủ mới có thể được lấy bằng lệnh uname
:
uname -r
Output 5.4.0-26-generic
Đây là phiên bản kernel mà hệ thống nguồn của bạn đang sử dụng. Để quá trình chuyển đổi diễn ra suôn sẻ, bạn nên cố gắng sử dụng phiên bản tương tự trên hệ thống đích.
Bạn cũng nên cố gắng khớp với bản phân phối và phiên bản của máy chủ nguồn. Nếu bạn không biết phiên bản của bản phân phối được cài đặt trên máy chủ nguồn, bạn có thể kiểm tra bằng cách gõ:
cat /etc/issue
Output Ubuntu 20.04.3 LTS \n \l
Bạn nên tạo máy chủ mới với các tham số này nếu có thể. Trong trường hợp này, bạn sẽ tạo một hệ thống Ubuntu 20.04. Ngoài ra, hãy cố gắng sử dụng phiên bản kernel càng gần với máy chủ nguồn càng tốt. Thông thường, nên sử dụng phiên bản kernel mới nhất có sẵn từ kho lưu trữ của bản phân phối Linux.
Bước 3 – Thiết lập truy cập SSH Key giữa máy chủ nguồn và đích
Bạn cần đảm bảo rằng các máy chủ có thể giao tiếp với nhau để chuyển file. Để thực hiện điều này, bạn nên trao đổi SSH keys giữa chúng. Bạn có thể tìm hiểu cách cấu hình SSH keys trên máy chủ Linux.
Bạn sẽ cần tạo một key mới trên máy chủ đích để thêm vào file authorized_keys
của máy chủ nguồn hiện có. Cách này sạch sẽ hơn so với làm ngược lại, vì máy chủ mới sẽ không có key dư thừa trong file authorized_keys
sau khi quá trình di chuyển hoàn tất.
Đầu tiên, trên máy đích, kiểm tra xem người dùng root đã có SSH key chưa bằng cách gõ:
ls ~/.ssh
Output authorized_keys
Nếu bạn thấy các file như id_rsa.pub
và id_rsa
, tức là bạn đã có key và chỉ cần chuyển chúng qua máy chủ nguồn.
Nếu không thấy các file đó, hãy tạo một cặp key mới sử dụng ssh-keygen
:
ssh-keygen -t rsa
Nhấn “Enter” qua tất cả các lời nhắc để chấp nhận giá trị mặc định.
Bây giờ, bạn có thể chuyển key sang máy chủ nguồn bằng cách chuyển đầu ra của file key qua SSH:
cat ~/.ssh/id_rsa.pub | ssh other_server_ip "cat >> ~/.ssh/authorized_keys"
Bạn nên có thể SSH đến máy chủ nguồn từ máy đích mà không cần nhập mật khẩu:
ssh other_server_ip
Quá trình này sẽ giúp các bước di chuyển tiếp theo diễn ra suôn sẻ hơn.
Bước 4 – Tạo danh sách yêu cầu
Bây giờ bạn sẽ thực hiện phân tích chi tiết hệ thống của mình.
Trong quá trình vận hành, các yêu cầu phần mềm có thể thay đổi. Đôi khi, các máy chủ cũ có những dịch vụ và phần mềm từng cần thiết nhưng đã được thay thế.
Nói chung, các dịch vụ không cần thiết có thể được tắt và, nếu hoàn toàn không cần, gỡ bỏ, nhưng việc kiểm kê chúng có thể mất thời gian. Bạn cần xác định những dịch vụ nào đang được sử dụng trên máy chủ nguồn và sau đó quyết định xem có nên triển khai chúng trên máy chủ mới hay không.
Cách phát hiện các dịch vụ và runlevel phụ thuộc vào hệ thống “init” mà máy chủ của bạn đang sử dụng. Hệ thống init chịu trách nhiệm khởi động và dừng các dịch vụ, dù theo lệnh của người dùng hay tự động. Từ khoảng năm 2014 trở đi, hầu hết các bản phân phối Linux lớn đã áp dụng hệ thống init có tên Systemd, và hướng dẫn này sẽ dựa trên Systemd.
Để liệt kê các dịch vụ được đăng ký với Systemd, bạn có thể sử dụng lệnh systemctl
:
systemctl list-units -t service
Output UNIT LOAD ACTIVE SUB DESCRIPTION > accounts-daemon.service loaded active running Accounts Service > apparmor.service loaded active exited Load AppArmor profiles > apport.service loaded active exited LSB: automatic crash repor> atd.service loaded active running Deferred execution schedul> blk-availability.service loaded active exited Availability of block devi> cloud-config.service loaded active exited Apply the settings specifi> cloud-final.service loaded active exited Execute cloud user/final s> cloud-init-local.service loaded active exited Initial cloud-init job (pr> cloud-init.service loaded active exited Initial cloud-init job (me> console-setup.service loaded active exited Set console font and keyma> containerd.service loaded active running containerd container runti> …
Đối với việc quản lý dịch vụ, Systemd triển khai khái niệm “targets”. Trong khi hệ thống sử dụng init truyền thống chỉ có thể ở một “runlevel” tại một thời điểm, một máy chủ sử dụng Systemd có thể đạt tới nhiều target cùng lúc. Điều này linh hoạt hơn trong thực tế, nhưng việc xác định các dịch vụ đang hoạt động có thể trở nên phức tạp hơn.
Bạn có thể xem các target đang hoạt động bằng cách gõ:
systemctl list-units -t target
Output UNIT LOAD ACTIVE SUB DESCRIPTION basic.target loaded active active Basic System cloud-config.target loaded active active Cloud-config availability cloud-init.target loaded active active Cloud-init target cryptsetup.target loaded active active Local Encrypted Volumes getty.target loaded active active Login Prompts graphical.target loaded active active Graphical Interface local-fs-pre.target loaded active active Local File Systems (Pre) local-fs.target loaded active active Local File Systems multi-user.target loaded active active Multi-User System network-online.target loaded active active Network is Online …
Bạn có thể liệt kê tất cả các target có sẵn bằng cách gõ:
systemctl list-unit-files -t target
Output UNIT FILE STATE VENDOR PRESET basic.target static enabled blockdev@.target static enabled bluetooth.target static enabled boot-complete.target static enabled cloud-config.target static enabled cloud-init.target enabled-runtime enabled cryptsetup-pre.target static disabled cryptsetup.target static enabled ctrl-alt-del.target disabled enabled …
Từ đây, bạn có thể xác định các dịch vụ liên quan đến từng target. Các target có thể có các dịch vụ hoặc các target khác làm phụ thuộc, vì vậy bạn có thể xem các chính sách mà mỗi target thực thi bằng cách gõ:
systemctl list-dependencies target_name.target
Ví dụ, target multi-user.target
thường được sử dụng trên máy chủ Systemd và được khởi động khi người dùng có thể đăng nhập. Bạn có thể gõ:
Output multi-user.target ● ├─apport.service ● ├─atd.service ● ├─console-setup.service ● ├─containerd.service ● ├─cron.service ● ├─dbus.service ● ├─dmesg.service ● ├─docker.service ● ├─grub-common.service ● ├─grub-initrd-fallback.service …
Lệnh này sẽ liệt kê cây phụ thuộc của target, cho bạn danh sách các dịch vụ và target khác được khởi động cùng với target đó.
Kiểm tra dịch vụ qua các phương pháp khác
Trong khi hầu hết các dịch vụ được cài đặt qua package manager sẽ được đăng ký với hệ thống init, một số phần mềm khác như các triển khai Docker có thể không được đăng ký.
Bạn có thể tìm các dịch vụ khác và tiến trình bằng cách kiểm tra các cổng mạng và Unix sockets mà các dịch vụ đó đang sử dụng. Trong hầu hết các trường hợp, các dịch vụ sẽ giao tiếp với nhau hoặc với các thực thể bên ngoài theo một cách nhất định. Vì số giao diện máy chủ cho giao tiếp có hạn, việc kiểm tra chúng là một cách tốt để phát hiện các dịch vụ khác.
Một công cụ hữu ích để khám phá các cổng mạng và Unix sockets đang được sử dụng là netstat
. Bạn có thể chạy netstat
với các tham số -nlp
để có cái nhìn tổng quan:
netstat -nlp
Các tham số:
-
-n
: Hiển thị địa chỉ IP ở dạng số thay vì tên miền hay tên người dùng. Khi kiểm tra máy chủ cục bộ, điều này thường hữu ích. -
-l
: Hiển thị chỉ các socket đang lắng nghe. -
-p
: Hiển thị ID tiến trình (PID) và tên tiến trình sử dụng cổng hoặc socket.
Output Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:8200 0.0.0.0:* LISTEN 104207/vault tcp 0 0 0.0.0.0:1935 0.0.0.0:* LISTEN 3691671/nginx: mast tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 3691671/nginx: mast tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3691671/nginx: mast tcp 0 0 0.0.0.0:1936 0.0.0.0:* LISTEN 197885/stunnel4 tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 162540/systemd-reso tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 129518/sshd: /usr/s tcp 0 0 127.0.0.1:3000 0.0.0.0:* LISTEN 99465/node /root/he tcp 0 0 0.0.0.0:8088 0.0.0.0:* LISTEN 3691671/nginx: mast tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 3691671/nginx: mast tcp 0 0 0.0.0.0:56733 0.0.0.0:* LISTEN 170269/docker-proxy tcp6 0 0 :::80 :::* LISTEN 3691671/nginx: mast tcp6 0 0 :::22 :::* LISTEN 129518/sshd: /usr/s tcp6 0 0 :::443 :::* LISTEN 3691671/nginx: mast tcp6 0 0 :::56733 :::* LISTEN 170275/docker-proxy udp 0 0 127.0.0.53:53 0.0.0.0:* 162540/systemd-reso raw6 0 0 :::58 :::* 7 162524/systemd-netw raw6 0 0 :::58 :::* 7 162524/systemd-netw Active UNIX domain sockets (only servers) Proto RefCnt Flags Type State I-Node PID/Program name Path unix 2 [ ACC ] STREAM LISTENING 5313074 1/systemd /run/systemd/userdb/io.systemd.DynamicUser unix 2 [ ACC ] SEQPACKET LISTENING 12985 1/systemd /run/udev/control unix 2 [ ACC ] STREAM LISTENING 12967 1/systemd /run/lvm/lvmpolld.socket unix 2 [ ACC ] STREAM LISTENING 12980 1/systemd /run/systemd/journal/stdout unix 2 [ ACC ] STREAM LISTENING 16037236 95187/systemd /run/user/0/systemd/private …
Output của netstat
được chia thành hai khối riêng biệt — một cho các cổng mạng và một cho các socket. Nếu bạn phát hiện ra các dịch vụ ở đây mà không có thông tin thông qua hệ thống init, bạn sẽ cần xác định nguyên nhân và xem xét có cần di chuyển những dịch vụ đó hay không.
Bạn có thể lấy thông tin tương tự về các cổng mà dịch vụ mở bằng cách sử dụng lệnh lsof
:
lsof
Output COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME node\x20/ 99465 root 20u IPv4 16046039 0t0 TCP 127.0.0.1:3000 (LISTEN) vault 104207 vault 8u IPv4 1134285 0t0 TCP *:8200 (LISTEN) sshd 129518 root 3u IPv4 1397496 0t0 TCP *:22 (LISTEN) sshd 129518 root 4u IPv6 1397507 0t0 TCP *:22 (LISTEN) systemd-r 162540 systemd-resolve 12u IPv4 5313507 0t0 UDP 127.0.0.53:53 systemd-r 162540 systemd-resolve 13u IPv4 5313508 0t0 TCP 127.0.0.53:53 (LISTEN) docker-pr 170269 root 4u IPv4 1700561 0t0 TCP *:56733 (LISTEN) docker-pr 170275 root 4u IPv6 1700573 0t0 TCP *:56733 (LISTEN) stunnel4 197885 stunnel4 9u IPv4 1917328 0t0 TCP *:1936 (LISTEN) sshd 3469804 root 4u IPv4 22246413 0t0 TCP 159.203.102.125:22->154.5.29.188:36756 (ESTABLISHED) nginx 3691671 root 7u IPv4 2579911 0t0 TCP *:8080 (LISTEN) nginx 3691671 root 8u IPv4 1921506 0t0 TCP *:80 (LISTEN) nginx 3691671 root 9u IPv6 1921507 0t0 TCP *:80 (LISTEN) nginx 3691671 root 10u IPv6 1921508 0t0 TCP *:443 (LISTEN) nginx 3691671 root 11u IPv4 1921509 0t0 TCP *:443 (LISTEN) nginx 3691671 root 12u IPv4 2579912 0t0 TCP *:8088 (LISTEN) nginx 3691671 root 13u IPv4 2579913 0t0 TCP *:1935 (LISTEN) nginx 3691674 www-data 7u IPv4 2579911 0t0 TCP *:8080 (LISTEN) nginx 3691674 www-data 8u IPv4 1921506 0t0 TCP *:80 (LISTEN) nginx 3691674 www-data 9u IPv6 1921507 0t0 TCP *:80 (LISTEN) nginx 3691674 www-data 10u IPv6 1921508 0t0 TCP *:443 (LISTEN) nginx 3691674 www-data 11u IPv4 1921509 0t0 TCP *:443 (LISTEN) nginx 3691674 www-data 12u IPv4 2579912 0t0 TCP *:8088 (LISTEN) nginx 3691674 www-data 13u IPv4 2579913 0t0 TCP *:1935 (LISTEN)
Cả lệnh netstat
và lsof
đều là các công cụ quản lý tiến trình cốt lõi trên Linux, hữu ích trong nhiều bối cảnh khác nhau.
Bước 5 – Thu thập phiên bản các gói phần mềm
Tại thời điểm này, bạn nên đã có một ý tưởng rõ ràng về các dịch vụ đang chạy trên máy chủ nguồn mà bạn cần triển khai trên máy chủ đích.
Bạn đã có danh sách các dịch vụ cần thiết. Để quá trình chuyển đổi diễn ra suôn sẻ, điều quan trọng là cố gắng khớp phiên bản của phần mềm càng nhiều càng tốt.
Bạn không cần phải kiểm tra mọi gói phần mềm được cài đặt trên máy chủ nguồn và tái tạo chúng trên hệ thống mới, nhưng bạn nên kiểm tra các thành phần phần mềm quan trọng và ghi lại số phiên bản của chúng.
Bạn có thể lấy số phiên bản của phần mềm bằng cách chạy phần mềm đó với các tham số -v
hoặc --version
, nhưng cách đơn giản hơn là sử dụng package manager. Nếu bạn sử dụng hệ thống dựa trên Ubuntu/Debian, bạn có thể xem phiên bản của một gói được cài đặt bằng lệnh:
dpkg -l | grep package_name
Nếu bạn sử dụng hệ thống dựa trên Rocky Linux, RHEL, hoặc Fedora, bạn có thể dùng rpm
để kiểm tra:
rpm -qa | grep package_name
Lệnh trên sẽ cung cấp cho bạn số phiên bản của gói phần mềm mà bạn muốn khớp. Hãy nhớ lưu lại số phiên bản của các phần mềm liên quan.