Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add manifest generator #3124

Merged
merged 14 commits into from
Jun 23, 2020

Conversation

charith-elastic
Copy link
Contributor

Adds tooling to generate installation manifests for supported configurations of the operator.

Fixes #2406

@charith-elastic charith-elastic added >feature Adds or discusses adding a feature to the product v1.2.0 labels May 21, 2020
Copy link
Contributor

@sebgl sebgl left a comment

Choose a reason for hiding this comment

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

This is great. I'm so happy we can rely on Helm internally instead of baking our own template tooling.
I left many comments, but for most of them I'd be ok with follow-up issues if you prefer to merge this early and iterate with more PRs.


```shell
make docker-gen-restricted RESTRICTED_NS=myns | kubectl apply -f -
```
Copy link
Contributor

Choose a reason for hiding this comment

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

I am a bit surprised about having those instructions rely on Docker. Do you have in mind docker run as the main way to run the manifest generator for users?
I was expecting a simple go binary that we may eventually release with ECK for various platforms (linux/windows/osx), and this README to mention something like:

Compile from source

NOTE: requires Go installed on your computer.

go build

Quickstart

eck manifests generate --profile=global | kubectl apply -f

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is more likely that users will have Docker installed on their machines rather than Go. Asking them to install Go and compile a binary is not a great user experience. That is one of the reasons why I was keen on the distribution model enabled by my initial proposal.

With the code staying inside the cloud-on-k8s repo, the options as I see them are:

  1. Tell users to build the manifest-gen container image locally
  2. Make the manifest-gen container image available in the public registry
  3. Bundle the manifest-gen binary with the ECK container image

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'd be fine with releasing the manifest-gen along with the ECK image, especially if they are versioned together (your option 3)?

However I think we should also consider:

  1. Release the manifest-gen as a standalone binary (windows/osx/linux) in our github releases

I imagine most users would either run it from the ECK Docker image, or from the standalone binary.
I would consider that users who run things from the source code after a git clone can manage installing Go?

I'm fine keeping things as they are if you think it makes more sense for now, and revisit once we settle on the release/distribution mechanism.

Copy link
Contributor

Choose a reason for hiding this comment

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

+1 to discuss an other release mechanism later (curl, brew install elastic/tap/eckctl, yum install eckctl ...)

Cluster-wide installation with access to all namespaces:

```shell
make docker-gen-global | kubectl apply -f -
Copy link
Contributor

Choose a reason for hiding this comment

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

It feels like a bug to me that we need to go through a Makefile + a shell script to run the command. vs. just invoking the CLI with the right args (feels like the CLI is too complicated to be used directly?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The script is simply there to update the chart with the latest CRDs and version. People can use the CLI directly if they wish but I think the main audience for the tool is non-developers who would prefer a simpler command to run rather than a complicated compilation + run recipe.

Copy link
Contributor

Choose a reason for hiding this comment

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

the main audience for the tool is non-developers

But in that case they would probably run either form a released docker image or released binary directly, not from cloning the github repo and running a make command?

@@ -0,0 +1,44 @@
ECK Manifest Generator
Copy link
Contributor

Choose a reason for hiding this comment

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

Longer term, I'm thinking about this as a general-purpose CLI tool for ECK, that we may release alongside ECK itself (same versioning), for people to use as a standalone binary or a kubectl plugin.

Potential use cases:

eck manifest $args                                      # printout yaml manifests
eck install                                             # apply yaml
eck license apply my/license.json                       # apply an Enterprise license
eck license trial start                                 # start an enterprise trial license
eck elasticsearch my-cluster stop-manage                # pause reconciliations for a cluster
eck reattach-volumes mycluster.yml                      # re-create a cluster with existing PVs
eck elasticsearch my-cluster replace-node my-cluster-data-0 # safe-remove a Pod for rescheduling on another host

(not sure about eck vs. for example eckctl to match our ecctl tool)

As such I would imagine this tool to live in cmd/cli (a real thing we maintain, not a "hack").

But of course this goes way beyond the scope of that PR, I'm totally fine with moving towards that goal later on.
Curious about what the rest of team thinks long-term @elastic/cloud-k8s.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I agree with the general direction you are outlining @sebgl
But does it change much for this PR, I don't think so.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That was my original proposal too :)

@@ -0,0 +1,7 @@
config:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not fond of restricted and global.
restricted sounds like a security thing to me (restricted Pod). global is a bit vague.

What do you think about cluster-wide and namespaced?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

namespaced is pretty obtuse compared to restricted IMO.

Copy link
Contributor

@sebgl sebgl May 29, 2020

Choose a reason for hiding this comment

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

@elastic/cloud-k8s curious what others think here? restricted feels very misleading to me but that could be because english isn't my 1st language.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm -1 on global and +1 on cluster-wide. I'm not sure about a namespaced as it doesn't map well to k8s usage where it means belonging to a single namespace. For us it's one or more namespaces.

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we really care if we can make it an implementation detail and hide this wording to the user:

> # Generate and install a "global", "cluster-wide" operator
> make | kubectl apply -f -
> # Generate and install an operator which only manages some namespaces
> make MANAGED_NAMESPACES="foo,bar" | kubectl apply -f -

I'm not sure there is a right wording, OLM has installation mode types, but as long as it is not exposed to the user we can change our mind later.

by the way it not clear what the default target actually does

Copy link
Contributor

Choose a reason for hiding this comment

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

Great point @barkbay! Either we have managed namespaces, either we don't (default), which seems good enough to switch on what yaml is required. So we could remove the profile variable entirely?

Copy link
Collaborator

@pebrc pebrc Jun 9, 2020

Choose a reason for hiding this comment

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

I think global and restricted are OK names in my ears. But I am no native speaker. The question whether we need a profile feature which as I understand it also controls whether we have a webhook or not and sets up the managed namespaces at the moment is almost separate from that.

Right now it seems that we can predicate that decision indeed on if and how many managed namespace the user defines. But I wonder if some form of configuration preset will be useful once this thing generates additional config /RBAC for Beats for example (we can of course add it then when we need it)

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the different OLM install mode types are pretty clear what they do so could see us adopting them, but I think we can leave that as something for later

Copy link
Contributor

Choose a reason for hiding this comment

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

As discussed out of band today it might be worth merging this in as is and opening a separate issue to discuss this as a refinement

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Although currently the profiles seems like installation modes, they are more than that. The idea is to provide a set of defaults than can then be individually customised. They also serve as documentation/examples for what can be achieved with the operator. For example, someone might want to install the operator to manage just a single namespace but with the webhook. Without profiles, that person would need to read and understand the whole Helm chart and construct a complicated command line with the "right" combination of parameters. However, with a profile, all that person has to do is to look at the profile definition that closely matches what they want and simply override the flag that disables the webhook.


cmd := &cobra.Command{
Use: "generate",
Short: "Generate ECK manifests",
Copy link
Contributor

Choose a reason for hiding this comment

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

We're a bit inconsistent in using manifests vs. manifest. Not sure what's best? Let's try to settle on one.

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 guess it's the awkwardness of using the plural form for names. manifests-gen doesn't sound right -- hence why sometimes manifest is used in places.

log.Fatalf("Failed to locate assets: %v", err)
}

cmd.PersistentFlags().StringVar(&sourceFlag, "source", sourceDir, "Source directory")
Copy link
Contributor

Choose a reason for hiding this comment

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

would it be more explicit to call it charts?

hack/manifest-gen/main.go Show resolved Hide resolved
usage() {
echo "Usage: $0 [-u | -g <args>]"
echo " '-u'"
echo " Update the chart and exit"
Copy link
Contributor

Choose a reason for hiding this comment

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

it's immediately clear to me what "update the chart" means, can we clarify a bit?

}

// Generate produces a manifest for installing ECK using an embedded Helm chart.
func Generate(opts *GenerateFlags) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

It'd be nice to have a few comments explaining how this relies on helm internally and differs (or not?) from what helm would normally do if you invoke it directly.

@pebrc pebrc added the release-highlight Candidate for the ECK release highlight summary label Jun 4, 2020

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application.
appVersion: 1.2.0
Copy link
Contributor

Choose a reason for hiding this comment

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

IIUC this field should be kept in sync with https://github.com/elastic/cloud-on-k8s/blob/master/VERSION ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

# Namespace to install the operator to.
namespace: elastic-system
# Version of the operator. Should be set to the desired container image tag.
version: 1.2.0
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we not reuse {{ .Chart.AppVersion }} ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That makes it tricky to test unreleased images. With an explicit setting, I can test a locally built snapshot by passing something like --set=operator.version=1.2.0-48b3bc4e --set=operator.image.repository=docker.elastic.co/eck-dev/eck-operator-cell

Copy link
Contributor

Choose a reason for hiding this comment

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

I see there's this related issue about allowing to set appversion without editing the chart yaml helm/helm#8194

hack/manifest-gen/Dockerfile Outdated Show resolved Hide resolved
hack/manifest-gen/Makefile Outdated Show resolved Hide resolved
hack/manifest-gen/Makefile Outdated Show resolved Hide resolved
hack/manifest-gen/Makefile Outdated Show resolved Hide resolved

cp -f "$ALL_CRDS" "${CHART_DIR}/crds/all-crds.yaml"
sed -i -E "s#version: [0-9]+\.[0-9]+\.[0-9]+#version: $VERSION#" "${CHART_DIR}/values.yaml"
sed -i -E "s#appVersion: [0-9]+\.[0-9]+\.[0-9]+#appVersion: $VERSION#" "${CHART_DIR}/Chart.yaml"
Copy link
Contributor

@david-kow david-kow Jun 12, 2020

Choose a reason for hiding this comment

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

This ends up with the below on MacOSX.

$ ls assets/charts/eck/Chart*
assets/charts/eck/Chart.yaml    assets/charts/eck/Chart.yaml-E
$ ls assets/charts/eck/values*
assets/charts/eck/values.yaml   assets/charts/eck/values.yaml-E

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Interesting... looks like -i is consuming -E as the backup suffix. It shouldn't do that though. What is the version of sed you have on your machine?

Copy link
Contributor

Choose a reason for hiding this comment

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

Can't check the version unfortunately. Apparently it's FreeBSD sed from 2005. For .ci/Makefile we've ended up with sed ... > tmp && mv tmp ....

Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I know in place edits that work on both gnu sed and freebsd aren't possible without something like that Makefile david linked

@charith-elastic charith-elastic force-pushed the manifest-generator branch 2 times, most recently from 5e378ed to c72d161 Compare June 18, 2020 10:18
Copy link
Collaborator

@pebrc pebrc left a comment

Choose a reason for hiding this comment

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

LGTM! I am in favour of merging as is and addressing any outstanding issue in follow up PRs.

@charith-elastic
Copy link
Contributor Author

Jenkins test this please

@charith-elastic charith-elastic merged commit 6e915e3 into elastic:master Jun 23, 2020
@charith-elastic charith-elastic removed the >feature Adds or discusses adding a feature to the product label Jun 25, 2020
@charith-elastic charith-elastic added the >enhancement Enhancement of existing functionality label Jun 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>enhancement Enhancement of existing functionality release-highlight Candidate for the ECK release highlight summary v1.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add tooling to customize the all-in-one manifests
7 participants