There are different strategies and, depending on your specific problem domain, you need to decide what makes sense for you.
For server side applications, especially micro services, you typically don't need release branches. You can work with pull requests, but once they hit master, it is common to deploy (from master) and never look back. Managing release branches comes with a cost and for server applications, there is not much benefit from my experience.
For other type of applications, release branches do make a lot of sense. In my current job, I'm working partly on Browser extensions where releases need to be planned. In contrast to the server side, pushing a broken extension release is something that you want to avoid at all costs, especially as rolling back is not possible. That is why we have code freezes (every two weeks or so).
At code freeze, we create a release branch from the current master. Trunk based development continues as before, but all new changes will not make it in the upcoming release. Instead there is a testing and stabilization window, where only bug fixes will be accept on the release branch. When a bug is found, it will be fixed on master first, and only then cherry-picked to the release branch. Once bugs are fixed, the release goes out and the whole process repeats.
Stable cycles of around 2-3 weeks tend to work well. Shorter is also good, but longer cycles can be problematic, as it encourages people to squeeze as much as possible in the upcoming release. Otherwise, if you miss it, you might have to wait for months. I would strong recommend to favor multiple small and predicable release cycles over big and unpredictable ones.
Our CI system runs for all development relevant branches (i.e., on master and all pull requests). To be best of my knowledge, we do not run tests for the release branches. Normally, a well-tested bug fix from master does not create problems on the release branch. However, I see no fundamental reason not to run tests on the release branch, too.
If you set it up from scratch, I would include release branches. However, from my personal experience, master (and pull requests) alone should give you most of the benefits already. Running tests on master helps to enforce that development does not break existing tests, or introduces warnings or other coding style violations.
In our setup, the CI system (Jenkins) runs after each commit. If there are no changes, it will not be triggered. However, in my previous job, we had costly integration tests, which were executed once a day but only on master, while unit tests ran after each commit. Again, that depends on your specific project.