The glibc is backwards compatible, so code built to work on glibc 2.27 should keep working on glibc 2.29.
To implement backwards compatibility, glibc uses symbol versioning to mark when a function was introduced. If a function ever changes behavior (specially when it changes prototype) a new symbol version will be introduced for that version. But code built with the older glibc (which depends on the older behavior) will still bind to the older symbol version with the older behavior.
Most Linux distributions don't really support installing multiple glibc versions in parallel, since they would have to be installed in paths that include the full version (the name of the library itself, called "SONAME", is the same for all glibc versions, so can't be used by itself to differentiate them.) But then there's a problem with deciding which one to use for which binary. So then you need separate loaders (dynamic linkers) for each library version, but then you need to set the interpreter when you build binaries for each version (or patch the interpreter on existing binaries.) In short, it's possible to install multiple versions of glibc, but it's a complex setup and it's really painful to use.
If your application really needs glibc 2.27 and doesn't work with glibc 2.29 (but, as mentioned above, this should work, so that would be a bug in glibc 2.29), then your best bet is to run it on a Linux distribution that ships glibc 2.27 by default.
If changing the Linux distribution of your host is not an option, then consider running your application in a container, and build the container image from a distribution with the appropriate version of glibc.