... server and the client sends unencrypted TCP keepalive messages
A TCP keepalive message is a packet with no payload, i.e. the length of the application data is 0. The objective of TLS is to protect the application data against sniffing and modification. Since there are no application data in the TCP keep alive message in the first place there is nothing to protect here. In fact, TLS is not even aware of TCP keepalive and there is no need that it needs to be aware of it.
For example: Man-in-the-middle attacker disrupt the communication. To spoof both sides that the connection is still alive, he regularly sends/forwards TCP keepalives.
TLS does not care about the status of the TCP connection. It only cares about the transferred application data. TLS does not even see the TCP keepalive messages and has no way to trigger these.
The whole purpose of TCP keepalive is to keep an idle connection open and to detect connection loss within an idle connection. Connection loss or failure to detect it is usually not seen as a security problem since no actual application data are affected. If your specific applications requires such detection for security reasons and in a tamper-resistant way then you need to implement some kind of heartbeat at your application level or use the infamous TLS heartbeat extension if supported by your specific TLS stack.