内网yum源及后续思考扩展

小牛椰椰
·发布于 6 个月前
部署本地yum源(内网)

基于ISO镜像操作(比如本次的CentOS-8.5.2111-x86_64-dvd1.iso)

  1. 将iso文件上传至/opt目录,并挂载

    mkdir -p /mnt/cdrom
    mount -o loop /opt/CentOS-8.5.2111-x86_64-dvd1.iso /mnt/cdrom
    

    若是使用物理光驱或者虚拟机光驱,可以直接挂载设备(如/dev/cdrom)

    在虚拟机里面可以通过lsblk查看到是否有挂载

    [root@hadoop204 cdrom]# lsblk
    NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
    loop0         7:0    0 10.1G  0 loop /mnt/cdrom
    sda           8:0    0   50G  0 disk
    ├─sda1        8:1    0    1G  0 part /boot
    └─sda2        8:2    0   49G  0 part
      ├─cl-root 253:0    0 45.1G  0 lvm  /
      └─cl-swap 253:1    0    4G  0 lvm  [SWAP]
    sr0          11:0    1 10.1G  0 rom  /run/media/root/CentOS-8-5-2111-x86_64-dvd
    

    可以看到上述信息,说明已经有镜像文件挂载到/run/media/root/CentOS-8-5-2111-x86_64-dvd

    但一开始我没注意,重新挂了一份...

    说明:CentOS 8 默认包管理器是 dnfyum 实际是 dnf 的软链接,命令行为一致。可用以下方式验证:

    ls -l /usr/bin/yum
    
  2. 备份并清理原有repo

    mkdir -p /etc/yum.repos.d/backup
    mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup
    
  3. 创建本地repo文件

    cat >/etc/yum.repos.d/local.repo<<EOF
    > [local]
    > name=Local Cent0s Repository
    > baseurl=file:///mnt/cdrom
    > enabled=1
    > gpgcheck=0
    > gpgkey=file:///mnt/cdrom/RPM-GPG-KEY-Cent0s-8
    > EOF
    

    上述gpgcheck可为1,也可为0.若要为1,下面的gpgkey注意对应配置(cd /mnt/cdrom/可以看到这个key)

  4. 验证本地源

    yum clean all 
    yum makecache
    yum repolist
    

    image-20251204104648287

​ 虽然仓库有了,但明显看yum list没成功,代表哪里有点问题...

插曲解决

上面可以看到他在说,读取不到/mnt/cdrom/repodata/repomd.xml

前往这个目录看到如下内容:

image-20251204105032082

确实连repodata这个文件夹都没有,用find命令查了一下有没有repomd.xml文件

[root@hadoop204 cdrom]# find /mnt/cdrom -name repomd.xml
/mnt/cdrom/AppStream/repodata/repomd.xml
/mnt/cdrom/BaseOS/repodata/repomd.xml
[root@hadoop204 cdrom]#

可以看到是有的,只是目录不对,后面了解了一下,是由于CentOS 8的仓库结构不同导致

CentOS 8的ISO中有两个主要仓库:

  • /mnt/cdrom/BaseOS/ - 基础操作系统包
  • /mnt/cdrom/AppStream/ - 应用流包

所以需要调整一下配置文件即可:

# 备份原有配置
cp /etc/yum.repos.d/local.repo /etc/yum.repos.d/local.repo.backup

# 创建新的配置文件
cat > /etc/yum.repos.d/local.repo << 'EOF'
[Local-BaseOS]
name=Local CentOS-BaseOS
baseurl=file:///mnt/cdrom/BaseOS
enabled=1
gpgcheck=0

[Local-AppStream]
name=Local CentOS-AppStream
baseurl=file:///mnt/cdrom/AppStream
enabled=1
gpgcheck=0
EOF

# 清除yum缓存
yum clean all

# 列出可用仓库
yum repolist

# 查看有无需要软件包
yum search 包名

image-20251204110420968

现在就可以使用本地yum源了。

必看小节

上述挂载后,若重启机器后又要重新挂载,若有需要可以设计开机自挂载。

echo "/opt/CentOS-8.5.2111-x86_64-dvd1.iso /mnt/cdrom iso9660 loop,ro 0 0" >> /etc/fstab
部署阿里yum源或其他(外网)

确保能通外网的情况下,直接下载阿里yum源(或者清华yum等等,确保对应yum源存在,符合使用要求)

// 下载对应阿里yum源
curl -o /etc/yum.repos.d/Centos-Base.repo https://mirrors.aliyun.com/repo/Centos-8.repo

//清理并生成缓存
yum clean all
yum makecache

// 查看当前所有yum
yum repolist all

image-20251208111154290

可以发现当前有的是禁用的(阿里源)

如果要启用可以用yum-config-manager --enable xxxxxx 开启(该命令需要安装,如果实在不能用就去对应的repo文件里将对应仓库的enabled修改为1)

//开启阿里对应的yum仓库
yum-config-manager --enable AppStream,extras,base
//关闭本地yum仓库
yum-config-manager --disable Local-*

现在就可以使用阿里的yum源了

!!!注意:切换后,都需要运行 sudo yum clean all && sudo yum makecache 来更新缓存

内网机器没有相关软件包的解决方案

方案1

通过同系统版本的外网机器下载可使用的软件包,然后用传到内网机器上,再进行安装。

比如:

内网机:192.168.157.238,外网机:192.168.157.103,两者系统版本一致。

安装postgresql

  1. 先在外网机器上安装相关下载工具
# 安装下载工具
yum install -y yum-utils createrepo
  1. 创建一个工作目录

    mkdir -p /tmp/pg_offline
    cd /tmp/pg_offline
    
  2. 下载相关依赖包(repotrack或者yumdownloader)

    如果是比较小的包且依赖不多,推荐用yum install --downloadonly,比如下载telnet

    # 如果下载包依赖比较少,推荐使用yum install --downloadonly
    yum install --downloadonly --downloaddir=/tmp/telnet_offline telnet
    # 如果外网机器上已经有这个包使用reinstall便可成功下载相关包
    yum reinstall --downloadonly --downloaddir=/tmp/telnet_offline telnet
    # 这里下载postgresql依赖较多使用repotrack(可能会因为系统版本原因导致命令不一样,建议使用前用repotrack --help看一下相关参数使用例子)
    repotrack --destdir=/tmp/pg_offline postgresql-server
    
    # 或者用yumdownloader
    yumdownloader --resolve --destdir=/tmp/pg_offline postgresql-server
    
    # 下载完成后可用ls查看一下
    ls
    
  3. 将相关包传输到内网机器(根据实际情况来,这里两台机器间是通的就用的scp或rsync)

    # 用scp
    scp -r /tmp/pg_offline root@192.168.157.238:/opt/
    
    # 用rsync
    rsync -avz --progress /tmp/pg_offline/ root@192.168.157.238:/opt/pg_offline
    # 参数解析
    -a:归档模式,保留文件属性(权限、时间戳等),并以递归方式同步。
    
    -v:详细输出,让你看到同步过程。
    
    -z:在传输过程中进行压缩,提高速度(尤其适合文本、RPM包)。
    
    --progress:显示每个文件的传输进度条,直观看到传输状态。
    
    /tmp/pg_offline/:注意源路径末尾的 /  这表示同步该目录下的内容到目标路径。
    
    root@192.168.157.238:/opt/pg_offline/:目标路径。如果 /opt/pg_offline/ 目录不存在,rsync 会自动创建。
    
  4. 在内网机使用rpm命令强制安装

    cd /opt/pg_offline
    # 使用 rpm 命令并忽略依赖(谨慎使用,可能导致软件不稳定)
    rpm -ivh *.rpm --nodeps --force
    

    上述是没招时使用的,这里一般还是制作离线yum仓库

    cd /opt/pg_offline
    # 根据已有包制作相关源
    createrepo .
    # 前往/etc/yum.repo.d创建一个新的repo文件:pg-offline.repo
    [pg-offline]
    name=PostgreSQL Offline Repo
    baseurl=file:///opt/pg_offline
    enabled=1
    gpgcheck=0
    # 执行安装
    yum clean all
    yum install postgresql-server
    
  5. 验证安装情况

# 确认rpm包已经安装
rpm -qa | grep postgresql
# 由于安装的postgresql,使用前必须初始化一个数据库簇(存储数据的目录)
postgresql-setup --initdb
# 启动服务及查看服务状态
systemctl start postgresql
systemctl status postgresql
systemctl enable postgresql

方案2

使用docker或者podman,运行包含相关软件的镜像

当然此方案前提是内网机器已经安装得有docker或者podman

此处以redis为例

  1. 确认内网机器是否有相关软件(docker或者podman)

    docker --version
    podman --version
    

    有版本输出信息代表有相关软件

  2. 找一台可以制作镜像或者打包镜像的可联网机器(这里我直接用的本地的Windows机器)

    注意点:注意制作镜像的机器要和使用镜像的机器的架构保持一致(比如x86架构的就一定要用x86架构的机器去制作)

    此处省略如何解决docker镜像拉取超时或失败的解决过程,后续单独写个文档。

  3. 得到相关镜像后,查看当前镜像并打包(本地Windows机器)

    [/home/mobaxterm ] docker images redis
    REPOSITORY   TAG        IMAGE ID       CREATED         SIZE
    redis        6-alpine   6dd588768b9b   11 months ago   30.2MB
    redis        latest     170a1e90f843   23 months ago   138MB
    

    可以看到已经有redis的最新镜像了,将其打包(我存放docker打包镜像的路径为:C:\docker-images-tar)

    # 前往存放docker镜像的目录
    cd C:\docker-images-tar
    # 打包对应镜像为tar
    docker save -o redis-latest.tar redis:latest
    # 然后将该包传到待使用机器上(U盘,scp,rsync都可以,我这里两者之间网是通的就直接scp了)
    scp redis-latest.tar root@192.168.157.238:/root/podman
    
  4. 内网机器得到对应tar包后,直接加载该镜像,然后运行(我内网机器只有podman,这里直接用podman加载)

    # 加载对应包
    [root@hadoop204 podman]# podman load -i redis-latest.tar
    Getting image source signatures
    Copying blob a483da8ab3e9 done
    Copying blob 8a99c598a0e4 done
    Copying blob e0fba71d9fb9 done
    Copying blob 88e2e151843a done
    Copying blob 31de0c7fac66 done
    Copying blob f9d024c0f809 done
    Copying blob 5f70bf18a086 skipped: already exists
    Copying blob 2a269272f7cf done
    Copying config 170a1e90f8 done
    Writing manifest to image destination
    Storing signatures
    Loaded image(s): localhost/latest:latest
    # 查看当前已有镜像
    [root@hadoop204 podman]# podman images
    REPOSITORY               TAG         IMAGE ID      CREATED        SIZE
    localhost/alpine-telnet  latest      a082e1c394ce  5 days ago     11.8 MB
    localhost/latest         latest      170a1e90f843  23 months ago  142 MB
    # 更改一下标签方便后续使用
    [root@hadoop204 podman]# podman untag 170a1e90f843
    [root@hadoop204 podman]# podman tag 170a1e90f843 redis:latest
    # 再次查看镜像信息
    [root@hadoop204 podman]# podman images
    REPOSITORY               TAG         IMAGE ID      CREATED        SIZE
    localhost/alpine-telnet  latest      a082e1c394ce  5 days ago     11.8 MB
    localhost/redis          latest      170a1e90f843  23 months ago  142 MB
    # 前台运行并映射端口到宿主机
    [root@hadoop204 podman]# podman run -d --name myredis -p 6379:6379 redis:latest
    3d83303b194aa51dbb082643e7ab68fdffbec12106d3ee029ba86069e50d57e4
    # 查看当前podman容器状态
    [root@hadoop204 podman]# podman ps -a
    CONTAINER ID  IMAGE                   COMMAND       CREATED         STATUS             PORTS                   NAMES
    3d83303b194a  localhost/redis:latest  redis-server  12 seconds ago  Up 12 seconds ago  0.0.0.0:6379->6379/tcp  myredis
    # 交互模式使用redis
    [root@hadoop204 podman]# podman exec -it myredis sh
    # redis-cli -h 127.0.0.1 -p 6379
    127.0.0.1:6379> ping
    PONG
    127.0.0.1:6379> set test "this is a test about using redis in podman"
    OK
    127.0.0.1:6379> get test
    "this is a test about using redis in podman"
    127.0.0.1:6379>
    
进阶使用

如果机器规模上来后,部分像传包这些操作会很耗时耗力,下面开始一些适合规模上来后的方案

1. 构建私有yum仓库(HTTP / Nginx)

适用场景

  • 内网机器 不能直连外网
  • 多台服务器需要 统一软件源
  • 避免每台机器都挂 ISO / 手工传 RPM

实现思路

[外网机器]          [内网 YUM 仓库机]         [业务服务器]
   yum ──下载RPM──▶  /repo (HTTP)  ◀── yum install

  • 一台 仓库服务器
  • RPM 统一存放
  • 通过 HTTP 提供服务
  • 所有内网机器指向它

实现方案

1.1最小实现方案

架构(最小可用)

[YUM 仓库服务器]
  └── /data/yumrepo
        ├── baseos
        └── appstream
          ↑
      nginx (80)
          ↑
[业务服务器] yum install

步骤

  1. 准备一台仓库机(系统同内网机机器一致,与内网机器网络畅通,准备一个iso文件)

  2. 挂载iso并准备目录

    mkdir -p /mnt/cdrom
    mount -o loop CentOS-8.5.2111-x86_64-dvd1.iso /mnt/cdrom
    
    mkdir -p /data/yumrepo/{baseos,appstream}
    
  3. 同步或者拷贝rpm

    来源可以是:

    ISO(BaseOS / AppStream)

    repotrack / yumdownloader

    手工拷贝

    cp -r /mnt/cdrom/BaseOS/* /data/yumrepo/baseos/
    cp -r /mnt/cdrom/AppStream/* /data/yumrepo/appstream/
    
  4. 生成元数据(必要)

    # 若没有createrepo先安装
    yum install -y createrepo
    createrepo /data/yumrepo/baseos
    createrepo /data/yumrepo/appstream
    
  5. 配置nginx,提供http服务

    # 先安装nginx
    yum install -y nginx
    # 在/etc/nginx/conf.d下创建一个新配置文件
    cd /etc/nginx/conf.d
    vi yum-repo.conf
    

    写入以下配置:

    server {
        listen 80;
        server_name yum.repo.local;
    
        location / {
            root /data/yumrepo;
            autoindex on;
        }
    }
    

    启动服务

    systemctl enable --now nginx
    
    
  6. 去客户端配置对应新repo(业务机器)

    cd /etc/yum.repos.d/
    vi local-store.repo
    
    # 写入以下配置
    [local-baseos]
    name=Local BaseOS
    # baseurl=http://192.168.157.238/baseos (这里直接使用仓库地址有一些问题)
    baseurl=http://yum.repo.local/baseos
    enabled=1
    gpgcheck=0
    
    [local-appstream]
    name=Local AppStream
    baseurl=http://yum.repo.local/appstream
    enabled=1
    gpgcheck=0
    

    上述的baseurl直接写仓库机的地址有一些问题,建议是在/etc/hosts文件里写入别名使用

    比如此处的仓库机地址为:192.168.157.238

    在业务机器的hosts文件里写入:192.168.157.238 yum.repo.local

    然后上述repo对应处变为:yum.repo.local

  7. 测试

    yum clean all
    yum makecache
    yum install -y tree
    

1.2 可维护实现方案(多版本+增量)

目标:仓库可扩建、可维护、不会每次全量重建

升级架构

/data/yumrepo
 ├── centos8
 │    ├── baseos
 │    └── appstream
 ├── epel
 └── custom

步骤

  • 实现支持【自定义RPM】
  1. 创建custom仓库(仓库机)

    mkdir -p /data/yumrepo/custom
    cp *.rpm /data/yumrepo/custom/
    createrepo /data/yumrepo/custom
    
  2. 客户端(业务机)写入custom的repo配置

    [custom]
    name=Custom Repo
    baseurl=http://yum.repo.local/custom
    enabled=1
    gpgcheck=0
    
    

    然后就可以通过此安装部分之前源没有的软件了(比如离线安装PostgreSQL / Redis RPM)

  • 实现增量更新仓库

    当有新增RPM后:

    createrepo --update /data/yumrepo/custom
    

    主要就是加上--update,然后更新custom的元数据,这样可以避免每次全量createrepo

  • 实现版本隔离(避免事故)

    # 比如可能当部分业务机有版本升级时,可能需要使用对应版本的软件包,那最好是对仓库机的yumrepo做版本隔离管理
    /data/yumrepo
     ├── centos8.5
     ├── centos8.6
    
    

    这样对应客户端只指向固定版本(在客户端的repo文件进行修改):

    baseurl=http://yum.repo.local/centos8.5/baseos
    

1.2该部分主要是要理解:

  • YUM 仓库是“版本契约”
  • 不能随便覆盖
  • 增量更新是生产要求

1.3 企业级实现方案

目标:稳定、安全、可审计、可自动化

SRE架构

         ┌────────────┐
         │   CI/同步机 │
         └─────┬──────┘
               │
        rsync / reposync
               │
        ┌──────▼────────┐
        │   YUM 主仓库   │
        │ (Nginx + HTTPS)│
        └──────┬────────┘
               │
        ┌──────▼────────┐
        │  多业务服务器  │
        └───────────────┘

  • 不再使用iso,而是在可通外网的机器使用官方源同步(reposync)

    yum install -y yum-utils
    reposync -r baseos -p /data/yumrepo/centos8
    reposync -r appstream -p /data/yumrepo/centos8
    
    # 生成元数据
    createrepo /data/yumrepo/centos8/baseos
    createrepo /data/yumrepo/centos8/appstream
    
  • 使用HTTPS + GPG

    • 自签证书
    • 开启gpgcheck = 1
    • RPM签名
    gpg --gen-key
    rpm --addsign *.rpm
    

    客户端:

    gpgcheck=1
    gpgkey=http://yum.repo.local/RPM-GPG-KEY
    
  • 使用Ansible来自动化

    ....

服务器
$ cd ..