Hacker News new | ask | show | jobs
by guslees 2755 days ago
Making an "easier" app-level experience very quickly becomes (necessarily) opinionated, because you need to anticipate which k8s parameters need to be exposed and which can be derived/assumed. Narrowing the configuration space in this way is entirely the point of "easier".

The way I've been approaching this is that you need a local "power user" who produces a simple abstraction that captures local patterns and policies, and the rest of the company then reuses that abstraction (or abstractions). Helm sort of lets you build this, but in practice it requires re-packaging helm charts with local customisations - which rapidly becomes a lot of overhead. The alternative is to expose every possible k8s option through the original helm parameters, which in turn means the helm chart becomes bewilderingly complex, and we're back to our original problem statement.

Instead, I've been advocating an "overlay" approach with jsonnet and the design of kube.libsonnet. The idea is that each consumer can import some upstream k8s manifests (described in jsonnet), apply some further jsonnet-based translations, and then publish the result as newer/simpler "templates". Someone else can then consume that, add another layer, republish, rinse, repeat. Importantly, each "republished" layer is still as easy to consume as the original. Eventually you end up with a jsonnet-based template that becomes highly opinionated and specialised to your actual problem domain, and hopefully is terse enough for local devs to use without having to learn all about k8s.

Example strawman:

  local mycompany = import "mycompany.libsonnet";
  mycompany.PhpApp {
    repo: "webgroup/guestbook",
    url: "https://mycompany.com/guestbook",
    requires_mysql: true,
  }
This might (hypothetically) turn into a:

- k8s Deployment that derived the docker image from the repo name (using knowledge of local build/publish conventions) and the command from the fact it was a php app

- k8s Service to point to the Deployment

- k8s Ingress from the provided URL (and local policy), pointing to the Service

- Bring in a mysql instance via any one of several approaches (eg: new standalone instance, or configure a new user/table on a centrally-managed DB server)

None of the above would be hard to do right now using kubecfg (or other approaches), but requires at least one person who understands both local policies and kubernetes - and for them to express that knowledge in "mycompany.libsonnet".

Importantly, whatever "mycompany.PhpApp" did would be quite different to "mycompany.PeriodicSparkJob" or "someothercompany.PhpApp" - so this isn't really something the _community_ can provide, without it rapidly becoming generic again and missing the whole point of the exercise. Coming back to your question, I think this is why you won't (and will never in the general case) find already-made tools that just happen to match your particular local needs.

1 comments

Those are some great points. I agree with the premise that Jsonnet and schema-based config generation opens up the possibility of actually composable, "layerable" building blocks, something Helm doesn't do at all. I also see your point about the top layer being org-specific.

That said, I was actually thinking more about the CLI itself, and wrapping the underlying config generation in something that, for example, knows how to tag the config (so that, if it uses Kubecfg internally, --gc-tag is automatically provided, for example. And using git as a base for release versioning. As I mentioned earlier, one thing our internal tool does on deploy is to present you with what commits will be deployed, which is derived from running "git log HEAD..<currently deployed commit>". It's a nice UX for the person doing the deploy. It just uses Kubernetes annotations for that, but it ends up being pretty powerful. Something we were also thinking about was using a CRD to record each deploy, so that you can get a history, with what commit, who deployed, and so on.

Another thing we do is provide a real-time progress view of the Kubernetes resources that your deploy creates/updates/deletes. This lets the operator know when the new version is live, and also alerts them if the deploy failed. Again, it's about UX.

I think I'd want to extract what we have into a general-purpose tool, and use something like Kubecfg or Ksonnet to do the actual applying of configs. But I don't hear a lot about what people are using, and looking for, in terms of deployment tools. For me, creating an in-house tool like this was an obvious thing because we just can't run kubectl or Helm from the shell to do things, it would be way too many steps even for simple apps. Is everyone writing tools like this? Or are they actually writing out full "helm install" commands?

A point on flags: yes it would be great if the user wouldn't have to remember to provide --gc-tag explicitly. Bringing that even further, I'd like to be able to specify the cluster in the config (likely in the last "actualization" layer). Conceptually it's like the namespace: you can currently craft configs that are parametric on a given namespace and then fix that value to a given deployment specific choice. IMHO clusters should be the same except currently they are "outside the config" since the choice of the cluster affects the API endpoint the tool has to talk to.

In my ideal scenario my colleagues would just need to know which file to "apply". The file itself (through its name or directory location or comments or more documentation) will guide the user to the meaning of what environment that actually is (dev, staging, production, some well knownv deployment X)