Why rigid body is overlap?

You have specified the first segment as static, which is what you expect. Maybe you wanted to do it.

import direct.directbase.DirectStart
from panda3d.core import Vec3, TransformState, Point3
from panda3d.bullet import BulletWorld, BulletDebugNode, BulletCylinderShape
from panda3d.bullet import BulletPlaneShape, BulletSphericalConstraint, BulletConeTwistConstraint
from panda3d.bullet import BulletRigidBodyNode
from panda3d.bullet import BulletBoxShape

base.cam.setPos(0, -10, 0)
base.cam.lookAt(0, 0, 0)


debugNode = BulletDebugNode('Debug')
debugNode.showWireframe(True)
debugNode.showConstraints(True)
debugNode.showBoundingBoxes(True)
debugNode.showNormals(False)
debugNP = render.attachNewNode(debugNode)
debugNP.show()

# World
world = BulletWorld()
world.setGravity(Vec3(0, 0, -9.81))
world.setDebugNode(debugNP.node())

# Plane
shape = BulletPlaneShape(Vec3(0, 0, 1), 0)
node = BulletRigidBodyNode('Ground')
node.addShape(shape)
np = render.attachNewNode(node)
np.setPos(0, 0, 0)
world.attachRigidBody(node)

num_segment = 5 # 5段圆柱
segment_length = 1.0
segment_radius = 0.2

shape = BulletCylinderShape(radius=segment_radius, height=segment_length)
previous_node = None
for i in range(num_segment):
    node = BulletRigidBodyNode(f'segment_{i}')
    node.addShape(shape)

    if i == 0:
        node_path = render.attachNewNode(node)
        node_path.setPos(0, 0, segment_length/2)
    else:
        node.setMass(1.0)
        node_path = render.attachNewNode(node)
        node_path.setPos(previous_node_path.get_pos() + Vec3(0, 0, segment_length))


    previous_node = node
    previous_node_path = node_path
    world.attachRigidBody(node)

# Update
def update(task):
    dt = globalClock.getDt()
    world.doPhysics(dt)
    return task.cont

taskMgr.add(update, 'update')
base.run()