---
title: "OpenStack 네트워크 최적화: unattended-upgrades 문제 해결과 netplan으로의 전환"
description: "unattended‑upgrades가 네트워크 관련 패키지를 업데이트하면 netplan이 자동으로 apply되어 rc‑local에서 만든 bridge, veth, 라우팅 설정이 초기화되는 문제가 발생한다. 이를 해결하기 위해 rc‑local 대신 netplan YAML에서 물리 NIC와 bridge, virtual‑ethernets(veth 페어)를 직접 정의하고, 필요한 경우 OVS 연결은 rc‑local에 남겨두는 구조로 전환한다. netplan 0.107 이상에서 virtual‑ethernets를 지원하므로 veth 양쪽을 모두 정의하고 peer를 지정해야 하며, 적용 전 "
date: "2026-02-12"
last_modified: "2026-08-06T00:36:00.000Z"
type: "Post"
tags:
  - "network"
  - "ubuntu"
  - "troubleshooting"
categories:
  - "🤖 Computer Science"
series:
  - "오픈스택 운영"
canonical_url: "https://blog.pieroot.xyz/openstack-net-opt"
markdown_url: "https://blog.pieroot.xyz/openstack-net-opt.md"
---

# OpenStack 네트워크 최적화: unattended-upgrades 문제 해결과 netplan으로의 전환

unattended‑upgrades가 네트워크 관련 패키지를 업데이트하면 netplan이 자동으로 apply되어 rc‑local에서 만든 bridge, veth, 라우팅 설정이 초기화되는 문제가 발생한다. 이를 해결하기 위해 rc‑local 대신 netplan YAML에서 물리 NIC와 bridge, virtual‑ethernets(veth 페어)를 직접 정의하고, 필요한 경우 OVS 연결은 rc‑local에 남겨두는 구조로 전환한다. netplan 0.107 이상에서 virtual‑ethernets를 지원하므로 veth 양쪽을 모두 정의하고 peer를 지정해야 하며, 적용 전 

[OpenStack NIC 설정 최적화: 리눅스 브릿지와 VETH 페어를 활용한 효과적인 네트워크 구성 방법](https://app.notion.com/p/214067c015d0805e9568c256a1d36c75) 

이전에 OpenStack을 구성하던 중에 여러 개의 네트워크 구성을 위해 `rc-local`을 사용해서 인터페이스에 veth와 Linux bridge를 생성하여 연결하는 작업을 했었다. 나름 잘 돌아갔고, 나쁘지 않은 방법이었다.

그렇게 잘 쓰던 중 몇 가지 문제에 직면했다. 바로 `unattended-upgrades`라는 프로그램과 이를 통한 `netplan` 초기화다.

> **이 글에서 다루는 내용**
> 
> - `unattended-upgrades`가 뭔지, 왜 문제가 되는지
> 
> - netplan이 자동으로 apply 되면서 네트워크가 초기화되는 현상
> 
> - rc-local 대신 netplan으로 bridge + veth를 구성하는 방법
> 
> - 최종 netplan YAML 구성 예시

---

### unattended-upgrades

Ubuntu에서 최신 보안 패치 및 기타 업데이트들을 자동으로 수행하고 시스템을 유지, 관리하는 것이 목적인 서비스다. 개인이 사용하는 workstation이나 데스크탑 시스템에서는 보안을 자동으로 관리해주니 나름 안전을 위한 프로그램이지만, 패키지 리포지토리에 관련 패키지들이 업데이트되면 언제고 시도때도없이 업데이트를 진행해버리는 문제가 있다.

> **unattended-upgrades의 동작 원리**
> 
> - `/etc/apt/apt.conf.d/50unattended-upgrades` 설정 파일에 따라 동작한다
> 
> - 기본적으로 **보안 업데이트(security)**만 자동 적용되도록 설정되어 있다
> 
> - `systemd` 타이머(`apt-daily-upgrade.timer`)에 의해 주기적으로 실행된다
> 
> - 업데이트 로그는 `/var/log/unattended-upgrades/` 에서 확인할 수 있다

서버 환경에서는 이 서비스가 꽤 골칫거리가 될 수 있다. 예를 들어, `apt` 락이 걸려서 수동으로 패키지를 설치하려고 하면 **"Waiting for unattended-upgr to exit"** 같은 메시지가 뜨면서 대기해야 하는 상황이 발생하기도 한다. ~~이거 때문에 삽질한 적 한두 번이 아니다~~

#### 그래서 뭐가 문제인가?

여기에 추가로 network 관련 보안 조치들이 업데이트되거나 network 관련 패키지가 업데이트되면 **netplan이 자동으로 apply** 되는데, 이게 `/etc/netplan/**.yaml`와 같은 파일들의 내용이 자동으로 적용된다.

문제라면 우리의 netplan에는 **최소한의 네트워크 통신만을 설정**하고, 나머지를 rc-local로 `ip` 명령어를 사용하여 직접 설정하였다는 것이다. netplan이 다시 apply 되면 rc-local로 설정한 내용들이 전부 날아가버린다.

> **실제로 일어나는 일**
> 
> 1. `unattended-upgrades`가 네트워크 관련 패키지를 업데이트한다
> 
> 1. 업데이트 후 `netplan apply`가 자동으로 트리거된다
> 
> 1. netplan에는 최소 설정만 있으므로, rc-local로 만들어둔 **bridge, veth, 라우팅 테이블이 전부 초기화**된다
> 
> 1. 서버 접속이 끊긴다 😭
> 
> 1. 서버실에 직접 가서 복구해야 한다

이 문제를 해결하기 위해 찾던 중 netplan이 **모든 걸 다 할 수 있다**는 사실을 알아버렸다. ~~젠장~~

#### unattended-upgrades 비활성화는?

물론 `unattended-upgrades`를 비활성화하는 방법도 있다.

```bash
# 서비스 비활성화
sudo systemctl stop unattended-upgrades
sudo systemctl disable unattended-upgrades

# 또는 패키지 자체를 제거
sudo apt remove unattended-upgrades
```

하지만 보안 업데이트를 완전히 끄는 건 서버 운영 관점에서 그리 좋은 선택은 아니다. 특히 외부에 노출된 OpenStack 환경이라면 더더욱. 그래서 **근본적인 해결책**으로 netplan 자체에서 모든 네트워크 설정을 관리하기로 했다. netplan이 apply 되더라도 우리가 원하는 설정이 그대로 적용되니까.

---

### netplan으로 전환하기

[YAML configuration](https://netplan.readthedocs.io/en/stable/netplan-yaml/#properties-for-device-type-virtual-ethernets)

Top-level configuration structure: The general structure of a Netplan YAML file is shown below. version(number) Defines what version of the configuration format is used. The only value supported is...

위 링크는 netplan yaml을 설정할 수 있는 공식 문서인데 이걸 참고하면 진행 가능하다.

> **netplan의 ****`virtual-ethernets`**** 지원 히스토리**
> 
> 원래 netplan에서는 veth 디바이스를 설정하는 것이 불가능했다. 오래전부터 커뮤니티에서 요청이 있었지만, **netplan 0.107 버전부터** `virtual-ethernets` 키가 추가되면서 드디어 veth 페어를 YAML로 정의할 수 있게 되었다. 🚀
> 
> Ubuntu 24.04 이상을 사용하고 있다면 기본 탑재된 netplan 버전으로 사용 가능하다.

기존에는 rc-local 스크립트에서 `ip link add`, `brctl addbr` 같은 명령어로 직접 설정했지만, 이제는 netplan YAML 하나로 깔끔하게 관리할 수 있다.

---

### bridges

![image](https://blog.pieroot.xyz/api/image-proxy?id=343a0408-402e-4d89-88a3-f83dbeeefcb4&kind=s3&pageId=305067c0-15d0-807c-b74a-fe3f4505ad58&source=block&blockId=305067c0-15d0-803b-8f75-cbc5d14a760b)

Linux bridge는 어떤 인터페이스에 물릴지와 물린 인터페이스의 아이피 정보들을 적어주면 된다.

```yaml
network:
  version: 2
  ethernets:
    enp2s0:
      mtu: 9000
      dhcp4: false
  bridges:
    mybr0:
      interfaces:
        - enp2s0
      mtu: 9000
      addresses:
      - "172.30.0.11/16"
      nameservers:
        addresses:
        - 8.8.8.8
        search: []
      routes:
      - to: "default"
        via: "172.30.0.1"
```

사실상 `enp2s0`에 적어두었던 내용을 그대로 `mybr0`로 옮기고 `interfaces`만 추가해주는 것과 같다고 볼 수 있다.

> **bridge 설정 시 주의사항**
> 
> - 물리 인터페이스(`enp2s0`)에는 `dhcp4: false`만 설정하고, **IP는 브릿지에 할당**해야 한다
> 
> - `mtu`는 물리 인터페이스와 브릿지 모두 동일하게 설정해야 한다. 불일치하면 패킷 드롭이 발생할 수 있다
> 
> - `nameservers`와 `routes`도 물리 인터페이스가 아닌 **브릿지 쪽에 설정**한다. 브릿지가 실제 통신의 진입점이기 때문이다

---

### virtual-ethernets

![image](https://blog.pieroot.xyz/api/image-proxy?id=4208fccc-0427-4300-8b8a-6b4186b90f28&kind=s3&pageId=305067c0-15d0-807c-b74a-fe3f4505ad58&source=block&blockId=305067c0-15d0-80f7-8f4a-e2adbc5904fb)

`virtual-ethernets` 설정을 통해 `veth0`, `veth1`을 설정할 수 있고, bridge의 `interfaces` 옵션으로 연결할 수 있다.

```yaml
network:
  version: 2
  bridges:
    mybr0:
      interfaces:
        - veth0
  virtual-ethernets:
    veth0:
      peer: veth1
    veth1:
      peer: veth0
```

> **veth 페어 설정 시 포인트**
> 
> - veth 페어는 **양쪽 모두 정의**해야 한다. `veth0`만 정의하고 `veth1`을 생략하면 동작하지 않는다
> 
> - `peer` 값은 반드시 서로를 가리켜야 한다 (`veth0` → `veth1`, `veth1` → `veth0`)
> 
> - 기존 rc-local에서 `ip link add veth0 type veth peer name veth1` 했던 것과 동일한 효과다

기존에는 `ip` 명령어로 veth를 생성하고, `brctl addif`나 `ip link set master`로 bridge에 연결하는 과정을 스크립트로 작성해야 했다. 이제는 YAML에 선언만 해두면 netplan이 알아서 처리해준다. ~~세상 참 좋아졌다~~

---

### 최종 YAML 구성

아래는 최종본이다.

`vlans`는 컨트롤 노드에서 Octavia를 사용하기 위해 설정한 건데, 지금으로서는 무시해도 좋다.

```yaml
network:
  version: 2
  ethernets:
    eno1:
      dhcp4: false
    eno2:
      dhcp4: false
    enp2s0:
      mtu: 9000
      dhcp4: false
  bridges:
    mybr0:
      interfaces:
        - enp2s0
        - veth0
      mtu: 9000
      addresses:
      - "172.30.0.11/16"
      nameservers:
        addresses:
        - 8.8.8.8
        search: []
      routes:
      - to: "default"
        via: "172.30.0.1"
  virtual-ethernets:
    veth0:
      peer: veth1
    veth1:
      peer: veth0
  vlans:
    eno1.210:
      id: 210
      link: eno1
      addresses:
        - 172.32.0.1/16
```

> **최종 구성 해설**
> 
> - `ethernets`: 물리 NIC 3개를 정의. IP는 할당하지 않고 `dhcp4: false`로 설정
> 
> - `bridges`: `mybr0` 브릿지에 물리 NIC(`enp2s0`)와 veth 페어의 한쪽(`veth0`)을 연결
> 
> - `virtual-ethernets`: veth 페어 생성. `veth1`은 OVS에서 수동으로 연결
> 
> - `vlans`: Octavia용 VLAN 인터페이스 (선택사항)

#### 적용 방법

```bash
# YAML 파일 작성
sudo vi /etc/netplan/01-network-config.yaml

# 문법 확인 (적용 전 반드시!)
sudo netplan try

# 문제 없으면 적용
sudo netplan apply

# 적용 확인
ip addr show
bridge link show
```

> **`netplan try`****를 반드시 먼저 실행하자**
> 
> `netplan try`는 설정을 임시로 적용한 뒤 120초 내에 확인하지 않으면 자동으로 롤백해준다. 원격으로 작업 중이라면 이걸 먼저 실행하는 것이 정신 건강에 이롭다. 잘못된 설정으로 서버 접속이 끊겨도 2분만 기다리면 원래대로 돌아온다.

#### rc-local에서 남은 작업

netplan으로 bridge와 veth 설정을 옮겼지만, **OVS 브릿지에 veth1을 연결하는 작업**은 여전히 rc-local이나 별도 스크립트에서 처리해야 한다. netplan은 OVS 포트 추가를 직접 관리하지 않기 때문이다.

```bash
#!/bin/bash
# /etc/rc.local (OVS 연결 부분만 남김)

OVS_BR="br-vpn"
VETH1="veth1"

# OVS 브릿지에 veth1 연결
if ovs-vsctl br-exists $OVS_BR; then
    ovs-vsctl --may-exist add-port $OVS_BR $VETH1
else
    ovs-vsctl add-br $OVS_BR
    ovs-vsctl add-port $OVS_BR $VETH1
fi

echo "OVS setup complete."
```

이전에 비하면 rc-local의 역할이 대폭 줄어들었다. netplan이 네트워크 기본 설정을 책임지고, rc-local은 OVS 연동만 담당하는 깔끔한 구조가 되었다. ~~삽질의 결과물 치고는 나쁘지 않다~~

---

### 핵심 정리

✅ **문제**: `unattended-upgrades`가 네트워크 패키지 업데이트 시 `netplan apply`를 자동 트리거하여 rc-local 설정이 초기화됨

✅ **해결책**: rc-local 대신 netplan YAML에서 bridge + veth를 직접 정의

✅ **bridges**: 물리 NIC를 브릿지에 연결하고, IP는 브릿지에 할당

✅ **virtual-ethernets**: netplan 0.107+에서 지원. 양쪽 peer를 모두 정의해야 함

✅ **OVS 연동**: veth1을 OVS에 연결하는 부분만 rc-local에 남김

✅ **안전한 적용**: `netplan try`로 먼저 테스트 후 `netplan apply`

### 주의사항

⚠️ **netplan 버전 확인**: `virtual-ethernets`는 netplan 0.107 이상에서만 지원된다. `netplan --version`으로 확인하자

⚠️ **MTU 일관성**: 물리 NIC와 bridge의 MTU가 다르면 패킷 드롭이 발생할 수 있다

⚠️ **원격 작업 시 ****`netplan try`**** 필수**: 잘못된 설정은 서버 접속 불가로 이어질 수 있다

⚠️ **OVS 포트 확인**: netplan apply 이후 OVS 포트 연결이 정상인지 `ovs-vsctl show`로 확인하자

⚠️ **unattended-upgrades 비활성화는 비추**: 보안 업데이트를 끄는 것보다 netplan으로 설정을 통합하는 것이 올바른 해결책이다

### 참고 자료

- [Netplan YAML Configuration (공식 문서)](https://netplan.readthedocs.io/en/stable/netplan-yaml/)

- [Ubuntu Automatic Updates 공식 문서](https://documentation.ubuntu.com/server/how-to/software/automatic-updates/)

- [Linux Bridge 공식 문서](https://wiki.linuxfoundation.org/networking/bridge)

- [Open vSwitch 공식 문서](https://docs.openvswitch.org/en/latest/)
