Public Subnets have public IP and can communicate with the outside world through Internet gateway.
Private subnets cannot, that's why they are private in the end, they have no route and no public IP address.
But we can somehow make possible that an instance in a private subnet communicates with the outside world via so-called Bastion Hosts.
Basically we have one instance in the Public Subnet which has a route table association with the Internet Gateway (which allows bidirectional communication with outside world). That will act as a Jump Server to then establish the connection (via SSH or RDP) with the instances in the Private Subnet.
Since we don't want to store ssh keys on the instance in the public subnet we will need SSH Agent forwarding so that our PEM certificate on our machine is used when we ssh into the instance in the Public subnet, and forwarded it to connect to the instance in the private subnet.