Qual é a beleza de dividir o tempo de execução dos contêineres em componentes instrumentais separados? Em particular, o fato de que essas ferramentas podem começar a ser combinadas para se protegerem.

Muitas pessoas são atraídas pela idéia de construir
OCIs de contêineres no
Kubernetes ou em um sistema similar. Suponha que tenhamos um CI / CD que colete imagens constantemente, algo como o
Red Hat OpenShift / Kubernetes seria muito útil em termos de balanceamento de carga durante a montagem. Até recentemente, a maioria das pessoas simplesmente dava acesso aos contêineres no soquete do docker e tinha permissão para executar o comando docker build.
Mostramos vários anos atrás que isso é muito inseguro; na verdade, é ainda pior do que fornecer um root ou sudo sem senha.
Portanto, as pessoas estão constantemente tentando executar o Buildah em um contêiner. Em resumo, criamos
um exemplo de como, em nossa opinião, é melhor executar o Buildah dentro do contêiner e colocar as imagens apropriadas em
quay.io/buildah . Vamos começar ...
Personalização
Essas imagens são compiladas a partir do Dockerfiles, que podem ser encontrados no repositório Buildah, na pasta
buildahimage .
Aqui, examinamos a
versão estável do Dockerfile .
# stable/Dockerfile # # Build a Buildah container image from the latest # stable version of Buildah on the Fedoras Updates System. # https://bodhi.fedoraproject.org/updates/?search=buildah # This image can be used to create a secured container # that runs safely with privileges within the container. # FROM fedora:latest # Don't include container-selinux and remove # directories used by dnf that are just taking # up space. RUN yum -y install buildah fuse-overlayfs --exclude container-selinux; rm -rf /var/cache /var/log/dnf* /var/log/yum.* # Adjust storage.conf to enable Fuse storage. RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf
Em vez de OverlayFS, implementado no nível do kernel Linux do host, usamos o programa de
sobreposição de fusíveis dentro do contêiner, porque no momento o OverlayFS pode ser montado apenas se tiver privilégios SYS_ADMIN pelos recursos do Linux. E queremos executar nossos contêineres Buildah sem privilégios de root. A sobreposição de fusível é muito rápida e tem melhor desempenho do que o driver de armazenamento VFS. Observe que ao iniciar um contêiner Buildah usando o Fuse, você deve fornecer o dispositivo / dev / fuse.
podman run --device /dev/fuse quay.io/buildahctr ... RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock
Em seguida, criamos um diretório para armazenamento adicional.
O contêiner / armazenamento suporta o conceito de conexão de
armazenamentos adicionais de imagens somente leitura. Por exemplo, você pode configurar a área de armazenamento de sobreposição em uma máquina e, em seguida, usar o NFS para montar esse armazenamento em outra máquina e usar imagens dela sem fazer o download via pull. Precisamos desse armazenamento para poder conectar algum tipo de armazenamento de imagem do host como um volume e usá-lo dentro do contêiner.
# Set up environment variables to note that this is # not starting with user namespace and default to # isolate the filesystem with chroot. ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot
Finalmente, usando a variável de ambiente BUILDAH_ISOLATION, dizemos que, por padrão, o contêiner Buildah deve começar com o isolamento de chroot. Isolamento adicional não é necessário aqui, pois já trabalhamos no contêiner. Para que o Buildah crie seus próprios contêineres com separação de espaços de nome, é necessário o privilégio SYS_ADMIN, e para isso será necessário enfraquecer as regras SELinux e SECCOMP para o contêiner, o que contradiz a instalação de um contêiner seguro.
Execute o Buildah dentro do contêiner
O esquema de imagem de contêiner Buildah discutido acima permite variar de maneira flexível a maneira como você executa esses contêineres.
Velocidade vs. Segurança
A segurança do computador é sempre um compromisso entre a velocidade do processo e a quantidade de proteção que o envolve. Essa afirmação também é verdadeira ao montar contêineres; portanto, consideraremos abaixo opções para esse compromisso.
A imagem do contêiner discutida acima manterá seu repositório em / var / lib / containers. Portanto, precisamos montar o conteúdo nesta pasta e a maneira como fazemos isso afetará bastante a velocidade de montagem das imagens do contêiner.
Vamos considerar três opções.
Opção 1. Se for necessária segurança máxima, para cada contêiner você poderá criar sua própria pasta para contêineres / imagem e conectá-la ao contêiner via montagem de volume. Além disso, coloque o diretório de contexto no próprio contêiner, na pasta / build:
# mkdir /var/lib/containers1 # podman run -v ./build:/build:z -v /var/lib/containers1:/var/lib/containers:Z quay.io/buildah/stable\ buildah -t image1 bud /build # podman run -v /var/lib/containers1:/var/lib/containers:Z quay.io/buildah/stable buildah push \ image1 registry.company.com/myuser # rm -rf /var/lib/containers1
Segurança O Buildah em execução nesse contêiner tem segurança máxima: ele não recebe privilégios de root com ferramentas de recursos e todas as restrições SECOMP e SELinux se aplicam a ele.Este contêiner pode até ser executado com o isolamento do namespace do usuário, adicionando uma opção como --uidmap 0: 100000: 10000 .
Performance. Mas o desempenho aqui é mínimo, pois todas as imagens dos registros do contêiner são copiadas para o host todas as vezes, e o cache não funciona com a palavra "de jeito nenhum". Ao concluir seu trabalho, o contêiner Buildah deve enviar a imagem ao registro e destruir o conteúdo no host. Quando a imagem do contêiner for coletada na próxima vez, ela terá que ser baixada do registro novamente, porque nesse momento nada permanecerá no host.
Opção 2. Se você precisar de desempenho no nível do Docker, poderá montar o contêiner / armazenamento do host diretamente no contêiner.
# podman run -v ./build:/build:z -v /var/lib/containers:/var/lib/containers --security-opt label:disabled quay.io/buildah/stable buildah -t image2 bud /build # podman run -v /var/lib/containers:/var/lib/containers --security-opt label:disabled \ quay.io/buildah/stable buildah push image2 registry.company.com/myuser
Segurança Essa é a maneira menos segura de criar contêineres, porque aqui o contêiner pode modificar o armazenamento no host e, potencialmente, pode inserir no Podman ou no CRI-O uma imagem maliciosa. Além disso, você precisará desativar a separação do SELinux para que os processos no contêiner Buildah possam interagir com o armazenamento no host. Observe que essa opção ainda é melhor que o soquete do Docker, pois o contêiner é bloqueado pelas demais funções de segurança e não pode simplesmente pegar e executar qualquer contêiner no host.
Performance. Aqui está o máximo, pois o cache está totalmente envolvido. Se o Podman ou o CRI-O já conseguiu baixar a imagem desejada para o host, o processo Buildah dentro do contêiner não precisará baixá-lo novamente, e os assemblies subsequentes baseados nessa imagem também poderão obter o necessário do cache.
Opção 3. A essência desse método é combinar várias imagens em um projeto com uma pasta compartilhada para imagens de contêiner.
# mkdir /var/lib/project3 # podman run --security-opt label:level=s0:C100, C200 -v ./build:/build:z \ -v /var/lib/project3:/var/lib/containers:Z quay.io/buildah/stable buildah -t image3 bud /build # podman run --security-opt label:level=s0:C100, C200 \ -v /var/lib/project3:/var/lib/containers quay.io/buildah/stable buildah push image3 \ registry.company.com/myuser
Neste exemplo, não excluímos a pasta do projeto (/ var / lib / project3) entre as partidas, portanto todas as construções subseqüentes no projeto aproveitam o cache.
Segurança Algo entre as opções 1 e 2. Por um lado, os contêineres não têm acesso ao conteúdo no host e, portanto, não podem colocar algo ruim no armazenamento de imagens do Podman / CRI-O. Por outro lado, como parte de seu projeto, um contêiner pode interferir na montagem de outros contêineres.
Performance. Aqui é pior do que ao usar um cache compartilhado no nível do host, pois você não pode usar imagens já baixadas anteriormente usando o Podman / CRI-O. No entanto, depois que o Buildah faz o download da imagem, ela pode ser usada em quaisquer compilações subseqüentes no projeto.
Armazenamento adicional
Os contêineres / armazenamento têm algo interessante como lojas adicionais, graças às quais os mecanismos de contêineres podem usar lojas de imagens externas no modo de sobreposição somente leitura ao iniciar e construir contêineres. De fato, você pode adicionar um ou mais armazenamentos somente leitura ao arquivo storage.conf para que, quando o contêiner for iniciado, o mecanismo do contêiner procure a imagem desejada neles. Além disso, ele baixará a imagem do registro apenas se não a encontrar em nenhum desses repositórios. O mecanismo de contêiner somente poderá gravar no armazenamento gravável ...
Se você rolar para cima e ver o Dockerfile, que usamos para criar a imagem quay.io/buildah/stable, existem as seguintes linhas:
# Adjust storage.conf to enable Fuse storage. RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock
Na primeira linha, modificamos o /etc/containers/storage.conf dentro da imagem do contêiner, solicitando ao driver de armazenamento que use “additionalimagestores” na pasta / var / lib / shared. E na próxima linha, crie uma pasta compartilhada e adicione alguns arquivos de bloqueio para que não haja abuso de contêineres / armazenamento. Basicamente, apenas criamos um armazenamento de imagem de contêiner vazio.
Se você montar contêineres / armazenamento acima desta pasta, o Buildah poderá usar imagens.
Agora, de volta à opção 2 discutida acima, quando um contêiner Buildah pode ler e gravar em contêineres / loja em hosts e, consequentemente, tem desempenho máximo devido ao armazenamento em cache de imagens no nível Podman / CRI-O, mas oferece um mínimo de segurança, pois pode gravar diretamente em armazenamento. E agora vamos fixar armazenamento adicional aqui e obter o melhor dos dois mundos.
# mkdir /var/lib/containers4 # podman run -v ./build:/build:z -v /var/lib/containers/storage:/var/lib/shared:ro -v \ /var/lib/containers4:/var/lib/containers:Z quay.io/buildah/stable \ buildah -t image4 bud /build # podman run -v /var/lib/containers/storage:/var/lib/shared:ro \ -v >/var/lib/containers4:/var/lib/containers:Z quay.io/buildah/stable buildah push image4 \ registry.company.com/myuser # rm -rf /var/lib/continers4
Observe que o host / var / lib / containers / storage está montado em / var / lib / compartilhado dentro do container no modo somente leitura. Portanto, trabalhando em um contêiner, o Buildah pode usar qualquer imagem baixada anteriormente usando o Podman / CRI-O (alta velocidade), mas pode gravar apenas em seu próprio repositório (alta segurança). Observe também que isso é feito sem desativar a separação do SELinux para o contêiner.
Nuances importantes
Em nenhum caso você deve remover as imagens do armazenamento subjacente. Caso contrário, o contêiner Buildah pode voar para fora.
E este não é todos os benefícios.
Recursos de armazenamento adicionais não estão limitados ao cenário acima. Por exemplo, você pode colocar todas as imagens de contêiner em um armazenamento de rede compartilhado e dar acesso a todos os contêineres da Buildah. Suponha que tenhamos centenas de imagens que nosso sistema de CI / CD usa regularmente para criar imagens de contêiner. Concentramos todas essas imagens em um único host de armazenamento e, usando as ferramentas preferidas de armazenamento em rede (NFS, Gluster, Ceph, ISCSI, S3 ...), abrimos o armazenamento compartilhado para todos os nós Buildah ou Kubernetes.
Agora é suficiente montar esse armazenamento de rede no contêiner Buildah em / var / lib / shared e isso é tudo - os contêineres Buildah não precisam mais fazer o download de imagens via pull. Assim, jogamos fora a fase pré-populacional e estamos imediatamente prontos para lançar os contêineres.
E, é claro, isso pode ser usado no sistema Kubernetes ou na infraestrutura de contêiner existente para iniciar e executar contêineres em qualquer lugar sem baixar imagens via pull. Além disso, o registro de contêiner, recebendo uma solicitação por push para carregar uma imagem atualizada, pode enviar automaticamente essa imagem para um armazenamento de rede compartilhado, onde fica instantaneamente disponível para todos os nós.
Às vezes, o tamanho das imagens do contêiner pode atingir muitos gigabytes. A funcionalidade de armazenamentos adicionais permite que você faça sem clonar essas imagens por nós e torna o lançamento de contêineres quase instantâneo.
Além disso, atualmente estamos trabalhando em uma nova função de montagens de volume de sobreposição que tornará a montagem do contêiner ainda mais rápida.
Conclusão
A execução de um Buildah dentro de um contêiner no Kubernetes / CRI-O, Podman ou mesmo no Docker é real, e é mais simples e muito mais segura do que usar o docker.socket. Melhoramos bastante a flexibilidade de trabalhar com imagens e agora você pode iniciá-las de várias maneiras para obter o equilíbrio ideal entre segurança e desempenho.
A funcionalidade de armazenamentos adicionais permite acelerar ou até eliminar completamente o download de imagens para os nós.