1. You build custom VM images that have everything you need baked in. You don't upgrade these VMs, instead you build new ones and delete the old ones.
2. You use cluster management tools like Kubernetes or Nomad and run your software as containers. You upgrade by running a new version of the container. (If you choose to manage your own nodes in the cluster, you manage them as VMs using method 1.)
3. You don't run your software on servers you manage. You use so-called "serverless" services where your software doesn't have to think too hard about the OS it's running on.