Hard disagree with replacing yaml with HCL. Developers find HCL very confusing. It can be hard to read. Does it support imports now? Errors can be confusing to debug.
Why not use protobuf, or similar interface definition languages? Then let users specify the config in whatever language they are comfortable with.
I see some value instead. Lately I've been working on Terraform code to bring up a whole platform in half a day (aws sub-account, eks cluster, a managed nodegroup for karpenter, karpenter deployment, ingress controllers, LGTM stack, public/private dns zones, cert-manager and a lot more) and I did everything in Terraform, including Kubernetes resources.
What I appreciated about creating Kubernetes resources (and helm deployments) in HCL is that it's typed and has a schema, so any ide capable of talking to an LSP (language server protocol - I'm using GNU Emacs with terraform-ls) can provide meaningful auto-completion as well proper syntax checking (I don't need to apply something to see it fail, emacs (via the language server) can already tell me what I'm writing is wrong).
I really don't miss having to switch between my ide and the Kubernetes API reference to make sure I'm filling each field correctly.
I do something similar except with pulumi, and as a result I don't need to learn HCL, and I can rely on the excellent language servers for e.g. Typescript or python.
It's disappointing that your terraform experience with Typescript or python is better than your experience with HCL. HCL should really be better than it is.
I mean, I don't want to get into a debate about semantics, but when I open config.json files or kubernetes.yaml files in neovim, i get tab completed fields and values as well as inline errors about unsupported entries. That seems to qualify in my book.
Interesting - but is that because neovim has specifically added support for those formats (i.e. you've got some kind of Kubernetes-specific highlighting, not just generic yaml highlighting code?)
In this case it comes in via the coc plugin, which in turn has a plugin named coc-json, which, among other things, tries to download "well known" json schemas although now that I think about I'm not sure where those live.
Agree HCL is terrible. K8s YAML is fine. I have yet to hit a use case that cant be solved with its types. If you are doing too much perhaps a config map is the wrong choice.
It's just easier to shoot yourself in the foot with no proper type support (or enforcement) in YAML. I've seen Kubernetes updates fail when the version field was set to 1.30 and it got interpreted as a float 1.3. Sure, someone made a mistakes but the config language should/could stop you from making them.
Helm supports typing the values passed to the Chart but most charts aren't providing it. Most fields within out-of-the-box Kubernetes resources are using well-defined typed.
As much as Helm is prone to some type of errors, it will validate the schema before doing an install or upgrade so `version: 1.30` won't apply but `version: "1.30"` will.
You can very easily build and serialize/deserialize HCL, JSON, YAML or whatever you can come up with outside Kubernetes from the client-side itself (e.g. kubectl). This has actually nothing to do with Kubernetes itself at all.
Given that we're apparently discussing an entire k8s 2.0 based on HCL that hardly seems like a barrier. You'd have needed to write the HCL tooling to get the 2.0 working anyway.
Sort of. The hand-written go types are the source of truth and the proto definitions are generated from there, solely for the purpose of generating protobuf serializers for the hand-written go types. The proto definition is used more as an intermediate representation than an “API spec”. Still useful, but the ecosystem remains centered on the go types and their associated machinery.
Given that i can just take generated.proto and ingest it in my software then marshal any built-in type and apply it via standard k8s api, why would I even need all the boilerplate crap from apimachinery? Perfectly happy with existing rest-y semantics - full grpc would be going too far
In the age of AI arguments about a configuration language are moot. Nobody is going to hand craft those deployment configs anymore. The AIs can generate whatever weird syntax the underlying K8s machinery needs and do it more reliably than any human. If not today then probably in 3 months or something.
If you want to dream big for K8s 2.0 let AI parse human intent to generate the deployments and the cluster admin. Call it vibe-config or something. Describe what you want in plain language. A good model will think about the edge cases and ask you some questions to clarify, then generate a config for your review. Or apply it automatically if you're an edgelord ops operator.
Let's face it, modern code generation is already heading mostly in that direction. You're interacting with an AI to create whatever application you have in your imagination. You still have to guide it to not make stupid choices, but you're not going to hand craft every function. Tell the AI "I want 4 pods with anti-affinity, rolling deployment, connected to the existing Postgres pod and autoscaling based on CPU usage. Think hard about any edge cases I missed." and get on with your life. That's where we're heading.
I'm emotionally prepared for the roasting this comment will elicit so go for it. I genuinely want to hear pro and con arguments on this.
All the more reason you need a concise, strict representation of your actual config. If you're trusting an AI to translate fuzzy human intention into a machine protocol, there's less need for fuzzy human affordances in that machine protocol, and you should use one that plays to the strengths of a machine representation - one that's canonical and unambiguous.
If you want to dream big, why not give that post to AI and let it parse it to generate K8s 2.0, then you can get it to generate the application first, then the deployment. You can even have it feature-ask itself in a continuous loop.
Confusing? Here I am working on the infrastructure side thinking that I’m working with a a baby configuration language for dummies who can’t code when I use HCL/Terraform.
The idea that someone who works with JavaScript all day might find HCL confusing seems hard to imagine to me.
To be clear, I am talking about the syntax and data types in HCL, not necessarily the way Terraform processes it, which I admit can be confusing/frustrating. But Kubernetes wouldn’t have those pitfalls.
Paradoxically, the simplicity itself can be part of the confusion: the anemic "for loop" syntax, crazy conditional expressions to work around that lack of "if" statements, combine this with "count" and you can get some weird stuff. It becomes a flavor all its own.
But because we know that nginx is a configuration language for a server where we define the behavior we want through creating a set of resources (servers in this example, but "example"s or "whut"s in yours)
I am glad that you don't find the syntax confusing, but in my 25 years of monkeying with computer stuff, [] have been the canonical "I have a list of things" characters for a long as I can remember, so I sure am glad that Hashicorp decided that just repeating the key name is how one indicates list membership
I did see the "inspired by nginx" on hcl's readme, but that must be why you and Mitchell like hcl so much because I loathe nginx's config with all my heart
I was just saying HCL didn't invent block config. Perhaps nginx, Caddy, Lisp, F#'s Computation Expressions all primed me for HCL style syntax so it looks pretty clear to me. The key is understanding the value of that "repeating the key name", because it doesn't just become a keyname, it becomes a constructor and makes the syntax much simpler.
At the end of the day HCL isn't that much more complex than something like yaml. Saying "You don't want your developers learning yaml" is like saying "You don't want your developers learning Yaml. They send an email to the SRE guys, and the SRE guys are the Yaml experts"
Uh-huh, I think you are secretly supporting my argument of "who can possibly decipher this insanity?!" because https://github.com/tmccombs/hcl2json believes that it is valid
$ hcl2json <<FOO | jq -r '"has \(length) keys"'
outer {
example {
foo = "bar"
}
example {
foo = "baz"
}
}
FOO
has 1 keys
Why do I care what some random guy’s HCL to JSON conversion tool thinks is valid?
Terraform converts HCL to JSON in a different way that makes a lot more sense, and hcldec provided by Hashicorp lets you define your own specification for how you want to use it.
I would like to point out that perfect compatibility with JSON is not a goal nor a requirement of a decent configuration language.
I can't speak to the quality of CDK, which is 10x less popular by GitHub stars than base Terraform and is marked as experimental/bleeding edge and pre-1.0 by Hashicorp's own documentation. If they're using a hacky workaround of some guy's software that definitely sounds like something that pre-1.0 software would do.
I've found HCL perfectly adequate for vanilla Terraform, furthermore I've found no real reason to leverage CDK.
To be clear I am not saying HCL is amazing, merely that it's adequate and better than YAML, and that I'm not sure how it could be considered confusing. I personally think HashiCorp has jumped the shark since the IBM acquisition and that CDK will never gain mass adoption in a significant way.
You seem to have skipped over your initial citation of it being invalid syntax, to say nothing of the sibling comment to yours also using that opaque syntax
As for why I linked to "some random guy," that's because the Hashicorp people in their infinite wisdom didn't ship any rendering binary so some kind soul had to glue one to the official sdkhttps://github.com/tmccombs/hcl2json/blob/v0.6.7/go.mod#L8
I hear you about JSON might not be a goal, but I can tell you that Terraform accepts .json files just as much as it accepts .hcl files so that sane people can generate them, because sane people cannot generate HCL https://developer.hashicorp.com/terraform/language/syntax/js...
It was mentioned pretty deep in another thread, but this is just straight up user hostile
variable "my_list" { default = ["a", "b"] }
resource whatever something {
for_each = var.my_list
}
The given "for_each" argument value is unsuitable: the "for_each" argument must be a map, or set of strings, and you have provided a value of type tuple.
This is what you get if you want a declarative syntax. HCL doesn't have any concept of a for loop, and can't have any concept of a for loop— it's a data serialization format. Terraform can be transformed to and from JSON losslessly. The looping feature is implemented in Terraform.
Ansible's with_items: and loop: do the exact same thing with YAML.
The concept of repeated operations executing with respect to some condition is always going to be a bit different in declarative / functional constructs than in imperative ones. A purely functional language is never going to have the equivalent of: for (...) a++;
Good functional languages like Clojure make something like this awkward and painful to do, because it doesn't really make sense in a functional context.
I think you missed the error message; I wasn't whining about for_each syntax masquerading as if it was a property of the resource, I was pointing out the moronic behavior of attempting to iterate over a list of strings and being given the finger
It is claiming the provided thing is not a set of strings it's a tuple
The fix is
for_each = toset(var.my_list)
but who in their right mind would say "oh, I see you have a list of things, but I only accept unordered things"
It's not about them being ordered it's about them being unique. You're generating a resource for each element and that resource has a unique name. The stackoverflow way to iterate over a list is to use toset() but more often what people want is
zipmap(range(length(var.my_list)), var.my_list)
where you get {0 => item, 1=>item} and your resources will be named .0, .1, .2. I get the annoyance about the type naming but in HCL lists and tuples are the same thing.
I'm confused by your question, lists don't enforce uniqueness—you can do ["a", "a"] and it's perfectly valid. Sets and the key values of hash maps can't have repeating elements. You can for_each over lists that come from a data block so you can't statically know if a list is effectively a set.
If you don't want .0, .1 then you agree with Terraform's design because that's the only way you could for_each over an arbitrary list that might contain duplicate values. Terraform making you turn your lists into sets gets you what you want.
I just tell people to avoid writing loops in Terraform if it could be at all avoided. And if you iterate make sure it’s a keyed dictionary instead of array/list like data structure
> Developers find HCL very confusing. It can be hard to read. Does it support imports now? Errors can be confusing to debug.
This sounds a lot more like “I resented learning something new” than anything about HCL, or possibly confusing learning HCL simultaneously with something complex as a problem with the config language rather than the problem domain being configured.
Issue is that you do not want a dev learning hcl. Same as you don't want your SRE team learning next and react out of necessity.
The ideal solution would be to have an abstraction that is easy to use and does not require learning a whole new concept (especially an ugly one as hcl). Also learning hcl is simply just the tip of the iceberg, with sinking into the dependencies between components and outputs read from a bunch of workspaces etc.
It is simply wasted time to have the devs keeping up with all the terraform heap that SREs manage and keep evolving under the hood.
The same dev time better spent creating features.
Why? If they can’t learn HCL, they’re not going to be a successful developer.
If your argument is instead that they shouldn’t learn infrastructure, then the point is moot because that applies equally to every choice (knowing how to indent YAML doesn’t mean they know what to write). That’s also wrong as an absolute position but for different reasons.
You don't see my point. The ideal solution would be something that can be learned easily by both the dev and infra side without having to boil the ocean on one side or the other. Something like protobuf was mentioned above which is a better idea than hcl imho
I understand but do not agree with your point. I think two things are being conflated: the difficulty of learning HCL itself and the domain complexity of what almost everyone is learning HCL to do. I’ve seen people bounce off of Terraform and make lengthy rants about how HCL is hard, write thousands of lines of code in their preferred Real Programming Language™, and only eventually realize that the problem was that they thought they were learning one thing (IaC) but were actually learning two things at the same time (IaC and AWS/GCP/etc.) without taking time to formalize their understanding of both.
I have no objections to protobufs, but I think that once you’re past a basic level of improvements over YAML (real typing, no magic, good validation and non-corrupting formatters) this matters less than managing the domain complexity. YAML is a bad choice for anything but text documents read by humans because it requires you to know how its magic works to avoid correct inputs producing unexpected outputs (Norway, string/float confusion, punctuation in string values, etc.) and every tool has to invent conventions for templating, flow control, etc. I think HCL is better across the board but am not dogmatic about it - I just want to avoid spending more time out of people’s lives where they realize that they just spent two hours chasing an extra space or not quoting the one value in a list which absolutely must be quoted to avoid misinterpretation.
Terraform is good overall but HCL just isn't a very good language.
Given that its main purpose is to describe objects of various types, its facilities for describing types are pretty weak and its facilities for describing data are oddly inconsistent. Its features for loops and conditionals are weak and ad-hoc compared with a regular programming language. Identifier scope / imports are a disaster and defining a function is woeful.
Some of this is influenced by Terraform's problem domain but most of it isn't required by that (if it was required, people wouldn't have such an easy time doing their Terraform in python/go/rust).
Despite this, Terraform is overall good. But there's a reason there's a small industry of alternatives to HCL.
Say what? Protobuf may be type safe but it is far from a configuration language, can you even refer to variables or do loops. Unless you are thinking about serializing it with builders in code, which takes away the benefit of declarative configuration. It's also not readable without tooling. As parent said, this really sounds like refusal to learn something new.
> This sounds a lot more like “I resented learning something new” than anything about HCL, or possibly confusing learning HCL simultaneously with something complex as a problem with the config language rather than the problem domain being configured.
What would you expect to be hearing different if HCL really was just an objectively bad language design?
HCL can be represented as JSON and thus can be represented as YAML. Why did we need another configuration language which I'll also simply deal with with a proper programming language at any level serious usage?
The example in the blog post shows full-on logic structures (if this then that else this), which... no thank you.
I don't think I can take a JSON or YAML document and export it to an HCL that contains logic like that, but at the same time we shouldn't be doing that either IMHO. I very much do not want my configuration files to have side effects or behave differently based on the environment. "Where did this random string come from?" "It was created dynamically by the config file because this environment variable wasn't set" sounds like a nightmare to debug.
YAML is bad for a great many reasons and I agree with the author that we should get rid of it, but HCL is bad for this use case for the same reasons - it does too much. Unfortunately, I'm not sure if there's another configuration language that makes real honest sense in this use case that isn't full of nightmarish cruft also.
Any of the modern configuration languages would be better. They're all very sensitive to the problems of side effects and environment-specific behaviour - it's a defining characteristic. For example, pkl.
Obligatory mentions of cuelang and dhall here. I've used both for kubernetes and other large configs in multiple software teams and both are significantly more of a joy to work with than HCL or yaml
> Obligatory mentions of cuelang and dhall here. I've used both for kubernetes
Could you elaborate on your setup? Do you just convert them to JSON/YAML before passing them to kube/helm or…? (Are you able to type-constrain your values.dhall?)
Why not use protobuf, or similar interface definition languages? Then let users specify the config in whatever language they are comfortable with.