You can limit resources using Virtualization solutions such as Kubernetes or use Systemd.
Please note however that you should not consider a single limit. The load on your system will vary over time depending on what the node is currently doing.
At first, your node will be syncing and you will see lots of networking and io. Once your node is "cruising", you still will see spikes from time to time and you need to account for those as well. Those spikes can be due to regular and plannable events such as new Eras, etc... or sporadic events such as a runtime upgrade or having to process a big transaction.
I personally like to set my limits tight at first to see what they really need to be, then add a 30% buffer to account for those spikes. For a non validator node, this is rather easy to do and you can easily "take the risk", for a validator, I would suggest having a "plan B" (ie validator node ready to take over) if your limits happen to be to tight and your node gets killed.
Also note that whatever limits you define today will change in the future based on:
- new versions of the runtime
- new version of the client
- number and type of transactions to process