I'm currently using a Kubernetes cluster running on bare metal nodes provisioned with Ansible. There are plans to move to the cloud and I'm reading about Terraform and Packer, in preparation for this. Leaving the data migration aside, it seems like there is a pretty straight forward migration path for us:
- Build image with Packer using our existing Ansible scripts
- Deploy built image to the cloud with Terraform
- Deploy our Kubernetes resources with our current tooling
That's all great. We now have immutable infrastructure, using state of the art tooling.
What I am struggling to find is how images built with Packer are versioned. Somewhere down the line, we will have to upgrade some software in those images. Sometimes the Ansible scripts will change, but sometimes it's just a matter of having the latest security updates in the image. Either way, Packer will have to build a new image for us and we will have to deploy it with Terraform. If the new image ends up causing trouble, we will have to revert to the old one.
I can imagine how this could be done manually by editing the template before running it and then editing the terraform configuration to pick up the new version, but that's not going to work for a CI/CD pipeline. Another issue is that we may move between different regions and vendors. So a version of the image may be present in one region, but not the other, and ideally, the pipeline should create the image if it doesn't exist and use the existing one if it is already there. This may cause images in different regions or clouds to be different, especially since they might be built on different days and have different security updates applied.
All of this is built in to the Docker workflow, but with Packer, it's far from obvious what to do. I haven't found any documentation or tutorials that cover this topic. Is there any built-in versioning functionality in Packer and Terraform? Is Terraform able to invoke Packer if an image is missing? Is there any accepted best practice?
I can imagine automating this by using the API from the cloud provider to check for the existence of the required images and invoke Packer for any missing images, before executing Terraform. This would work, but I wouldn't want to write custom integration for each cloud provider and it sounds like something that should already be provided by Terraform. I haven't used Terraform before, so maybe I just don't know where to look, and maybe it's not that difficult to implement in Terraform, but then why aren't there any tutorials showing me how?