How you go about this really depends on what you want to use the output for. I've found that the generic Region* functions have lots of problems with certain kinds of regions, especially if you want very accurate details. The Discretize* functions do better for most of my use cases. But again, it really depends on what you're going to do next.
Anyway, to just get a more accurate visualization of your system, you might try this:
DiscretizeRegion[RegionUnion @@ cylinders, MaxCellMeasure -> .0001]
As for "any insight" into why the generic Region cropped the visualization, I have no idea. That's the kind of stuff I've come to expect from Region* functions.