Ubuntu ROS 실습(4)

zeusqoi·2026년 9월 18일

개인공부

목록 보기
23/42

이번 실습에서는 Canonical Robotics의 튜토리얼을 따라 ROS 2 Humble Talker/Listener 예제를 Snap 패키지로 빌드해 보았다.

실습 환경은 Ubuntu 22.04.5 LTS + ROS 2 Humble이며, Snapcraft에서 사용하는 LXD 환경까지 구성한 뒤 실제 패키징을 시도했다.


1. Snapcraft 설치

먼저 Snapcraft를 설치했다.

sudo snap install snapcraft --classic

설치가 완료된 후 버전을 확인했다.

snapcraft --version

실습 환경에서는 다음과 같이 확인되었다.

snapcraft 9.0.1

2. LXD 설치 및 초기화

Snapcraft는 빌드 과정에서 LXD 기반의 빌드 환경을 사용할 수 있기 때문에 LXD도 설치했다.

sudo snap install lxd

설치 후 LXD를 자동으로 초기화했다.

lxd init --auto

그리고 LXD 네트워크를 확인했다.

lxc network list

lxdbr0라는 브리지 네트워크가 생성되어 있는 것을 확인할 수 있었다.

lxdbr0
IPv4: 10.66.137.1/24

3. ROS 2 Talker/Listener Snap 예제 가져오기

Canonical Robotics 튜토리얼에서 사용하는 예제 저장소를 Clone했다.

git clone https://github.com/ubuntu-robotics/ros2-humble-talker-listener-snap.git

프로젝트 디렉터리로 이동했다.

cd ~/ros2-humble-talker-listener-snap

프로젝트에는 다음과 같은 구조가 있었다.

ros2-humble-talker-listener-snap/
├── .git/
├── .github/
├── snap/
│   └── snapcraft.yaml
├── README.md
├── LICENSE
└── ...

4. snapcraft.yaml 확인

Snap 패키징에 필요한 설정은 snap/snapcraft.yaml에 작성되어 있었다.

주요 내용은 다음과 같다.

name: ros2-talker-listener
version: '0.1'
summary: ROS 2 Talker/Listener Example

description: |
  This example launches a ROS 2 talker and listener.

confinement: devmode
base: core22

parts:
  ros-demos:
    plugin: colcon
    source: https://github.com/ros2/demos.git
    source-branch: humble
    source-subdir: demo_nodes_cpp
    build-packages:
      - build-essential
    stage-packages:
      - ros-humble-ros2launch

apps:
  ros2-talker-listener:
    command: opt/ros/humble/bin/ros2 launch demo_nodes_cpp talker_listener.launch.py
    extensions:
      - ros2-humble

이 설정을 통해 ROS 2 Humble의 demo_nodes_cpp를 빌드하고, Talker/Listener를 실행하는 Snap을 생성하도록 구성되어 있다.


5. Snap 패키징 시도

기존의 snapcraft 명령 대신 현재 방식에 맞춰 다음 명령으로 패키징을 시도했다.

snapcraft pack

하지만 여기서 문제가 발생했다.

craft-providers error:
A network related operation failed in a context of no network access.

즉, 호스트 Ubuntu에서는 인터넷이 정상적으로 연결되지만 Snapcraft가 생성한 LXD 빌드 환경에서는 외부 네트워크 연결이 되지 않는 문제가 발생했다.


6. 호스트 인터넷 연결 확인

먼저 호스트 자체의 인터넷 연결에는 문제가 없는지 확인했다.

curl -I https://github.com

호스트에서는 정상적으로 GitHub에 접속할 수 있었다.

따라서 단순히 Ubuntu 자체의 인터넷 연결 문제는 아니었다.


7. LXD 컨테이너 네트워크 확인

문제의 원인을 확인하기 위해 테스트용 LXD 컨테이너를 생성했다.

lxc launch ubuntu:22.04 snap-test

컨테이너 내부에서 GitHub 연결을 테스트했다.

lxc exec snap-test -- curl -I https://github.com

하지만 연결이 되지 않았다.

반면 LXD 브리지 자체와 컨테이너 사이의 통신은 정상적으로 확인되었다.

lxc exec snap-test -- ping -c 3 10.66.137.1

결과:

3 packets transmitted, 3 received, 0% packet loss

즉,

컨테이너
   ↓
lxdbr0

까지의 통신은 정상적이었다.


8. 외부 네트워크 연결 테스트

컨테이너에서 Google DNS로 직접 통신을 시도했다.

lxc exec snap-test -- ping -c 3 8.8.8.8

결과:

3 packets transmitted, 0 received, 100% packet loss

GitHub에 대한 TCP 연결도 확인했다.

lxc exec snap-test -- curl -4 -v --connect-timeout 5 https://github.com

DNS 주소는 정상적으로 확인되었지만 TCP 연결은 timeout이 발생했다.

* Trying 20.26.156.215:443...
* connect to 20.26.156.215 port 443 failed: Connection timed out
curl: (28) Connection timeout after 5001 ms

9. LXD NAT 설정 확인

LXD 브리지의 NAT 설정도 확인했다.

lxc network show lxdbr0

다음과 같이 NAT가 활성화되어 있었다.

config:
  ipv4.address: 10.66.137.1/24
  ipv4.nat: "true"

실제로 nftables에도 LXD의 NAT 규칙이 존재하는 것을 확인했다.

sudo nft list chain inet lxd pstrt.lxdbr0

결과에는 다음과 같은 masquerade 규칙이 존재했다.

ip saddr 10.66.137.0/24
ip daddr != 10.66.137.0/24
oifname != "lxdbr0"
masquerade

따라서 LXD에 NAT 설정 자체가 빠져 있는 상황은 아니었다.


10. Docker와 FORWARD 정책 확인

호스트의 nftables 설정을 확인하면서 Docker의 FORWARD 체인 정책이 DROP으로 설정되어 있는 것도 확인했다.

sudo iptables -L FORWARD -n -v --line-numbers

결과:

Chain FORWARD (policy DROP ...)

이를 확인하기 위해 테스트 목적으로 lxdbr0에서 들어오는 패킷을 허용하는 규칙을 추가했다.

sudo iptables -I DOCKER-USER 1 -i lxdbr0 -j ACCEPT

그리고 FORWARD에도 임시 허용 규칙을 추가했다.

sudo iptables -I FORWARD 1 -i lxdbr0 -j ACCEPT

규칙이 실제로 패킷을 잡는 것은 확인할 수 있었다.

num   pkts bytes target
1       34  2040 ACCEPT  all  --  lxdbr0 *

하지만 이렇게 해도 컨테이너의 외부 통신은 정상적으로 되지 않았다.


11. 패킷 흐름 확인

tcpdump를 이용해 실제 패킷이 어느 구간까지 전달되는지 확인했다.

컨테이너에서:

lxc exec snap-test -- ping -c 3 8.8.8.8

를 실행하면서 lxdbr0를 확인했을 때 컨테이너의 패킷은 확인되었다.

10.66.137.49 > 8.8.8.8

하지만 외부 네트워크 인터페이스인 enp7s0에서는 컨테이너의 패킷이 확인되지 않았다.

sudo tcpdump -ni enp7s0 host 8.8.8.8

여기서는 다음과 같이 호스트 자신의 IP에서 나가는 패킷만 확인되었다.

203.237.142.127 > 8.8.8.8

즉, 컨테이너의 패킷이

LXD 컨테이너
    ↓
lxdbr0
    ↓
FORWARD
    ↓
??? 
    ↓
enp7s0

과정에서 외부 인터페이스까지 전달되지 않는 상황으로 확인했다.


12. Snapcraft 빌드 실패 결과

최종적으로 snapcraft pack을 다시 시도했지만 동일한 문제가 발생했다.

craft-providers error:
A network related operation failed in a context of no network access.

Snapcraft의 로그에서도 빌드 컨테이너가 네트워크가 준비되기를 기다리는 과정이 확인되었다.

Waiting for networking to be ready...
Executing in container:
getent hosts snapcraft.io

즉, Snapcraft 자체의 패키징 설정 문제라기보다 Snapcraft가 사용하는 LXD 빌드 환경에서 외부 네트워크가 정상적으로 연결되지 않는 문제가 남아 있는 상태이다.


13. 실습 결과

이번 실습에서는 다음 과정까지 진행했다.

  • Snapcraft 설치
  • LXD 설치 및 초기화
  • ROS 2 Humble Talker/Listener Snap 예제 Clone
  • snapcraft.yaml 확인
  • snapcraft pack 실행
  • Snapcraft 빌드 환경 생성 확인
  • LXD 네트워크 구성 확인
  • LXD 컨테이너 네트워크 테스트
  • NAT 및 nftables 규칙 확인
  • Docker FORWARD 정책 확인
  • iptables를 이용한 임시 네트워크 허용 테스트
  • tcpdump를 이용한 패킷 흐름 확인

하지만 LXD 컨테이너에서 외부 인터넷으로 나가는 네트워크 연결 문제가 해결되지 않아 최종 Snap 패키지 생성에는 실패했다.


마무리

이번 실습에서는 여기까지 진행하고, LXD 네트워크 문제 해결 및 Snap 패키지 생성은 이후에 이어서 진행할 예정이다.

0개의 댓글