I'm trying to accomplish blue/green deployments with terraform/elastic beanstalk. How would one swap environment urls with this stack? I don't see anything obvious here.
The best I can come up with is...
running a terraform apply to spin up my entire architecture
spins up aws_elastic_beanstalk_environment's blue env
When wanting to deploy a new version of an app, running terraform
apply module.elasticbeanstalk.aws_elastic_beanstalk_environment.green to only spin up the other aws_elastic_beanstalk_environment resource
Now I have both blue & green up. Time for actually swapping the URLs...
through the command line eb swap API, swap the two environment URLs
update tfstate manually
terraform push new state
I would love it if there was a solution where I didn't have to manually manipulate the state. Or is this the only way to accomplish this function using these two tools?
I believe you just toggle the cname prefix of each
If you are looking to update the state after the swap you could note the ids of the beanstalk environments and do:
# Remove the old state information, using the command line not manually
terraform state rm module.elasticbeanstalk.aws_elastic_beanstalk_environment.blue
terraform state rm module.elasticbeanstalk.aws_elastic_beanstalk_environment.green
# Import these to the opposite environment resources
terraform import module.elasticbeanstalk.aws_elastic_beanstalk_environment.blue <green id>
terraform import module.elasticbeanstalk.aws_elastic_beanstalk_environment.green <blue id>
This doesn't exactly seem ideal, but it does avoid needing to manually manipulate the state file and could be scripted fairy easily.
Related
I'm trying to make my container image as small as possible by using quarkus/quarkus-micro-image:1.0 as my base image. I create a native executable, and it runs well.
However, my application needs to read data, and it runs on OpenShift. So my idea was to have a persistent volume for the data and pass the mounting information with an environment variable to my application.
My problem is that I can't manage to use oc rsync. The Red Hat documentation tells me that oc rsync requires rsync to exist in the container. The fallback would be tar according to Red Hat, but the container has neither rsync nor tar.
So my question is: What is the "Quarkus way" to solve that problem? I really don't want to use a huge image just to be able to oc rsync my data.
Any ideas?
What I want to do is to make a web app that lists in one single view the version of every application deployed in our Openshift (a fast view of versions). At this moment, the only way I have seen to locate the version of an app deployed in a pod is the ARTIFACT_URL parameter in the envirorment view, that's why I ask for that parameter, but if there's another way to get a pod and the version of its current app deployed, I'm also open to that option as long as I can get it through an API. Maybe I'd eventually also need an endpoint that retrieves the list of the current pods.
I've looked into the Openshift API and the only thing I've found that may help me is this GET but if the parameter :id is what I think, it changes with every deploy, so I would need to be modifying it constantly and that's not practical. Obviously, I'd also need an endpoint to get the list of IDs or whatever that let me identify the pod when I ask for the ARTIFACT_URL
Thanks!
There is a way to do that. See https://docs.openshift.com/enterprise/3.0/dev_guide/environment_variables.html
List Environment Variables
To list environment variables in pods or pod templates:
$ oc env <object-selection> --list [<common-options>]
This example lists all environment variables for pod p1:
$ oc env pod/p1 --list
I suggest redesigning builds and deployments if you don't have persistent app versioning information outside of Openshift.
If app versions need to be obtained from running pods (e.g. with oc rsh or oc env as suggested elsewhere), then you have a serious reproducibility problem. Git should be used for app versioning, and all app builds and deployments, even in dev and test environments should be fully automated.
Within Openshift you can achieve full automation with Webhook Triggers in your Build Configs and Image Change Triggers in your Deployment Configs.
Outside of Openshift, this can be done at no extra cost using Jenkins (which can even be run in a container if you have persistent storage available to preserve its settings).
As a quick workaround you may also consider:
oc describe pods | grep ARTIFACT_URL
to get the list of values of your environment variable (here: ARTIFACT_URL) from all pods.
The corresponding list of pod names can be obtained either simply using 'oc get pods' or a second call to oc describe:
oc describe pods | grep "Name: "
(notice the 8 spaces needed to filter out other Names:)
profile.properties file not found in Source code in repository?
Is it possible using environment variable in openshift?
If yes, how can set -Dkeycloak.profile.feature.scripts=enabled in Openshift environment?
Environment Variables are a first class concept in Openshift. There are many ways to use them:
You can set them directly on your BuildConfig to ”bake them into” your containers. This isn't best practices as then they won't change when you move them through environments but may be necessary to configure your build or set things that won't change (e.g. set the port number node.js uses to match the official node.js image with ”PORT=8080”)
You can put such variables into either ConfigMap or Secret configuration objects to easily share them between many similar BuildConfig
You can set them directly on DeploymentConfig so that they are set for every pod that is launched by that deployment. This is a fairly common way of setting up application specific environment variables. Its not a good idea to use this for settings that are shared between multiple applications as you would have to change common variables in many places.
You can set them up in ConfigMaps and Secrets and apply them to multiple DeploymentConfigs. That way you can manage them in one place.
Its common to see devs use a .env file that is named in .gitignore so not in git. In the past I have written scripts to load that into a Secret within openshift then use envFrom to set that secret on the deployment. Then have an .env.staging and .env.live that we git secret encrypt into git.
The problem with .env files is that they tend to get messy and have unused junk after a while. So we broke the file into one Secret to be database creds, separate Secrets for each api creds, a ConfigMap for app specific settngs. A ConfigMap for shared settings.
These days we use Helmfile to load all our config from git based on git webhooks. All the config is yaml in a git repo (with secret yaml encrypted). If you merge a change to the config git repo a webhook handler decrypts the config and runs Helmfile to update the settings in openshift. I am in the process of open sourcing everything including using a chatbot to manage releases (optional) over on GitHub
I should also say that openshift automatically creates many environment variables to help you configure you apps. In each project a lot of variables are set in every pod telling you the details of all the services you have setup in that project.
Openshift also sets up internal dns entries for your services. This means that if App A uses App B you don't have to configure A with a URL for B yourself. Rather there will be a dns entry for B and you can use the env vars that openshift sets on A to work out the dns entry to and the port number to use (e.g. dns entry includes project name and that is automatically set as an env var by openshift). So our apps can find a redis service running in the same project using that technique.
I have several EB applications that I would like to convert from a classic to an application load balancer. In the documentation it seems that the default way is to create a new environment from scratch with the proper load balancer. Considering that I have many environment variables and several environments, I would prefer not to have to rebuild applications. Is there a way to switch out the load balancer on an already running application?
It is not possible to set a a load balancer type except at creation time. You can use elastic beanstalk cli and aws cli to clone the application with the same config and version. To get the deployed application version run:
aws elasticbeanstalk describe-environments --application-name ${APPLICATION_NAME} --environment-names ${SRC_ENV_NAME} | jq -r '.Environments | .[] | .VersionLabel'
The jq pipe filters out the rest of the json blob.
After that, you can save the config of the curent appication using:
eb config save $SRC_ENV_NAME --cfg "${SRC_ENV_NAME}_save"
Then create an application clone using:
eb create $NEW_ENV_NAME --elb-type application --cfg "${SRC_ENV_NAME}_save" --version $APP_VERSION
Where APP_VERSION is the string extracted in step one.
It is not simple, but it can be done.
If the Envivornment name is important to you, it gets a little trickier.
Here is it how it should go, step by step (using the web console):
Save the configuration of the Environment you want to change
From the Saved config, generate a new Env (select Customize settings)
2.1) Change the LB type to Application and fill out all the necessary info for this
Swap the URLs from the original env to the new one (check if everything is working with the new env, if not swap back)
[STEPS ONLY NECESSARY IF ENV NAME IS IMPORTANT]
Delete the original env (which now is not receiving traffic and has a Classic LB)
Wait until the original name disappears from the console (it make take a couple of hours)
Clone the production env, and give the new env the original env name
Swap URLs
Done!
I'm going through the "Getting Started with Openshift" guide trying to learn this stuff. I have successfully added and configured a postgres db in my python gear.
If I run an env on the gear itself, I see the database environment variables:
[]\> env |grep POSTGRESQL_DB
OPENSHIFT_POSTGRESQL_DB_HOST=x.x.x.x
OPENSHIFT_POSTGRESQL_DB_USERNAME=admindb
OPENSHIFT_POSTGRESQL_DB_PORT=5432
But in my deployed code, I dump all the env variables with logging.error(os.environ) and none of the POSTGRESQL_DB variables are set. All the python ones seem to load properly.
I know I could set these vars manually, but since these vars are controlled by the gear they could become stale. The documentation implies that these variables should be set (they are used in the sample code).
Found the problem.
In the instructions we set a hot_deploy marker (so the application doesn't bounce when code changes are committed). The next step in the instructions is to add the postgres cartridge, but the environment variables won't load until the cartridge is restarted. So bounce the application and all is well.
Thanks,
Ryan
Is your deployed code running through the same logged-in shell environment as you log in with?
A common solution to making code see shell environment variables that are launched via some non-shell method is to launch them through a login shell.
For example:
/bin/bash -lc "/whatever/you/are/launching --args stuff"