Konfig
Konfig is a configuration system for application configuration.
Background
Configuration is a very interesting topic. As we build more microservices we need to rethink how we get distributed systems to get their configuration. More info please read External Configuration Store pattern.
Environment Variables
Well we have environment variables so why do we need a whole service for this solved problem? That is a great question.
Here are some reasons:
- They are global state.
- The values cannot handle structures more complex than a string.
- They can't be versioned.
- They are hard to verify/validate for correctness.
Configuration as Code
We want to standardize configuration and check it into version control. We are firm believers of using GitOps. Take a look at Your configs suck? Try a real programming language. Some systems to have a look at:
This system is geared around a very specific system that we use to build services. The content type of this config is YAML.
We recommend that you find a way to validate your configurations. We recommend looking at the following:
Providers
The configuration can be augmented with values that might be sensitive and need to be retrieved at runtime.
Environment Variables
To retrieve an environment variables the value of the key in the config should be env:VARIABLE
, ex: env:GITHUB_URL
.
Vault
You can store values in vault for safe keeping.
Key
The key format is as follows:
vault:/secret/data/key
An example:
vault:/secret/data/transport/http/user_agent
Value
The value format is as follows:
{"data": { "value": {} }}
An example:
{"data": { "value": "Konfig-server/1.0 http/1.0" }}
SSM
You can store values in ssm for safe keeping.
Key
The key format is as follows:
ssm:/secret/data/key
An example:
ssm:/secret/data/transport/http/user_agent
Value
The value format is as follows:
{"data": { "value": {} }}
An example:
{"data": { "value": "Konfig-server/1.0 http/1.0" }}
Server
The server is defined by the following proto contract. So each version of the service will have a new contract.
To configure we just need the have the following configuration:
server:
v1:
source:
kind: git, s3, or folder (see below)
Source
This system allows you to store your configuration from various sources. Though we highly recommend that you follow configuration as code.
Git
Distributed version control is awesome and we believe should be used when managing configuration.
To configure we just need the have the following configuration:
source:
kind: git
git:
url: https://github.com/alexfalkowski/app-config (the configuration repo)
dir: tmp/app-config (where to clone the repo to)
token: a GitHub token or can be set in KONFIG_GIT_TOKEN env variable
We expect that the folders to have the following conventions:
application
└── environment
├── continent
│ ├── country
│ │ └── app.config.yml
│ └── app.config.yml
└── app.config.yml
The tag name should be application/version
Some examples:
S3
S3 is another way to store your configurations.
To configure we just need the have the following configuration:
source:
kind: s3
s3:
access: Specifies an AWS access key associated with an IAM user or role.
secret: Specifies the secret key associated with the access key. This is essentially the "password" for the access key.
region: AWS Region to send the request to.
bucket: The bucket that contains all the configs.
We expect that the folders to have the following conventions:
application
└── version
└── environment
├── continent
│ ├── country
│ │ └── app.config.yml
│ └── app.config.yml
└── app.config.yml
Some examples:
s3://bucket/test/v1.5.0/production/server.config.yml
s3://bucket/test/v1.5.0/production/eu/server.config.yml
s3://bucket/test/v1.5.0/production/eu/de/server.config.yml
Folder
This is mainly used for testing or if you want to quickly run it. If you have a secure way to mount these configs, then by all means go for it.
To configure we just need the have the following configuration:
source:
kind: folder
folder:
dir: .config (the folder where the configurations can be found)
We expect that the folders to have the following conventions:
application
└── version
└── environment
├── continent
│ ├── country
│ │ └── app.config.yml
│ └── app.config.yml
└── app.config.yml
Client
The client is used to get the config that is defined in the config. These values reflect how the config is stored in the above sources.
To configure we just need the have the following configuration:
client:
host: localhost:8080
timeout: 5s
application: test
version: v1.5.0
environment: staging
continent: '*'
country: '*'
command: server
The client writes the config to the location specified by APP_CONFIG_FILE
environment variable.
Health
The system defines a way to monitor all of it's dependencies.
To configure we just need the have the following configuration:
health:
duration: 1s (how often to check)
timeout: 1s (when we should timeout the check)
Deployment
Since we are advocating building microservices, you would normally use a container orchestration system. Here is what we recommend when using this system:
Other Systems
We love discovering systems that inspire us to make better systems. Below is a list of such systems:
Development
If you would like to contribute, here is how you can get started.
Structure
The project follows the structure in golang-standards/project-layout.
Dependencies
Please make sure that you have the following installed:
Setup
The get yourself setup, please run the following:
make setup
Binaries
To make sure everything compiles for the app, please run the following:
make build-test
Tests
To be able to test things locally you have to setup the environment.
Starting
Please run:
make start
Stopping
Please run:
make stop
Features
To run all the features, please run the following:
make features
Changes
To see what has changed, please have a look at CHANGELOG.md