Skip to content
This repository has been archived by the owner on Sep 30, 2020. It is now read-only.

Initial plugins proposal #751

Merged
merged 1 commit into from
Aug 3, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions proposals/plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Introduction

A draft design for [kube-aws plugins](https://github.com/kubernetes-incubator/kube-aws/issues/509). Plugins are initially defined as additions to a kube-aws generated
cluster that are not part of the core feature set of providing an easy to use, highly available,
best practice cluster on AWS. Plugins can also later be used for built-in functionality to provide a more modular deployment and ability to test.

# Initial Use Cases

1. A user wishes to deploy a component by default to their cluster instances outside of Kubernetes, e.g. a
monitoring agent.
1. A user wishes to deploy a component into their cluster by default that is not part of core
Kubernetes such as cluster wide services, addons, ingress controller or even persistent volumes.
Reasons can vary from company restrictions to always having this component form part of every
cluster. e.g. [the rescheduler](https://github.com/kubernetes-incubator/kube-aws/issues/118)
1. A user wishes to add [customised parts to the CloudFormation template](https://github.com/kubernetes-incubator/kube-aws/issues/96#issuecomment-263835808)
produced by kube-aws. Anything they add would need access to the same parameters and template
engine that already exists.
1. A user wishes to customise existing parts of the CloudFormation template produced by kube-aws
without necessarily having to diff all the files for changes with there sometimes being large
conflicts or huge updates due to kube-aws changes that can be difficult to digest while
being able to merge in the simple changes they need. Examples
[here](https://github.com/kubernetes-incubator/kube-aws/issues/340) and
[here](https://github.com/kubernetes-incubator/kube-aws/issues/338)

# Specific Examples

* Deployment outside of Kubernetes - Dex uses some additional API server parameter, Datadog agent still has more functionality if not using the containerised version
* Deployment to Kubernetes - rescheduler, kube2iam
* Add new parts to CloudFormation - bastion host
* Customisations to existing parts of CloudFormation - IAM roles/groups

# Plugin Principles

1. Plugin functionality should first be added in places where kube-aws needs it most, i.e. where
kube-aws receives more feature requests which do not fit with the core feature set.
1. kube-aws should dogfood the plugins system, i.e. use the plugins system where possible on existing functionality
1. Everything that is pluggable should be kept as modular as possible, from lists of IAM roles to kube API server parameters.
1. Where possible, checks will be added to kube-aws to ensure the integrity of the cluster via validation or disallowing particular changes. e.g. disallow overriding node pool init metadata
* Note, this could be gradually added rather than forming part of the first implementation
* Some of this will likely be provided by CloudFormation but kube-aws could possibly replicas the checks to save time for the stack create/update to fail

# Design

## Plugin Types

* Built-in plugins versus ad-hoc user specific plugins
* Some plugins will be provided by kube-aws and some will be specific to a user
* Both will use the same mechanisms to hook into kube-aws/deploy etc
* Both types of plugins will be enabled and configured in the same way
* Built-in plugins versus contrib plugins
Copy link
Contributor

@mumoshu mumoshu Jul 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please let me also add that contrib plugins will be hosted remotely in the kube-aws repo which can be installed locally and then work similarly to adhoc plugins.

Related: https://github.com/kubernetes-incubator/kube-aws/pull/751/files#r126319557

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, we can add that.

* kube-aws will accept contrib plugins for features considered to be applicable to many users
* Contrib plugins will be enabled in a similar way but specifically marked as not fully
battle tested; they will still be configured in the same way
* Plugins will be allowed to act across the whole cluster or act on a specific set of node pools, this should form part of the base configuration for which plugins to run

## Stages

The workflow for kube-aws should consist of the following stages, each of which will be called on the plugins in turn. Each stage will complete across all plugins prior to proceeding to the next stage. All plugins will receive input based on the whole setup, not just their own. This will allow them to hook into parameters from other plugins or core logic. The stages are not intended to become kube-aws commands and should mostly be transparent to a kube-aws user.

1. initialise
* Perform any prerequisite setup required such as calls to external system. Configuration, presence of files etc can be validated.
* Input - configuration
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how plugins communicate with core? will it be YAML? JSON? binary protocols? which communication channel is used? pipes? socket? passed file descriptors?

* Output - configuration with any initialised values, internal kube-aws model with primary constructs for CloudFormation, Kubernetes YAML/JSON, Helm charts, systemd units, kube API server parameters and any other key areas that allow customisation. Some of these will be file references but some will be full kube-aws internal models. The available list of constructs will be added to in further implementations.
1. render
* Stack files are gathered and rendered locally, most plugins will perform a no-op here but some may choose to output additional CloudFormation stacks or perform additional validation. A core plugin could grab all the primary constructs and create the main CloudFormation or a kube API server plugin could validate none of the parameters it has set are conflicting.
* Input - output of `initialise` stage
* Output - CloudFormation file(s), other file reference(s) such as Helm Charts
1. deploy
* Take the CloudFormation and file(s), upload the files to S3 and deploy the template(s) to CloudFormation. This is an opportunity for plugins to perform waiting tasks and/or actions that need to be done on deploy/install, for example post to an endpoint created during deploy.
* Input - output of `render` stage, stack name
* Output - stack details such as stack name, endpoints, certs
1. validate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about naming this validatePostConditions as it takes the output of deploy stage as its input?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The motivation for suffixing it with "post" is that at first glance I misunderstood that validate corresponds to kube-aws validate which validates pre-conditions before running kube-aws up and kube-aws update.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to rename. I agree we should avoid name clashes in cases we expose this to the users, in this case it will be exposed directly in our operator documentation so worth picking something more descriptive. How about postDeployValidate? Or simply postDeploy is an option as well if we wish to allow plugins to perform other "post" actions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I like your idea of postDeployValidate 👍

* Plugins can check they are functioning as expected which may depend on the configuration
* Input - output of `deploy` stage, configuration
* Output - validation errors

Validation errors can also be returned at any stage and can be:
1. fatal, kube-aws will stop processing further and log the problem
1. warning, kube-aws will continue processing but log a warning, can be used for deprecation

The output of the `initialise` stage is similar to `render stack` in kube-aws as of today with templates and a few other files. The output of the `render` stage is the fully formed CloudFormation without templating. Both of these could be stored as the user wishes and potentially version controlled.

## Examples

### Deployment Outside of Kubernetes

An example is a non-containerised monitoring agent or healthcheck. systemd units and other commands
could be output from plugins during the `initialise` stage and hence get included in the generated cluster.

### Dex / Rescheduler / Add-on Installation

Dex installation requires changes to the kube API server parameters plus a deployment into a running Kubernetes cluster.
kube API server parameters will be one of the constructs available as an output from `initialise` and so can be added to from the Dex plugin.
The deployment can be performed either via Kubernetes YAML or Helm Chart both of which would be a file/directory reference.

### Additional Worker IAM Permissions / kube2iam

Additional worker IAM permissions requires either additions to the existing IAM policies or new IAM policies
being attached to the worker instance role. This could be done in a few ways, for example `initialise` could
output the additional CloudFormation template snippet needed along with name/ref of the IAM policy.
The policies and policy document for the workers would be primarily managed by a core plugin that deals
with the worker permissions. It would take the output of `initialise` and render the final CloudFormation required.

The kube2iam add-on requires Kubernetes YAML or a Helm Chart to be installed which is covered by the Dex
example above plus changes to the worker IAM permissions.

### Bastion Host

A bastion host requires additional CloudFormation to deploy the instance into the correct part of the
VPC. It therefore requires knowledge of the VPC/network setup as input. This plugin would take the
configuration in `initialise` and output the additional CloudFormation based on the VPC settings.

### CloudFormation Renderer

During the `initialise` stage a core CloudFormation render plugin could output the basic CloudFormation templates for the cluster. Then during the `render` stage the same core plugin could choose to take all the output across all plugins from `initialise` and render the final CloudFormation.

### Kube API Server

A Kubernetes API server plugin could be responsible for main piece of cloud config that sets up the API server. It could then also perform additional validation during the `render` stage to ensure any plugins that have added to the kube API server parameters primary construct have not made the final state invalid.

# Implementation

* [Helm](https://github.com/kubernetes/helm) should be the main method for deploying additional components into the Kubernetes cluster
* How can kube-aws deal with plugin ordering? The ordering could be defined in a fixed YAML file and anything not present is always run last.
* What is the process to include and compile plugins?
* One idea is to use [go-plugin](https://github.com/hashicorp/go-plugin) since the native 1.8 plugins is not mature yet
* We need to protect sensitive information if uploading files, some Helm charts have secrets as config values so how will these be input?

## Configuration

All plugins will be enabled and configured via the `cluster.yaml` plus a set of plugin specific
configuration files. However, as above, the whole configuration model will be passed to all plugins
so they can access parameters from another plugin if necessary.

## Plugin Locations

* Built-in plugins can either be part of the kube-aws binary or downloadable from a secure source
if/when the user enables that plugin. The second is recommended.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider that built-in plugins should be part of the kube-aws binary hence "built-in",
while calling downloadable plugins contrib plugins.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was also considering that:

  • contrib plugins can be downloaded from kubernetes-incubator/kube-aws/contrib/plugins/<PLUGIN_NAME> to <USER_DIRECTORY>/plugins/<PLUGIN_NAME>
  • The user can also install or create an adhoc plugin under <USER_DIRECTORY>/plugins/<PLUGIN_NAME>.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was considering built-in to mean they can be configured out of the box a bit easier but I think it's fine if they are part of the same package, I don't much of a preference either way for initial implementation.

I like your idea about contrib plugins going to the same place as the adhoc plugins.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@c-knowles Thanks for the confirmation 👍
I'm even considering that a built-in plugin, when it is enabled, should be extracted from the kube-aws binary and then rendered into the working tree like adhoc plugins, so that it can be customized freely by the user without rebuilding the whole kube-aws binary.
What do you think?

cc @redbaron

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was considering built-in to mean they can be configured out of the box a bit easier

Btw I agree on this 👍

* Built-in plugins will live under `kubernetes-incubator/kube-aws/plugins/<PLUGIN_NAME>`
* This location can be thought of as the built-in plugin repository
* User contributed plugins will live under `kubernetes-incubator/kube-aws/contrib/plugins/<PLUGIN_NAME>`
until they are considered core or deprecated.
* This location can be thought of as the contrib plugin repository kube-aws plugins
* User provided will live under `<USER_DIRECTORY>/plugins/<PLUGIN_NAME>`
* This location can be thought of as user provided repository
* A user can specify a set of directories for plugins to be read from, likely as a CLI argument