Resgatando a chave pública de um perfil no Jenkins

Categoria: Linux Publicado: Terça, 09 Novembro 2021 Escrito por Helio Loureiro

Pode parecer meio estranho, mas foi isso mesmo que precisei fazer: pegar a chave pública de ssh de um perfil que estava no jenkins pra configurar o acesso num repositório Gitlab.

Mas o Jenkins, sabiamente, não guarda ou mostra essas credenciais pra você.  Então precisei recorrer a meios não muito convencionais pra fazer isso.

Primeiro fooi pegar a chave privada que ele tinha armazenado.  Pra isso encontrei uma receita de bolo, escrita em Groovy.

https://scriptcrunch.com/groovy-script-retrieve-jenkins-credentials/


import jenkins.*
import jenkins.model.* 
import hudson.*
import hudson.model.*
def jenkinsCredentials = com.cloudbees.plugins.credentials.CredentialsProvider.lookupCredentials(
        com.cloudbees.plugins.credentials.Credentials.class,
        Jenkins.instance,
        null,
        null
);
for (creds in jenkinsCredentials) {
    // descomente essa parte abaixo se precisar de mais detalhes
    //println(jenkinsCredentials.id)
    println(creds.username))
    if(creds.id == "2671e11a-4831-fa3f-0d58-7b331318c04d"){
    	println(creds.privateKey)
    }
}

E pra rodar junto ao Jenkins, na área de scripts.  Se não sabia ainda, é possível rodar script pela interface web atráves da url que tem do Jenkins mais o final "/script".

No laço "if" onde olho se o creds.id bate com um número gigante, esse é o identificador que você vê como ID nas credenciais.

Esse foi o resultado:


user1
user2
user3
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyONzf1Ti1Dv8jI68/oyGJ2Gf6CNkN64ncZAVB5QnR+0NbyzN
G9U6uFqKUoSuuYblqANJNGR3PKCVhCJCB6Ge7azPK10eYEHFyYXGuIwi9Rb3MsjN
Cof57NzenIUcErm0Cuxk34xEXdR5UFm8GI0q3MEuBSwopQfAnfGa5L+QxGt/+YuY
ei/n/V0QsgYuZb9RVF2NbTrNLk09vBQ7SVwyDzKBaaGFkO0uh6fvCz/gq8L+f9cL
Z/twZNy1/Z13VSe2Agd/1ErLBqlTrxabPCFPMWm4YiAAwIUqhwaI6GU7IRLo/HWo
9eqfvYUWh6FyBKRf7bdSdWfWSSTNxgwPCfJavQIDAQABAoIBADjjaG6znDSb9C3d
shmns8ntNHppo1S9RcA8HCh0RRdyQu6r0j3CiYlxYmBx4IT7dYe5vn5OwRFzLEQp
62b71uTZniVajmKV3avu7VKPpMqhQUmpYZ9M2HLCLWxHqaaH3juFrB8+OpITvHML
pl+RgoTXU+/1DGGHq31O0R1cPmPQyRDhaxVpzsYwbCcIYGJ1hjz2g+098LwtIr5W
5i2Z6JUpE6GyXlVZAM1f9tsYWgGGEBqbH4frUjH9Ao1F7dKARDHsiwcjbreywBx1
aVk8AsTP31vqdOJgUJC9JcM/cf2GLUQxg7ZjdDTrTPWnNzWFhALoFe79UKw4lhE7
ezrqi0UCgYEA457BTvaKI+pcxuh5waV1SrfBYDC9czZpYht1R1i3lmYJKdQFHtVl
HAoy18zuYec9MaNPdqbzWysqkH6D6R8T/qdogQ9/5XpSnPVGbsg2IRKq4jNPrh1M
y8Kx2SOYpk6eLtPxYeRHaAKv/GYbQMs8Sh+GNkSiudhTEESj+KKhmO8CgYEA4e93
phLCmzP+SI2pgqFkZ2H2R5X8aCkbuV7pdcnTb4T/rH0Zah2vFEOmjWaUaGHJDOWk
6y+JPzWmxdweb+2FKTg1g6m8ig1DazcmkTG0CEWwwDLJ93LiQYl59uXt2UuQSkj6
Be+JcUzY2w1lhD0+vNfVF/RrH+xTaYfze1PiDxMCgYBtHNUdvSFLRjVjRF3Zbi9j
ueKA8dxfNl4eIXt+0BBxkEgkPPaXaUQmxNzKhfpgBDFZcifNgQp3UaH90if5wGQd
VrLJ61wr7Q9dHla9FEyeXgx8koxHstP1eUc4B9BNKLK7T+4ONxfjzCYAoBHAZaxo
++OicBRxcjmfOsg/j/ZXEQKBgQDZS84gfJSMXsIml5C7YWvGfpI2IUukBj1y2JTi
w1zGOf0IsTybMbdsXvA1uL3tcnbCH6+wvoRatcgTLfRcI+3ZSgU1/y6k+8KmwGEo
bcw/1H79KxvSEL0I2SbjThqmzaUVvQAya0IeJRHABC9pstm/GDoLkvjguBM1QRrs
ty2I3wKBgEBRpeSp/07x6LaIqHULNuV515BqtvWmWQuc8ngMOkcOO1mcQ745VbDj
YO0pIFHmK1iCtrXhyKPxOOitBjiQOZTeR6cZehm/7Mg+LWR6qdloqOOOij//WND6
PEeIskhUu6Dg07S91meHs3u/TRL0Gmr+zjCIn/0P40O38iyZTaVK
-----END RSA PRIVATE KEY-----
user4
user5
user6

De posse da chave privada, foi então questão de salvar em arquivo, que chamei de jenkins, e gerar a chave pública a partir dela.

Achei que o openssl iria fazer isso, mas todas as tentativas foram frustradas.  No fim descobri como resolver com o próprio ssh-keygen olhando no stackoverflow, sempre ele pra nos ajudar:

https://stackoverflow.com/questions/10271197/how-to-extract-public-key-using-openssl


> ssh-keygen -y -f jenkins
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABA
AABAQDI43N/VOLUO/yMjrz+jIYnYZ/oI2Q3ridxkBUHlCdH7Q1vLM0b1Tq4W
opShK65huWoA0k0ZHc8oJWEIkIHoZ7trM8rXR5gQcXJhca4jCL1FvcyyM0Kh
/ns3N6chRwSubQK7GTfjERd1HlQWbwYjSrcwS4FLCilB8Cd8Zrkv5DEa3/5i
5h6L+f9XRCyBi5lv1FUXY1tOs0uTT28FDtJXDIPMoFpoYWQ7S6Hp+8LP+Crw
v5/1wtn+3Bk3LX9nXdVJ7YCB3/USssGqVOvFps8IU8xabhiIADAhSqHBojoZ
TshEuj8daj16p+9hRaHoXIEpF/tt1J1Z9ZJJM3GDA8J8lq9

e foi assim que consegui conectar o Jenkins usando o user3 com chave ssh no Gitlab.  Peço desculpas em ter quebrado a chave em 60 colunas aqui, mas o fiz pra que ficasse bom pra ler também em smartphones.

AVISO: todos os dados aqui não são os verdadeiros.  Antes de alguém perder tempo usando isso pra tentar invadir alguma coisa minha, eu gerei tanto o ID com sha256sum da data atual e preenchi pra parecer o ID do Jenkins quanto a chave privada, que gerei também só pra mostrar aqui.  Nada disso está em uso em lugar algum.

Usando a GPU para renderizar vídeo

Categoria: Linux Publicado: Domingo, 31 Outubro 2021 Escrito por Helio Loureiro

Durante a útima gravação do Unix Load On, Ingo comentou sobre aceleração de hardware via VAAPI.  Eu imaginava que isso apenas era possível com GPUs da NVIDIA, mas depois que ele comentou sobre VAPI rodando em Intel, fui atrás de como isso funcionava.

Então fiz o teste de criar um vídeo a partir das imagens que fiz da troca de pneus da bicicleta pros de inverno.

O primeiro foi usando a CPU.

  $ rm -f out.mp4; time ffmpeg -r 60 -i image-%03d.jpg -c:v libx264 -vf fps=60 -pix_fmt yuv420p out.mp4                                                                                                          
  ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers
    built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
    configuration: --prefix=/usr --extra-version=0ubuntu0.2
    --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu
    --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping
    --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa
    --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca
    --enable-libcdio --enable-libflite --enable-libfontconfig
    --enable-libfreetype --enable-libfribidi --enable-libgme
    --enable-libgsm --enable-libmp3lame --enable-libmysofa
    --enable-libopenjpeg --enable-libopenmpt --enable-libopus
    --enable-libpulse --enable-librubberband --enable-librsvg
    --enable-libshine --enable-libsnappy --enable-libsoxr
    --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame
    --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp
    --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq
    --enable-libzvbi --enable-omx --enable-openal --enable-opengl
    --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883
    --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264
    --enable-shared
    libavutil      55. 78.100 / 55. 78.100
    libavcodec     57.107.100 / 57.107.100
    libavformat    57. 83.100 / 57. 83.100
    libavdevice    57. 10.100 / 57. 10.100
    libavfilter     6.107.100 /  6.107.100
    libavresample   3.  7.  0 /  3.  7.  0
    libswscale      4.  8.100 /  4.  8.100
    libswresample   2.  9.100 /  2.  9.100
    libpostproc    54.  7.100 / 54.  7.100
  Input #0, image2, from 'image-%03d.jpg':
    Duration: 00:00:25.24, start: 0.000000, bitrate: N/A
      Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown),
      4000x3000 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 25 tbn, 25 tbc
  Stream mapping:
    Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (libx264))
  Press [q] to stop, [?] for help
  [swscaler @ 0x56448c3106c0] deprecated pixel format used, make sure you did set range correctly
  [libx264 @ 0x56448c268ee0] using SAR=1/1
  [libx264 @ 0x56448c268ee0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 BMI2 AVX2
  [libx264 @ 0x56448c268ee0] profile High, level 6.0
  [libx264 @ 0x56448c268ee0] 264 - core 152 r2854 e9a5903 - H.264/MPEG-4
  AVC codec - Copyleft 2003-2017 - http://www.videolan.org/x264.html -
  options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7
  psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1
  8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6
  lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0
  bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1
  b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=25
  scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0
  qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
  Output #0, mp4, to 'out.mp4':
    Metadata:
      encoder         : Lavf57.83.100
      Stream #0:0: Video: h264 (libx264) (avc1 / 0x31637661), yuv420p,
      4000x3000 [SAR 1:1 DAR 4:3], q=-1--1, 60 fps, 15360 tbn, 60 tbc
      Metadata:
        encoder         : Lavc57.107.100 libx264
      Side data:
        cpb: bitrate max/min/avg: 0/0/0 buffer size: 0 vbv_delay: -1
  frame=  631 fps=1.1 q=-1.0 Lsize=   64381kB time=00:00:10.46 bitrate=50388.8kbits/s speed=0.0188x
  video:64372kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.013232%
  [libx264 @ 0x56448c268ee0] frame I:11    Avg QP:23.13  size:216485
  [libx264 @ 0x56448c268ee0] frame P:236   Avg QP:25.43  size:133712
  [libx264 @ 0x56448c268ee0] frame B:384   Avg QP:25.38  size: 83278
  [libx264 @ 0x56448c268ee0] consecutive B-frames: 14.1% 11.7%  7.6% 66.6%
  [libx264 @ 0x56448c268ee0] mb I  I16..4: 16.8% 81.8%  1.4%
  [libx264 @ 0x56448c268ee0] mb P  I16..4: 24.8% 44.9%  0.4%  P16..4:
  16.1%  1.8%  0.9%  0.0%  0.0%    skip:11.1%
  [libx264 @ 0x56448c268ee0] mb B  I16..4: 12.5% 18.4%  0.1%  B16..8:
  21.0%  2.2%  0.3%  direct: 2.5%  skip:43.1%  L0:50.8% L1:46.8% BI: 2.4%
  [libx264 @ 0x56448c268ee0] 8x8 transform intra:62.8% inter:92.5%
  [libx264 @ 0x56448c268ee0] coded y,uvDC,uvAC intra: 29.1% 18.4% 0.7% inter: 11.4% 16.9% 0.1%
  [libx264 @ 0x56448c268ee0] i16 v,h,dc,p: 41% 27% 23%  9%
  [libx264 @ 0x56448c268ee0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 29% 22% 42%  2%  1%  1%  1%  1%  1%
  [libx264 @ 0x56448c268ee0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 31% 17% 19%  6%  6%  6%  6%  5%  3%
  [libx264 @ 0x56448c268ee0] i8c dc,h,v,p: 66% 16% 18%  1%
  [libx264 @ 0x56448c268ee0] Weighted P-Frames: Y:33.5% UV:16.5%
  [libx264 @ 0x56448c268ee0] ref P L0: 40.1% 13.1% 23.2% 17.1%  6.5%
  [libx264 @ 0x56448c268ee0] ref B L0: 59.5% 30.9%  9.6%
  [libx264 @ 0x56448c268ee0] ref B L1: 83.0% 17.0%
  [libx264 @ 0x56448c268ee0] kb/s:50142.36
  1190.99user 25.61system 9:17.29elapsed 218%CPU (0avgtext+0avgdata 2714684maxresident)k
  117280inputs+128944outputs (45major+630483minor)pagefaults 0swaps

9 minutos e 17 segundos.  Usando 218% de CPU, de um laptop com 4 CPUs.  Esse é o funcionamento normal.

E usando a GPU pra isso?  Eu demorei um pouco pra acertar os parâmetros pra usar a VAAPI, mas no fim deu certo.

  $ rm -f out.mp4; time ffmpeg -vaapi_device /dev/dri/renderD128 -r 60 -i image-%03d.jpg -vf 'format=nv12,hwupload,fps=60' -c:v h264_vaapi  -pix_fmt vaapi_vld out.mp4                                           
  ffmpeg version 3.4.8-0ubuntu0.2 Copyright (c) 2000-2020 the FFmpeg developers
    built with gcc 7 (Ubuntu 7.5.0-3ubuntu1~18.04)
    configuration: --prefix=/usr --extra-version=0ubuntu0.2
    --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu
    --incdir=/usr/include/x86_64-linux-gnu --enable-gpl --disable-stripping
    --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa
    --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca
    --enable-libcdio --enable-libflite --enable-libfontconfig
    --enable-libfreetype --enable-libfribidi --enable-libgme
    --enable-libgsm --enable-libmp3lame --enable-libmysofa
    --enable-libopenjpeg --enable-libopenmpt --enable-libopus
    --enable-libpulse --enable-librubberband --enable-librsvg
    --enable-libshine --enable-libsnappy --enable-libsoxr
    --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame
    --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp
    --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq
    --enable-libzvbi --enable-omx --enable-openal --enable-opengl
    --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883
    --enable-chromaprint --enable-frei0r --enable-libopencv --enable-libx264
    --enable-shared
    libavutil      55. 78.100 / 55. 78.100
    libavcodec     57.107.100 / 57.107.100
    libavformat    57. 83.100 / 57. 83.100
    libavdevice    57. 10.100 / 57. 10.100
    libavfilter     6.107.100 /  6.107.100
    libavresample   3.  7.  0 /  3.  7.  0
    libswscale      4.  8.100 /  4.  8.100
    libswresample   2.  9.100 /  2.  9.100
    libpostproc    54.  7.100 / 54.  7.100
  Input #0, image2, from 'image-%03d.jpg':
    Duration: 00:00:25.24, start: 0.000000, bitrate: N/A
      Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg/unknown/unknown),
      4000x3000 [SAR 1:1 DAR 4:3], 25 fps, 25 tbr, 25 tbn, 25 tbc
  Stream mapping:
    Stream #0:0 -> #0:0 (mjpeg (native) -> h264 (h264_vaapi))
  Press [q] to stop, [?] for help
  [swscaler @ 0x5577c4cfb3c0] deprecated pixel format used, make sure you did set range correctly
  Output #0, mp4, to 'out.mp4':
    Metadata:
      encoder         : Lavf57.83.100
      Stream #0:0: Video: h264 (h264_vaapi) (High) (avc1 / 0x31637661),
      vaapi_vld, 4000x3000 [SAR 1:1 DAR 4:3], q=0-31, 60 fps, 15360 tbn,
      60 tbc
      Metadata:
        encoder         : Lavc57.107.100 h264_vaapi
  frame=  631 fps=9.3 q=-0.0 Lsize=  133604kB time=00:00:10.48
  bitrate=104401.7kbits/s speed=0.154x
  video:133596kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB
  muxing overhead: 0.006032%
  59.94user 1.03system 1:08.18elapsed 89%CPU (0avgtext+0avgdata 120480maxresident)k
  3504inputs+267264outputs (0major+44766minor)pagefaults 0swaps

Resultado?  1 minuto e 08 segundos.  Incrível.  Usou 89% de CPU, o que significa que das 4 CPUs, uma somente ficou ocupada.  E não 100%, apenas 90%.

Realmente incrível.

Não são todos os formatos de vídeo que são suportados, mas pra ter esse desempenho acho que vale sacrificar os formatos pra gerar um simples mp4.

 UPDATE: 2021-11-01.  O vídeo que renderizei pros testes.

 

A briga entre Docker e firewalld

Categoria: Linux Publicado: Segunda, 16 Agosto 2021 Escrito por Helio Loureiro

Tirei férias longas demais.   Na verdade foram apenas 3 semanas, mas eu meio que deixei de postar aqui durante o período de férias.  E a procrastinação voltou forte.   Então aqui vamos nós com uma tentativa de voltar a escrever semanalmente.

Hoje, fazendo um troubleshooting the um serviço que não funcionava como devia (um scan de aplicação com o OWASP ZAP), descobri que meus containers em docker não estavam acessando a rede.   O que mudou?   Minha máquina de trabalho é um Ubuntu 18.04.  O repositório bionic-update trouxe uma versão nova do docker que reiniciou o daemon, mas... a parte de rede não funcionando.  E só percebi isso hoje.

root@dell-latitude-7480 /u/local# apt show docker.io
Package: docker.io
Version: 20.10.7-0ubuntu1~18.04.1
Built-Using: glibc (= 2.27-3ubuntu1.2), golang-1.13 (= 1.13.8-1ubuntu1~18.04.3)
Priority: optional
Section: universe/admin
Origin: Ubuntu
Maintainer: Ubuntu Developers <Este endereço de email está sendo protegido de spambots. Você precisa do JavaScript ativado para vê-lo.>
Original-Maintainer: Paul Tagliamonte <Este endereço de email está sendo protegido de spambots. Você precisa do JavaScript ativado para vê-lo.>
Bugs: https://bugs.launchpad.net/ubuntu/+filebug
Installed-Size: 193 MB
Depends: adduser, containerd (>= 1.2.6-0ubuntu1~), iptables, debconf (>= 0.5) | debconf-2.0, libc6 (>= 2.8), libdevmapper1.02.1 (>= 2:1.02.97), libsystemd0 (>= 209~)
Recommends: ca-certificates, git, pigz, ubuntu-fan, xz-utils, apparmor
Suggests: aufs-tools, btrfs-progs, cgroupfs-mount | cgroup-lite, debootstrap, docker-doc, rinse, zfs-fuse | zfsutils
Breaks: docker (<< 1.5~)
Replaces: docker (<< 1.5~)
Homepage: https://www.docker.com/community-edition
Download-Size: 36.9 MB
APT-Manual-Installed: yes
APT-Sources: mirror://mirrors.ubuntu.com/mirrors.txt bionic-updates/universe amd64 Packages
Description: Linux container runtime
 Docker complements kernel namespacing with a high-level API which operates at
 the process level. It runs unix processes with strong guarantees of isolation
 and repeatability across servers.
 .
 Docker is a great building block for automating distributed systems:
 large-scale web deployments, database clusters, continuous deployment systems,
 private PaaS, service-oriented architectures, etc.
 .
 This package contains the daemon and client. Using docker.io on non-amd64 hosts
 is not supported at this time. Please be careful when using it on anything
 besides amd64.
 .
 Also, note that kernel version 3.8 or above is required for proper operation of
 the daemon process, and that any lower versions may have subtle and/or glaring
 issues.

N: There is 1 additional record. Please use the '-a' switch to see it

Primeira coisa que tentei foi reiniciar o docker mesmo.

root@dell-latitude-7480 /u/local# systemctl restart --no-block docker; journalctl -u docker -f
[...]
Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.203367946+02:00" level=info msg="Firewalld: docker zone already exists, returning"
Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.549158535+02:00" level=warning msg="could not create bridge network for id 88bd200
b5bb27d3fd10d9e8bf86b1947b2190cf7be36cd7243eec55ac8089dc6 bridge name docker0 while booting up from persistent state: Failed to program NAT chain:
ZONE_CONFLICT: 'docker0' already bound to a zone" Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.596805407+02:00" level=info msg="stopping event stream following graceful shutdown"
error="" module=libcontainerd namespace=moby Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: time="2021-08-12T10:29:25.596994440+02:00" level=info msg="stopping event stream following graceful shutdown"
error="context canceled" module=libcontainerd namespace=plugins.moby Aug 12 10:29:25 dell-latitude-7480 dockerd[446605]: failed to start daemon: Error initializing network controller: Error creating default "bridge" network:
Failed to program NAT chain: ZONE_CONFLICT: 'docker0' already bound to a zone Aug 12 10:29:25 dell-latitude-7480 systemd[1]: docker.service: Main process exited, code=exited, status=1/FAILURE Aug 12 10:29:25 dell-latitude-7480 systemd[1]: docker.service: Failed with result 'exit-code'. Aug 12 10:29:25 dell-latitude-7480 systemd[1]: Failed to start Docker Application Container Engine. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Service hold-off time over, scheduling restart. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Scheduled restart job, restart counter is at 3. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: Stopped Docker Application Container Engine. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Start request repeated too quickly. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: docker.service: Failed with result 'exit-code'. Aug 12 10:29:27 dell-latitude-7480 systemd[1]: Failed to start Docker Application Container Engine.

As linhas estão editadas pra facilitar a visualização uma vez que o systemd usa linhas bem maiores que 120 colunas.  Mas o resultado foi... falha.

Parando o firewalld e somente reiniciando docker levava a uma condição em que o daemon iniciava, mas ao iniciar o container, novamente ficava sem acesso à rede.

root@dell-latitude-7480 /u/local# docker run -it --rm --init ubuntu:20.04 bash
root@f45dcbb1ecaa:/# ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
^C
--- 1.1.1.1 ping statistics ---
6 packets transmitted, 0 received, 100% packet loss, time 5153ms

root@f45dcbb1ecaa:/# exit

Olhando somente as regras do firewall eu pude ver que realmente o docker estava carregando a regra correta sem o firewalld:

root@dell-latitude-7480 /u/local# systemctl stop firewalld.service 
root@dell-latitude-7480 /u/local# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
root@dell-latitude-7480 /u/local# systemctl restart docker
root@dell-latitude-7480 /u/local# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2021-08-12 12:01:12 CEST; 4s ago
     Docs: https://docs.docker.com
 Main PID: 484649 (dockerd)
    Tasks: 27
   CGroup: /system.slice/docker.service
           └─484649 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock

Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061383466+02:00" level=warning msg="Your kernel does not support swap 
 memory limit"
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061414030+02:00" level=warning msg="Your kernel does not support CPU
 realtime scheduler"
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061421558+02:00" level=warning msg="Your kernel does not support cgroup
 blkio weight"
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061427194+02:00" level=warning msg="Your kernel does not support cgroup
 blkio weight_device"
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.061796106+02:00" level=info msg="Loading containers: start."
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.531851162+02:00" level=info msg="Loading containers: done."
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.549979768+02:00" level=info msg="Docker daemon"
 commit="20.10.7-0ubuntu1~18.04.1" graphdriver(s)=overlay2 version=20.10.7
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.550057275+02:00" level=info msg="Daemon has completed initialization"
Aug 12 12:01:12 dell-latitude-7480 dockerd[484649]: time="2021-08-12T12:01:12.558188106+02:00" level=info msg="API listen on /var/run/docker.sock"
Aug 12 12:01:12 dell-latitude-7480 systemd[1]: Started Docker Application Container Engine.
root@dell-latitude-7480 /u/local# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DOCKER     all  --  0.0.0.0/0           !127.0.0.0/8          ADDRTYPE match dst-type LOCAL

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  172.16.0.0/24       0.0.0.0/0           

Chain DOCKER (2 references)
target     prot opt source               destination         
RETURN     all  --  0.0.0.0/0            0.0.0.0/0           

Claramente existia uma regra de MASQUERADE vinda da rede do docker (172.16.0.0/24).  E o firewalld estava sumindo com essa regra ao ser ativado (pra ficar menos poluído com várias regras peguei só a saída da cadeia do POSTROUTING.

root@dell-latitude-7480 /u/local# systemctl start firewalld.service 
root@dell-latitude-7480 /u/local# iptables -L POSTROUTING -n -t nat 
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
POSTROUTING_direct  all  --  0.0.0.0/0            0.0.0.0/0           
POSTROUTING_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0           
POSTROUTING_ZONES  all  --  0.0.0.0/0            0.0.0.0/0

A minha primeira ideia: inserir à força uma regra de MASQUERADE direto na cadeia de POSTROUTING.

root@dell-latitude-7480 /u/local# iptables -I  POSTROUTING 1 -s 172.16.0.0/24 -j MASQUERADE -t nat
root@dell-latitude-7480 /u/local# iptables -L POSTROUTING --line-numbers -t nat
Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination         
1    MASQUERADE  all  --  172.16.0.0/24       anywhere            
2    POSTROUTING_direct  all  --  anywhere             anywhere            
3    POSTROUTING_ZONES_SOURCE  all  --  anywhere             anywhere            
4    POSTROUTING_ZONES  all  --  anywhere             anywhere            

E, claro, não deu certo.

Depois de procurar na Internet sobre docker e firewalld, encontrei o próprio site do Docker explicando como fazer isso em https://docs.docker.com/network/iptables/ com o seguinte comando:

# Please substitute the appropriate zone and docker interface
$ firewall-cmd --zone=trusted --remove-interface=docker0 --permanent
$ firewall-cmd --reload

Beleza.  Agora não teria como dar errado. E...

root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0
public
root@dell-latitude-7480 /u/local# firewall-cmd --zone=public --remove-interface=docker0 --permanent
The interface is under control of NetworkManager and already bound to the default zone
The interface is under control of NetworkManager, setting zone to default.
success
root@dell-latitude-7480 /u/local# systemctl start docker
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xe" for details.

Caramba... algo de errado não estava certo.  Bom... se tivesse funcionado de primeira, eu provavelmente não teria escrito esse artigo.

Então vamos rever em qual zona está a interface docker0, remover essa interface dessa zona e adicionar na zona do docker.

root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0
public
root@dell-latitude-7480 /u/local# firewall-cmd --zone=public --remove-interface=docker0 --permanent
The interface is under control of NetworkManager and already bound to the default zone
The interface is under control of NetworkManager, setting zone to default.
success
root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0
public
root@dell-latitude-7480 /u/local# firewall-cmd --reload
success
root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0
public

Mas que catzo... esse foi problema que encontrei.  Por mais que eu removesse ou tentasse remover a interface docker0 da zone public, sempre voltava.

Foram algumas horas nesse vai e vem, procurando na Internet o que fazer, lendo documentação do firewalld, até que finalmente acertei.

root@dell-latitude-7480 /u/local# firewall-cmd --zone=docker --add-interface=docker0 --permanent
The interface is under control of NetworkManager, setting zone to 'docker'.
success
root@dell-latitude-7480 /u/local# firewall-cmd --get-zone-of-interface=docker0
docker
root@dell-latitude-7480 /u/local# firewall-cmd --reload
success
root@dell-latitude-7480 /u/local# systemctl start docker

Então não precisava do comando pra remover.  Apenas adicionar diretamente na zona desejada.

root@dell-latitude-7480 /u/local# docker run -it --rm --init ubuntu:20.04 bash
root@e5d78d7f081b:/# ping -c 5 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=58 time=1.95 ms
64 bytes from 1.1.1.1: icmp_seq=2 ttl=58 time=2.02 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=58 time=1.68 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=58 time=1.62 ms
64 bytes from 1.1.1.1: icmp_seq=5 ttl=58 time=1.76 ms

--- 1.1.1.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4003ms
rtt min/avg/max/mdev = 1.621/1.808/2.026/0.162 ms
root@e5d78d7f081b:/# exit

via GIPHY

Limpando entradas de um disco removido do LVM

Categoria: Linux Publicado: Segunda, 24 Maio 2021 Escrito por Helio Loureiro

E minhas aventuras com LVM continuam.  Um dos HDDs começou a chiar.  Mas chiar mesmo, fazendo barulho de marteladas e resets.   Olhando nos logs eu vi que já tinha dado o que tinha que dar.  E justamente o HDD que fazia parte do mirroring em que estão os jogos da steam.

Então procedi com o comando pra terminar a montagem em mirroring.

lvconvert -m 0 diskspace/steam /dev/sdb3

Infelizmente eu dei um reboot em seguida e não salvei nada pra poder postar aqui.  Mas o mais importante foi depois de removido HDD e instalado um novo (também de 2 TB) que tinha parado aqui.  Como eu esqueci de remover o /dev/sdb3 do LVM, claro que subiu com vários erros. Particionei o novo HDD (/dev/sdb) com uma só partição LVM. E fui adicionar quando...

root@goosfraba ~# pvcreate /dev/sdb1
  WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
  WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
  Physical volume "/dev/sdb1" successfully created.

Epa!  Que catzo de CvlXC4-não-sei-lá-o-que é esse?  Sim, o disco que removi fisicamente e não tirei logicamente do LVM.  Com "vgdisplay" pude ver que realmente o problema estava lá.

root@goosfraba ~# vgdisplay 
  WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
  WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
  --- Volume group ---
  VG Name               diskspace
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  230
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                9
  Open LV               2
  Max PV                0
  Cur PV                2
  Act PV                1
  VG Size               5.45 TiB
  PE Size               4.00 MiB
  Total PE              1429493
  Alloc PE / Size       518912 /

Resolver não foi nada complicado.  Bastou o seguinte comando:

root@goosfraba ~# vgreduce  --removemissing diskspace
  WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
  WARNING: VG diskspace is missing PV CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa (last written to /dev/sdb3).
  WARNING: Couldn't find device with uuid CvlXC4-LiEI-mr0c-vSky-oryk-Khrl-J1dyBa.
  Wrote out consistent volume group diskspace.

Pronto!  Metadados do disco antigo removidos.

root@goosfraba ~# vgdisplay 
  --- Volume group ---
  VG Name               diskspace
  System ID             
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  231
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                9
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size

Agora o trabalho seguinte foi adicionar o espaço novo dentro do VG (diskspace é o nome):

root@goosfraba ~# vgextend diskspace /dev/sdb1
  Volume group "diskspace" successfully extended
root@goosfraba ~# vgdisplay 
  --- Volume group ---
  VG Name               diskspace
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  232
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                9
  Open LV               2
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               

Em seguida colocar o disco novo como mirroring novamente:

root@goosfraba ~# lvconvert -m 1 /dev/diskspace/steam /dev/sdb1
Are you sure you want to convert linear LV diskspace/steam to raid1 with 2 images enhancing resilience? [y/n]: y
  Logical volume diskspace/steam successfully converted.

E pronto.  Acabou.  Isso mesmo.  Foi fácil assim.  Agora é só ir monitorando o progresso da cópia no disco novo.

root@goosfraba ~# lvs
  LV       VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home     diskspace -wi-a----- 500.00g                                                    
  opt      diskspace -wi-a-----   2.00g                                                    
  root     diskspace -wi-ao----  10.00g                                                    
  steam    diskspace rwi-a-r--- 750.00g                                    0.88            
  swap     diskspace -wi-a-----  15.00g                                                    
  tmp      diskspace -wi-a-----   5.00g                                                    
  usr      diskspace -wi-ao----  95.00g                                                    
  usrlocal diskspace -wi-a----- 600.00g                                                    
  var      diskspace -wi-a-----  50.00g                                                    
root@goosfraba ~# lvs
  LV       VG        Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
  home     diskspace -wi-a----- 500.00g                                                    
  opt      diskspace -wi-a-----   2.00g                                                    
  root     diskspace -wi-ao----  10.00g                                                    
  steam    diskspace rwi-a-r--- 750.00g                                    1.10            
  swap     diskspace -wi-a-----  15.00g                                                    
  tmp      diskspace -wi-a-----   5.00g                                                    
  usr      diskspace -wi-ao----  95.00g                                                    
  usrlocal diskspace -wi-a----- 600.00g                                                    
  var      diskspace -wi-a-----  50.00g                                                    

Como são 750 GB a coisa demora um pouco.  Mas com LVM, tudo é muito fácil.

Happy hacking :)

Migrando seus dados pra um disco novo

Categoria: Linux Publicado: Quinta, 01 Abril 2021 Escrito por Helio Loureiro

Essa dúvida surgiu no grupo de Ubuntu do Telegram (https://t.me/ulboficial) e ao invés de responder lá eu preferi escrever um artigo sobre isso.

O método que uso, principalmente em laptops novos, é basicamente o mesmo desde... acho que aprendi a fazer isso por volta dos anos 2000.  Era um capítulo do venerado livro "Unix Power Tools", a bíblia dos scripts pra sysadmins.

Livro Unix Power Tools
Livro Unix Power Tools

Eu primeiramente insiro o HD novo e particiono.  Não vou usar o exemplo de LVM, que é mais simples, mas o mais cabeludo que é quando se cria todas as partições que vai usar.  Então digamos que eu adicione um novo HD que aparecerá para mim como /dev/sdb (pra facilitar).  Supondo que o particionamento seja o seguinte:

  • /dev/sdb1: /boot
  • /dev/sdb5: /
  • /dev/sdb6: /home

O passo seguinte, após formatar as partições no formato desejado (eu geralmente uso XFS), é montar essas partições em um local onde possa copiar os dados.  Eu normalmente uso o /mnt pra essa finalidade.

root@goosfraba ~# mount /dev/sdb5 /mnt
root@goosfraba ~# mount /dev/sdb1 /mnt/boot
root@goosfraba ~# mount /dev/sdb6 /mnt/home

Uma vez com tudo montado é fazer cópia de um lado pro outro evitando copiar o /mnt, que já está em uso com o disco novo, e diretórios como /proc, /dev ou /sys, que são criados durante o boot.  E pra isso eu uso o comando tar.

root@goosfraba ~# tar cvf - --exclude=./proc --exclude=./sys --exclude=./dev --exclude=./mnt -C / . | tar xf -C /mnt

Com isso o disco já está todo pronto em /mnt.  Resta corrigir o boot.  Pra isso eu uso chroot pra acessar o disco novo a partir de /mnt e montando tanto /proc quanto /dev pro grub localizar o disco corretamente.

root@goosfraba ~# mkdir /mnt/{proc, dev}
root@goosfraba ~# mount --bind /proc /mnt/proc
root@goosfraba ~# mount --bind /dev /mnt/dev
root@goosfraba ~# chroot /mnt
root@chroot ~$ grub-install /dev/sdb 

Assumindo que vá remover o primeiro disco, /dev/sda, e sdb será o novo sda, nada mais é preciso.  Agora caso vá ficar com sdb como disco principal, então é preciso modificar as entradas do /etc/fstab pra conter os dados corretos do novo disco.

Ao terminar e antes de rebootar, tenha com você o disco de instalação em mãos pra utilizar o modo de recuperação em caso de algum problema (e não precisar ficar colocando o disco antigo).