메인 콘텐츠로 건너뛰기
블로그 리눅스릴리스 일: 리눅스 배포판 자동화 (특징 Ubuntu 20.04)

출시일: Linux Distro 자동화 (Ubuntu 20.04 기능)

automating-distributions

​안녕! 저는 Linode의 시스템 엔지니어인 브래드 (Brad)입니다. 오늘은 가장 인기 있는 배포판 중 하나인 LTS (장기 지원) 버전인 Ubuntu 20.04가 출시되는, Linux 세계의 행복한 날입니다. 2년 전 Ubuntu 18.04와 마찬가지로 이것이 이미 모든 Linode 고객이 사용할 수 있는 가장 널리 배포된 이미지가 될 것으로 기대하고 있습니다.

Linode에서는 새로운 이미지를 빌드, 테스트 및 배포하기 위해 개발한 자동화 덕분에 당일 배포 가용성이 표준이 되었습니다. 그러나 이미지 (또는 템플릿 이라고도 함)는 무엇이며 이를 만드는 데 무엇이 필요한가요? 이 질문에 답하기 위해 OS 설치가 일반적으로 작동하는 방식부터 살펴보겠습니다. ​

OS 설치

가정용 컴퓨터 또는 서버에 운영 체제를 수동으로 설치하는 프로세스에 익숙할 수 있습니다. 일반적으로 설치 ISO를 다운로드한 뒤, CD 또는 USB 드라이브에 굽고 여기에서 시스템을 부팅합니다. 여기에서 어떤 하드 드라이브에 설치할지, 어떤 소프트웨어 / 패키지 등을 포함할지, 사용자 이름, 비밀번호 등을 커스텀 할지 등의 다양한 측면을 제어할 수 있는 일련의 메뉴 (또는 수동 명령)을 실행합니다. 모든 작업이 완료된 후에는 부팅만 하면 사용할 수 있는, 완전히 작동하는 OS를 갖게 됩니다.

이 프로세스는 일회성 설치를 수행하는 개별 사용자에게 잘 작동하지만, 소수의 시스템 이상을 설치해야 하는 경우에는 수동 설치 프로세스는 불가능합니다. 이제 이미지가 필요한 과정입니다. ​

이미지란?

이미지는 기본적으로 필요한 만큼 많은 시스템에 배포할 수 있는, 사전 설치가 된 OS입니다. 일반 설치를 한 번 수행 한 다음 나중에 다른 시스템에 "붙여 넣기"할 수 있는 해당 설치의 복사본을 만들어 작동합니다. 나중에 사용하기 위해 이미지를 저장할 수 있는 다양한 방법과 형식이 있지만, 대부분의 경우 원본 설치의 정확한 바이트 단위 사본입니다.

이제 수동 설치를 한 번만 수행하면 다른 모든 곳에서 다시 사용할 수 있습니다. 그러나 우리는 여전히 더 잘할 수 있습니다. Linode는 일반적인 서스펙트 (Debian, Ubuntu, CentOS, OpenSUSE)에서 다른 공급자 (Alpine, Arch, 심지어 Gentoo)에서는 찾을 수 없는 것에 이르기까지 다양한 배포를 지원합니다. 각각 고유한 릴리스 일정과 지원 수명이 있습니다. 지원되는 모든 배포판에 대해 수동 설치를 수행하고 (단 한 번이라도), 결과 이미지가 작동하고 실수가 없는지 확인하면 엄청난 시간이 걸리고 사고가 발생하기 쉽습니다. 대신 HashiCorp에서 만든 Packer라는 멋진 도구를 사용하여 이미지 구축 프로세스 자체를 자동화하기로 선택했습니다. ​

빌드 자동화

모든 Linux 배포판은 공통 기반 (즉, Linux 커널)을 공유하지만, 설치 방법을 포함힌 모든 것이 서로 매우 다릅니다. 일부 배포판은 명령 줄 지침을 사용하고, 일부는 메뉴 인터페이스를 사용하며, 일부는 해당 메뉴를 자동으로 탐색하고 답변을 제공하는 방법을 포함합니다. 다행히도 Packer는 매우 다재다능한 도구이며 이러한 모든 사용 사례를 처리할 수 있습니다.

가장 먼저 할 일은 Packer에게 가능한 한 Linode와 유사한 가상 머신 (또는 VM)을 생성하도록 지시하는 것입니다. 이는 실제 Linode에 사용하는 것과 동일한 "하드웨어" 및 기능을 에뮬레이트하는 것을 의미합니다. 이렇게 하면 최종 런타임 환경과 매우 유사한 환경에서 설치가 수행됩니다. USB 드라이브에 OS를 설치한 다음 해당 드라이브를 사용하여 완전히 다른 컴퓨터를 부팅한다고 상상해보십시오. 운이 좋으면 문제가 해결될 수도 있지만, 하드웨어 장치가 감지되지 않거나 전혀 부팅되지 않을 수도 있습니다. 실제 실행 환경과 일치하는 설치 환경을 갖춤으로써 이러한 문제를 제거합니다.

VM이 생성되면 Packer는 지정된 URL에서 가져오는 배포판의 설치 ISO에서 VM을 부팅합니다. 여기서의 프로세스는 배포판마다 크게 다릅니다. Arch와 같은 명령 기반 배포판의 경우 기본 설치를 수행하는 bash 스크립트를 제공합니다. Ubuntu와 같은 메뉴 기반 배포판의 경우 설치 프로그램에 대한 답변을 제공하는 배포판에서 선호하는 방법을 사용합니다 (일반적으로 Debian과 유사한 배포판의 Preseed 또는 RHEL과 같은 배포판의 Kickstart). VM 외에도 Packer는 필요한 파일을 VM으로 전송할 수 있는 작은 HTTP 서버를 만듭니다. ​

이 모든 것은 Packer가 사용할 설정 및 빌드 옵션을 정의하는 JSON 파일을 통해 제어됩니다. 빌드를 시작하려면 다음을 실행하기만 하면 됩니다 (예: packer build ubuntu-20.04.json.

커스터마이징

대부분의 경우 가능한 한 기본적인 설치를 수행합니다. 이것은 주어진 배포판이 "기본" (때때로 "베이스" 또는 "표준"이라고도 함)으로 간주하는 패키지를 설치하는 것을 의미합니다. 이러한 기본 패키지 외에도 발생할 수있는 문제를 디버깅하는 데 도움이 될 수있는 iotop, mtr 및 sysstat와 같은 기본 유틸리티 인 "지원" 패키지 중 일부도 설치합니다. 결과적으로 Linode 지원팀은 고객을 지원하면서 이러한 도구가 설치되었다고 합리적으로 가정할 수 있습니다.

설치가 완료된 후 VM이 종료되기 전에 Linode 플랫폼의 모든 기능을 사용하여 적절한 기능을 보장하기 위해 몇 가지 최종 사용자 지정을 수행합니다. 예를 들어 부트 로더가 LISH (대역 외 콘솔 액세스를위한 도구)에 대한 올바른 설정으로 구성되었는지 확인합니다. 일반적으로 우리는 가능한 한 기본값에 가깝게 유지하려고 노력합니다. 이렇게 하면 특정 배포판을 선호하는 사용자는 익숙한 정보를 얻을 수 있으며 다른 사람의 차를 운전하는 느낌이 들지 않습니다.

패키징

설치 및 구성이 완료되면 Packer는 VM을 종료하고 디스크 이미지를 파일로 내보냅니다. 완료된 것처럼 들릴 수 있지만, 아직 몇 단계가 남아 있습니다. 일반 컴퓨터의 하드 드라이브는 파티션 테이블 (최신 시스템에서는 MBR 또는 GPT)로 시작됩니다. Linode는 GRUB 부트 로더 자체가 실제로 각 Linode가 아닌 호스트에 있다는 점에서 약간 독특합니다 (그러나 구성은 여전히 Linode에서 읽음). 이것은 실제로 파티션 테이블을 완전히 제거하여 단일 파티션만 남길 수 있음을 의미합니다.

이를 수행하기 위해, 우리는 다음을 실행합니다. fdisk -l disk.img 디스크 이미지에서 파티션이 시작되고 끝나는 위치와 블록 크기를 결정합니다. 그런 다음 dd if=disk.img of=part.img bs=### skip=### count=### 이전 명령의 시작 오프셋을 사용하여 파티션을 "포크 리프트" 합니다. 보다 구체적으로 말하자면, 해당 명령의 각 "###"은 fdisk 이전 명령으로 교체됩니다.

새 컴퓨터에서와 마찬가지로 드라이브의 대부분의 공간이 비어 있으며 이는 디스크 이미지에 반영됩니다. 이러한 "빈" 바이트를 모두 복사하는 것은 어리석은 일이므로 다음 작업은 꺾는 것입니다 이미지 (나중에 Linode에 이미지를 배포 할 때 다시 팽창시켜 인스턴스에서 사용 가능한 공간을 채웁니다). 모든 이미지가 ext4 파티션을 사용하기 때문에 다음을 실행할 수 있습니다. resize2fs -M part.img, 빈 공간을 제거하여 이미지를 가능한 가장 작은 크기로 자동 축소합니다. 마지막으로 결과 이미지의 무결성을 보장하기 위해 최종 fsck 압축하기 전에 ​함께 gzip.

테스팅

이미지를 빌드하고 준비한 후 프로세스의 다음 단계는 실제로 작동하는지 확인하는 것입니다. 새로 생성된 이미지는 테스트 환경에 배포되며, 여기서 여러 Linode 인스턴스가 다양한 구성으로 이미지에서 프로비저닝됩니다. 우리는 네트워크 연결 및 작동하는 패키지 관리자와 같은 모든 종류의 다른 사항과 백업 및 디스크 크기 조정과 같은 Linode 플랫폼의 다양한 기능을 확인하는 자동화된 테스트 스위트를 개발했습니다. 검사가 실패하면 프로세스가 즉시 중단되고 빌드가 실패하고 검사가 실패한 이유와 실패한 이유에 대한 세부 정보가 함께 제공됩니다.

이와 같이 자동화된 방식으로 빌드하고 테스트하면 빠른 개발주기가 가능해져 더 나은 이미지를 더 빨리 출시할 수 있습니다. 우리는 새로운 검사를 추가하는 것이 사소한 것처럼 테스트 프로세스를 구성했습니다. 고객이 지금 우리의 이미지 중 하나에 문제를 보고하면 우리는 신속하게 수정을 해제 할 수 있고 우리의 성장 검사 목록에 다른 항목을 추가하여 거의 면역 시스템처럼 설계할 수 있습니다! ​

동일하지만 다릅니다

공통 이미지에서 시스템을 대량으로 배포하는 것은 좋지만, 루트 암호 또는 네트워킹 구성과 같이 특정 인스턴스에 고유한 사항들은 어떻게 합니까? 기본적으로 이미지는 DHCP를 사용하도록 구성되어 있음으로 시스템이 할당된 IP 주소와 DHCP 서버에서 고유한 호스트 이름을 자동으로 수신하게 됩니다. 그러나 우리는 또한 네트워크 도우미 (Linode에서 정적 네트워킹을 자동으로 구성)와 같은 다양한 "도우미" 및 루트 암호 재설정 도구 (초기 루트 암호를 재설정하고 다음과 같은 경우에도 사용할 수 있음)를 제공합니다. 이러한 도구를 사용하면 기본 이미지 위에있는 Linode에 인스턴스 별 정보를 적용 할 수 있습니다.

물론 모든 배포판이 동일한 방식으로 이러한 작업을 처리하는 것은 아니므로 도구는 지원되는 모든 배포판에서 이러한 작업을 수행하는 방법을 알고 있어야 합니다. 배포판의 새로운 주요 버전은 일반적으로 완전히 작동하기 위해 이러한 시스템에 대한 일부 업데이트가 필요합니다. 예를 들어, Debian은 일반적으로 다음에서 네트워킹을 구성합니다. /etc/network/interfaces, CentOS는 네트워크를 다음에 구성합니다 /etc/sysconfig/network-scripts. 다행스럽게도 대부분의 배포판은 베타 릴리스를 미리 제공하므로 이러한 변경 작업을 수행하고 모든 것이 출시일을 준비할 수 있도록 충분한 시간을 제공합니다. ​

결론

보시다시피 새로운 배포판을 지원하는 데 많은 것들이 있습니다. 그렇다면 이 프로세스를 자동화하는 것의 진정한 이점은 무엇일까요? 글쎄요, 우리가 오늘날의 프로세스를 갖기 몇 년 전에 일반적인 배포판 릴리스 (빌딩에서 테스트, 가용성까지)는 최소 하루 종일 걸리지만, 일반적으로 며칠이 걸리며 많은 사람들이 참여해야 했습니다. 이에 비해 오늘의 Ubuntu 20.04 릴리스에는 5줄의 코드 변경만이 필요했고, 처음부터 끝까지 1시간도 채 걸리지 않았습니다. 이러한 이미지 빌드 방식은 많은 시간과 번거로움을 줄여주며 철저한 테스트를 거친 일관된 빌드를 제공합니다. 또한 지속해서 개선됩니다. 어떤 제안이나 보고 싶은 것이 있으면 알려주세요! 나는 OFTC의 blaboon과 Freenode의 lblaboon으로 IRC에서 놀고 있습니다. Packer를 직접 사용 해보고 싶다면 여기 에서 찾을 수 있는 훌륭한 문서가 있습니다. 우리는 또한 우리 플랫폼에서 자신만의 맞춤형 이미지를 만드는 데 사용할 수 있는 Packer 용 Linode 빌더를 보유하고 있습니다. Packer 용 Linode 빌더 사용에 대한 추가 문서는 가이드 및 튜토리얼 라이브러리 여기에서 찾을 수 있습니다.


Linode 고객이 아니십니까?  여기에서 $20 크레딧으로 가입하세요.

댓글 (4)

  1. Author Photo

    This is brilliant and very timely (for me) as I happened to spend some of last weekend to “reverse engineer” the build process (and discovered the GRUB config quirks) while tried to test migrating a Linode VM over to a on-premises (lab) VM Host and vice versa. Maybe this would be a good write-up, if you are searching for tutorial/blog topics. Many thanks for publishing this!

  2. Nathan Melehan

    Hey A. –

    That sounds like a cool topic! If you’re interested, we actually have a paid freelance contributor program for our documentation library called Write For Linode. You can learn more about the program and apply to it here: https://www.linode.com/lp/write-for-linode/

    • Author Photo

      Hi Nathan
      Thanks for this, it looks very tempting. I started to work on the process for the first migration but I was stopped by Grub2. As described in the Packaging section above, the stripped out boot partition stops me to boot up the the image in my VM Host and I haven’t been able boot up the image dd’d out of Linode. If I create a vanilla VM image with the same Ubuntu version as in my Linode VM, the (virtual) disk is partitioned with two partitions, sda1 hosting grub (I assume this is what you strip out in the build process) and sda2, which is “/”. The image “exported” out of Linode, on the other hand has only a single partition as described above. Is there any documentation describing how to undu the stripping out of sda1, or how insert a new boot (sda1) partition back into the image? Many thanks, A

      • Author Photo

        Ok, I managed to get through booting my local clone in the end and it turns out that the startup process didn’t crash (as I thought), it was just slow*. It is because (unsurprisingly) it has a hard-coded static IP address which now lives on the wrong network, so I had to wait until the network config time-out* during the boot-up process.

        That’s easy enough I’ll just change the config in /etc/network/interfaces (the default/standard place in Ubuntu, and as also mentioned in this article). Looking at the “interfaces” file it, is blank with a note that things have moved on (since I last had to deal with linux networking) and it is now handled by something called “netplan”. [grrrrr….]

        No matter, it can’t be that hard, let’s see what /etc/netplan says. Well, the yaml file says my ethernet interface should be called `enp0s3` and should be getting the address from dhcp. But my actual interface name is `eth0` and has a static address. Where is this coming from?! [&$#^%#]

        Time to “brute force” search the entire config.
        `find /etc/ -exec grep ‘12.34.56.78’ {} \; 2>/dev/null` results in 3 hits, one is by an application so there are only two potential places to change, it might be easy enough to check**:

        `grep -Rn ‘12.34.56.78’ * 2>/dev/null`

        systemd/network/05-eth0.network
        systemd/network/.05-eth0.network

        It was auto-generated by Linode’s Network Helper (as described in the article) which is not available in my lab, unsurprisingly, so let’s just copy back the original config:

        `cp 05-eth0.network 05-eth0.network.bak`
        `cp .05-eth0.network 05-eth0.network`
        `shutdown -r now`

        Bingo!!! The VM came up with a new dynamic IP address and I can ping and nslookup to my heart content!!! I haven’t checked if the actual web application survived the extraction, and what else may have broken in the process.

        *and probably a lot more linode specific configs that are inaccessible to my local clone.
        **The actual IP address is not this

        Lessons learned: It is a lot more complicated to migrate out of Linode to a local VM or different cloud and require a lot of effort to fix/adapt the extracted application and the OS, it would be a lot faster just to build the lab up from the ground up. It might be a simpler process to move the other way around (i.e. develop in my own lab and pull the result into Linode) but wouldn’t hold my breath trying.

        Not sure if my experience warrants an article beyond this (chain of) comment(s). But it was a great weekend project and an inspirational learning exercise, many thanks, Linode!

댓글 남기기

이메일 주소는 게시되지 않습니다. 필수 필드가 표시됩니다 *