The way to do this is via CoreVideo PixelBuffers. You can create a CVPixelBuffer and then create both a Metal texture and an OpenGL texture that share the same underlying storage.
The broad steps would be:
// setup
Create a CVPixelBufferPool
Create a CVMetalTextureCache
Create a CVOpenGLESTextureCache
(the Cache objects cache Metal and OpenGL textures for buffers within the pool, so they don't end up thrashing)
// per frame
Get a CVPixelBuffer from the pool
Get a Metal texture from the cache, issue rendering, commit, and waitUntilScheduled
Get a OpenGL texture from the cache, issue rendering commands that read from that texture.
If you are building something like a media pipeline, you may be cycling through a set of CVPixelBuffers in the pool. If you only ever need one texture and you can reuse it frame after frame, then you can move the 'get textures from the cache' to the Setup phase.