搭建局域网内的APT源

本文档详述如何在局域网内搭建一个本地的Docker环境来试验OpenStack。首先,通过Apache搭建局域网内的APT源以解决网络问题,接着介绍如何本地编译DEB包,最后探讨建立OpenStack特定的局域网APT源并解决遇到的问题,如locale错误、keystone依赖问题和chronyd/nptd权限问题。
部署运行你感兴趣的模型镜像

新手轻喷,不定期更新… …
这里是用docker搭建openstack实验环境的手工记录,是一步步实际操作而来,因此不会用到script来进行自动化处理。等我实际搭建成功后会写一个自动化的搭建脚本。

一,需求及基础环境

  • 需求:博主现正进行openstack相关的开发,刚开始接触这个项目,但苦于其规模庞大,同时其部署非常麻烦且易出错,对新手极其不友好。博主现在只使用mirantis在虚拟机上搭建成功过一次,部署一次非常麻烦且耗时很长,因此想利用docker的便捷性快速搭建openstack的实验环境。当然博主考察过kolla项目,它就是使用docker来部署openstack的,但限于网络问题,如果不将其docker的repo的地址更改到国内一些镜像源,则实际上是无法使用的,但这个项目也非常庞大,对新手而言还是很不友好,还不如自己动手,丰衣足食 >_<
  • 基础环境:
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 16.04.6 LTS
Release:        16.04
Codename:       xenial

$ uname -a
Linux docker 4.4.0-157-generic #185-Ubuntu SMP Tue Jul 23 09:17:01 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

$ docker --version
Docker version 18.09.7, build 2d0083d

这里由于博主的工作笔记本用的是windows,但是WSL毕竟不是linux,而且windows对docker的支持也面临许多权限的限定,特别是关于网络设备这类比较底层的问题,WSL是没有权限操作的。综合各方面因素考虑博主是使用虚拟机作为主机的,可以选择ubuntu14/16版本的,至于debian,redhat,suse等也可以,但博主没有试过,其可以调整内存、磁盘、cpu等参数,比较方便。因为openstack的节点多的时候对计算机资源的要求是很大的,最好能选用大一些的内存和磁盘空间。具体多少等博主实际测过后再说。

二,搭建过程

1,搭建局域网内的apt源

因为在openstack的搭建过程中,非常容易出问题,这时网速就成为最令人头疼的问题,如果能在本地的局域网内搭建一个apt源,则可以大大减轻由网络异常带来的问题,甚至可以说已成功了一半。

搭建apt源的局域网拓扑
上图是使用container搭建局域网内apt源的网络拓扑,使用的网络是docker的默认网桥,因为该网桥可以连通外部网络,同时每个container默认都连接这个网桥,所以非常合适。

(1) 安装http server

http server可以有很多选择,我这里就简单地使用Apache。

## 进入container
$ docker run -it ubuntu:16.04.3 /bin/bash
## 使用这个container作为apt server
$ apt update
$ apt install -y apache2
## 启动apache
$ service apache2 start
## 检查apache是否正常启动
$ service apache2 status

为了检查apt server是否正常启动http的服务,可以在docker所在的主机或任何能连上局域网(172.17.0.2/16)的主机向它发送http的请求

# 在apt server的container中
$ cd /var/www/html
$ echo "apache run successfully!" > test.txt

# 然后在另一个在该局域网内的主机上
$ curl -g -i -X GET http://172.17.0.2/test.txt
HTTP/1.1 200 OK
Date: Thu, 26 Sep 2019 01:34:40 GMT
Server: Apache/2.4.18 (Ubuntu)
Last-Modified: Thu, 26 Sep 2019 01:21:31 GMT
ETag: "1a-5936a96ef8426"
Accept-Ranges: bytes
Content-Length: 26
Content-Type: text/plain

apache run successfully!

## 显示成功,说明http服务已开启

(2) 搭建apt源

参考资料:
How to create a local APT repository?: 这是stackflow中的问题,里面的讨论很详细,由apt本地源拓展到局域网,以及认证问题。

## 准备好工具
$ sudo apt-get install dpkg-dev
## 准备好apt库的位置,因为使用apache2做为http服务,为了简单起见,直接使用其默认的路径
$ cd /var/www/html
$ ls
index.html
## index.html是apache的主页面,这个路径就是apache的默认主路径
## 在这个路径下设置离线库
$ mkdir -p debs/amd64 && cd debs/amd64
## 通过外网下载需要的离线包,同时保证依赖的库也能一起下载下来
$ apt-cache depends <packagename> -i --recurse | awk '/^[a-z]/ {print $0}' | xargs apt-get download
## 当下载完成后需要扫描生成包的信息文件
$ cd .. ## -> debs
$ dpkg-scanpackages amd64 /dev/null | gzip -9c > amd64/Packages.gz

(3) 添加apt源

当apt server搭建好之后,需要认局域网内的其它主机能够使用这个源,因为本文主要服务于openstack基于docker的搭建,因此让所有其它的container都使用这个apt源

## 进入另外一个新的container中,首先确定其能连接到apt server的http服务,
## 这一步参考[(1)安装http server]的验证操作
$ cd /etc/apt/
$ mv sources.list sources.list.backup
$ echo "deb http://172.17.0.2/debs amd64/" > sources.list
## 更新及下载
## 注意,由于这里为了简便没有建权的步骤,
## 关于建权的部分,可以参考[(2) 搭建apt源]的资料
$ sudo apt-get --allow-unauthenticated update
Ign:1 http://172.17.0.2/debs amd64/ InRelease
......
Fetched 49.8 kB in 1s (30.8 kB/s)
Reading package lists... Done
$ sudo apt-get --allow-unauthenticated install <packagename>

(4) 验证apt源 --> 实例

按照上面两步可以在局域网内搭建好一个apt源,现在以安装ping为例来验证这个局域网内的apt源是否正常工作

## 进入apt server中,准备好ping的安装包及依赖
$ apt-cache depends iputils-ping -i --recurse | awk '/^[a-z]/ {print $0}' | xargs apt-get download
$ cd /var/www/html/debs
$ dpkg-scanpackages amd64/ /dev/null | gzip -9c > amd64/Packages.gz

## 任意进入一个已经添加了apt server源的container中
$ sudo apt-get --allow-unauthenticated update
$ sudo apt-get --allow-unauthenticated install iputils-ping
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  iputils-ping
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/52.7 kB of archives.
After this operation, 164 kB of additional disk space will be used.
WARNING: The following packages cannot be authenticated!
  iputils-ping
Authentication warning overridden.
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package iputils-ping.
(Reading database ... 27948 files and directories currently installed.)
Preparing to unpack .../iputils-ping_3%3a20121221-5ubuntu2_amd64.deb ...
Unpacking iputils-ping (3:20121221-5ubuntu2) ...
Setting up iputils-ping (3:20121221-5ubuntu2) ...
Setcap is not installed, falling back to setuid

$ ping -c 1 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.091 ms

--- 172.17.0.2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.091/0.091/0.091/0.000 ms

可以看见验证成功!

2,本地源码编绎deb包

在container环境下部署openstack有时会遇到从apt源中得到的包无法正常使用或干脆无法使用的情况,这时就只能下载适配的源码,手动编绎安装了。但这个过程是枯燥的,而且当部署量较大时也非常麻烦,不便于管理,因此需要将源码本地打包。

使用的工具: checkinstall,这个工具在官方的apt源中有,可以直接使用apt install得到它
参考资料: Linux 的源码安装工具 CheckInstall: 这个有对checkinstall的使用的简单介绍

下面以chrony源码为例

$ cd chrony-3.5
## 这里是各种编绎选项,为了后续使用方便,把安装路径都写成"/usr",因为默认路径一般是"/usr/local",这样还要去修改环境变量。
$ ./configure --prefix=/usr  ## 这里是各种编绎选项
$ make
## 打包
$ checkinstall
checkinstall 1.6.2, Copyright 2009 Felipe Eduardo Sanchez Diaz Duran
           This software is released under the GNU GPL.


The package documentation directory ./doc-pak does not exist.
Should I create a default set of package docs?  [y]: y

...
## 在打包时会有一些交互性的问题,按照提示写入即可
$ ls chrony_3.5-1_amd64.deb
## 查看编绎成功的deb包
$ dpkg -I chrony_3.5-1_amd64.deb
 new debian package, version 2.0.
 size 256614 bytes: control archive=330 bytes.
       0 bytes,     0 lines      conffiles
     234 bytes,    12 lines      control
 Package: chrony
 Priority: extra
 Section: checkinstall
 Installed-Size: 1084
 Maintainer: root@sola
 Architecture: amd64
 Version: 3.5-1
 Provides: chrony
 Description: chrony-3.5
  compiled by eouylei, used for deployment in docker.

3,建立openstack的局域网apt源

有了前面两步的基础,现在可以根据openstack官网的要求,将其需要的所以依赖都下载下来构建一个局域网内的apt源,同时还可以将一些不适应container的包替换成合适的包。

(1) 更新相应包的脚本

为了方便安装,以下是用于从远程APT源下载相应包(包括其依赖的包)到本地apache2下面,并建立本地APT源的脚本

update_local_apt_repo.sh
方法: update_local_apt_repo.sh [packages]
例: update_local_apt_repo.sh vim apache2 iproute2 iputils-ping

 ## openstack_repo_dir 与 openstack_repo 为两个环境变量,其表示httpd server的根路径与源的名字
 ## 例如:apt客户端指定source.list为 "deb http://172.17.0.2/debs openstack/"
 ## 而apt server指定的根路径为"/var/www/html"
 ## 	则 openstack_repo_dir=/var/www/html/debs 
 ## 	   openstack_repo=openstack
repo_dir=$openstack_repo_dir
repo=$openstack_repo
err_log="$HOME/update_local_apt_repo_err.log"

packages=$*
existed_packages_str=""
install_failed_packages=""
install_existed_packages=""

function init_err_log() {
    [ -f $err_log ] || touch $err_log
    printf "

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
start date: %s
script wants to apt download debs as followed:
<%s>

start download... ... ...

" "$(date)" "$packages" | tee -a $err_log
}

function finish_err_log() {
    printf "

finish ... ... ...
finish date: %s
--> all the packages are:
    <$packages>
--> already existed packages are:
    <$install_existed_packages>
--> failed packages are:
    <$install_failed_packages>

vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv

" "$(date)" | tee -a $err_log
}

function show_err_and_exit() {
    echo "Error: $1" | tee -a $err_log
    exit 1
}

function generate_existed_package_array() {
    echo "----->  scanning existed packages ... ... ..." | tee -a $err_log
    cd $repo_dir/$repo
    existed_packages_str=$(gunzip -9c Packages.gz | egrep "^Package:" | \
                           cut -d ' ' -f 2)
}

function assert_package_not_existed() {
    local package="$1"
    local result=""

    result=$(echo "$existed_packages_str" | \
        while read item;
        do
            if [ "$item" = "$package" ]; then
                echo "existed"
                return 0
            fi
        done
    )
    [ "$result" = "existed" ] && return 1 || return 0
}

init_err_log

[ -z "$repo_dir" -o -z "$repo" ] && \
    show_err_and_exit "The envir argv is not exist!"
[ -d $repo_dir ] || \
    show_err_and_exit "the dir of repo <$repo_dir> is not exist!"
[ -d $repo_dir/$repo ] || \
    show_err_and_exit "repo <$repo_dir: $repo> is not exist!"

generate_existed_package_array
cd $repo_dir/$repo
for package in $@;
    do
        printf "\n--> start to download apt debs <$package>\n" | \
            tee -a $err_log

        assert_package_not_existed "$package"
        if [ $? != 0 ]; then
            printf "the package <$package> is existed, jump it\n" | \
                tee -a $err_log
            install_existed_packages="$install_existed_packages $package"
            continue;
        fi
        printf "    download package <$package>\n" | tee -a $err_log

        apt-cache depends "$package" -i --recurse | \
            awk '/^[a-z]/ {print $0}' | \
            xargs apt-get download

        if [ $? != 0 ]; then
            echo "**** Exception: apt download <$package> failed" | \
                tee -a $err_log;
            install_failed_packages="$install_failed_packages $package"
        fi
    done

printf "\n***********\n" | tee -a $err_log
cd ..
dpkg-scanpackages $repo /dev/null | \
    gzip -9c > \
    $repo/Packages.gz 2>&1 | tee -a $err_log

finish_err_log

(2) 需要的软件包

参考资料:
openstack Environment:下面的包就是根据这部分安装文档来的,如果要安装其它版本也是一样的做法

Environment

项目备注
Security--
Host networking--
Network Time Protocol (NTP)chrony如果发现使用有问题(参考下面的内容),需要按照上述方法手工制作deb包
OpenStack packagepython-openstackclient请参考该文档,根据docker image选择,博主这里用的是ubuntu 16.04,请按照下面注释[python-openstack]的方式下载
SQL databasemariadb-server python-pymysql-
Message queuerabbitmq-server-
Memcachedmemcached python-memcache-
Etcdetcd-
  • python-openstackclient

    这个软件包需要加载以下apt库
    $ apt install software-properties-common
    $ add-apt-repository cloud-archive:queens

Install OpenStack services

这里博主根据自己的docker images为ubuntu16.04而选择了Queens版本

项目备注
keystonekeystone apache2 libapache2-mod-wsgi-
glanceglance-
novanova-api nova-conductor nova-consoleauth nova-novncproxy nova-scheduler nova-placement-api nova-compute其中nova-compute是为compute节点准备的
neutron for controllerneutron-server neutron-plugin-ml2 neutron-linuxbridge-agent neutron-dhcp-agent neutron-metadata-agentNetworking Option 1: Provider networks
neutron-server neutron-plugin-ml2 neutron-linuxbridge-agent neutron-l3-agent neutron-dhcp-agent neutron-metadata-agentNetworking Option 2: Self-service networks
neutron for computeneutron-linuxbridge-agent-
horizonopenstack-dashboard-
cinder for storagelvm2 thin-provisioning-tools-
cinder for controllercinder-api cinder-scheduler-
cinder for backupcinder-backup-

三,遇到的问题

* pip install 时locale.Error: unsupported locale setting

参考locale.Error: unsupported locale setting 的解决方案

$ locale ## 查看当前语言设置
$ locale -a ## 查看当前系统所有可用语言

## 根据比对发现有某种语言缺失,便是原因所在
## 解决方法:
	* 下载该语言包 'sudo apt install language-pack-xxxxx'
	* 直接更改当前语言设置 'export LC_ALL=C'

* 安装keystone的依赖 --> Modules/constants.h

问题描述:在安装keystone的依赖时,触发了以下错误:
In file included from Modules/LDAPObject.c:8:0:
Modules/constants.h:7:18: fatal error: lber.h: Aucun fichier ou dossier de ce type compilation terminated.
error: command ‘x86_64-linux-gnu-gcc’ failed with exit status 1

解决方法:

## You need to have the development files (headers) in order to compile the Python module.
$ sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev

参考资料:
pip install -r requirements.txt fails on linux #8849

* container里运行chronyd或ntpd时failed, <adjtimex() failed>

先更新到最新版本,旧的版本似乎不支持在container中运行,因为涉及硬件的时间处理。

## remove existed chrony
$ apt purge chrony
$ wget https://launchpad.net/ubuntu/+archive/primary/+sourcefiles/chrony/3.5-2ubuntu2/chrony_3.5.orig.tar.gz
## make and install chrony
$ tar xzvf chrony_3.5.orig.tar.gz
$ cd chrony-3.5
$ ./configure --prefix=/usr && make
$ make install
## start chronyd
$ service chrony start

此时在container中运行chrony会报以下错误:

Permission denied

这是因为docker运行container时对权限有所限制,但chrony或ntp的服务需要设置内核时间,它不能运行在有限制的环境中。解决办法,给docker run传递 –privileged参数。

## docker run container with privilege
$ docker run --privileged xxx

参考资料:
Running NTP in a Container: 里面是讨论了ntp在container中的使用,但chrony也是同样的道理。

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

搭建Ubuntu局域网apt-get是为了提供一个内部网络上的软件下载和更新服务,以减少对外部网络的依赖并提高下载速度。 首先,我们需要一台拥有Ubuntu操作系统的服务器作为apt-get服务器。确保该服务器能够连接至互联网,并设置一个静态IP地址,以便其他设备能够访问到它。 接下来,打开终端并以root用户身份登录服务器。首先我们需要安装apache2软件包来搭建一个Web服务器。在终端中输入以下命令进行安装: sudo apt-get update sudo apt-get install apache2 安装完成后,我们需要配置apt仓库的根目录。默认情况下,apt仓库的根目录位于/var/www/html目录下。我们可以通过修改默认的配置文件来更改该目录。在终端中输入以下命令打开配置文件: sudo nano /etc/apache2/sites-available/000-default.conf 在编辑器中,找到并修改以下行: DocumentRoot /var/www/html 将其修改为你希望的apt仓库的根目录路径。保存文件并退出。 接下来,我们需要在该根目录下创建一个文件夹作为apt仓库的存储位置。在终端中输入以下命令: sudo mkdir -p /var/www/html/ubuntu 然后,将需要的Ubuntu软件包拷贝到该文件夹下。你可以通过下载这些软件包,然后使用以下命令将其复制到该文件夹下: sudo cp [软件包路径] /var/www/html/ubuntu 注意,你可以将多个软件包复制到该文件夹下,以便提供不同的软件选择。 最后,我们需要更新apt列表以添加新的。在终端中输入以下命令: sudo apt-get update 现在,你的局域网内的其他设备就可以通过以下命令来访问并安装这些软件包: sudo apt-get install [软件包名称] 通过搭建Ubuntu局域网apt-get,你的内部网络就能够更高效地下载和更新软件,减少对外部网络的依赖。同时,你也可以根据需要添加更多的软件包到apt仓库中,以提供更多的选择。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值