Onde estou? – Definição de variável de ambiente para informar a aplicação de qual é o ambiente
Esse é um texto sobre uma definição que é bem simples de arquitetura, mas que muitos “arquitetos” não fazem. O conceito é informar a aplicação, com o uso de uma definição externa, em qual ambiente essa aplicação se encontra. Com isso, a aplicação é capaz de tomar ações com base no ambiente em que ela está em execução.
Leia mais: Onde estou? – Definição de variável de ambiente para informar a aplicação de qual é o ambienteNesse cenário, o código é o menos importante. O conceito é o que faz a diferença. Mas caso queira fazer o acompanhamento, aqui está o código: https://github.com/escovabit-tec-br/nodejs-env-environment
Bem, vamos ao conceito.
Nossa aplicação precisa se relacionar com o meio (ambiente) em que ela está em execução, e o meio deve influenciar como nossa aplicação se comporta. Partindo disso, podemos definir um padrão:
Deve existir uma variável de ambiente com o nome
environment
que pode ter os valores:
- local
- development
- staging
- production
Sabendo disso. Nossa aplicação deve ser capaz de se adaptar ao “ambiente” que se encontra, abaixo um exemplo bem simples:
const appConfig = { development: { apiUrl: "https://api.publicapis.org/entries", }, production: { apiUrl: "https://catfact.ninja/fact", }, }; const environment = process.env.ENVIRONMENT || "development"; const resultData = appConfig[environment]; module.exports = resultData;
Podemos ver que o conteúdo no module.export
muda de acordo com o ambiente em que e aplicação se encontra. Assim, para cada ambiente, a apiUrl
será diferente.
Este é um modelo bem simples de fazer o uso deste tipo de arquitetura. Já falei aqui de um modelo mais organizado que é usando o spring-cloud.
Do lado do “ambiente”, é necessário de alguma forma ter esse valor de ENVIRONMENT
disponível para a aplicação. Como exemplo, vou simular a aplicação rodando em um Kubernetes.
Primeiro, criamos uma secret com o dado:
apiVersion: v1 kind: Secret metadata: name: default-cfg-environment namespace: l2-app-backend labels: app.kubernetes.io/managed-by: Helm annotations: meta.helm.sh/release-name: base meta.helm.sh/release-namespace: l4-cfg-helm type: Opaque data: ENVIRONMENT: ZGV2ZWxvcG1lbnQ= #development
Abaixo em destaque a configuração no deployment:
apiVersion: apps/v1 kind: Deployment spec: spec: containers: - name: ms-generic envFrom: - secretRef: name: default-cfg-environment
Aqui o arquivo de deployment completo com o uso da secret:
apiVersion: apps/v1 kind: Deployment metadata: name: my-app namespace: l2-app-backend labels: app.kubernetes.io/instance: my-app app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: my-app annotations: deployment.kubernetes.io/revision: '24' meta.helm.sh/release-name: my-app meta.helm.sh/release-namespace: l2-app-backend spec: replicas: 1 selector: matchLabels: app.kubernetes.io/instance: my-app app.kubernetes.io/name: my-app template: metadata: creationTimestamp: null labels: app.kubernetes.io/instance: my-app app.kubernetes.io/managed-by: Helm app.kubernetes.io/name: my-app spec: containers: - name: ms-generic image: ### IMAGE NAME ### ports: - name: app containerPort: 3000 protocol: TCP envFrom: - secretRef: name: my-app-helm - secretRef: name: default-cfg-environment resources: {} livenessProbe: httpGet: path: /metrics port: app scheme: HTTP initialDelaySeconds: 80 timeoutSeconds: 10 periodSeconds: 10 successThreshold: 1 failureThreshold: 3 readinessProbe: httpGet: path: /metrics port: app scheme: HTTP initialDelaySeconds: 80 timeoutSeconds: 10 periodSeconds: 10 successThreshold: 1 failureThreshold: 3 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: IfNotPresent securityContext: {} restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst serviceAccountName: my-app serviceAccount: my-app securityContext: {} schedulerName: default-scheduler strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 25% maxSurge: 25% revisionHistoryLimit: 10 progressDeadlineSeconds: 600
Com “tudo” isso feito, agora temos uma aplicação “portável” entre ambientes. Podendo assim levar a mesma aplicação sem precisar recompilar (“re-buildar”) ela.
Obrigado pela atenção, e até a próxima.