Como gerar pacotes .RPM – gere seu próprio pacote rpm

Uma excelente utilidade ao gerar seus próprios pacotes é a possibilidade de fazer upgrade e downgrade de aplicações com facilidade e agilizar as entregas em Dev, Qa, e Produção.
Hoje em dia com CI e CD é imprescindível que ao executar um deploy se tenha a possibilidade de rollback, isto é o básico.
Então neste tutorial vou demonstrar como gerar pacotes rpms, assim como o processo de instalação, upgrade e downgrade dos pacotes.

1. Criação de um usuário para gerar pacotes RPM
É opcional mas recomendo criar um usuário dedicado para o build de pacotes .rpm, neste tutorial eu criei o usuário “buildrpm”.

2. Instale os pacotes rpmdevtools e rpm-build

# yum -y install rpmdevtools rpm-build

3. Crie a árvore de diretórios para gerar o pacote

$ rpmdev-setuptree
$ ls -R rpmbuild/
rpmbuild/:
BUILD  RPMS  SOURCES  SPECS  SRPMS

Ou pode ser criado na mão.

$ mkdir rpmbuild
$ cd rpmbuild
$ mkdir BUILD RPMS SOURCES SPECS SRPMS

4. Vou criar um arquivo de repositório .repo, no caso é o “MEU-REPO.repo”

$ cd rpmbuild/SOURCES
$ mkdir -p repo-versao-1/etc/yum.repos.d
$ cp -v ~/MEU-REPO.repo repo-versao-1/etc/yum.repos.d

Foi criado um repositório qualquer no caso “MEU-REPO.repo”, mas poderia ser qualquer arquivo.
Criei uma pasta versionada “repo-versao-1”, sendo assim sugiro que a cada modificação altere a versão da pasta (repo-versao-1.1, repo-versao-1.2, repo-versao-2.0, …).

5. Gere o tarball da pasta “repo-versao-1”

$ cd rpmbuild/SOURCES
$ # tar cvzf repo-versao-1.tar.gz repo-versao-1

$ tar cvzf repo-versao-1.tar.gz repo-versao-1
repo-versao-1/
repo-versao-1/etc/
repo-versao-1/etc/yum.repos.d/
repo-versao-1/etc/yum.repos.d/MEU-REPO.repo

Este pacote .tar.gz será utilizado na definição do .spec logo abaixo.

6. Criação do arquivo .Spec
O arquivo .spec é onde serão definidas as informações para a gerar o pacote .rpm.

$ cd rpmbuild/SPECS
$ rpmdev-newspec  repo-versao-1.spec
$ cat repo-versao-1.spec
Name:           repo-versao
Version:        1
Release:        0
Summary:        Resumo Este e um repositorio repo devopslab bla bla bla

License:        GPL
URL:            http://repo.devopslab.com.br/repo/CentOS/
Source0:        repo-versao-1.tar.gz

BuildArch:	noarch
BuildRoot:	%{_tmppath}/%{name}-buildroot

%description
Escreva uma descricao para o pacote
Este e um novo repositorio bla bla bla

%prep
%setup -q

%install
mkdir -p $RPM_BUILD_ROOT
cp -R * $RPM_BUILD_ROOT

%files
%defattr(-,root,root,-)
/etc/yum.repos.d/MEU-REPO.repo

7. Gere o pacote utilizando as definições do arquivo .spec

$ cd rpmbuild/SPECS/
$ # rpmbuild -v -bb repo-versao-1.spec

buildrpm@rpmbuild-01 SPECS]$ rpmbuild -v -bb repo-versao-1.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.DowMqD
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ cd /home/buildrpm/rpmbuild/BUILD
+ rm -rf repo-versao-1
+ /usr/bin/gzip -dc /home/buildrpm/rpmbuild/SOURCES/repo-versao-1.tar.gz
+ /usr/bin/tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd repo-versao-1
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.xb3qI7
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ '[' /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64 '!=' / ']'
+ rm -rf /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
++ dirname /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ mkdir -p /home/buildrpm/rpmbuild/BUILDROOT
+ mkdir /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ cd repo-versao-1
+ mkdir -p /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ cp -R etc /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ '[' noarch = noarch ']'
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: repo-versao-1-0.noarch
Provides: repo-versao = 1-0
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
Wrote: /home/buildrpm/rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.lNfmk8
+ umask 022
+ cd /home/buildrpm/rpmbuild/BUILD
+ cd repo-versao-1
+ /usr/bin/rm -rf /home/buildrpm/rpmbuild/BUILDROOT/repo-versao-1-0.x86_64
+ exit 0
#

8. Verifique o pacote criado na pasta RPMS

$ ls rpmbuild/RPMS/noarch/ 
rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm

$ rpm -qpl rpmbuild/RPMS/noarch/repo-versao-1-0.noarch.rpm
/etc/yum.repos.d/MEU-REPO.repo

9. Instale o pacote e veja se foi criado o arquivo “/etc/yum.repos.d/MEU-REPO.repo”

$ sudo rpm -hiv repo-versao-1-0.noarch.rpm

$ ls -l /etc/yum.repos.d/MEU-REPO.repo 
-rw-r--r--. 1 root root 202 Apr 14 13:10 /etc/yum.repos.d/MEU-REPO.repo

10. Teste de remoção de pacote
Remova o pacote repo-versao-1-0. Após a remoção o arquivo “/etc/yum.repos.d/MEU-REPO.repo” terá que ser removido.

$ sudo yum remove repo-versao-1-0.noarch
$ ls -l /etc/yum.repos.d/MEU-REPO.repo 
ls: cannot access /etc/yum.repos.d/MEU-REPO.repo: No such file or directory

11. Teste de Upgrade e Downgrade
Vou gerar algumas versões para fazer o teste de upgrade e downgrade.
Primeiramente crie novos arquivos “.spec” e altere a versão e o source0.

SPECS/repo-versao-1.1.spec
Name: repo-versao
Version: 1.1
Release: 0
Source0: repo-versao-1.1.tar.gz

SPECS/repo-versao-1.2.spec
Name: repo-versao
Version: 1.2
Release: 0
Source0: repo-versao-1.2.tar.gz

Agora crie novas pastas dentro do SOURCES com as respectivas versões.
SOURCES/repo-versao-1.1
SOURCES/repo-versao-1.2

Altere os arquivos que você quiser, e gere um novo tarball tar.gz.
tar -cvzf repo-versao-1.1.tar.gz repo-versao-1.1
tar -cvzf repo-versao-1.2.tar.gz repo-versao-1.2

Por fim gere os novos pacotes.
$ rpmbuild -v -bb SPECS/repo-versao-1.1.spec
$ rpmbuild -v -bb SPECS/repo-versao-1.2.spec

Verifique os pacotes rpms gerados.
$ cd /home/buildrpm/rpmbuild/RPMS/noarch
$ ls
repo-versao-1-0.noarch.rpm
repo-versao-1.1-0.noarch.rpm
repo-versao-1.2-0.noarch.rpm

Instalação do pacote versão 1.1 repo-versao-1.1-0.noarch.rpm

$ sudo rpm -hiv repo-versao-1.1-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1.1-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.1 - Repositorio Teste Meu Repo - DevOpsLab

Upgrade para a versão 1.2 repo-versao-1.2-0.noarch.rpm

$ sudo rpm -Uvh repo-versao-1.2-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1.2-0                ################################# [ 50%]
Cleaning up / removing...
   2:repo-versao-1.1-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.2 - Repositorio Teste Meu Repo - DevOpsLab
$ rpm -qa | grep repo-versao
repo-versao-1.2-0.noarch

Downgrade para a versão 1.0 repo-versao-1-0.noarch.rpm

$ sudo rpm -Uvh --oldpackage repo-versao-1-0.noarch.rpm
Preparing...                          ################################# [100%]
Updating / installing...
   1:repo-versao-1-0                  ################################# [ 50%]
Cleaning up / removing...
   2:repo-versao-1.2-0                ################################# [100%]
$ cat /etc/yum.repos.d/MEU-REPO.repo | grep Versao
name=Versao 1.0 - Repositorio Teste Meu Repo - DevOpsLab
$ rpm -qa | grep repo-versao
repo-versao-1-0.noarch

Remoção do pacote repo-versao-1-0.noarch.rpm

$ sudo rpm -e repo-versao-1-0.noarch
$ ls  /etc/yum.repos.d/MEU-REPO.repo
ls: cannot access /etc/yum.repos.d/MEU-REPO.repo: No such file or directory
$ rpm -qa | grep repo-versao
$ 

É isto aí, novidades só chamar.

Leonardo Macedo

Como criar e configurar um repositório local Centos

Criar um repositório local pode ser útil por diversos motivos como por exemplo:

• Rede isolada
Você tem uma rede isolada porém quer manter os servidores atualizados.

• Segurança
Para alguns servidores críticos da empresa, por exemplo ambientes sob na norma PCI (ambientes de pagamento), a rede precisa ser isolada por questões de segurança, os servidores não podem ter acesso a internet, neste caso um repositório local é a solução.
PCI são normas de segurança aplicadas a ambientes de tecnologia.

• Velocidade
Baixar de uma rede local quase sempre será mais rápido que baixar da internet. Hoje em dia todos nós queremos fazer um deploy mais rápido, criar uma VM mais rápido, criar um container mais rápido, um processo de Bootstrap mais rápido, enfim para todos estes casos um repositório local será interessante.

• Economia de banda
Além de baixar os pacotes mais rápido, você não vai gastar banda de internet, já que seus servidores não vão precisar buscar lá fora os pacotes.

• Criação de pacotes localmente
Pode ser que na sua empresa vocês mesmos criam seus pacotes, é muito comum isto, você baixa um pacote qualquer, modifica o conteúdo e empacota novamente, após isto você manda para o repositório local. Ou então cria um pacote do zero e envia para o repositório.

Pré-requisitos

Centos 7 – 64 bits – atualizado – instalação mínima.
Web Server: Apache ou Nginx.

Como criar e configurar um repositório local Centos

O conceito aplicado aqui também pode ser utilizado em ambientes Debian/Ubuntu.

Domínio teste: repo.devopslab.com.br

Crie uma pasta para o armazenamento dos pacotes “.rpm”

#mkdir -p /var/www/html/repo/CentOS/7/os
#mkdir -p /var/www/html/repo/CentOS/7/updates

Instale o pacote createrepo

#yum install createrepo -y

Inicialize o repositório

#createrepo  /var/www/html/repo/CentOS/7/

[root@repo-01 ~]# createrepo  /var/www/html/repo/CentOS/7/
Saving Primary metadata
Saving file lists metadata
Saving other metadata
Generating sqlite DBs
Sqlite DBs complete

Sincronização dos pacotes
Vamos sincronizar um repositório público CentOS com nosso repositório local.

Escolha um espelho próximo a sua localidade, escolha aquele que você consiga uma boa velocidade de download.

https://www.centos.org/download/mirrors/
http://mirror-status.centos.org/

No meu caso vou baixar do espelho rsync://linorg.usp.br/CentOS

Quando você abrir a url via navegador existirão várias pastas, como isos, extras, centosplus e etc. Nós não precisamos de nada disto para manter um ambiente atualizado, sendo assim vou sincronizar apenas a pasta “os” e “updates”.
*Antes de prosseguir veja dica no final deste tutorial.

#rsync -avz rsync://linorg.usp.br/CentOS/7/os/ /var/www/html/repo/CentOS/7/os
#rsync -avz rsync://linorg.usp.br/CentOS/7/updates/ /var/www/html/repo/CentOS/7/updates

Este primeiro sync vai demorar pois serão baixados todos os arquivos do repositório, mas no próximo processo de sincronização será baixado apenas o que foi modificado ou novos pacotes. O Rsync é inteligente e verifica e baixa apenas as alterações.

Update do repositório
Após você sincronizar o repositório local será preciso atualizar a lista de pacotes do repositório.

#createrepo --update /var/www/html/repo/CentOS/7/

Web Server
Você precisa subir um web server, pode ser um Apache ou Nginx ou qualquer um de sua preferência.

Instalação do Nginx
Repositório EPEL.

#rpm -hiv http://mirror.globo.com/epel/7/x86_64/e/epel-release-7-5.noarch.rpm

Instalação

#yum install nginx –y

Altere a pasta raiz para “/var/www/html” e adicione “autoindex on”

#vi /etc/nginx/nginx.conf

root         /var/www/html;
autoindex 		on;

Restart do Nginx e ativação.

#systemctl restart nginx
#systemctl enable nginx

Liberação do Firewall

 
#firewall-cmd --permanent --add-service http
#systemctl reload firewalld

Configuração dos clientes
Antes limpe a pasta “yum.repos.d”, então mova todos os arquivos “.repo” para outra pasta e crie um novo repositório.

#mv -v /etc/yum.repos.d/*.repo ~
#vi /etc/yum.repos.d/meurepositorio.repo
[os-devopslab]
name=Repositorio Base - DevOpsLab
baseurl=http://repo.devopslab.com.br/repo/CentOS/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

[updates-devopslab]
name=Repositorio Upadates - DevOpsLab
baseurl=http://repo.devopslab.com.br/repo/CentOS/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

Substitua o domínio “repo.devopslab.com.br” pelo seu ip ou domínio.

Verificação do repositório.

#yum clean all
#yum repolist all

[root@client-01 ~]# yum repolist all
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
repo id                                       repo name                                           status
os-devopslab/7/x86_64                         Repositorio Base - DevOpsLab                        enabled: 9,007
updates-devopslab/7/x86_64                    Repositorio Upadates - DevOpsLab                    enabled:   826
repolist: 9,833

Verificação de um pacote.

[root@client-01 ~]# yum info PyYAML
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Available Packages
Name        : PyYAML
Arch        : x86_64
Version     : 3.10
Release     : 11.el7
Size        : 153 k
Repo        : os-devopslab/7/x86_64
Summary     : YAML parser and emitter for Python
URL         : http://pyyaml.org/
License     : MIT
Description : YAML is a data serialization format designed for human readability and
            : interaction with scripting languages.  PyYAML is a YAML parser and
            : emitter for Python.

Instalação de um pacote.

[root@client-01 ~]# yum install PyYAML
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
Resolving Dependencies
--> Running transaction check
---> Package PyYAML.x86_64 0:3.10-11.el7 will be installed
--> Processing Dependency: libyaml-0.so.2()(64bit) for package: PyYAML-3.10-11.el7.x86_64
--> Running transaction check
---> Package libyaml.x86_64 0:0.1.4-11.el7_0 will be installed
--> Finished Dependency Resolution
Dependencies Resolved
================================================================================================================
 Package                Arch                  Version                         Repository                   Size
================================================================================================================
Installing:
 PyYAML                 x86_64                3.10-11.el7                     os-devopslab                153 k
Installing for dependencies:
 libyaml                x86_64                0.1.4-11.el7_0                  os-devopslab                 55 k
Transaction Summary
================================================================================================================
Install  1 Package (+1 Dependent package)
Total size: 208 k
Total download size: 55 k
Installed size: 760 k
Is this ok [y/d/N]: y
Downloading packages:
Delta RPMs disabled because /usr/bin/applydeltarpm not installed.
libyaml-0.1.4-11.el7_0.x86_64.rpm                                                        |  55 kB  00:00:00     
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : libyaml-0.1.4-11.el7_0.x86_64                                                                1/2 
  Installing : PyYAML-3.10-11.el7.x86_64                                                                    2/2 
  Verifying  : libyaml-0.1.4-11.el7_0.x86_64                                                                1/2 
  Verifying  : PyYAML-3.10-11.el7.x86_64                                                         2/2 
Installed:
  PyYAML.x86_64 0:3.10-11.el7                                                                                   
Dependency Installed:
  libyaml.x86_64 0:0.1.4-11.el7_0                                                                               
Complete!

Atualização dos repositórios.
Deixe o repositório sempre atualizado, então faça um script de atualização.
Uma atualização semanal é suficiente.

#vi /root/reposync.sh

#!/bin/bash
rsync -az rsync://linorg.usp.br/CentOS/7/os/ /var/www/html/repo/CentOS/7/os
rsync -az rsync://linorg.usp.br/CentOS/7/updates/ /var/www/html/repo/CentOS/7/updates
createrepo --update /var/www/html/repo/CentOS/7/
#Permissão de execução
chmod +x /root/reposync.sh

#Cron
crontan –l
00 03 * * 6 /root/reposync.sh

O Cron vai rodar todo sábado as 3 horas da madrugada.

*Dica
É possível otimizar ainda mais a sincronização.
Mesmo sincronizando apenas as pastas “os” e “updates” ainda é possível eliminar alguns pacotes desnecessários como segue no rsync abaixo.

rsync -avz --exclude=LiveOS --exclude=images --exclude=EFI --exclude=isolinux rsync://linorg.usp.br/CentOS/7/os/ /var/www/html/repo/CentOS/7/os

Qualquer dúvida, correção e sugestão fique à vontade.