Can't ping internal network namespace

You can troubleshoot with the route command:

# ip -n red route get 192.168.15.2
RTNETLINK answers: Network is unreachable

That's a good hint. You don't have a proper routing in the namespaces. In this case, it is because you missed the netmask when adding the IP address:

# ip -o -n red a
7: veth-red    inet 192.168.15.1/32 scope global veth-red\       valid_lft forever preferred_lft forever 

Try adding the IP address with a /24 so the routing table knows that it can reach other IPs in the network through this interface.

  1. clear all IP addresses first
# ip -n red  addr flush dev veth-red
# ip -n blue addr flush dev veth-blue

  1. Add the correct IP with netmask (using /24 as least confusing, but even /30 will work for your example).
# ip -n red  addr add 192.168.15.1/24 dev veth-red
# ip -n blue addr add 192.168.15.2/24 dev veth-blue

And you're done:

# ip netns exec red ping -c2 192.168.15.2
PING 192.168.15.2 (192.168.15.2) 56(84) bytes of data.
64 bytes from 192.168.15.2: icmp_seq=1 ttl=64 time=0.034 ms
64 bytes from 192.168.15.2: icmp_seq=2 ttl=64 time=0.022 ms

--- 192.168.15.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1035ms
rtt min/avg/max/mdev = 0.022/0.028/0.034/0.006 ms```