Kubernetes set environment variables depending on namespace - configuration

I want to set specific env variables depending on the namespace.
The goal is to have one config yaml file for different namespaces and set different env variables/config maps for dev, qa and prod depending on the namespace which the config file is applied to.

Afaik, kubernetes doesn't come with this capability out of the box.
There are two ways to get around this:
Deploy a standard ConfigMap that contains everything any deployment needs. Make your app recognise the namespace and use the appropriate variable.
Deploy a sidecar app that generates a namespace-specific ConfigMap from a template. This sidecar will need access to kube-apiserver to deploy new ConfigMap manifests automatically.

Related

How to share environment properties between apps in manifest in PCF

I have a single manfiest to deploy a set of services. Some of these services use same environment variables. Is there a way I can group common configuration across apps in manifest?
May be you can try this:
create a file called env-mainfest.yml with content:
---
env
name: value
and use below in your manifest files for deployment
inherit: env-mainfest.yml
Isn't a good idea to have spring_active_profiles set with env: specific settings for all services and just create an application-system.properties file and use spring profiles OR something similar if not spring based?
create base manifest file with common env variables for all services.
Create service specific manifest file like, manifest-.yml
Inherit base yml file in service specific manifest file.
Start application specific file with inheriting base yml file
---
inherit: manifest.yml
<application specific env properties>

How to manage settings in Openshift?

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.

How to trigger new deployment in openshift when we change openshift config maps

i have implemented following things in openshift
created Config Map In openshift for environmental configurations
reading those config maps as environmental variables in openshift.
I have a requirement like whenever i change values in the config maps new POD
needs to be created.
Please suggest me how i can achieve this?
Unfortunately there is no out of the box solution yet.
However i solved this issue by generating a hash of my config map "CONFIG_HASH".
This hash is then mounted in the container as an environment variable:
env:
- name: CONFIG_HASH
value: ${CONFIG_HASH}
Consequently, each time the config changes, a deployment is triggered (because the environment has changed).
You will however likely have to use a pipeline (Jenkins, GitlabCI,...) to do this...

Have `oc` follow a cluster depending on directory

I use the oc tool for several different clusters.
Since I am usually keeping local yaml files for any OpenShift objects I view/modify, either ad hoc or due to some config management scheme of the individual cluster, I have a separate directory on my machine for each cluster (which, in turn, is of coursed versioned in git). Let's call them ~/clusters/a/, ~/clusters/b/ etc.
Now. When I cd around on my local machine, the oc command uses the global ~/.kube/config to find the cluster I logged in last, to. Or in other words, oc does not care at all about which directory I am in.
Is there a way to have oc store a "local" configuration (i.e. in ~/clusters/a/.kube_config or something like that), so that when I enter the ~/clusters/a/ directory, I am automatically working with that cluster without having to explicitely switch clusters with oc login?
You could set the KUBECONFIG environment variable to specify different directories for configuration for each cluster. You would need to set the environment variable to respective directories in each separate terminal session window.
https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/#set-the-kubeconfig-environment-variable
To expand on Graham's answer, KUBECONFIG can specify a list of config files which will be merged if more than one exist. The first to set a particular value wins, as described in the merging rules.
So you can add a local config with just the current-context, e.g. ~/clusters/a/.kube_config could be
current-context: projecta/192-168-99-100:8443/developer
and ~/clusters/b/.kube_config:
current-context: projectb/192-168-99-101:8443/developer
Obviously need to adjust this for your particular cluster using the format
current-context: <namespace>/<cluster>/<user>
Then set KUBECONFIG with a relative path and the global config
export KUBECONFIG=./.kube_config:~/.kube/config
Note that if ./.kube_config does not exist it will be ignored.
The current-content will then be overridden by the one defined in the local .kube_config, if one exists.
I tested this locally with 2 minishift clusters and it seemed to work ok. Have not tested what the behaviour is when setting config though.

How to get production configuration variables when executing in another environment

In laravel configuration variables can be accessed like this
Config::get('xxx')
By default it returns the configuration values for the current environment. How do you get configuration data for other environments?
A call to Config::get() will already get you information of your current environment, if you are in dev it will be dev, if you are in production it will be the production data.
If you need to get a configuration information about another environment you can do by:
return Config::get('environment/config.name');
Example:
return Config::get('testing/cache.driver');
If you need to get things from your production environment while being in any other one, I'm afraid you'll have to create a 'production' folder inside your config folder and put those things there:
app/config/production/database.php
Add to that particular file only what you need to read outside from your environment:
'default' => 'postgresql',
And then you'll have access to it:
return Config::get('production/database.default');
You should be able to just do Config::get('xxx');
Unless you are overriding it in your testing/local/develop environments it should always be available. If you are, just remove it from the other envs.
I cannot see why you would define a config variable in another environment but then still need the production config.