Melhores práticas do Kubernetes. Criando pequenos contêineres

Melhores práticas do Kubernetes. Criando pequenos contêineres

A primeira etapa da implantação no Kubernetes é colocar seu aplicativo em um contêiner. Nesta série, veremos como você pode criar uma imagem de contêiner pequena e segura.
Graças ao Docker, criar imagens de contêiner nunca foi tão fácil. Especifique uma imagem base, adicione suas alterações e crie um contêiner.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Embora essa técnica seja ótima para começar, o uso de imagens base padrão pode levar a um trabalho inseguro com imagens grandes e cheias de vulnerabilidades.

Além disso, a maioria das imagens no Docker usa Debian ou Ubuntu como imagem base e, embora isso forneça excelente compatibilidade e fácil personalização (um arquivo Docker ocupa apenas duas linhas de código), as imagens base podem adicionar centenas de megabytes de carga adicional ao seu contêiner. Por exemplo, um arquivo node.js simples para um aplicativo Go "hello-world" tem cerca de 700 megabytes, enquanto seu aplicativo real tem apenas alguns megabytes de tamanho.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Portanto, toda essa carga de trabalho extra é um desperdício de espaço digital e um ótimo esconderijo para vulnerabilidades e bugs de segurança. Então, vejamos duas maneiras de reduzir o tamanho de uma imagem de contêiner.

A primeira é a utilização de pequenas imagens de base, a segunda é a utilização do Builder Pattern. Usar imagens de base menores é provavelmente a maneira mais fácil de reduzir o tamanho do seu contêiner. Provavelmente, a linguagem ou pilha que você está usando fornece uma imagem original do aplicativo muito menor que a imagem padrão. Vamos dar uma olhada em nosso contêiner node.js.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Por padrão no Docker, o tamanho da imagem base node:8 é 670 MB, e o tamanho da imagem node: 8-alpine é de apenas 65 MB, ou seja, 10 vezes menor. Ao usar a imagem base Alpine menor, você reduzirá significativamente o tamanho do seu contêiner. Alpine é uma distribuição Linux pequena e leve que é muito popular entre os usuários do Docker porque é compatível com muitos aplicativos, ao mesmo tempo que mantém os contêineres pequenos. Ao contrário da imagem "node" padrão do Docker, "node:alpine" remove muitos arquivos de serviço e programas, deixando apenas aqueles que são suficientes para executar seu aplicativo.

Para passar para uma imagem base menor, basta atualizar o Dockerfile para começar a trabalhar com a nova imagem base:

Melhores práticas do Kubernetes. Criando pequenos contêineres

Agora, diferentemente da antiga imagem onbuild, você precisa copiar seu código para o contêiner e instalar todas as dependências. Em um novo Dockerfile, o contêiner começa com uma imagem node:alpine, depois cria um diretório para o código, instala dependências usando o gerenciador de pacotes NPM e, finalmente, executa server.js.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Essa atualização resulta em um contêiner com tamanho 10 vezes menor. Se sua linguagem de programação ou pilha não tiver funcionalidade básica de redução de imagem, use Alpine Linux. Também fornecerá a capacidade de gerenciar totalmente o conteúdo do contêiner. Usar imagens de base pequenas é uma ótima maneira de criar pequenos contêineres rapidamente. Mas uma redução ainda maior pode ser alcançada usando o Builder Pattern.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Nas linguagens interpretadas, o código-fonte é primeiro passado ao intérprete e depois executado diretamente. Em linguagens compiladas, o código-fonte é primeiro convertido em código compilado. No entanto, a compilação geralmente usa ferramentas que não são realmente necessárias para executar o código. Isso significa que você pode remover completamente essas ferramentas do contêiner final. Você pode usar o Builder Pattern para isso.

Melhores práticas do Kubernetes. Criando pequenos contêineres

O código é criado no primeiro contêiner e compilado. O código compilado é então empacotado em um contêiner final sem os compiladores e ferramentas necessárias para compilar esse código. Vamos executar um aplicativo Go nesse processo. Primeiro, passaremos da imagem onbuild para o Alpine Linux.

Melhores práticas do Kubernetes. Criando pequenos contêineres

No novo Dockerfile, o contêiner começa com uma imagem golang:alpine. Em seguida, ele cria um diretório para o código, copia-o no código-fonte, cria esse código-fonte e executa o aplicativo. Este contêiner é muito menor que o contêiner onbuild, mas ainda contém o compilador e outras ferramentas Go que realmente não precisamos. Então vamos extrair o programa compilado e colocá-lo em seu próprio contêiner.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Você pode notar algo estranho neste arquivo Docker: ele contém duas linhas FROM. A primeira seção de 4 linhas é exatamente igual ao Dockerfile anterior, exceto que usa a palavra-chave AS para nomear este estágio. A próxima seção tem uma nova linha FROM para iniciar uma nova imagem, onde em vez da imagem golang:alpine usaremos Raw alpine como imagem base.

O Raw Alpine Linux não possui nenhum certificado SSL instalado, o que fará com que a maioria das chamadas de API via HTTPS falhem, então vamos instalar alguns certificados CA raiz.

Agora vem a parte divertida: para copiar o código compilado do primeiro contêiner para o segundo, basta usar o comando COPY localizado na linha 5 da segunda seção. Ele copiará apenas um arquivo do aplicativo e não afetará as ferramentas do utilitário Go. O novo arquivo Docker de vários estágios conterá uma imagem de contêiner com apenas 12 megabytes de tamanho, em comparação com a imagem de contêiner original que tinha 700 megabytes, o que é uma grande diferença!
Portanto, usar imagens de base pequenas e Builder Pattern são ótimas maneiras de criar contêineres muito menores sem muito trabalho.
É possível que, dependendo da pilha de aplicativos, existam maneiras adicionais de reduzir o tamanho da imagem e do contêiner, mas os contêineres pequenos realmente trazem um benefício mensurável? Vejamos duas áreas onde os contêineres pequenos são extremamente eficazes: desempenho e segurança.

Para avaliar o aumento de desempenho, considere a duração do processo de criação de um contêiner, inserção no registro (push) e recuperação de lá (pull). Você pode ver que um contêiner menor tem uma vantagem distinta sobre um contêiner maior.

Melhores práticas do Kubernetes. Criando pequenos contêineres

O Docker armazenará em cache as camadas para que as compilações subsequentes sejam muito rápidas. No entanto, muitos sistemas de CI usados ​​para construir e testar contêineres não armazenam camadas em cache, portanto, há uma economia significativa de tempo. Como você pode ver, o tempo para construir um contêiner grande, dependendo da potência da sua máquina, é de 34 a 54 segundos, e ao usar um contêiner reduzido usando o Builder Pattern - de 23 a 28 segundos. Para operações deste tipo, o aumento de produtividade será de 40-50%. Então pense em quantas vezes você constrói e testa seu código.

Após a construção do contêiner, você precisa enviar sua imagem (imagem do contêiner push) para o registro do contêiner para que possa usá-la em seu cluster Kubernetes. Eu recomendo usar o Google Container Registry.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Com o Google Container Registry (GCR), você paga apenas pelo armazenamento bruto e pela rede, e não há taxas adicionais de gerenciamento de contêineres. É privado, seguro e muito rápido. O GCR usa muitos truques para acelerar a operação pull. Como você pode ver, inserir um contêiner Docker Container Image usando go:onbuild levará de 15 a 48 segundos, dependendo do desempenho do computador, e a mesma operação com um contêiner menor levará de 14 a 16 segundos, e para máquinas menos produtivas a vantagem na velocidade de operação aumenta 3 vezes. Para máquinas maiores, o tempo é praticamente o mesmo, já que o GCR usa um cache global para um banco de dados compartilhado de imagens, o que significa que você não precisa carregá-las. Em um computador de baixo consumo de energia, a CPU é o gargalo, então a vantagem de usar contêineres pequenos é muito maior aqui.

Se você estiver usando GCR, recomendo usar o Google Container Builder (GCB) como parte de seu sistema de compilação.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Como você pode ver, seu uso permite obter resultados muito melhores na redução da duração da operação Build+Push do que até mesmo uma máquina produtiva - neste caso, o processo de construção e envio de contêineres para o host é acelerado em quase 2 vezes . Além disso, você recebe 120 minutos de construção gratuitos todos os dias, o que cobre suas necessidades de construção de contêineres na maioria dos casos.

Em seguida vem a métrica de desempenho mais importante – a velocidade de recuperação ou download de contêineres Pull. E se você não se importa muito com o tempo gasto em uma operação push, a duração do processo pull terá um sério impacto no desempenho geral do sistema. Digamos que você tenha um cluster de três nós e um deles falhe. Se você estiver usando um sistema de gerenciamento como o Google Kubernetes Engine, ele substituirá automaticamente o nó morto por um novo. No entanto, este novo nó estará completamente vazio e você terá que arrastar todos os seus contêineres para ele para que comece a funcionar. Se a operação pull demorar o suficiente, seu cluster funcionará com desempenho inferior o tempo todo.

Há muitos casos em que isso pode acontecer: adicionar um novo nó a um cluster, atualizar nós ou até mesmo mudar para um novo contêiner para implantação. Assim, minimizar o tempo de extração pull torna-se um fator chave. É inegável que o download de um contêiner pequeno é muito mais rápido do que um grande. Se você estiver executando vários contêineres em um cluster Kubernetes, a economia de tempo poderá ser significativa.

Melhores práticas do Kubernetes. Criando pequenos contêineres

Dê uma olhada nesta comparação: uma operação pull em contêineres pequenos leva de 4 a 9 vezes menos tempo, dependendo da potência da máquina, do que a mesma operação usando go:onbuild. O uso de imagens de base de contêiner pequenas e compartilhadas acelera significativamente o tempo e a velocidade com que novos nós do Kubernetes podem ser implantados e ficar online.

Vejamos a questão da segurança. Contêineres menores são considerados muito mais seguros que os maiores porque possuem uma superfície de ataque menor. É realmente? Um dos recursos mais úteis do Google Container Registry é a capacidade de verificar automaticamente vulnerabilidades em seus contêineres. Há alguns meses, criei contêineres onbuild e multistage, então vamos ver se há alguma vulnerabilidade neles.

Melhores práticas do Kubernetes. Criando pequenos contêineres

O resultado é surpreendente: apenas 3 vulnerabilidades médias foram detectadas em um contêiner pequeno, e 16 vulnerabilidades críticas e 376 outras vulnerabilidades foram encontradas em um contêiner grande. Se olharmos o conteúdo de um grande contêiner, podemos ver que a maioria dos problemas de segurança não tem nada a ver com nossa aplicação, mas estão relacionados a programas que nem usamos. Então, quando as pessoas falam sobre uma grande superfície de ataque, é isso que elas querem dizer.

Melhores práticas do Kubernetes. Criando pequenos contêineres

A conclusão é clara: crie contêineres pequenos porque eles fornecem benefícios reais de desempenho e segurança ao seu sistema.

Melhores práticas do Kubernetes. Organização do Kubernetes com namespace

Alguns anúncios 🙂

Obrigado por ficar com a gente. Gostou dos nossos artigos? Quer ver mais conteúdos interessantes? Apoie-nos fazendo um pedido ou recomendando a amigos, nuvem VPS para desenvolvedores a partir de US$ 4.99, um análogo exclusivo de servidores básicos, que foi inventado por nós para você: Toda a verdade sobre VPS (KVM) E5-2697 v3 (6 núcleos) 10 GB DDR4 480 GB SSD 1 Gbps a partir de $ 19 ou como compartilhar um servidor? (disponível com RAID1 e RAID10, até 24 núcleos e até 40 GB DDR4).

Dell R730xd 2x mais barato no data center Equinix Tier IV em Amsterdã? Só aqui 2 x Intel TetraDeca-Core Xeon 2x E5-2697v3 2.6GHz 14C 64GB DDR4 4x960GB SSD 1Gbps 100 TV a partir de US$ 199 na Holanda! Dell R420 - 2x E5-2430 2.2Ghz 6C 128GB DDR3 2x960GB SSD 1Gbps 100TB - a partir de US$ 99! Ler sobre Como construir uma empresa de infraestrutura. classe com o uso de servidores Dell R730xd E5-2650 v4 no valor de 9000 euros por um centavo?

Fonte: habr.com

Adicionar um comentário