如何迁移 Linux 服务器 第一部分 - 系统准备

发布于:2024-10-17 ⋅ 阅读:(5) ⋅ 点赞:(0)

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站

简介

在许多情况下,您可能需要将数据和操作需求从一个服务器迁移到另一个服务器。您可能需要在新的数据中心实施解决方案,升级到更大的机器,或者过渡到新的硬件或新的 VPS 提供商。

无论您的原因是什么,在从一个系统迁移到另一个系统时,您应该考虑许多不同的因素。如果您没有使用 Chef、Puppet 或 Ansible 等配置管理解决方案,要获得功能上等效的配置可能会很困难。您不仅需要传输数据,还需要配置您的服务在新机器上以相同的方式运行。

在本指南中,您将了解如何准备源系统和目标系统进行迁移。这将包括让您的两台机器使用 SSH 密钥进行通信,并调查需要转移的组件。您将在本系列的下一篇文章中开始实际迁移。

步骤 1 – 创建备份

执行任何可能具有破坏性的操作时,首先要采取的步骤是创建全新的备份。您不希望在替换正在运行的生产机器之前,某个命令在当前生产机器上出现故障。

有许多不同的方法可以备份服务器。您的选择将取决于对您的情况有意义的选项以及您最熟悉的选项。

如果您可以访问物理硬件并有备份空间(磁盘驱动器、USB 等),您可以使用许多可用的镜像备份解决方案之一来克隆磁盘。在处理云服务器时,功能上等效的方法是在控制面板界面内拍摄快照或镜像。

完成备份后,您就可以继续进行下一步了。在本指南的其余部分,您将需要以 root 用户身份运行许多命令,或者使用 sudo

步骤 2 – 收集有关源系统的信息

在开始迁移之前,您应该配置目标系统以匹配源系统。

您将希望在当前服务器和计划迁移到的服务器之间尽可能匹配。您可能希望在迁移到较新的目标系统之前升级当前服务器,并在此之后再次进行备份。重要的是,当开始实际迁移时,它们尽可能匹配。

大部分可以帮助您决定为新机器创建哪种服务器系统的信息可以使用 uname 命令检索:

uname -r
5.4.0-26-generic

这是您当前系统正在运行的内核版本。为了使事情顺利进行,最好尝试在目标系统上匹配它。

您还应该尝试匹配源服务器的发行版和版本。如果您不知道在源机器上安装的发行版版本,可以通过输入以下命令来查找:

cat /etc/issue
Ubuntu 20.04.3 LTS \n \l

如果可能的话,您应该使用相同的参数创建新服务器。在这种情况下,您将创建一个 Ubuntu 20.04 系统。您还应尽量匹配内核版本。通常情况下,这应该是来自您的 Linux 发行版存储库的最新内核。

步骤 3 – 在源和目标服务器之间设置 SSH 密钥访问

您需要让您的服务器能够通信以便传输文件。为了做到这一点,您应该在它们之间交换 SSH 密钥。您可以学习如何在 Linux 服务器上配置 SSH 密钥。

您需要在目标服务器上创建一个新密钥,以便将其添加到现有服务器的 authorized_keys 文件中。这比另一种方式更清晰,因为这样,当迁移完成时,新服务器的 authorized_keys 文件中就不会有多余的密钥。

首先,在目标机器上,通过输入以下命令检查您的 root 用户是否已经拥有 SSH 密钥:

ls ~/.ssh
authorized_keys

如果您看到名为 id_rsa.pubid_rsa 的文件,则表示您已经拥有密钥,您只需要将它们传输过去。

如果您没有看到这些文件,可以使用 ssh-keygen 创建新的密钥对:

ssh-keygen -t rsa

按照提示按下 “Enter” 键以接受默认值。

现在,您可以通过 ssh 将密钥传输到源服务器:

cat ~/.ssh/id_rsa.pub | ssh other_server_ip "cat >> ~/.ssh/authorized_keys"

现在,您应该能够在目标系统上自由地通过 SSH 连接到源服务器,而无需提供密码:

ssh other_server_ip

这将使任何进一步的迁移步骤更加顺利。

步骤 4 – 创建需求清单

现在你将进行系统的深入分析。

在运营过程中,你的软件需求可能会发生变化。有时旧服务器上可能存在一些曾经需要的服务和软件,但已经被替换。

一般来说,不需要的服务可以被禁用,如果完全不需要,也可以被卸载,但是清点它们可能会耗费时间。你需要发现在源服务器上正在使用的服务,然后决定这些服务是否应该存在于新服务器上。

你发现服务和运行级别的方式取决于服务器所采用的“init”系统的类型。init 系统负责在用户命令或自动启动和停止服务。从 2014 年开始,几乎所有主要的 Linux 发行版都采用了一个名为 Systemd 的 init 系统,本指南将反映 Systemd。

为了列出已注册到 Systemd 的服务,你可以使用 systemctl 命令:

systemctl list-units -t service
  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>
…

Systemd 通过“targets”实现服务管理。传统 init 系统的系统一次只能处于一个“运行级别”,而使用 Systemd 的服务器可以同时达到多个 targets。这在实践中更加灵活,但确定哪些服务是活动的可能更加困难。

你可以通过输入以下命令来查看当前活动的 targets:

systemctl list-units -t target
  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
…

你可以通过输入以下命令来列出所有可用的 targets:

systemctl list-unit-files -t target
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
…

从这里,你可以找出每个 target 关联的服务。Targets 可以有服务或其他 targets 作为依赖项,因此你可以通过输入以下命令来查看每个 target 实施的策略:

systemctl list-dependencies target_name.target

multi-user.target 是 Systemd 服务器上常用的一个 target,在启动过程中达到该目标时,用户可以登录。例如,你可以输入以下命令:

systemctl list-dependencies multi-user.target
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
…

这将列出该目标的依赖树,给出当达到该目标时启动的服务和其他 targets 的列表。

通过其他方法检查服务

虽然大多数由软件包管理器配置的服务将被注册到 init 系统中,但一些其他软件,如 Docker 部署,可能不会。

你可以尝试通过查看这些服务使用的网络端口和 Unix 套接字来找到这些其他服务和进程。在大多数情况下,服务以某种方式相互通信或与外部实体通信。服务器上只有一定数量的接口可以用于服务通信,检查这些接口是发现其他服务的好方法。

你可以使用 netstat 工具来发现正在使用的网络端口和 Unix 套接字。你可以使用 -nlp 标志运行 netstat 以获得概述:

netstat -nlp
  • -n 指定输出中应显示数字 IP 地址,而不是主机名或用户名。在检查本地服务器时,这通常更加信息丰富。
  • -l 指定 netstat 只显示活动监听套接字。
  • -p 显示每个使用端口或套接字的进程 ID(PID)和名称。
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
…

netstat 输出包含两个独立的块 —— 一个用于网络端口,一个用于套接字。如果你在这里看到了通过 init 系统没有信息的服务,你将不得不弄清楚原因,并确定是否打算迁移这些服务。

你可以使用 lsof 命令获取关于服务提供的端口的类似信息:

lsof
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)

netstatlsof 都是核心 Linux 进程管理工具,在各种其他情境中都很有用。

第五步 – 收集软件包版本

此时,你应该已经对源服务器上运行的服务有了一个很好的了解,你应该在目标服务器上实施这些服务。

你应该有一个服务列表,你知道你需要在新服务器上实施这些服务。为了顺利过渡,重要的是尽可能匹配版本。

你不一定要审查源系统上安装的每个软件包,并尝试在新系统上复制它,但你应该检查对你的需求重要的软件组件,并尝试找到它们的版本号。

你可以尝试从软件本身获取版本号,有时通过向每个命令传递 -v--version 标志,但通过你的软件包管理器更加直接。如果你使用基于 Ubuntu/Debian 的系统,你可以使用 dpkg 命令查看安装的软件包版本:

dpkg -l | grep package_name

如果你使用基于 Rocky Linux、RHEL 或 Fedora 的系统,你可以使用 rpm 来实现相同的目的:

rpm -qa | grep package_name

这将让你对要匹配的软件包版本有一个很好的了解。确保保留任何相关软件的版本号。

结论

现在,你应该已经很清楚源服务器上需要迁移到新机器的进程和服务。你还应该已经完成了允许你的两台服务器相互通信的初步步骤。

你的迁移基础现在已经完成。在本系列的下一篇文章中,你将开始实际的迁移过程。


网站公告

今日签到

点亮在社区的每一天
去签到