如何制作本地软件仓库

如何制作软件仓库

某些情况下在没有外网的环境需要安装一些软件,但是软件依赖比较多,那么可以提前将所有依赖下载到本地,然后将他们制作成一个yum repo,安装的时候就会自动将依赖包都安装好。

centos下是 yum 仓库,Debian、ubuntu下是apt仓库,我们先讲 yum 仓库的制作,Debian apt 仓库类似

收集所有rpm包

创建一个文件夹,比如 Yum,将收集到的所有rpm包放在里面,比如安装ansible和docker需要的依赖文件:

1
2
3
4
5
6
7
8
9
10
11
12
-rwxr-xr-x 1 root root  73K 7月  12 14:22 audit-libs-python-2.8.4-4.el7.x86_64.rpm
-rwxr-xr-x 1 root root 295K 7月 12 14:22 checkpolicy-2.5-8.el7.x86_64.rpm
-rwxr-xr-x 1 root root 23M 7月 12 14:22 containerd.io-1.2.2-3.el7.x86_64.rpm
-rwxr-xr-x 1 root root 26K 7月 12 14:22 container-selinux-2.9-4.el7.noarch.rpm
-rwxr-xr-x 1 root root 37K 7月 12 14:22 container-selinux-2.74-1.el7.noarch.rpm
-rwxr-xr-x 1 root root 14M 7月 12 14:22 docker-ce-cli-18.09.0-3.el7.x86_64.rpm
-rwxr-xr-x 1 root root 29K 7月 12 14:22 docker-ce-selinux-17.03.2.ce-1.el7.centos.noarch.rpm
-r-xr-xr-x 1 root root 22K 7月 12 14:23 sshpass-1.06-2.el7.x86_64.rpm
-r-xr-xr-x 1 root root 22K 7月 12 14:23 sshpass-1.06-1.el7.x86_64.rpm
-r-xr-xr-x 1 root root 154K 7月 12 14:23 PyYAML-3.10-11.el7.x86_64.rpm
-r-xr-xr-x 1 root root 29K 7月 12 14:23 python-six-1.9.0-2.el7.noarch.rpm
-r-xr-xr-x 1 root root 397K 7月 12 14:23 python-setuptools-0.9.8-7.el7.noarch.rpm

收集方法:

1
2
3
4
5
6
7
8
//先安装yum工具
yum install yum-utils -y
//将 ansible 依赖包都下载下来
repoquery --requires --resolve --recursive ansible | xargs -r yumdownloader --destdir=/tmp/ansible
//将ansible rpm自己下载回来
yumdownloader --destdir=/tmp/ansible --resolve ansible
//验证一下依赖关系是完整的
//repotrack ansible

创建仓库索引

需要安装工具 yum install createrepo -y:

1
2
3
4
5
6
7
8
9
10
# createrepo ./public_yum/
Spawning worker 0 with 6 pkgs
Spawning worker 1 with 6 pkgs
Spawning worker 23 with 5 pkgs
Workers Finished
Saving Primary metadata
Saving file lists metadata
Saving other metadata
Generating sqlite DBs
Sqlite DBs complete

会在yum文件夹下生成一个索引文件夹 repodata

1
2
3
4
5
6
7
8
9
drwxr-xr-x 2 root root 4.0K 7月  12 14:25 repodata
[root@az1-drds-79 yum]# ls repodata/
5e15c62fec1fe43c6025ecf4d370d632f4b3f607500016e045ad94b70f87bac3-filelists.xml.gz
7a314396d6e90532c5c534567f9bd34eee94c3f8945fc2191b225b2861ace2b6-other.xml.gz
ce9dce19f6b426b8856747b01d51ceaa2e744b6bbd5fbc68733aa3195f724590-primary.xml.gz
ee33b7d79e32fe6ad813af92a778a0ec8e5cc2dfdc9b16d0be8cff6a13e80d99-filelists.sqlite.bz2
f7e8177e7207a4ff94bade329a0f6b572a72e21da106dd9144f8b1cdf0489cab-primary.sqlite.bz2
ff52e1f1859790a7b573d2708b02404eb8b29aa4b0c337bda83af75b305bfb36-other.sqlite.bz2
repomd.xml

生成iso镜像文件

非必要步骤,如果需要带到客户环境可以先生成iso,不过不够灵活。

也可以不用生成iso,直接在drds.repo中指定 createrepo 的目录也可以,记得要先执行 yum clean all和yum update

1
2
3
4
5
6
7
8
9
10
11
12
13
#mkisofs -r -o docker_ansible.iso ./yum/
I: -input-charset not specified, using utf-8 (detected in locale settings)
Using PYTHO000.RPM;1 for /python-httplib2-0.7.7-3.el7.noarch.rpm (python-httplib2-0.9.1-3.el7.noarch.rpm)
Using MARIA006.RPM;1 for /mariadb-5.5.56-2.el7.x86_64.rpm (mariadb-libs-5.5.56-2.el7.x86_64.rpm)
Using LIBTO001.RPM;1 for /libtomcrypt-1.17-25.el7.x86_64.rpm (libtomcrypt-1.17-26.el7.x86_64.rpm)
6.11% done, estimate finish Sun Jul 12 14:26:47 2020
97.60% done, estimate finish Sun Jul 12 14:26:48 2020
Total translation table size: 0
Total rockridge attributes bytes: 14838
Total directory bytes: 2048
Path table size(bytes): 26
Max brk space used 21000
81981 extents written (160 MB)

将 生成的 iso挂载到目标机器上

1
2
3
# mkdir /mnt/iso
# mount ./docker_ansible.iso /mnt/iso
mount: /dev/loop0 is write-protected, mounting read-only

配置本地 yum 源

yum repository不是必须要求iso挂载,直接指向rpm文件夹(必须要有 createrepo 建立索引了)也可以

1
2
3
4
5
6
7
8
9
# cat /etc/yum.repos.d/drds.repo 
[drds]
name=drds Extra Packages for Enterprise Linux 7 - $basearch
enabled=1
failovermethod=priority
baseurl=file:///mnt/repo #baseurl=http://192.168.1.91:8000/ 本地内网
priority=1 #添加priority=1,数字越小优先级越高,也可以修改网络源的priority的值
gpgcheck=0
#gpgkey=file:///mnt/cdrom/RPM-GPG-KEY-CentOS-5 #注:这个你cd /mnt/cdrom/可以看到这个key,这里仅仅是个例子, 因为gpgcheck是0 ,所以gpgkey不需要了

到此就可以在没有网络环境的机器上直接:yum install ansible docker -y 了

yum 仓库代理

如果需要代理可以在docker.repo 最后添加:

1
proxy=socks5://127.0.0.1:12345 //socks代理 或者 proxy=http://ip:port

如果要给全局配置代理,则在 /etc/yum.conf 最后添加如上行

测试

测试的话可以指定repo 源: yum install ansible –enablerepo=drds (drds 优先级最高)

本地会cache一些rpm的版本信息,可以执行 yum clean all 得到一个干净的测试环境

1
2
3
yum clean all
yum list
yum deplist ansible

yum 源问题处理

Yum commands error “pycurl.so: undefined symbol”

xargs 作用

xargs命令的作用,是将标准输入转为命令行参数。因为有些命令是不接受标准输入的,比如echo

xargs的作用在于,大多数命令(比如rmmkdirls)与管道一起使用时,都需要xargs将标准输入转为命令行参数。

dnf 使用

DNF 是新一代的rpm软件包管理器。他首先出现在 Fedora 18 这个发行版中。而最近,它取代了yum,正式成为 Fedora 22 的包管理器。

DNF包管理器克服了YUM包管理器的一些瓶颈,提升了包括用户体验,内存占用,依赖分析,运行速度等多方面的内容。DNF使用 RPM, libsolv 和 hawkey 库进行包管理操作。尽管它没有预装在 CentOS 和 RHEL 7 中,但你可以在使用 YUM 的同时使用 DNF 。你可以在这里获得关于 DNF 的更多知识:《 DNF 代替 YUM ,你所不知道的缘由》

DNF 包管理器作为 YUM 包管理器的升级替代品,它能自动完成更多的操作。但在我看来,正因如此,所以 DNF 包管理器不会太受那些经验老道的 Linux 系统管理者的欢迎。举例如下:

  1. 在 DNF 中没有 –skip-broken 命令,并且没有替代命令供选择。
  2. 在 DNF 中没有判断哪个包提供了指定依赖的 resolvedep 命令。
  3. 在 DNF 中没有用来列出某个软件依赖包的 deplist 命令。
  4. 当你在 DNF 中排除了某个软件库,那么该操作将会影响到你之后所有的操作,不像在 YUM 下那样,你的排除操作只会咋升级和安装软件时才起作用。

安装yum源

安装7.70版本curl yum源

1
rpm -Uvh http://www.city-fan.org/ftp/contrib/yum-repo/city-fan.org-release-2-1.rhel7.noarch.rpm

其它技巧

rpm依赖查询

1
2
3
4
5
6
rpm -q --whatprovides file-name //查询一个文件来自哪个rpm包
rpm -qf /usr/lib/systemd/libsystemd-shared-239.so // 查询一个so lib来自哪个rpm包
或者 yum whatprovides /usr/lib/systemd/libsystemd-shared-239.so
yum provides */libmysqlclient.so.18

rpm -qi //查看rpm包安装的安装信息

多版本问题

1
2
3
4
5
6
7
//查看protobuf 的多个版本
yum --showduplicates list protobuf
//or
repoquery --show-duplicates protobuf

//指定版本安装,一般是安装教老的版本
yum install protobuf-3.6.1-4.el7

制作debian 仓库

适合ubuntu、deepin、uos等, 参考:https://lework.github.io/2021/04/03/debian-kubeadm-install/

1
2
#添加新仓库
sudo apt-add-repository 'deb http://ftp.us.debian.org/debian stretch main contrib non-free'

img

rpm转换成 dpkg

apt-mirror

先要安装apt-mirror 工具,安装后会生成配置文件 /etc/apt/mirror.list 然后需要手工修改配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#cat /etc/apt/mirror.list
############# config ##################

#下载下来的仓库文件放在哪里
set base_path /polarx/debian

set mirror_path $base_path/mirror
set skel_path $base_path/skel
set var_path $base_path/var
set cleanscript $var_path/clean.sh
set defaultarch amd64
#set postmirror_script $var_path/postmirror.sh
set run_postmirror 0
set nthreads 20
set _tilde 0
#
############# end config ##############

#从哪里镜像仓库
deb http://yum.tbsite.net/mirrors/debian/ buster main non-free contrib
#deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main

#deb http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-src http://ftp.us.debian.org/debian unstable main contrib non-free

# mirror additional architectures
#deb-alpha http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-amd64 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-armel http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-hppa http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-i386 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-ia64 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-m68k http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-mips http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-mipsel http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-powerpc http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-s390 http://ftp.us.debian.org/debian unstable main contrib non-free
#deb-sparc http://ftp.us.debian.org/debian unstable main contrib non-free

#clean http://ftp.us.debian.org/debian
clean http://yum.tbsite.net/mirrors/debian/

debian仓库介绍

一个Debian仓库包含多个发行版。Debian 的发行版是以 “玩具总动员 “电影中的角色命名的 (wheezy, jessie, stretch, …)。 代号有别名,叫做套件(stable, oldstable, testing, unstable)。一个发行版会被分成几个组件。在 Debian 中,这些组件被命名为 main, contrib, 和 non-free,并表并表示它们所包含的软件的授权条款。一个版本也有各种架构(amd64, i386, mips, powerpc, s390x, …)的软件包,以及源码和架构独立的软件包。

仓库的根目录下有一个dists 目录,而这个目录又有每个发行版和套件的目录,后者通常是前者的符号链接,但浏览器不会向您显示出这个区别。每个发行版子目录都包含一个加密签名的Release文件和每个组件的目录,里面是不同架构的目录,名为binary-*<架构>*和sources。而在这些文件中,Packages是文本文件,包含了软件包。嗯,那么实际的软件包在哪里?

image-20220829163817671

软件包本身在仓库根目录下的pool。在pool下面又有所有组件的目录,其中有0,…,9ab,.., z, liba, … , libz。 而在这些目录中,是以它们所包含的软件包命名的目录,这些目录最后包含实际的软件包,即.deb文件。这个名字不一定是软件包本身的名字,例如,软件包bsdutils在目录pool/main/u/util-linux 下,它是生成软件包的源码的名称。一个上游源可能会生成多个二进制软件包,而所有这些软件包最终都会在pool下面的同一个子目录中。额外的单字母目录只是一个技巧,以避免在一个目录中有太多的条目,因为这是很多系统传统上存在性能问题的原因。

pool下面的子目录中,通常会有多个版本的软件包,而每个版本的软件包属于什么发行版的信息只存在于索引中。这样一来,同一个版本的包可软件以属于多个发行版,但只使用一次磁盘空间,而且不需要求助于硬链接或符号链接,所以镜像相当简单,甚至可以在没有这些概念的系统中进行。

常用命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
apt install kubeadm=1.20.12-00 //指定版本安装

#查询可用版本
apt-cache policy kubeadm
apt list --all-versions kubeadm

#清理
apt clean --dry-run
apt update
apt list/dpkg -l //列出本机所有已经安装的软件
apt show kubeadm //显示版本、作者等信息

#查询某个安装包的所有文件
dpkg-query -L kubeadm

#列出所有依赖包
apt-cache depends ansible

#被依赖查询
apt-cache rdepends kubelet

dpkg -I kubernetes/pool/kubeadm_1.21.0-00_amd64.deb

#下载依赖包
apt-get download $(apt-rdepends kubeadm|grep -v "^ ")
aptitude --download-only -y install $(apt-rdepends kubeadm|grep -v "^ ") //不能下载已经安装了的依赖包

apt download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances kubeadm | grep "^\w" | sort -u)

简单仓库

下载所有 deb 包以及他们的依赖

1
apt download $(apt-cache depends --recurse --no-recommends --no-suggests --no-conflicts --no-breaks --no-replaces --no-enhances kubeadm | grep "^\w" | sort -u)

到deb 包所在的目录下生成 index

1
dpkg-scanpackages -m . > Packages

/etc/apt/source.list 指向这个目录

1
2
3
deb [trusted=yes] file:/polarx/test /
or
deb [trusted=yes] http://kunpeng/pool/ ./

验证:

1
apt update //看是否能拉取你刚配置的仓库

Kubernetes 仓库

debian 上通过kubeadm 安装 kubernetes 集群

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//官方
echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | tee -a /etc/apt/sources.list.d/kubernetes.list

//阿里云仓库
echo 'deb https://mirrors.aliyun.com/kubernetes/apt kubernetes-xenial main' > /etc/apt/sources.list.d/kubernetes.list
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -
apt-get update

export KUBE_VERSION="1.20.5"
apt-get install -y kubeadm=$KUBE_VERSION-00 kubelet=$KUBE_VERSION-00 kubectl=$KUBE_VERSION-00
sudo apt-mark hold kubelet kubeadm kubectl

[ -d /etc/bash_completion.d ] && \
{ kubectl completion bash > /etc/bash_completion.d/kubectl; \
kubeadm completion bash > /etc/bash_completion.d/kubadm; }

[ ! -d /usr/lib/systemd/system/kubelet.service.d ] && mkdir -p /usr/lib/systemd/system/kubelet.service.d
cat << EOF > /usr/lib/systemd/system/kubelet.service.d/11-cgroup.conf
[Service]
CPUAccounting=true
MemoryAccounting=true
BlockIOAccounting=true
ExecStartPre=/usr/bin/bash -c '/usr/bin/mkdir -p /sys/fs/cgroup/{cpuset,memory,systemd,pids,"cpu,cpuacct"}/{system,kube,kubepods}.slice'
Slice=kube.slice
EOF
systemctl daemon-reload

systemctl enable kubelet.service

docker 仓库

1
2
3
4
5
6
7
apt-get install -y apt-transport-https ca-certificates curl gnupg2 lsb-release bash-completion

curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/debian/gpg | sudo apt-key add -
echo "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/debian $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker-ce.list
sudo apt-get update
apt-get install -y docker-ce docker-ce-cli containerd.io
apt-mark hold docker-ce docker-ce-cli containerd.io

锁定已安装版本

1
2
//锁定这三个软件的版本,避免意外升级导致版本错误:
sudo apt-mark hold kubeadm kubelet kubectl

参考资料

xargs 命令教程