Estratégia para implantar / hospedar sites estáticos baseados em javascript em contêineres

7

De tempos em tempos, isso ocorre em várias de nossas equipes de desenvolvimento, sem que tenhamos descoberto o caminho "certo":

Usamos muitos aplicativos da Web baseados em reação que "compilam" em sites estáticos que são apenas alguns arquivos html, js e css.

No entanto, a "construção" desses aplicativos utiliza várias variáveis ​​que ativam / desativam sinalizadores de recursos, configuram URLs de back-end etc. Isso significa que não podemos "construir" um binário no sentido tradicional e apenas aplicar um arquivo de configuração no deploy- time - o "build" em si precisa ter essas variáveis ​​específicas do ambiente definidas e, portanto, o único momento em que podemos "build" é no momento da implantação.

Por enquanto, resolvemos isso injetando as variáveis ​​de ambiente necessárias no contêiner do Docker e executamos um cmd inicial ao longo das linhas de

npm build && nginx run

Isso tem algumas desvantagens:

  1. O processo de compilação requer muita CPU / memória em relação aos requisitos de tempo de execução do contêiner. Isso significa que precisamos escalar o contêiner para o processo de compilação em vez dos requisitos de tempo de execução - o que parece errado
  2. Falhas de construção são difíceis de "rastrear". Podemos usar verificações de saúde no Kubernetes, mas se uma compilação levar 2 minutos, ainda temos que esperar 3 minutos (1 extra por segurança) antes de começarmos a testar o ponto de extremidade de verificação de saúde do contêiner para ver se está vivo.
  3. As implantações podem demorar muito: se configurarmos o Kubernetes para fazer uma implantação "serial", ele iniciará cada pod e aguardará o período "initialDelay" de 2 a 3 minutos antes de iniciar o próximo. Isso significa que observamos facilmente um tempo de implantação de 10 minutos se a implantação for dimensionada para 3-4 pods.

Tudo isso me parece muito abaixo do ideal. Eu ficaria muito interessado em saber como a comunidade resolve o dilema "compilar no momento da implantação" com os modernos aplicativos javascript.

Percebo que, para o Kubernetes, poderíamos usar "init-containers" que executam a construção, colocar os artiacts em armazenamento persistente e fazer com que os contêineres de aplicativos simplesmente retirassem do armazenamento persistente durante a inicialização, mas isso ainda parece mais "contornar" o problema do que resolvendo o problema raiz.

Trondh
fonte
Desculpe, eu não entendo - por que você está executando npm buildem tempo de execução e não durante a construção do contêiner?
Xiong Chiamiov 02/02
@XiongChiamiov Suponho que a configuração do frontend seja feita durante a compilação e não seja modificável sem a reconstrução (eu diria que ela deve ser separada em um arquivo incluído que, na pior das hipóteses, pode ser 'sed' na inicialização do contêiner)
Tensibai
exatamente. npm buildé apenas um comando arbitrário. Pode ser react buildou o sanity buildque a estrutura JS espera. Somos forçados a fazê-lo na implantação de contêineres, porque é quando conhecemos o ambiente build.
Trondh

Respostas:

5

Do meu ponto de vista, a melhor abordagem seria:

  1. Processo de construção separado usando Jenkins que criaria o projeto NodeJS na distribuição e o envolveria na imagem do Docker
  2. Gire o registro do Docker que acumulará imagens do Docker do Jenkins (esse registro deve estar acessível no cluster Kubernetes)
  3. Mova as variáveis ​​de ambiente para os segredos do Jenkins ou use uma ferramenta separada para coletar e combinar configurações do repositório Git externo (usamos o Spring Cloud Config por meio da API REST para coletar definições de json / yml para cada aplicativo em qualquer ambiente)

Usando o Jenkins, você pode configurar o sistema de entrega contínua com base em pipelines genéricos. O fluxo possível seria:

  1. Os desenvolvedores finalizam seu trabalho em correspondência com o GitFlow (a última solicitação de solicitação mesclada no ramo Release)
  2. O Webhook aciona o pipeline Jenkins:
    • Etapa 1: coletar a definição do ambiente
    • Etapa 2: criar o aplicativo NodeJS usando o npm
    • Etapa 3: criar a imagem do Nginx Docker com distribuição
    • Etapa 4: enviar a imagem do Docker para o registro do Docker
    • Etapa 5: implantar / atualizar o serviço no Kubernetes usando definições padrão
  3. Notificações enviadas em relação aos resultados

Esse processo pode ser visualizado usando o Rancher. Eu posso responder suas perguntas no chat.

Maksim
fonte
Então você está propondo ter uma imagem por ambiente? Essa é uma solução alternativa consumindo um monte de espaço para apenas algumas variáveis ...
Tensibai
@Tensibai ur falando sobre imagens de ~ 15mb por cada ambiente. Com rotação e serviço de zelador adicional, 1 Gb seria suficiente para lidar com todos os projetos.
Maksim
Com base nessa solução, como você produziria várias "configurações" de um aplicativo, por exemplo, uma para "teste" e outra para "prod"? (vamos fingir que existe uma configuração chamada "BackendApi" que difere, por exemplo.
Trondh
@ Trondh como eu disse, usamos o Spring Cloud Config. O que ele faz é para cada aplicativo que obtém a configuração básica e aplica configurações adicionais profiles. Por exemplo, se você solicitar, https://config/backend.ymlreceberá configuração application.ymle propriedades adicionais de backend.yml. Pois https://config/backend-stage.ymlele responderá com propriedades aplicadas por application.yml<- backend.yml<- backend-stage.yml.
Maksim
O @Maksim 15MB para alguns bytes de texto é um desperdício, em algum momento com centenas de microsserviços em vários ambientes com várias versões, ele se tornará TB de dados para os mesmos poucos bytes na origem. Esse é um caminho errado na minha opinião, se eu entendi direito o que você está propondo, pois você não pode garantir que a imagem no controle de qualidade e no produto seja realmente a mesma de duas versões (mesmo com o mesmo código, elas não serão o mesmo ID e validação se tornam uma bagunça). Mas talvez eu tenha entendido errado e você tenha apenas uma imagem e configuração ao girar o pod, se é que não entendi corretamente sua postagem.
Tensibai