Skip to content

Readme 0.1

JohnHoliver edited this page Apr 24, 2019 · 2 revisions

Pligos generates your infrastructure and additionally tries to loosen the boundaries between the service implementation and the infrastructure, by auto-generating a well-defined API to the infrastructure configuration.

Issue description

Our primary interface to the cluster, when it comes to deployments is helm. Helm allows us to use externally created configurations for databases, or other third-party technologies. Helm also allows us, in the same fashion, to configure infrastructure for our services, which allows us to have smooth, repeatable deployments. However, as the number of services grows, the amount of configuration grows as well, up to an unmaintainable level. This unmaintainable is based on several observations:

  1. Our infrastructure requirements change regularly. The change that led us to start development of Pligos was the introduction of an Istio mixer adapter.
  2. We often come up with more effective ways to configure our infrastructure, which means refactoring of all helm charts. As this work has only long-term effects, it's often neglected. An example is a management of configuration through type-specific files (config.json, config.yaml) and not as part of the values.yaml
  3. Creating new helm charts only amplifies the previous two points, as not all strategies are correctly documented, or just ignored which leads to imperfect helm charts from the beginning.

Also, we observed that the majority of the services behave in the same way, which means that a lot of the configuration is just duplicated.

Solution

When analyzing the properties of one infrastructure instance, we can identify a finite set, which, when structured correctly, allows us to generate the infrastructure into any form we want (Pligos calls these flavors). Some of the most important properties are:

  • Image
  • Command
  • Probe (analyze the status of the service for each lifecycle state)
  • Route (service listening port → FQDN)
  • Mounts (filesystem interface)

As some of those properties differ based on the context of execution (development, CI, staging, production), Pligos allows the user to define these properties context-aware. To achieve this, Pligos leverages the configuration strategy of kubectl (the kubernetes client command). As an example, the user may configure a command for each environment:

commands:
  - name: watch
    type: script
    fileName: script/watch.sh
  - name: binary
    type: executable
    command: ["/tokend"]

When the user, later on, configures each context, the commands can be assigned:

contexts:
  - name: prod
	command: binary
  - name: dev
	command: watch

In the same way, each of the above-described properties can be assigned to a context.

Secret management (Secret Provider)

Some secrets are shared alongside each instance of configuration (TLS certificates, docker registry credentials, ...). To access those secrets, Pligos can access a secret provider . As those secrets tend to be used to allow communication with third party technology (docker registry, host identity validation, ...) they are usually confidential and may not be added to the git repository. Therefore it is favorable to use a Vault based secret provider. However, up until now, only a file-based secret provider is implemented.

Service Dependencies (Friends)

Services, most of the times, need to talk to other services in the cluster, therefore our service has service dependencies. As we can observe, that the configuration for a single service dependency is always the same, it makes sense to create a library of configurations. Pligos calls these friends (a friend is a service, our service directly talks to, or is dependent on). A friend needs to define

  1. the configuration, that will be injected into our service (for instance hostname, port)
  2. In the case of externally defined configurations: default values to customize the friend into our environment
  3. chart reference: Where can we find the configuration for this service
  4. Type: Here we distinguish between requirement and dependency. A requirement is deployed for each service. Dependencies are shared between all deployed services and are therefore only deployed once.

Code Generation

TODO