<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用 Docker 構(gòu)建 yum/apt 離線源

          共 4626字,需瀏覽 10分鐘

           ·

          2021-09-10 12:19

          對于 PaaS toB 產(chǎn)品來講,客戶往往會要求產(chǎn)品的部署方案必須做到離線安裝,即在部署時不能依賴任何在線的資源,比如安裝一些 OS 軟件包時依賴的 yum/apt 源;docker.io、k8s.gcr.io 、quay.io 上面的容器鏡像;GitHub 上開源軟件的二進(jìn)制下載文件等。
          作為平臺部署工具的開發(fā)者,始終被離線部署這個難題困擾著。在線的容器鏡像和二進(jìn)制文件比較好解決,因為這些資源是與 OS 無關(guān)的,只要下載下來放到安裝包里,部署的時候啟動一個 HTTP 服務(wù)器和鏡像倉庫服務(wù)提供這些資源的下載即可。
          但是對于 yum/apt 之類的軟件來講并不那么簡單:
          • 首先由于各個包之間的依賴關(guān)系比較復(fù)雜,并不能將它們直接下載下來;
          • 其次即便下載下來之后也無法直接通過 yum/apt 的方式安裝指定的軟件包,雖然也可以使用 scp 的方式將這些包復(fù)制到部署節(jié)點,通過 rpm 或 dpkg 的方式來安裝上,但這樣并不是很優(yōu)雅,而且通用性能也不是很好;
          • 最后需要適配的 Linux 發(fā)行版和包管理器種類也有多種,而且有些包的包名或者版本號在不同的包管理之間也相差甚大,無法做到統(tǒng)一管理。
          綜上,將平臺部署依賴的在線 yum/apt 之類的軟件包資源制作成離線安裝包是一件很棘手的事情。個人就這個問題折騰了一段時間,終于找到了一個比較合適的解決方案:即通過一個 YAML 配置文件來管理包,然后使用 Dockerfile 來構(gòu)建成離線的 tar 包或者容器鏡像。如果有類似需求的小伙伴,可以參考一下本方案。
          K8sMeetup
          Docker build
          傳統(tǒng)制作離線源的方式是找一臺相應(yīng)的 Linux 機(jī)器,在上面通過包管理器下載這些軟件包,然后再創(chuàng)建這些軟件包的 repo 索引文件。
          可以看出這種方式十分不靈活,假如我想要制作 Debian 9 的 apt 離線源,我就需要一臺 Debian 9 的機(jī)器。如果要適配多個 Linux 發(fā)行版就需要多個相應(yīng)的 OS 機(jī)器。要管理和使用這么多種類的 OS 不是一件容易的事兒,而如今使用已經(jīng)相當(dāng)普遍的容器技術(shù)恰恰能幫助我們解決這類問題。比如我想運行一個 Debian 9 的操作系統(tǒng),我只需要運行一個 Debian 9 鏡像的容器即可,而且不需要額外的管理成本,使用起來也十分輕量。
          日常工作中我們常使用容器來構(gòu)建一些 Golang 寫的后端組件,那么構(gòu)建離線源是不是也可以這樣做?實踐證明確實可以,我們只需要為不同的 OS 和包管理器寫一個相應(yīng)的 Dockerfile 即可。使用 Docker build 多階段構(gòu)建的特性,可以將多個 Dockerfile 合并成一個,然后最后使用 COPY --from 的方式將這個構(gòu)建的產(chǎn)物復(fù)制到同一個鏡像中,比如提供 HTTP 的 nginx 容器,或者使用 BuildKit 的特性將這些構(gòu)建產(chǎn)物導(dǎo)出為 tar 包或者本地目錄。
          K8sMeetup
          適配 OS
          根據(jù)自己的 PaaS toB 從業(yè)經(jīng)驗可知,目前國內(nèi)的私有云客戶在生產(chǎn)環(huán)境中使用的 OS,CentOS 應(yīng)該是最多的,其次是 Ubuntu 和 Debian。至于 RedHat 則需要付費訂閱才能使用,DockerHub 更是沒有免費可使用的鏡像,因此本方案無法確保適用于 RedHat。產(chǎn)品方面 CentOS 需要的版本只有 7.9;Ubuntu 需要支持 18.04 和 20.04;Debian 需要支持 9 和 10。因為時間和精力有限,本方案支持的 Linux 發(fā)行版和相應(yīng)的版本只有 CentOS 7,Debian 9/10,Ubuntu 18.04/20.04 這五個。如果要支持其他 OS 的離線源比如 OpenSUSE,也可以參考本方案編寫一個 Dockerfile 文件來實現(xiàn)適配。
          K8sMeetup
          構(gòu)建
          構(gòu)建的過程十分簡單,使用一個 YAML 格式的配置文件來管理不同的包管理器或 Linux 發(fā)行版安裝不同的包,并在一個 Dockerfile 里完成所有的構(gòu)建操作。

          構(gòu)建過程
          使用 Docker Build 的方式構(gòu)建離線源大致可以分為如下幾個步驟:
          • 在構(gòu)建容器內(nèi)配置 yum/apt 源,安裝構(gòu)建時需要工具;
          • 生成系統(tǒng)內(nèi)的 rpm/deb 包的列表和需要下載的包列表,解決一些軟件包依賴的問題;
          • 根據(jù)生成的包列表使用相應(yīng)的包管理器工具下載需要的軟件包;
          • 使用相應(yīng)的包管理器生成這些包的 index 文件,如 repodata 或 Packages.gz 文件;
          • 將上述的構(gòu)建產(chǎn)物 COPY 到同一個容器鏡像里,比如 nginx ;也可以導(dǎo)出為 tar 包或目錄;
          packages.yaml
          這個文件用來管理不同的包管理器或者 Linux 發(fā)行版需要安裝的軟件包。根據(jù)不同的包管理器和發(fā)行版我們可以將這些包大致劃分為以下 4 類:
          • common:適用于一些所有包管理器中包名相同或者對版本無要求的包,比如 vim 、curl、wget 這類工具。一般情況下使用這些工具我們并不關(guān)心它的版本,并且這類包的包名在所有的包管理器中都是相同的,所以這類可以劃分為公共包。
          • yum/apt/dnf:適用于不同的發(fā)行版使用相同的包管理器。比如 nfs 的包,在 yum 中包名為 nfs-utils 但在 apt 中為 nfs-common,這類軟件包可以劃分為一類。
          • OS:適用于一些該 OS 獨有的包,比如安裝一個 Ubuntu 中有但 Debian 中沒有的包(比如 debian-builder 或 ubuntu-dev-tools)。
          • OS-發(fā)行版代號:這類包的版本和發(fā)行版代號綁定在一起,比如 docker-ce=5:19.03.15~3-0~debian-stretch

          在這里需要額外注意一下,在不同的包管理器之間指定包版本的方式也各不相同,比如在 yum 中如果要安裝 19.03.15 版本的 docker-ce 包名為 docker-ce-19.03.15,而在 debian 中包名則為 docker-ce=5:19.03.15~3-0~debian-stretch??梢允褂冒芾砥鞑榭聪嗤囊粋€包(如 docker-ce)在不同的包管理器之間的差異,如下:

          這個版本號的問題在 Kubespray 的源碼中也是同樣做了特殊處理,目前確實沒有太好的方案來解決,只能手動維護(hù)這個版本號。
          • roles/container-engine/docker/vars/redhat.yml

          • roles/container-engine/docker/vars/ubuntu.yml

          CentOS 7
          介紹完上述的包配置文件之后,接下來我們就根據(jù)這個 packages.yml 配置文件使用 Dockerfile 構(gòu)建這些包的離線源。以下是構(gòu)建 CentOS 7 離線源的 Dockerfile。

          在最后的一個 FROM 鏡像中,我指定的是 scratch,這是一個特殊的鏡像名,它代表的是一個空的鏡像 layer。這樣方便將它導(dǎo)出為 tar 包和目錄格式。

          也可以直接將構(gòu)建出來的產(chǎn)物放到 nginx 容器中,這樣直接運行 nginx 容器就能提供 yum/apt 源的服務(wù)。

          • 如果要構(gòu)建為 tar 包或者本地目錄的方式,需要為 Docker 開啟 DOCKER_BUILDKIT=1 這個特性。

          • 構(gòu)建日志如下:

          • 構(gòu)建產(chǎn)物如下:

          Debian 9
          下面是 Debian 9 構(gòu)建 Dockerfile,流程上和 CentOS 相差不多,只是包管理器的使用方式不太相同,這里就不再做詳細(xì)的源碼介紹。
          • Dockerfile.debian

          Ubuntu
          Ubuntu 離線源的制作步驟和 Debian 差不多,只需要簡單修改一下 Debian 的 Dockerfile 應(yīng)該就 OK ,比如 's/debian/ubuntu/g' ,畢竟 Debian 是 Ubuntu 的爸爸嘛~~,所以 apt 使用的方式和包名幾乎一模一樣,這里就不再贅述了。
          All-in-One
          將上述幾個 Linux 發(fā)行版的 Dockerfile 整合成一個,這樣只需要一個 Docker Build 命令就能構(gòu)建出所需要的所有 OS 的離線源了
          • Dockerfile


          K8sMeetup
          使用
          構(gòu)建好了離線源之后,在部署的機(jī)器上運行一個 Nginx 服務(wù),用于提供 HTTP 方式下載這些軟件包,同時需要配置一下機(jī)器的包管理器 repo 配置文件。
          • CentOS 7

          • Debian 9 stretch

          • Debian 10 buster

          • Ubuntu 18.04 bionic

          • Ubuntu 20.04 focal
          K8sMeetup
          優(yōu)化
          Dockerfile
          可以考慮將 Dockerfile 中的構(gòu)建過程合并成一個 shell 腳本,然后在 Dockerfile 中調(diào)用這個腳本即可。這樣可優(yōu)化 Dockerfile 代碼的可維護(hù)性,同時后續(xù)適配多種 OS 的時候也可以復(fù)用部分相同的代碼,但這種做法可能會導(dǎo)致 Docker Build 緩存的失效問題。
          Package version
          對于一些版本中包含 Linux 發(fā)行版本代號的包來講,手動維護(hù)這個代號不太方便,可以考慮將它魔改成占位變量的方式,在構(gòu)建容器內(nèi)生成 package.list 文件后統(tǒng)一使用 sed 把這些占位的變量給替換一下,如下:

          使用 sed 處理一下 packages.list 中的這些占位符變量:

          雖然這樣做很不美觀,但這種方式確實可行 ??,最終能夠得到正確的版本號??傊覀?strong>盡量地少維護(hù)一些包的版本,比如使用這種方式就可以將某個版本的 docker-ce 包放在配置文件的 apt 中,而不是 debian/ubuntu 中,通過一些環(huán)境變量或者 shell 腳本自動添加上這些特殊項,這樣能減少一些維護(hù)成本。
          參考
          • aptly.info:https://www.aptly.info/tutorial/mirror/
          • jq 常用操作:https://mozillazg.com/2018/01/jq-use-examples-cookbook.html
          • yq 之讀寫篇:https://lyyao09.github.io/2019/08/02/tools/The-usage-of-yq-read-write/
          • Build images with BuildKit:https://docs.docker.com/develop/develop-images/build_enhancements/
          • kubernetes-sigs/kubespray/pull/6766:https://github.com/kubernetes-sigs/kubespray/pull/6766
            萬字長文:徹底搞懂容器鏡像構(gòu)建
            為 CentOS 與 Ubuntu 制作離線本地源:https://www.xiaocoder.com/2017/09/12/offline-local-source/
          瀏覽 190
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  五月婷婷激情网 | 天天躁日日躁AAAXXⅩ | 一级片免费视频 | 国产色情视频在线观看 | 日韩精品AV电影 |