Multiple Nodejs applications in elastic beanstalk - node.js

I have a nodejs project with multiple services, web and workers. All these services are in the same repo with only difference being the script used to invoke them.
I want different config for each service but I also want to keep them under 1 repo. I could use environments, but then It would mess my real environments like production, staging etc.
How can I use elastic beanstalk for this kind of architecture? Is compose Environments the best solution?

There are a lot of ways to handle this, each with their pros and cons. What I did in the past was upload my configs to a particular S3 bucket that was normally unreadable by public. I would then create a signed URL (good for the next couple years, or whatever) and set it as an environment variable in the Beanstalk config. Then, in my .ebextensions/01-setup.config (or somewhere similar), I have this:
{
"container_commands": {
"copy_config": {
"command": "curl $CONFIG_URL > conf/config.json"
}
}
}
On startup, the container would snag a copy of the config from the S3 bucket, copy it locally, and then the application would start up with this config.
Very simple to maintain.

Related

How to share config across multiple Node.js Lambda functions

I am new to AWS serverless application building. How can I share global config data across multiple Lambda function written in Node.js.
For configuration, consider:
JSON (or other) properties files packaged with the Lambda functions
environment variables configured on the Lambda functions
If you really need a common persistent source of configuration so that Lambdas do not need to be re-deployed when a configuration change happens, then consider:
Parameter Store
DynamoDB
For lambda configuration, use AWS Lambda Environment Variables:
https://docs.aws.amazon.com/lambda/latest/dg/env_variables.html
If you want same config for multiple lambdas use DynamoDB or any other storage.

Doing tasks before heroku nodejs server is ready

When deploying a new release, I would like my server to do some tasks before actually being released and listen to http requests.
Let's say that those tasks take around a minute and are setting some variables: until the tasks are done I would like the users to be redirected to the old release.
Basically do some nodejs work before the server is ready.
I tried a naive approach:
doSomeTasks().then(() => {
app.listen(PORT);
})
But as soon as the new version is released, all https request during the tasks do not work instead of being redirect to old release.
I have read https://devcenter.heroku.com/articles/release-phase but this looks like I can only run an external script which is not good for me since my tasks are setting cache variables.
I know this is possible with /check_readiness on App Engine, but I was wondering for Heroku.
You have a couple options.
If the work you're doing only changes on release, you can add a task as part of your dyno build stage that will fetch and store data inside of the compiled slug that will be deployed to virtual containers on Heroku and booted as your dyno. For example, you can run a task in your build cycle that fetches data and stores/caches it as a file in your app that you read on-boot.
If this data changes more frequently (e.g. daily), you can utilize “preboot” to capture and cache this data on a per-dyno basis. Depending on the data and architecture of your app you may want to be cautious with this approach when running multiple dynos as each dyno will have data that was fetched independently, thus this data may not match across instances of your application. This can lead to subtle, hard to diagnose bugs.
This is a great option if you need to, for example, pre-cache a larger chunk of data and then fetch only new data on a per-request basis (e.g. fetch the last 1,000 posts in an RSS feed on-boot, then per request fetch anything newer—which is likely to be fewer than a few new entries—and coalesce the data to return to the client).
Here's the documentation on customizing a build process for Node.js on Heroku.
Here's the documentation for enabling and working with Preboot on Heroku
I don't think it's a good approach to do it this way. you can use an external script ( npm script ) to do this task and then use the release phase. the situation here is very similar to running migrations you can require the needed libraries to the script you can even load all the application to the script without listening to a port let's make it clearer by example
//script file
var client = require('cache_client');
// and here you can require all the needed libarires to the script
// then execute your logic using sync apis
client.setCacheVar('xyz','xyz');
then in packege.json in "scripts" add this script let assume that you named it set_cache
"scripts": {
"set_cache": "set_cache",
},
now you can use npm to run this script as npm set_cache and use this command in Procfile
web: npm start
release: npm set_cache

scalable architecture with node.js

As a part of next assignment, I need to prepare a scalable and full concurrent supporting node architecture. I am confused with kubernetes/containers concept and really need some help. And I cannot use any paid service! Just plain raw DO servers and load balancers.
Basically a basic sketch/idea/explanation/pointers to The architecture which should explain API endpoints, data service connectivity and data flows between database, server and client is needed!
Here is what I have in my mind:
Client <-> NginX -> Nodejs <-> MongoDB
So above is a standard setup for nodejs based REST APIs I believe. Now how to add scalability to this and concurrency?
Any help would be appreciated!
Let me give you a quick overview and after that just ask more questions in the comments of my answer if you need to know more.
You need a docker image of all your services:
You will need an nginx image wich contains your frontend code. (https://serversforhackers.com/c/dckr-nginx-image)
You will need a docker image with which contains your backend code.
(https://nodejs.org/en/docs/guides/nodejs-docker-webapp/)
You will need an simple mongo-db base image.
(https://medium.com/#pablo_ezequiel/creating-a-docker-image-with-mongodb-4c8aa3f828f2)
Now for beginners I would go to Google Cloud Plattform and set up a manged kubernetes cluster. This is done in 1 minute and you will have a fulll functinal kubernetes environment. (https://cloud.google.com/kubernetes-engine/docs/quickstart) - In the first year you will have 300$ for free usage. So this is more then enough to play arround and set up an environment for your assignment.
Now you will need an Ingress API. The Ingress is the only access point to the Services you will later deploy on your cluster. Lets say your Ingress is listening to 14.304.233. When your write 14.304.233/customerBackend, it will redirect this request to the customerBackend Service (You need to define this of course) More information here: https://kubernetes.io/docs/concepts/services-networking/ingress/#what-is-ingress
Now you need to deploy the images you created. In Kubernetes you have the concept of Pods (see here: https://kubernetes.io/docs/concepts/workloads/pods/pod/).Normally in each Pod there runs only one container. Each Pod-Group (f.e all Pods which have an Node Container inside) has one so called Service, which is managing the access on the pod. Let say you want to have 3 instances of your NodeJS backend. Each of the 3 Container will run in a individual pod. If you want to send a request to the backend, it will go trough the Service, which then redirects the requests to one of the pos. When you need to scale, you simply deploy more pods. The Service automaticly balances the load over the deployed pods.
How many pods you want have is deployt is defined in a so called deployment.yaml
(see: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/).
This is very simular to a docker-compose.yaml but with some more attributes you can configure.

Centralized access for config value management

We are using NodeJS as our codebase and all our config value is stored as process.env.variable1
Since our codebase is managed by AWS opsworks it takes almost 10 minutes to deploy config change on 1 machine and we have 23 machine likewise, is there any way through which all config values are stored at a centralised place and code access them without having latency also if there is any auto-refresh mechanism present so that we access the new config value in realtime.

Set Heroku environment variable without restarting app

Is it possible to set a Heroku environment variable without restarting the app?
My app connects out to different online services via OAuth2. For each service I connect to, I need to set an OAuth2 ID and secret. To keep these configuration variables outside of my code, I'm using environment variables, and reading them in on process.env (node.js).
Each time I add a new service to my app, I need to add the corresponding environment variables for the ID and secret. I need to do this before pushing the latest code, so that when the app next starts up with the new service connection, the OAuth2 ID and secret variables are available.
Currently my workflow is as follows:
Set the environment variables using the Heroku toolbelt: heroku config:set <SERVICE>_ID=foo <SERVICE>_SECRET=bar
Push the latest code: git push heroku master
Currently, both of these operations will restart the app. I'd really prefer the first operation to not restart the app, as the changes to these config vars don't need to take effect until step 2). By restarting at step 1) my app will experience unnecessary downtime.
So, is there any way to prevent step 1) from restarting the app?
According to this article it pretty explicitly states that
Whenever you set or remove a config var, your app will be restarted.
Personally I also wish there was a way to do what you're asking. On larger apps, a system-wide hard restart can be painful when you have many process types running. Many times I set environment variables that aren't crucial for the app to grab ahold of immediately, such as that involving future functionality, or settings that are OK having the old value but you want the new value to take effect in a rolling-restart fashion.
At the present, is not possible to avoid the app restart. But you can use the command heroku config:edit to edit your env at once or even paste a new env set, avoiding many restarts.
In according to the heroku config help:
(...)
COMMANDS
config:edit interactively edit config vars
config:get display a single config value for an app
config:set set one or more config vars
config:unset unset one or more config vars
So you can run
heroku config:edit
Additionally, you might want to take a look on this issue (proposal):
https://github.com/heroku/cli/issues/1570

Resources