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 kinds of this config that are supported are:
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" }}
Configuration
Environment Variables
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" }}
Configuration
Environment Variables
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:
KONFIG_GIT_TOKEN=GitHub token
source:
kind: git
git:
url: https://github.com/alexfalkowski/app-config (the configuration repo)
dir: tmp/app-config (where to clone the repo to)
We expect that the folders to have the following conventions:
application
└── environment
├── continent
│ ├── country
│ │ └── app.kind
│ └── app.kind
└── app.kind
The tag name should be application/version
and kind is yml
.
Some examples:
S3
S3 is another way to store your configurations.
To configure we just need the have the following configuration:
Environment Variables
source:
kind: s3
s3:
bucket: The bucket that contains all the configs.
We expect that the folders to have the following conventions:
application
└── version
└── environment
├── continent
│ ├── country
│ │ └── app.kind
│ └── app.kind
└── app.kind
Some examples:
s3://bucket/test/v1.5.0/production/server.kind
s3://bucket/test/v1.5.0/production/eu/server.kind
s3://bucket/test/v1.5.0/production/eu/de/server.kind
Kind is yaml
, toml
.
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.kind
│ └── app.kind
└── app.kind
Kind is yaml
, toml
.
Server
The server is defined by the following proto contract. So each version of the service will have a new contract.
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.
./konfig client --help
Start the client.
Usage:
konfig client [flags]
Flags:
-h, --help help for client
-o, --output string output config location (format kind:location, default env:APP_CONFIG_FILE) (default "env:APP_CONFIG_FILE")
Global Flags:
-i, --input string input config location (format kind:location, default env:CONFIG_FILE) (default "env:CONFIG_FILE")
To configure we just need the have the following configuration:
client:
v1:
host: localhost:8080
timeout: 5s
application: test
version: v1.5.0
environment: staging
continent: '*'
country: '*'
command: server
kind: yml
mode: 0o600
The client writes the config to the location specified by the flag called --output
. As per the following:
env:APP_CONFIG_FILE
- Write to an env variable called APP_CONFIG_FILE
. This is the default if nothing is passed.
file:path
- Write to the path.
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