This is how I accomplished these things before. It involved simpler independent pieces which would not collapse whenever something went wrong. They were easy to reason about and building and fixing such tooling did not require me to hire an expensive consultant.
* declarative define your infrastructure
Declare in README.md that we have 3 web servers and that
Bob Jones set them up and manages them. Include Bob's email address and phone number.
* gives you load balancing, automatic recovery and scaling
Load balancing via a load balancer or another scheme. DNS is good enough for some cases. There are other solutions.
Automatic recovery - daemon scripts on the box to start all services when the box boots. VPS provider bounces the box when it crashes. That's one. There are others.
Scaling - automatic scaling is not needed at vast majority of companies that are starting out. When we need to scale to 4 servers, change README.md and send Bob Jones a quick message.
* provides great observability into your whole stack (kubectl, k9s, ...)
This is a need that is introduced because of k8s. There's a lot less to observe without k8s, and tools exist for it.
It's like saying "my backhoe has great diagnostic tools for diagnosing backhoe issues." That's true, but I don't have a backhoe and don't need a backhoe for what I am doing.
* has a huge amount of pre-packaged software available (helm charts)
This is a need that is introduced because of k8s. See above.
* allows you to stand up mostly the same infrastructure in the cloud, on your own servers (k3s), and locally (KIND), and thus doesn't tie you into a specific cloud provider
> doesn't tie you into a specific cloud provider
Not a real problem for most companies. If you're preparing to change cloud providers from day one, you are likely spending time on the wrong problem.
> same infrastructure in different envs
This is a benefit, which other solutions come close to, but k8s shines at. You can go a long way without having reproducible multi-machine setups in different envs and can come pretty close when needed, with manual work.
> Kubernetes could have been much simpler, and probably was intentionally built to not be easy to use end to end.
If true, this is a strange design choice. I'd be wary of anything that was made complex just for the sake of it.
k8s gets enough flack without having to accuse it of being complex just for funsies.
> But it's still by far the best we've got.
k8s is the best we've got when we want k8s. The trick is to not want k8s for the sake of wanting k8s.
There are times when k8s provides tremendous value. Most companies who decide to use it do not have the problems that k8s promises to solve, and never will. Sadly, sometimes it's because they've spent their time and money on unnecessary complexity like k8s instead of building a product that delivers value.