服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

266次阅读
没有评论

共计 10721 个字符,预计需要花费 27 分钟才能阅读完成。

内容目录

时光匆匆,发现自己已经很久没有动笔写博客了。瞥了一眼掘金,上一篇博客居然还停留在 22 年。五年间,似乎自己变得越发慵懒,或许是因为一旦进入舒适区,就不太愿意再去挑战自己,不管是在技术上还是生活中。刚毕业时,心怀梦想,全力钻研各种新技术,渴望进入大厂一窥天地,然而渐渐发现,这一切似乎并没有给自己带来太多的惊喜。最近和一位同学聊天,他说自己坚持工作的动力就是知道下周就发工资了。或许对我来说也是如此,只有在即将面试时才会匆匆刷技术文档,编写开源代码。废话不多说,直入正题吧。

简单说一下写这篇博客的原因吧,一是最近闲着也是闲着,写与不写周末这样都过去了;二是用最近很火的庆余年 2 中话说就是做事要留痕,毕竟也是实打实的将云服务迁移到了自建服务器上嘛,写写日志。

物联网应用基建

云服务器,大家熟悉到不能在熟悉的词,不管什么岗位,只要是和计算机沾边的工作,什么阿里云、腾讯云、华为云
天翼云,国内外有一大批的云服务商。
不讨论企业级的应用,单说对于个人开发者和技术爱好者来说,云服务器给确实带来了许多便利和好处。云服务器的灵活性和方便性大大降低了技术学习的试错成本,通过云服务器可以随意的折腾系统,部署服务,有问题大不了直接重置服务器,也不用担心主板烧了,开不了机。
但是,就像所有事物一样,云服务器也有它的弊端。首先是价格问题,虽然云服务器提供了按需付费的方式,但长期使用可能会带来不小的花费,特别是对于个人开发者来说,这就是是个负担。此外,对于一些技术水平较低的人来说,如果要基于物理机自己搭建和管理服务器可能会有一定的技术难度,需要花费额外的时间和精力来学习和解决各种技术问题。因此,这篇博客的意义就在于给技术萌新指一条除云服务器之外的一条道,当然技术大佬们也可以一起指点指点。

起因

这几年断断续续的做了一些个人的项目,都部署在云服务器上,这些服务器大都是三年前捡漏购置的云服务器,比如三年前以极低价买了台某讯云 4 核 8G 的。最近这几台服务器都濒临到期,一看账单就是不想掏的冤枉钱,比如说这个,2 核 4g 续一年就是一千多。
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略
再比如说这个更离谱一年七千多

服务器迁徙大作战:从虚拟到物理的服务迁移全攻略
因为大部分都是流量非常小的应用,还不如自己搞台物理机搭建,搞搞穿透,配置又高,成本又低,尔乐而不为,说干就干,所以说到底还是穷,不想掏这些资源的费用。

准备台物理主机

搭建服务器受首先就得有台主机,家里其实是有废弃的台式电脑,最开始想想也能用,但看了下能耗和噪音,确实是有些不太理想,服务器这东西总不能频繁的关机吧,耗电确实是个问题,而且分贝太高,风扇呼呼的转影响睡眠。所以目光最后投向了最近这两年特火的迷你主机,千元内的新机大部分配置相当可以,能耗、配置、造影都是相当能打的,之前论坛说零刻系列性价比可以,但看了看价格还是在预期之外,最后还是选了铭凡系列的 UNI100,4 核 CPU + 500G 存储 + 16G 内存,配置杠杠的, 可以把之前的的伪 K83 集群直接改成单节点,物理机准备就绪接下来就是系统改造。

系统装配

Ubuntu Server 安装

服务器端的操作系统很多,随便选一个适合自己的操作系统就行,我个人习惯 Ubuntu, Ubuntu 有各种的发行版,常见的 Ubuntu Desktop、Ubuntu Server、Kubuntu 等,直接上 Ubuntu Server 中规中矩。Ubuntu Desktop 它是面向桌面、笔记本电脑和工作站的版本。该版本包括了大量的预装软件,当作服务器来说太重了。

IOS 下载

直接进入官网 Ubuntu Server 找到适合的版本下载,文件比较大,耐心等待下载完毕即可。

启动盘

大部分重装系统方式都是通过启动盘的方式。找一个口碑比较好的启动盘制作工具,此处以 UltraISO 为例,插入空闲的 U 盘后直接写入 IOS 即可,按提示步骤即可。
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

系统安装

启动盘制作完成后,插入主机,通过 BIOS 启动进入系统安装界面,不同型号的电脑进入方式可能不一样,大部分 长按 F2 或者 F7 再或者 F8。

进入安装引导菜单

选择【Try or Install Ubuntu Server】安装系统。
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

选择安装语言 && 不更新安装

默认选择【English】,没有中文,可以不用找了,然后继续选择【Continue without updating】
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

选择键盘布局

默认就好,不用修改
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

选择安装类型

默认 Ubuntu Server, 不用改直接下一步;
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

Network 配置(非常重要)

网络配置非常重要,不熟悉的建议第一次配置成 DHCP(自动获取 IP 地址),系统装配完成后再设置静态 IP,新手上路第一次建议直接配置 wifi,配置 wifi 时选中 对应的端口选中 DHCP 即可进入 wifi 的连接界面(这里忘记截图了)。
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

代理配置默认不填

服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

atp 源 配置

这个看自己情况吧,也可以配置成国内的,像阿里的,清华的都可以

分区配置

新手不建议改,默认就好,老手其实也可以不改(没有截图,网上找了张顶一顶);
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

配置登录的普通用户和主机名

服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

安装 ssh

服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

重启

安装完成后重启
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

服务器组网

系统安装完成后,建议将机器的 IP 固定,一是 连接 SSH 方便,二是代码开发时服务时不用每次调整 Api。
先通过 ip addr 查看当前主机的 ip 地址(安装系统时配置了 DHCP, 已经获取了一个可用的 ip),如果没有特殊要求,可以直接拿这个 IP 当作静态 IP, 按正常的架构来说,服务器应该有独立的路由,单本次因为只有单节点,故家中的路由器直接拿来用。
服务器迁徙大作战:从虚拟到物理的服务迁移全攻略

网络配置

Ubuntu 的网络配置文件一般在 /etc/netplan 目录下,至于哪个文件,不同的版本不太一样,例如 50-cloud-init.yaml,找到配置文件后直接编辑配置

# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    ethernets:
        enp1s0:
            dhcp4: false   # 宽带的接口也禁用掉自动获取 IP
        enp3s0:
            dhcp4: false   # 宽带的接口也禁用掉自动获取 IP
    version: 2
    wifis:
        wlo1:
            access-points:
                "wifi 名称 ":  # wifi 名称,无法直接输入中文的,需要先进行 ascii 编码
                    password: 'wifi 密码 '  # wifi 的密码
            dhcp4: false  # 禁用掉自动获取 IP
            routes:  # 路由配置
              - to: 0.0.0.0/0   # 所有的来源
                via: x.x.x.x   # 全部路由到网关层面
            addresses: [192.168.3.26/24] # 需要固定的 IP
            nameservers:
                addresses:   ## DNS 配置 国内建议配置国内的解析
                  - 180.76.76.76
                  - 114.114.114.114
                  - 8.8.8.8

编辑设置完成后执行更新即可

sudo netplan apply
sudo systemctl restart systemd-networkd

国内常用的 DNS

  • 114DNS 服务 114.114.114.114
  • 阿里 DNS 服务 223.5.5.5
  • 百度 DNS 服务 180.76.76.76
  • 腾讯 DNS(DNSPod)119.29.29.29

    常见问题

    有部分的 Ip、域名无法 ping 通

    设置 wifi 后 可以 ping 通 www.baidu.com 但无法 ping 通外部的 ip 例如 ping 114.114.114.114 显示 ping: connect: Network is unreachable
    这是目前的 route , 发现当前并未配置网关。

    Kernel IP routing table
    Destination Gateway Genmask Flags Metric Ref Use Iface
    172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
    192.168.3.0 0.0.0.0 255.255.255.0 U 0 0 0 wlo1     

    针对这种问题,只需要编辑 配置网关路由即可 sudo vi /etc/netplan/50-cloud-init.yaml

    # This file is generated from information provided by the datasource.  Changes
    # to it will not persist across an instance reboot.  To disable cloud-init's
    # network configuration capabilities, write a file
    # /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
    # network: {config: disabled}
    network:
    ethernets:
        enp1s0:
            dhcp4: false   # 宽带的接口也禁用掉自动获取 IP
        enp3s0:
            dhcp4: false   # 宽带的接口也禁用掉自动获取 IP
    version: 2
    wifis:
        wlo1:
            access-points:
                "wifi 名称 ":  # wifi 名称,无法直接输入中文的,需要先进行 ascii 编码
                    password: 'wifi 密码 '  # wifi 的密码
            dhcp4: false  # 禁用掉自动获取 IP
            routes:  # 路由配置
              - to: 0.0.0.0/0   # 所有的来源
                via: x.x.x.x   # 全部路由到网关层面
            addresses: [192.168.3.26/24] # 需要固定的 IP
            nameservers:
                addresses:   ## DNS 配置 国内建议配置国内的解析
                  - 180.76.76.76
                  - 114.114.114.114
                  - 8.8.8.8

发现配置后还是无法 ping 通 发现是 114.114.114.144 的 dns 解析有问题时可以替换别的 DNS, 例如百度的 dns(180.76.76.76)。此时大概率就可以了,不论是内网还是公网。

marvin@ubuntu:~$ ping www.baidu.com
PING www.baidu.com (36.155.132.76) 56(84) bytes of data.
64 bytes from 36.155.132.76: icmp_seq=1 ttl=52 time=13.7 ms
64 bytes from 36.155.132.76: icmp_seq=2 ttl=52 time=15.4 ms
64 bytes from 36.155.132.76: icmp_seq=3 ttl=52 time=15.0 ms
^C
--- www.baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 13.687/14.681/15.373/0.720 ms
marvin@ubuntu:~$ ping 180.76.76.76
PING 180.76.76.76 (180.76.76.76) 56(84) bytes of data.
64 bytes from 180.76.76.76: icmp_seq=1 ttl=50 time=38.9 ms
64 bytes from 180.76.76.76: icmp_seq=2 ttl=50 time=40.7 ms
64 bytes from 180.76.76.76: icmp_seq=3 ttl=50 time=40.6 ms
^C
--- 180.76.76.76 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 38.917/40.068/40.675/0.814 ms
marvin@ubuntu:~$ ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.089 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.114 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.116 ms
^C
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2063ms
rtt min/avg/max/mdev = 0.089/0.106/0.116/0.012 ms

至此基于服务器的基础已经安装完毕,接下来就是安装一些底层的基座,例如 docker、k8s 集群等。

基础设施

docker

Docker 提供了一键脚本,可以直接使用进行安装,安装命令如下所示:

curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh

安装完成以后通过可以 docker version 即可确认到版本信息:

root@canyuegongzi:~# docker version
Client: Docker Engine - Community
 Version:           20.10.6
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        370c289
 Built:             Fri Apr  9 22:46:01 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       8728dd2
  Built:            Fri Apr  9 22:44:13 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.4
  GitCommit:        05f951a3781f4f2c1911b05e61c160e9c30eaa8e
 runc:
  Version:          1.0.0-rc93
  GitCommit:        12644e614e25b05da6fd08a38ffa0cfe1903fdec
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

通过 systemctl start docker 启动 Docker:

systemctl start docker  // 启动 docker
docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

k3s

k3s 是简化版的 K8S, 麻雀虽小,五脏俱全,特别喜欢轻量级的集群部署,详细信息可以移步 K3S
k3s 早期时候因为国内网络的原因,无法通过官方的提供的脚本一键安装,只能通过离线安装的方式。2020 年之后官方提供了国内环境下的安装脚本。

curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -s - --docker

通过 k3s kubectl get node 验证 k3s 是否安装成功。

k3s kubectl get node
k3s kubectl get node
NAME           STATUS   ROLES                  AGE   VERSION
ubuntu  Ready    control-plane,master   87s   v1.20.6+k3s1

至此一些底层的软件部署完毕,开始部署一些上层的应用,诸如 Mysql, redis 等

mysql

此处只是简单贴了下 mysql 的部署 yml 配置,其中的具体配置信息,感兴趣的可以深度钻研下 k8S 的配置。

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-data-dev.cnf
  namespace: test
data:
  my.cnf: |
    [mysqld]
    port = 3306
    character-set-server=utf8mb4
    collation-server=utf8mb4_unicode_ci
    skip-character-set-client-handshake=1
    default-storage-engine=INNODB
    max_allowed_packet = 500M
    explicit_defaults_for_timestamp=1
    long_query_time = 10

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-1gi-mysql-data
  labels:
    type: local
spec:
  storageClassName: manual-mysql-data
  capacity:
    storage: 4Gi
  accessModes:
    - ReadWriteOnce # 卷可以被一个节点以读写方式挂载
  hostPath:
    path: "/mnt/data"

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: mysql-data-pvc
  namespace: gpt
spec:
  storageClassName: manual-mysql-data
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 4Gi

---
# https://www.cnblogs.com/JoePotter/p/16703055.html
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mysql-data-deployment
  namespace: gpt
  labels:
    app: mysql-data
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mysql-data
  template:
    metadata:
      labels:
        app: mysql-data
    spec:
      containers:
        - name: mysql-data
          #image: mysql:8.0.24 #  mysql:8.0.30-debian
          image: mysql:8.0.24
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: 123456
          ports:
            - containerPort: 3306
          volumeMounts:
            - mountPath: /var/lib/mysql
              name: mysql-data
            - name: mysql-config
              mountPath: /etc/mysql/mysql.conf.d
      imagePullSecrets:
        - name: aliyun-register-pwd
      volumes:
        - name: mysql-data
          hostPath:
            path: /data/mysql
            type: Directory
        - name: mysql-config
          hostPath:
            path: /data/mysql-config
            type: Directory

## --tls-san 参数是可以允许公网 ip 证书

---
apiVersion: v1
kind: Service
metadata:
  name: mysql-data-service
  namespace: gpt
spec:
  type: LoadBalancer
  selector:
    app: mysql-data
  ports:
    - protocol: TCP
      port: 3306
      targetPort: 3306
      nodePort: 3306

redis

redis 也类似,K8S 的内容不在本次博客之内,感兴趣的可以深度学习 K8S 的运维之道。

apiVersion: v1
kind: ConfigMap
metadata:
  name: redis
  namespace: test
data:
  redis.conf: |+
    requirepass 123456
    protected-mode no
    port 6379
    tcp-backlog 511
    timeout 0
    tcp-keepalive 300
    daemonize no
    supervised no
    pidfile /var/run/redis_6379.pid
    loglevel notice
    logfile ""
    databases 16
    always-show-logo yes
    save 900 1
    save 300 10
    save 60 10000
    stop-writes-on-bgsave-error yes
    rdbcompression yes
    rdbchecksum yes
    dbfilename dump.rdb
    dir /data
    slave-serve-stale-data yes
    slave-read-only yes
    repl-diskless-sync no
    repl-diskless-sync-delay 5
    repl-disable-tcp-nodelay no
    slave-priority 100
    lazyfree-lazy-eviction no
    lazyfree-lazy-expire no
    lazyfree-lazy-server-del no
    slave-lazy-flush no
    appendonly yes
    appendfilename "appendonly.aof"
    appendfsync everysec
    no-appendfsync-on-rewrite no
    auto-aof-rewrite-percentage 100
    auto-aof-rewrite-min-size 64mb
    aof-load-truncated yes
    aof-use-rdb-preamble no
    lua-time-limit 5000
    slowlog-log-slower-than 10000
    slowlog-max-len 128
    latency-monitor-threshold 0
    notify-keyspace-events Ex
    hash-max-ziplist-entries 512
    hash-max-ziplist-value 64
    list-max-ziplist-size -2
    list-compress-depth 0
    set-max-intset-entries 512
    zset-max-ziplist-entries 128
    zset-max-ziplist-value 64
    hll-sparse-max-bytes 3000
    activerehashing yes
    client-output-buffer-limit normal 0 0 0
    client-output-buffer-limit slave 256mb 64mb 60
    client-output-buffer-limit pubsub 32mb 8mb 60
    hz 10
    aof-rewrite-incremental-fsync yes

---

apiVersion: v1
kind: PersistentVolume
metadata:
  name: redis-pv-1gi
  labels:
    type: local
spec:
  storageClassName: manual-redis
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce # 卷可以被一个节点以读写方式挂载
  hostPath:
    path: "/mnt/data"

# deploy nacos pvc
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: redis-pvc
  namespace: gpt
spec:
  storageClassName: manual-redis
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: gpt
  labels:
    app: redis
spec:
  strategy:
    type: Recreate
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          #image: redis
          image: registry.cn-hangzhou.aliyuncs.com/redis:2.1.1
          imagePullPolicy: Always
          command: ["redis-server","/etc/redis/redis.conf"]
          ports:
            - containerPort: 6379
          volumeMounts:
            - name: redis-config
              mountPath: /etc/redis/redis.conf
              subPath: redis.conf
            - name: redis-persistent-storage
              mountPath: /data
      imagePullSecrets:
        - name: aliyun-register-pwd
      volumes:
        - name: redis-config
          configMap:
            name: redis
            items:
              - key: redis.conf
                path: redis.conf
        - name: redis-persistent-storage
          persistentVolumeClaim:
            claimName: redis-pvc

---
kind: Service
apiVersion: v1
metadata:
  name: redis
  namespace: gpt
spec:
  type: LoadBalancer
  selector:
    app: redis
  ports:
    - port: 6379
      protocol: TCP
      targetPort: 6379

业务应用

业务应用 此处也不再录累赘,后续有时间刻印挑几个应用做示例

网络穿透

暂时还没有做这部分的能力,马上完成后再做博客分享。

正文完
 7
评论(没有评论)