It does not defeat GIL, but the way asyncio is working makes GIL irrelevant.
In simplest use case you have a single thread (an actual OS thread) and as soon as certain operation blocks (e.g. waiting a response from server) another coroutine is scheduled.
The reason why GIL is irrelevant is because only a single coroutine executes at given time[1]. The way it works is similar to cooperative multitasking. The new task that was scheduled will execute until it encounters an operation that will make it block (typically an I/O operation).
[1] You actually can spin multiple threads and each could have its own event loop and then schedule coroutines on different threads.