Angular - Como ler informações do ambiente em tempo de execução para CI / CD

Se você estiver usando o NGINX como servidor da web e o Kubernetes para a implantação

Foto de Tim Gouw em Unsplash

O Angular fornece opções de configuração no momento da construção, o que significa que você precisa definir arquivos de ambiente diferentes para cada ambiente e o Angular assume a configuração apropriada ao criar o projeto, fornecendo o sinalizador --configuration para a construção ng. Você pode conferir este artigo sobre a leitura de informações do ambiente durante o tempo de compilação.

Porém, a metodologia de doze fatores e as estratégias de DevOps atuais sugerem que precisamos criar uma vez e executar em qualquer lugar, o que significa que você terá apenas uma chance de fornecer o arquivo de configuração. Opções de configuração angular não são suficientes. Você precisa fornecer informações de configuração ou ambiente em tempo de execução. Nesta postagem, veremos como podemos conseguir isso e leremos as definições de configuração ou as informações do ambiente em tempo de execução.

  • Projeto de exemplo
  • O problema que estamos enfrentando
  • Solução
  • Implementação
  • Como depurar
  • Sumário
  • Conclusão

Projeto de exemplo

Aqui está um exemplo de projeto para a demonstração. Você pode clonar e executá-lo em sua máquina.

// clona o projeto git clone https://github.com/bbachi/angular-envread-runtime.git
// para desenvolvimento local npm install npm start

Este é um projeto Angular simples que carrega o arquivo de configuração app.config.json da pasta / assets.

Estamos usando APP_INITIALIZER para carregar este arquivo app.config.json antes de inicializar e usar essas configurações. Aqui estão os arquivos app.module.ts e app.service.ts.

Depois de carregar as configurações e você pode ler essas configurações em app.component.ts, como abaixo.

Com base na configuração, você pode ver a cor, cabeçalho e tabela do cabeçalho. Por exemplo, se for um ambiente de desenvolvimento, a cor do cabeçalho é preta e o cabeçalho é desenvolvimento. Você pode ver uma tela semelhante à abaixo.

tela de desenvolvimento

Se você alterar o backgroundColor e o cabeçalho para vermelho e produção, respectivamente. Você pode ver uma tela como abaixo.

tela de produção

O problema que estamos enfrentando

A metodologia de doze fatores sugere que precisamos construir uma vez executados em qualquer lugar, mas, neste caso, estamos construindo para cada ambiente. Para simplificar, estamos considerando apenas o desenvolvimento e a produção de dois ambientes. Como estamos servindo o aplicativo Angular com NGINX, podemos fornecer configuração apenas no tempo de compilação, em vez de no tempo de execução. Não podemos nem fornecer variáveis ​​de ambiente no lançamento, pois o navegador também não lê essas variáveis ​​de ambiente.

Passando a configuração no tempo de construção

Estamos construindo para cada ambiente porque tivemos que passar informações específicas do ambiente no momento da construção. Precisamos encontrar uma maneira de passar essas informações em tempo de execução. Se passarmos no tempo de execução, precisamos construir uma vez e executar em qualquer lugar, como vemos no diagrama abaixo.

Passando a configuração no tempo de execução

Solução

Vamos ver como podemos resolver esse problema. Uma maneira de resolver isso é ler o URL do navegador com a janela location.href e colocar toda a configuração no aplicativo e carregar a configuração apropriada com base em alguma parte específica da URL, como dev, prod, etc.

Se você estiver usando Java ou Nodejs com o aplicativo Angular, podemos obter essa configuração do servidor antes de inicializar o aplicativo com o APP_INITIALIZER. Mas como fazemos isso se estamos usando o NGINX como servidor da web?

Podemos usar o configmap do Kubernetes para injetar configuração no volume Pods, montado na pasta / usr / share / nginx / html / assets, para que o aplicativo Angular o obtenha antes de inicializá-lo com a ajuda de APP_INITIALIZER. Vejamos o diagrama abaixo para entender melhor.

Lendo a configuração em tempo de execução usando o configmap

Implementação

Vamos implementar a solução com o objeto configMap do Kubernetes. O objeto ConfigMap torna seus contêineres portáteis, dissociando a configuração deles. É assim que funciona.

A primeira coisa que precisamos fazer é criar a imagem do docker e enviá-la para o DockerHub. Aqui está o Dockerfile de vários estágios que cria o aplicativo Angular no primeiro estágio, pega esses ativos estáticos e o coloca na pasta raiz do NGINX.

Estas são as instruções para criar a imagem do Docker e enviá-la para o DockerHub. Você pode realmente vê-lo no DockerHub na imagem a seguir. Esta é uma imagem pública que você pode extrair diretamente do registro.

// construa a janela de encaixe de imagem build -t bbachin1 / envdemo.
// lista imagens da janela de encaixe
// faça login e envie-o para o hub docker docker de login docker push bbachin1 / envdemo
Hub do Docker

Agora precisamos criar objetos de implantação, serviço e configmap. estamos colocando todos esses objetos em um arquivo chamado manifest.yml. Estamos criando o Configmap primeiro com o config.json necessário. Se você observar o objeto de implantação, o Kubernetes extrai a imagem acima bbachin1 / envdemo do Docker Hub e cria 5 réplicas. Finalmente, temos um objeto de serviço com o tipo Nodeport que é exposto ao mundo exterior.

Carregamos o configmap no volume montado na pasta caminho / usr / share / nginx / html / assets /. Criamos todos esses objetos no desenvolvimento do namespace.

Aqui estão as instruções para criar objetos e verificá-los.

// cria objetos kubectl cria -f manifest.yml
// exclui objetos kubectl delete -f manifest.yml
// obtém a implantação kubectl get deploy -n development
// obtém o serviço kubectl get svc -n development
// obter os pods kubectl obter desenvolvimento po -n

Obtenha o endereço público do Kubernetes neste comando kubectl cluster-info e obtenha a porta do objeto de serviço kubectl get svc -n development e acesse o aplicativo em execução no namespace de desenvolvimento com este endereço http: // : / appui

porta de serviço e endereço público

No caso acima, você pode acessar o aplicativo em http://192.168.64.6:31935/appui. Certifique-se de alterar de https para http. Observe que toda a configuração é carregada a partir do configmap, como cabeçalho backgroundColor, title, etc.

Executando a implantação no Minikube

Vamos criar a implantação de produção a partir do arquivo manifest-prod.yml e siga as etapas acima para executar o aplicativo no seu local.

// cria objetos kubectl cria -f manifest-prod.yml
// exclui objetos kubectl delete -f manifest-prod.yml
// obtém a implantação kubectl get deploy -n production
// obtém o serviço kubectl get svc -n production
// obtém os pods kubectl obtém produção po -n

O serviço no namespace de produção está em execução na porta 31633.

serviço está sendo executado na porta 31633Executando a implantação no Minikube

Como depurar

Estas são algumas das opções de depuração, se você tiver algum problema ao implementar esta solução.

Primeiro, precisamos verificar se o configmap foi criado da maneira certa e no espaço de nomes certo.

// verifica se o configmap foi criado ou não, o kubectl get cm -n development
// verifica os dados no configmap kubectl descrevem cm -n development

Depois de verificar o configmap. Você pode verificar o volume montado carregado com o configmap.

// obtém o desenvolvimento do pod kubectl get po -n
// exec em um dos pod kubectl exec -it / bin / sh -n development # cd / usr / share / nginx / html / envapp / assets # cat app.config.json
app.config.json

Sumário

  • Angular fornece opções de configuração no momento da construção, o que significa que você precisa definir arquivos de ambiente diferentes para cada ambiente.
  • Precisamos construir uma vez executado em todos os lugares é a estratégia recomendada.
  • Não podemos usar a opção de ambiente Angular se quisermos construir uma vez e implantar em qualquer lugar, pois precisamos fornecer uma configuração separada para cada ambiente.
  • O Configmap fornece uma solução para separar a configuração da execução dos contêineres.
  • Se você estiver servindo seu aplicativo Angular com NGINX e precisar de uma maneira de passar a configuração em tempo de execução, o ConfigMaps é a solução mais fácil.
  • Você deve carregar o configmap no volume que pode ser montado no caminho do host e Angular obter esse JSON desse caminho.
  • Você pode excluir o configmap existente e recriar um e as alterações podem ser refletidas no contêiner em execução sem reiniciar os pods.

Conclusão

Use o Configmaps se desejar desacoplar a configuração dos contêineres e injetar a configuração apropriada no tempo de execução.