At the moment there are more than 100 different deployment files. The majority of the config is identical, but there are some differences and therefore every docker image has its own deployment template. If a change has to be made to one of the deployment.yamls, most of the time this has to be copied to other files as well and that is a little bit tedious. How to apply Don't Repeat Yourself (DRY) while constructing k8s files without creating spaghetti?
This is a similar problem I've been facing. And we're not the only ones it seems. GitLab just added a very interesting feature in their recent 10.5 release where you can pull external files into the pipeline.
In their blog post, they had this to say:
For many of our largest customers, the DevOps team is responsible for providing CI/CD pipelines to a large number of development teams throughout the organization. Previously, this was a painful process to manage. There wasn’t a scalable way to distribute reusable pipeline configuration which meant code needed to be manually copied between multiple .gitlab-ci.yml files in multiple projects. This was a labor-intensive and error-prone process. Additionally, it didn't provide adequate controls to ensure testing and deployment is consistently enforced for each repo.
Starting with 10.5, you can now include external files in CI/CD pipeline definition. Included files can be either local (contained in the same repo) or remote (accessible via HTTP/HTTPS). Including local files allows a large and complex .gitlab-ci.yml to be broken up in to modular chunks that are easier to maintain.
This is probably the best way to approach it from a OOP perspective as well: modularize certain aspects of your builds and include it in downstream code.
My peers working at another company do a similar approach with their Jenkins builds. They've essentially build on a 'makefile' for their builds that is based on templates and evaluates certain variables set in the Jenkins UI. Based on those variables, the code will then fetch (curl or git) 'module' files from a central 'builds' repository. It then uses all the modules to compile a single pipeline bash script and runs it.
This allows central changes to be done to a single file, that all the builds inherit.