안녕하세요. 오픈소스컨설팅에서 리눅스 엔지니어로 근무하고 있는 정광근 프로 입니다.

우리는 장비를 관리하기 위해 관리대장/장비리스트와 같은 형태의 문서를 작성하고 업데이트 하며 관리하고 있습니다.

오늘은 x86기반 Linux에서 시스템의 아이덴티티(Identity)로 활용하는 hostid에 대해 얘기해 보려 합니다.

먼저 테스트 환경은 RHEL 기반 리눅스 시스템으로 2가지 버전을 준비해 보았습니다.

먼저 따끈따끈한 Rocky Linux 9.1 버전과 잔존 세력으로 남아있는 CentOS 6.10 버전으로 테스트를 진행하였습니다.

hostid란?

시스템의 hostid는 호스트의 숫자 식별자입니다. 호스트 간에 고유한 것으로 간주 될 수 있는 정수로 구성되어야 합니다.

그렇다면 어떤 원리로 생성될까요?

hostid 10진로 이루어진 IPv4 주소값16진수(hexadecimal)로 bit-twiddling되어 생성됩니다.

일반적인 로컬 네트워크 환경에서는 동일한 IP를 사용하지 않기 때문에 이렇게 생성된 hostid값은 유니크한 값을 지니게 되며 이를 통해 노드에 대한 구분이 가능합니다.

사례가 많지는 않을 것 같은데요. 경우에 따라 서로 다른 서버팜에 값은 IP를 가지는 노드가 존재할 수 있고 서버팜에서 밖으로 나가는 output 네트워크 통신으로 NAT를 활용하는 경우가 있을 수도 있습니다. 이러한 경우에 hostid를 노드의 아이덴티티(Identity)로 사용할 수는 없을 것 같습니다.

그래서 그런지 레드햇 KB자료 자료에서도 hostid에 대해 아래와 같이 마지막에 이 값은 유니크하지 않을 수 있다는 표현을 하고 있습니다.

[ Red Hat Knowledgebase ]
glibc 구현에서 hostid는 /etc/hostid 파일에 저장됩니다. gethostid()가 호스트 ID를 포함하는 파일을 열 수 없으면 gethostname()을 사용하여 호스트 이름을 얻고 호스트의 IPv4 주소를 얻기 위해 해당 호스트 이름을 gethostbyname_r()에 전달하고 다음으로 얻은 값을 반환한다고 가이드하고 있습니다. 그리고 이 값은 유니크하지 않을 수 있습니다.

초기설정

자 이제 초기 설정값을 살펴보도록 하겠습니다.

Rocky Linux 9.1 버전의 OS 설치 이후 초기 hostid값을 살펴보도록 하겠습니다.

[root@rocky-9 ~]# hostid
007f0100

이때 나타나는 값은 흔히 알고 계신 로컬 IP의 IPv4주소인 127.0.0.1 주소16진수bit-twiddling 된 값입니다.

IP 설정을 살펴보면 아래와 같이 IPv4 주소로는 로컬 IP주소만 등록되어 있는 상태입니다.

[root@rocky-9 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:00:01:07 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::215:5dff:fe00:107/64 scope link tentative noprefixroute 
       valid_lft forever preferred_lft forever

6버전에서의 hostid값은 9버전과는 좀 다르게 확인됩니다.

CentOS 6버전에서의 초기 hostid값은 0x8값이 반환됩니다.

[root@centos-6 ~]# /usr/bin/hostid
00000000

IP 설정을 살펴보면 9버전과 동일한 형태이나 그 값은 다르게 반환된 것을 확인할 수 있었습니다.

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST> mtu 1500 qdisc mq state DOWN qlen 1000
    link/ether 00:15:5d:00:01:11 brd ff:ff:ff:ff:ff:ff

이 경우 고민할 필요 없이 hostid를 재 생성 해주면 됩니다.

호스트에 대한 hostid 생성 및 설정을 해주는 genhostid명령어를 사용해보겠습니다.

[root@centos-6 ~]# /sbin/genhostid 

확인을 해보니 정상적으로 hostid값이 생성되었습니다.

[root@centos-6 ~]# /usr/bin/hostid
6a2af908

이렇게 버전별 hostid 초기값을 알아 보았습니다.

genhostid

앞서 CentOS 6버전에서 초기 hostid 값이 나타나지 않아 genhostid 명령어를 통해서 hostid 값을 가져 왔었습니다.

IP정보가 없는데 값이 나타난 점, 이렇게 등록된 값이 bit-twiddling된 IPv4주소가 맞는지 궁금해져 genhostid 명령어를 여러번 수행해 보았습니다.

결과는 아래와 같이 바뀌는 것을 볼 수 있었습니다.

[root@centos-6 ~]# /usr/bin/hostid
24d7f639
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
3263c370
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
1fe21173
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
6e456b16
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
144cf75c
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
7f770446
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
6eed777d
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
3113aaa3
[root@centos-6 ~]# /sbin/genhostid
[root@centos-6 ~]# /usr/bin/hostid
399c4bd7

변경된 값들은 규칙성을 보이지 않았고, bit-twiddling 해 보았더니 IP정보로 활용할 수는 없었습니다.

여기서 알 수 있는 사실은 genhostid 명령어를 통해 hostid값을 생성/변경 할 수는 있습니다.

다만 우리가 알고 있는 IPv4의 주소값이 bit-twiddling된 데이터는 아니며, 지속적으로 바뀌기 때문에 노드의 아이덴티티로 활용할 수는 없습니다.

특별한 상황에서 genhostid 명령어를 통해 랜덤으로 hostid를 생성하여 사용할 수는 있겠으나, 노드를 구분하는 인자로는 사용하지 않으시길 바랍니다.

IP주소 등록 후 hostid 확인

이제 본론으로 들어가서 IP 주소를 등록하고, hostid 값이 정상적으로 생성되는지 확인해 보도록 하겠습니다.

eth0 인터페이스에 “172.20.140.10” 주소를 입력해 보겠습니다.

[root@rocky-9 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:00:01:07 brd ff:ff:ff:ff:ff:ff
    inet 172.20.140.10/18 brd 172.20.191.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fe00:107/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

hostid를 확인해 보겠습니다.

[root@rocky-9 ~]# hostid
14ac0a8c

hostid값은 IP주소를 입력하자마자 bit-twiddling된 “14ac0a8c” 값으로 변경되었으며 별다른 작업 없이 실시간 반영 되었습니다.

eth1 인터페이스에 “172.20.200.11” 주소를 입력해 보겠습니다.

[root@centos-6 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
    link/ether 00:15:5d:00:01:11 brd ff:ff:ff:ff:ff:ff
    inet 172.20.200.11/16 brd 172.20.255.255 scope global eth1
    inet6 fe80::215:5dff:fe00:111/64 scope link 
       valid_lft forever preferred_lft forever

hostid를 확인해 보겠습니다.

[root@centos-6 ~]# hostid
399c4bd7

이 값은 genhostid 명령어를 통해 마지막으로 변경했던 hostid값으로 bit-twiddling된 IP정보는 아닙니다.

이런 경우 /etc/hostid에 생성된 파일을 삭제 하고, /etc/hosts파일에 노드 정보를 등록을 해주어야 합니다.

[root@centos-6 ~]# ll /etc/hostid
-rw-r--r--. 1 root root 4 Dec 21 13:09 /etc/hostid
[root@centos-6 ~]# rm /etc/hostid
rm: remove regular file `/etc/hostid'? y
[root@centos-6 ~]# ll /etc/hostid
ls: cannot access /etc/hostid: No such file or directory

[root@centos-6 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.20.200.11    centos-6.10

다시 hostid를 확인해 보겠습니다.

[root@centos-6 ~]# hostid
14ac0bc8

값이 정상적으로 보이는 것을 확인 할 수 있었습니다.

bit-twiddling

그렇다면 이제 hostid 값이 어떻게 설정 되는지 로직을 살펴 보도록 하겠습니다.

  • 먼저 IPv4 IP주소를 dot(.)로 구분된 4개의 Octet으로 분리합니다.
  • 분리된 10진수를 16진수로 변환합니다.
  • Octet 2 – Octet 1 – Octet 4 – Octet 3 순으로 나열합니다.

테스트에 사용되었던 Rocky Linux 9.1 버전의 IP정보를 기반으로 bit-twiddling 되는로직을 표현 해 보았습니다.

Python Code

그렇다면 원하는 값을 hostid로 설정할 수는 없을까요?

당연히 가능합니다.

레드햇에서는 원하는 hostid 값을 등록할 수 있는 Python 코드를 아래와 같이 제공하고 있습니다.

from struct import pack

filename = "/etc/hostid"
hostid = pack("I",int("0x210a2501",16))
open(filename,"wb").write(hostid)

hostid = pack(“I”,int(“0x210a2501”,16)) 해당 줄의 “0x210a2501”에 해당되는 agurment의 값을 원하는 값으로 넣어주면 됩니다.

아래와 같이 테스트 해본 결과 hostid를 원하는 값으로 변경할 수 있었습니다.

[root@rocky-9 ~]# hostid
14ac0a8c

[root@rocky-9 ~]# cat hostid-setting.py 
from struct import pack

filename = "/etc/hostid"
hostid = pack("I",int("0x210a2501",16))
open(filename,"wb").write(hostid)

[root@rocky-9 ~]# python hostid-setting.py 

[root@rocky-9 ~]# hostid
210a2501

/etc/hostid 파일을 삭제하면 현재 노드에 설정된 IPv4 주소로 bit-twiddling된 값이 실시간 반영 됩니다.

[root@rocky-9 ~]# ll /etc/hostid 
-rw-r--r--. 1 root root 4 Dec 21 16:42 /etc/hostid

[root@rocky-9 ~]# rm /etc/hostid
rm: remove regular file '/etc/hostid'? y

[root@rocky-9 ~]# hostid
14ac0a8c

이렇게 hostid 설정 및 변경 그리고 생성원리에 대해 다루어 보았습니다.

hostid를 노드의 아이덴티티로 삼기 위해선 내부 네트워크 상 동일한 IP가 없는지 , /etc/hostid 파일이 있다면 삭제노드에 할당된 IP정보 기반의 bit-twiddling된 값 이 나타났는지 확인하는 것이 중요한 관리 포인트라 생각합니다.

본 블로그 작성과 관련하여 참조한 자료는 아래와 같습니다.

https://access.redhat.com/solutions/34365

https://access.redhat.com/articles/15452


안녕하세요. 오픈소스컨설팅의 리눅스 엔지니어 정광근입니다.

Leave a Reply

Your email address will not be published. Required fields are marked *