본문 바로가기
Virtualization & Cloud/Network Automation

네트워크 자동화 (Network Automation) - (2)

by TwoJun 2024. 8. 7.
728x90
반응형

2024-08-06(TUE)

 

 

● 금일 예정

(1) Ansible Infra Automation

(2) Configuration Settings(환경 구성)

(3) Ad-hoc Mode

(4) Playbook

 

 

 

 

01. 전일 내용 - Python을 활용한 Automation (Switch Setting)

01-1. UI Setting

(1) UI Drag & Drop은 좌측 Widget Wizard에서 수행

UI Setting

 

(1) 필드 이름 : Label

 

(2) 사용자명 : Text Edit

 

(3) 암호 : LineEdit 

- Password가 입력되므로 Attribute에서 echoMode를 Password로 설정

Password가 입력되므로 Attribute에서 echoMode를 Password로 설정

 

(4) IP Address, VLAN 이름 : Plain Text Edit

 

(5) 시작 및 종료 VLAN : Spin Box

 

 

 

 

01-2. Lab topology (Win10 Pnet Env.)

 

 

 

 

01-3. 스위치 설정

(1) switch03

en 

conf t

no cdp run

no ip domain-lookup

line vty 0 4

password cisco

login local

transport input telnet

username admin password cisco

enable password cisco

end

 

conf t

int vlan 1

ip addr 172.29.109.206 255.255.255.0

no sh

end

 

 

(2) 할당된 부분 확인

 

 

(3) switch04

en 

conf t

no cdp run

no ip domain-lookup

line vty 0 4

password cisco

login local

transport input telnet

username admin password cisco

enable password cisco

end

 

conf t

int vlan 2

ip addr 172.29.109.207 255.255.255.0

no sh

end

 

(4) 할당된 부분 확인

 

 

 

(5) ping test 확인 

- Switch 3에서 전구간 ping check

 

- Switch 4에서 전구간 ping check

 

 

 

 

01-4. 자동화 테스트를 위한 Telnet 접속 확인 

(1) Switch3, Switch4 접속 확인 완료

 

 

 

 

01-5. network_config02.py

from PyQt5 import QtCore, QtGui, QtWidgets
import telnetlib

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 581, 481))
        self.tabWidget.setObjectName("tabWidget")
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
        self.label = QtWidgets.QLabel(self.tab)
        self.label.setGeometry(QtCore.QRect(0, 0, 701, 451))
        self.label.setText("")
        self.label.setPixmap(QtGui.QPixmap("dataCenter.png"))
        self.label.setObjectName("label")
        self.tabWidget.addTab(self.tab, "")
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
        self.label_2 = QtWidgets.QLabel(self.tab_2)
        self.label_2.setGeometry(QtCore.QRect(30, 40, 56, 12))
        self.label_2.setObjectName("label_2")
        self.label_5 = QtWidgets.QLabel(self.tab_2)
        self.label_5.setGeometry(QtCore.QRect(30, 90, 71, 16))
        self.label_5.setObjectName("label_5")
        self.label_6 = QtWidgets.QLabel(self.tab_2)
        self.label_6.setGeometry(QtCore.QRect(40, 200, 71, 16))
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(self.tab_2)
        self.label_7.setGeometry(QtCore.QRect(310, 40, 56, 12))
        self.label_7.setObjectName("label_7")
        self.label_8 = QtWidgets.QLabel(self.tab_2)
        self.label_8.setGeometry(QtCore.QRect(300, 90, 71, 16))
        self.label_8.setObjectName("label_8")
        self.label_9 = QtWidgets.QLabel(self.tab_2)
        self.label_9.setGeometry(QtCore.QRect(300, 130, 81, 16))
        self.label_9.setObjectName("label_9")
        self.Ui_Sw_Password = QtWidgets.QLineEdit(self.tab_2)
        self.Ui_Sw_Password.setGeometry(QtCore.QRect(380, 30, 151, 31))
        self.Ui_Sw_Password.setObjectName("Ui_Sw_Password")
        self.Ui_Sw_VlanStart = QtWidgets.QSpinBox(self.tab_2)
        self.Ui_Sw_VlanStart.setGeometry(QtCore.QRect(390, 90, 91, 22))
        self.Ui_Sw_VlanStart.setMinimum(2)
        self.Ui_Sw_VlanStart.setMaximum(4095)
        self.Ui_Sw_VlanStart.setObjectName("Ui_Sw_VlanStart")
        self.Ui_Sw_VlanEnd = QtWidgets.QSpinBox(self.tab_2)
        self.Ui_Sw_VlanEnd.setGeometry(QtCore.QRect(390, 130, 91, 22))
        self.Ui_Sw_VlanEnd.setMinimum(3)
        self.Ui_Sw_VlanEnd.setMaximum(4095)
        self.Ui_Sw_VlanEnd.setObjectName("Ui_Sw_VlanEnd")
        self.plainTextEdit_2 = QtWidgets.QPlainTextEdit(self.tab_2)
        self.plainTextEdit_2.setGeometry(QtCore.QRect(40, 260, 481, 151))
        self.plainTextEdit_2.setObjectName("plainTextEdit_2")
        self.Ui_Sw_pushButton_2 = QtWidgets.QPushButton(self.tab_2)
        self.Ui_Sw_pushButton_2.setGeometry(QtCore.QRect(390, 200, 75, 23))
        self.Ui_Sw_pushButton_2.setObjectName("Ui_Sw_pushButton_2")
        self.Ui_Sw_pushButton_2.clicked.connect(self.SwitchConfig)
        self.Ui_Sw_Userid = QtWidgets.QTextEdit(self.tab_2)
        self.Ui_Sw_Userid.setGeometry(QtCore.QRect(110, 30, 151, 31))
        self.Ui_Sw_Userid.setObjectName("Ui_Sw_Userid")
        self.Ui_Sw_IpAddress = QtWidgets.QPlainTextEdit(self.tab_2)
        self.Ui_Sw_IpAddress.setGeometry(QtCore.QRect(110, 80, 151, 101))
        self.Ui_Sw_IpAddress.setObjectName("Ui_Sw_IpAddress")
        self.Ui_Sw_VlanName = QtWidgets.QPlainTextEdit(self.tab_2)
        self.Ui_Sw_VlanName.setGeometry(QtCore.QRect(110, 190, 151, 41))
        self.Ui_Sw_VlanName.setObjectName("Ui_Sw_VlanName")
        self.tabWidget.addTab(self.tab_2, "")
        self.tab_3 = QtWidgets.QWidget()
        self.tab_3.setObjectName("tab_3")
        self.userId = QtWidgets.QLabel(self.tab_3)
        self.userId.setGeometry(QtCore.QRect(10, 30, 71, 16))
        self.userId.setObjectName("userId")
        self.label_3 = QtWidgets.QLabel(self.tab_3)
        self.label_3.setGeometry(QtCore.QRect(210, 30, 56, 12))
        self.label_3.setObjectName("label_3")
        self.label_4 = QtWidgets.QLabel(self.tab_3)
        self.label_4.setGeometry(QtCore.QRect(360, 30, 56, 12))
        self.label_4.setObjectName("label_4")
        self.UserID = QtWidgets.QTextEdit(self.tab_3)
        self.UserID.setGeometry(QtCore.QRect(90, 20, 101, 31))
        self.UserID.setObjectName("UserID")
        self.PWDText = QtWidgets.QLineEdit(self.tab_3)
        self.PWDText.setGeometry(QtCore.QRect(250, 20, 101, 31))
        self.PWDText.setEchoMode(QtWidgets.QLineEdit.Password)
        self.PWDText.setObjectName("PWDText")
        self.HOSTIp = QtWidgets.QTextEdit(self.tab_3)
        self.HOSTIp.setGeometry(QtCore.QRect(420, 20, 111, 31))
        self.HOSTIp.setObjectName("HOSTIp")
        self.plainTextEdit = QtWidgets.QPlainTextEdit(self.tab_3)
        self.plainTextEdit.setGeometry(QtCore.QRect(10, 60, 531, 341))
        self.plainTextEdit.setObjectName("plainTextEdit")
        self.RouterBtn = QtWidgets.QPushButton(self.tab_3)
        self.RouterBtn.setGeometry(QtCore.QRect(270, 410, 75, 23))
        self.RouterBtn.setObjectName("RouterBtn")
        self.RouterBtn.clicked.connect(self.RouterConfig)
        self.tabWidget.addTab(self.tab_3, "")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def RouterConfig(self):
        print("RouterConfig")
        print("사 용 자 : ", self.UserID.toPlainText())
        user = self.UserID.toPlainText()
        print("암   호  :", self.PWDText.text())
        password = self.PWDText.text()
        print("Host IP : ", self.HOSTIp.toPlainText())
        HOST = self.HOSTIp.toPlainText()

        tn = telnetlib.Telnet(HOST)

        tn.read_until(b"Username: ")
        tn.write(user.encode('ascii') + b"\n")

        if password:
            tn.read_until(b"Password: ")
            tn.write(password.encode('ascii') + b"\n")

        tn.write(b"enable\n")
        tn.write(b"cisco\n")
        tn.write(b"conf t\n")

        wk_Contents = self.plainTextEdit.toPlainText()
        # 실제 타이핑을 통해 동적으로 설정을 주는 구간
        print(wk_Contents)
        print(type(wk_Contents))
        w_txt = wk_Contents.split("\n")
        print(type(w_txt))
        for data in w_txt:
            print(data)
            tn.write(data.encode('ascii') + b"\n")

        # tn.write(b"int loopback 7 \n")
        # tn.write(b"ip add 7.7.7.7 255.255.255.255 \n")
        tn.write(b"end \n")
        tn.write(b"exit \n")
        print(tn.read_all().decode('ascii'))

    def SwitchConfig(self):
        print("SwitchConfig")
        print("사 용 자 : ", self.Ui_Sw_Userid.toPlainText())
        user = self.Ui_Sw_Userid.toPlainText()
        print("암   호  :", self.Ui_Sw_Password.text())
        password = self.Ui_Sw_Password.text()
        wk_IpAddress = self.Ui_Sw_IpAddress.toPlainText()
        print(wk_IpAddress)
        print(type(wk_IpAddress))
        wk_StartVlan = self.Ui_Sw_VlanStart.value()
        print(wk_StartVlan)
        print(type(wk_StartVlan))
        wk_EndVlan = self.Ui_Sw_VlanEnd.value()
        print(wk_EndVlan)
        print(type(wk_EndVlan))
        wk_VlanName = self.Ui_Sw_VlanName.toPlainText()
        print(wk_VlanName)
        print(type(wk_VlanName))

        wk_ip = wk_IpAddress.split('\n')
        num = 0
        for HOST in wk_ip:
            print(HOST)
            tn = telnetlib.Telnet(HOST)
            tn.read_until(b"Username: ")
            tn.write(user.encode('ascii') + b"\n")
            if password:
                tn.read_until(b"Password: ")
                tn.write(password.encode('ascii') + b"\n")

            tn.write(b"enable\n")
            tn.write(b"cisco\n")
            tn.write(b"conf t\n")
            num += 1
            wk_host = 'hostname switch' + str(num)
            tn.write(wk_host.encode('ascii') + b"\n")

            for num_valn in range(wk_StartVlan,wk_EndVlan+1):
                tn.write(b"vlan " + str(num_valn).encode('UTF-8') + b"\n")
                #tn.write(b"name PYTHON_VLAN_" + str(num_valn).encode('UTF-8') + b"\n")
                tn.write(b"name "  +  wk_VlanName.encode('UTF-8') + str(num_valn).encode('UTF-8') + b"\n")

            tn.write(b"end\n")
            tn.write(b"exit\n")
            print(tn.read_all().decode('ascii'))

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "초기 화면"))
        self.label_2.setText(_translate("MainWindow", "사용자명"))
        self.label_5.setText(_translate("MainWindow", "IP Address"))
        self.label_6.setText(_translate("MainWindow", "VLAN 이름"))
        self.label_7.setText(_translate("MainWindow", "암호"))
        self.label_8.setText(_translate("MainWindow", "시작 VLAN"))
        self.label_9.setText(_translate("MainWindow", "종료 VLAN"))
        self.Ui_Sw_pushButton_2.setText(_translate("MainWindow", "실행"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Switch 설정"))
        self.userId.setText(_translate("MainWindow", "사용자 이름 :"))
        self.label_3.setText(_translate("MainWindow", "암호 :"))
        self.label_4.setText(_translate("MainWindow", "IP 주소 :"))
        self.RouterBtn.setText(_translate("MainWindow", "설정"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Router 설정"))

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

 

 

 

 

 

01-6. 프로그램 실행

 

 

(1) PyCharm 실행 결과

SwitchConfig
사 용 자 :  admin
암   호  : cisco
172.29.109.200
172.29.109.206
172.29.109.207
<class 'str'>
2
<class 'int'>
10
<class 'int'>
automation_
<class 'str'>
172.29.109.200

switchFalse>enable
Password:
switchFalse#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
switchFalse(config)#hostname switch1
switch1(config)#vlan 2
switch1(config-vlan)#name automation_2
switch1(config-vlan)#vlan 3
switch1(config-vlan)#name automation_3
switch1(config-vlan)#vlan 4
switch1(config-vlan)#name automation_4
switch1(config-vlan)#vlan 5
switch1(config-vlan)#name automation_5
switch1(config-vlan)#vlan 6
switch1(config-vlan)#name automation_6
switch1(config-vlan)#vlan 7
switch1(config-vlan)#name automation_7
switch1(config-vlan)#vlan 8
switch1(config-vlan)#name automation_8
switch1(config-vlan)#vlan 9
switch1(config-vlan)#name automation_9
switch1(config-vlan)#vlan 10
switch1(config-vlan)#name automation_10
switch1(config-vlan)#end
switch1#exit

172.29.109.206

switchFalse>enable
Password:
switchFalse#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
switchFalse(config)#hostname switch2
switch2(config)#vlan 2
switch2(config-vlan)#name automation_2
switch2(config-vlan)#vlan 3
switch2(config-vlan)#name automation_3
switch2(config-vlan)#vlan 4
switch2(config-vlan)#name automation_4
switch2(config-vlan)#vlan 5
switch2(config-vlan)#name automation_5
switch2(config-vlan)#vlan 6
switch2(config-vlan)#name automation_6
switch2(config-vlan)#vlan 7
switch2(config-vlan)#name automation_7
switch2(config-vlan)#vlan 8
switch2(config-vlan)#name automation_8
switch2(config-vlan)#vlan 9
switch2(config-vlan)#name automation_9
switch2(config-vlan)#vlan 10
switch2(config-vlan)#name automation_10
switch2(config-vlan)#end
switch2#exit

172.29.109.207

switch1>enable
Password:
switch1#conf t
Enter configuration commands, one per line.  End with CNTL/Z.
switch1(config)#hostname switch3
switch3(config)#vlan 2
switch3(config-vlan)#name automation_2
switch3(config-vlan)#vlan 3
switch3(config-vlan)#name automation_3
switch3(config-vlan)#vlan 4
switch3(config-vlan)#name automation_4
switch3(config-vlan)#vlan 5
switch3(config-vlan)#name automation_5
switch3(config-vlan)#vlan 6
switch3(config-vlan)#name automation_6
switch3(config-vlan)#vlan 7
switch3(config-vlan)#name automation_7
switch3(config-vlan)#vlan 8
switch3(config-vlan)#name automation_8
switch3(config-vlan)#vlan 9
switch3(config-vlan)#name automation_9
switch3(config-vlan)#vlan 10
switch3(config-vlan)#name automation_10
switch3(config-vlan)#end
switch3#exit

 

 

 

(2) Switch console 확인 

- SW

 

 

- SW3

 

- SW4

 

 

- 지금까지 실습한 내용?

(1) privilege mode로 접근하기 위해 사용자 이름 / 암호 확인

(2) 각 장비들에 대해 소프트웨어적으로 설정값들 넣어주고 반영되는지(자동화) 확인

 

 

 

 

 

 

 

1. Ansible Infra Automation

(1) 클라우드 기술이 활성화되면서 Public Cloud 또는 Private Cloud를 사용한다. Cloud Native 기술인 Kubernetes, 오픈시프트와 같은 컨테이너 시스템 사용률도 증가하고 있는데 이러한 상황에서 인프라 관리를 위한 반복작업이 늘어나고 있는 추세이다. 이 부분을 어떻게 해결하면 좋을까?

 

 

1-1. Ansible의 정의와 특징

(1) ansible은 다양하고 고도화된 인프라 관리(Provisioning, Configuration Settings, 애플리케이션 배포 등)를 위해 반복 작업을 수행하는 경우 이러한 부분들을 코드 기반으로 작성하여 여러 환경에 동일하게 적용되게 함으로써 인프라 관리의 업무 생산성에 있어 효율적으로 처리하고 관리하기 위한  오픈소스 기반 자동화 소프트웨어를 말한다.

 

- Ansible은 아래와 같은 주요 특징을 갖는다.

 

(2) Agentless

- 퍼펫, 셰프와 같은 데몬 형식(에이전트에 기반한 자동화 관리 도구, 서버나 특정 환경에 별도 에이전트 도구를 설치해야 함)과 달리 에이전트 설치 없이 SSH로 접속하여 대상 인프라 및 서버를 쉽게 관리한다.

 

(3) Idempotent

- 멱등성은 동일한 연산을 여러 번 적용하더라도 결과값이 달라지지 않는 성질로 주로 컴퓨터 과학(Computer Science), 소프트웨어 공학에서 주로 사용되는 연산 성질을 말한다. Ansible은 멱등성을 기반으로 시스템을 원하는 상태로 표현하고 유지하도록 설계되어 있어서 동일한 작업을 여러 번 실행하더라도 같은 작업을 반환하게 된다.

 

(4) 쉬운 사용법, 다양한 모듈 제공

- 자동화 단계의 경우 YAML 코드 문법만을 사용해 쉽게 작성하고 해석할 수 있다.

- 다양한 모듈 및 컬렉션을 제공해서 보다 쉬운 자동화 작업이 가능하다.

 

 

 

 

1-2. Ansible은 언제 사용할까?

(1) 시스템 환경 설정, 특정 애플리케이션의 설치, Public or Private Cloud 시스템의 가상 서버를 생성하거나 유지보수하는 과정에서 사용할 수 있다.

 

(2) 사용 빈도가 높고 시스템에 동일한 작업(수요가 높은 반복 작업)을 수행해야 할 때 Ansible이 사용된다.

 

(3) 업무 비중에서 반복 작업 수요가 높은 인프라 엔지니어, 개발과 인프라 관리를 모두 맡는 데브옵스 엔지니어, 클라우드 엔지니어처럼 자동화 업무 비중이 높은 직군이 Ansible을 많이 사용한다.

 

 

 

 

1-3. Ansible 구동 환경

Ansible Architecture

 

(1) Linux, MacOS, BSD 계열 Unix, WSL(Windows Subsystem for Linux)을 지원하는 Windows 환경에서 Python, Ansible Core만 설치되어 있다면 어디에서나 Playbook을 작성하고 이를 실행할 수 있다.

 

(2) 이러한 앤서블은 Control node, Managed node로 이루어져 있다.

 

(3) 인벤토리 파일은 제어 노드에서 관리 노드를 서포트하기 위한 설정 정보들이 포함되어 있다.

 

 

 

 

 

 

2. Ansible Architecture

(1) Ansible은 크게 Community Ansible, RedHat Ansible Automation Platform으로 구분된다.

 

(2) Community Ansible은 오픈소스 기반으로 리눅스만 설치되어 있다면 어디에서나 사용할 수 있고 RedHat 계열은 RedHat Subscript를 통해 사용할 수 있다.

 

 

Community Ansible Architecture

 

2-1. Community Ansible

(1) Ansible Architecture는 제어 노드, 관리 노드로 구성된다.

 

(2) 제어 노드(Control Node) 

- 앤서블 코어가 직접적으로 설치되는 노드이다.

 

- 운영체제가 리눅스라면 제어 노드가 설치될 수 있고 앤서블은 파이썬 모듈 기반이기 때문에 파이썬이 설치되어야 한다.

 

 

 

(3) 관리 노드(Managed Node)

- 앤서블이 직접적으로 제어하는 원격 시스템 또는 호스트를 의미한다.

 

- 리눅스 또는 윈도우가 설치된 노드일 수 있으며 public cloud or private cloud 시스템에서 생성한 가상 머신일 수도 있다.

 

- 관리 노드는 제어 노드와 SSH 통신이 가능해야 하며 파이썬 설치가 필수적이다.

 

 

 

(3) 인벤토리(Inventory)

- 인벤토리는 제어 노드가 관리하는 관리 노드의 집합을 나열해 놓은 파일을 의미한다.

 

- 앤서블은 인벤토리에 명시된 관리 노드에만 접근 가능하다.

 

 

- 인벤토리 목록은 관리 노드의 특징 및 성격별로 그룹핑이 가능하다.

 

 

(4) 모듈(Module)

- 관리 노드의 작업을 수행할 때 SSH를 통해 연결 후 앤서블 모듈(Ansible Module)이라는 스크립트를 통해 작동한다.

 

- 시스템 상태를 설명하는 매개변수를 허용하고 모듈 실행 완료 시 제거된다.

 

 

(5) 플러그인(Plug-in)

- 앤서블의 핵심 기능을 강화한다.

 

- 모듈이 대상 시스템에서 별도의 프로세스로 실행되는 동안 플러그인은 제어 노드에서 실행된다.

 

- 플러그인은 데이터 변환, 로그 출력, 인벤토리 연결 등 핵심 기능에 대한 옵션 및 확장 기능을 제공한다.

 

 

(6) 플레이북(Playbook)

- 관리 노드에서 수행할 작업을 YAML 문법을 통해 순서대로 작성해 놓은 파일을 의미한다. 플레이북을 활용해 SSH로 관리 노드에 접근하고 작업을 수행하게 된다.

 

- 자동화를 완성하는 주요 파일이며 사용자가 직접 작성한다.

 

 

 

 

 

2-2. RedHat Ansible Automation Platform

 

(1) Community와 RedHat의 Component는 동일하다

 

(2) 하지만 RedHat Ansible Automation Platform에는 커뮤니티와 다른 제어 노드에 대한 인증 정보, 실행 환경 등을 관리하는 CMDB가 존재한다.

 

(3) 이러한 자원을 관리하기 위한 별도의 UI가 존재하고 REST API를 제공하고 있다.

 

(4) RedHat Ansible Automation Platform은 크게 3가지 Required Component와 1개의 Optional Component로 구성된다.

- Automation Controller : Ansible 관리 웹 UI

- 실행 환경 : Ansible Module, Plugin이 존재하는 컨테이너 기반의 실행환경

- PostgreSQL : 인벤토리, 인증 정보, 실행환경 등의 메타 데이터를 관리하는 RDBMS 기반의 CMDB

- Automation Hub(Optional) : RedHat에서 기술지원을 받을 수 있는 서비스

 

 

 

 

2-3. Chapter II Summary

(1) 앤서블은 기본적으로 제어 노드, 관리 노드로 구성되어 있다.

 

(2) 인벤토리는 관리 노드의 집합이다.

 

(3) 플레이북은 수행해야 할 작업을 정의해 놓은 파일이다.

 

(4) 앤서블은 별도의 에이전트(작업 및 관리를 위한 별도의 도구) 없이 SSH 통신을 통해 작업을 수행한다.

 

 

 

 

 

 

 

3. Ansible Practice(Lab) Environment Settings

3-1. Virtual Machine을 통한 Lab 구성

 

(1) 가상 머신 네이밍

ywj-ansible-S

ywj-tnode1

ywj-tnode3

 

 

 

 

3-2. Control Node 구성

(1) 실습 장비 : DELL EMC(Enterprise Level Server)

(2) 가상화 소프트웨어 : VMWare ESXi

 

(1) 가상 머신에 대한 구성 정보를 설정한다.

 

 

(2) 가상 머신을 부팅하고 설정된 부팅 이미지로 부팅한다.

 

 

 

(3) 시간 및 날짜 영역에선 아시아/서울 선택

 

 

 

(4) 설치 환경의 경우 워크스테이션, 기능 설정은 시스템 툴을 선택한다.

 

 

 

(5) KDump 설정은 활성화하지 않는다.

 

 

 

 

(6) IP 주소, 호스트 이름을 위와 같이 할당한다.

 

 

 

(7) 최종 설치 Progress Bar가 진행되는 동안 Root Password, User Creation을 클릭해서 루트 암호, 사용자 정보를 입력하고 설치를 기다린다.

 

 

 

(8) 설치 완료 후 재부팅을 완료하고 마지막 약관 동의까지 완료한다.

 

(9) 로그인 화면에서 root 계정으로 변경한 후 비밀번호 입력 → 로그인 수행 → 한국어 설정 → 여러 가지 정보를 체크하고 로그인을 완료한다.

 

 

 

 

3-3. 제어 노드에 대한 인터페이스 주소 대역 확인

 

 

 

 

 

3-4. 첫 번째 관리 노드 설치 및 환경설정(CentOS, tnode-1)

(1) Thick Provisioning(씩 프로비저닝)

- 스토리지 프로비저닝에서 사용되는 용어로, 우선 스토리지 프로비저닝이란 하드디스크나 SSD와 같은 물리적 장치의 스토리지 공간을 각 클라이언트의 요청만큼 직접적으로 할당하는 작업을 의미한다.

 

- 특정 공간을 할당받고 일부분만 사용하고 있다면 나머지 공간은 따로 놀고 있는 셈이므로 낭비가 발생하는데 이 부분이 씩 프로비저닝 방식의 단점이라고 볼 수 있다.

 

 

(2) Thin Provisioning(씬 프로비저닝)

- 씬 프로비저닝 방식의 경우 클라이언트가 현재 실제로 사용 중인 만큼의 공간이 할당되는 스토리지 프로비저닝 방식을 말한다.

 

- 씬 프로비저닝은 저장공간을 보다 효율적으로 관리하기 위한 기술로, 스토리지 관리자나 시스템이 물리적인 저장공간을 실제로 필요할 때까지 할당하지 않는 방식이다. 이 기술을 사용하면 각 클라이언트에게 논리적으로는 특정 공간을 할당하지만, 물리적으로는 그 클라이언트가 실제로 사용하는 만큼만 공간을 할당하게 된다.

 

 

 

(3) tnode-1도 제어 노드에서 설정한 것처럼 위와 같이 동일하게 설정을 진행하고 설치를 진행한다.

 

 

(3) 설치를 완료 후 재부팅하고 약관 동의 → 로그인 페이지 과정에서 test 계정으로 로그인한다.

 

(4) 기타 설정을 끝내고 터미널을 열어서 인터페이스에 부여한 주소 대역과 동일한지 확인한다.

 

 

 

 

3-5. 두 번째 관리 노드 설치 후 환경설정 (CentOS, tnode-3)

(1) 마지막 관리 노드의 설치를 진행한다. 두 번째 관리 노드에 맞는 주소 대역을 설정하고  터미널에서 ifconfig 명령으로 정상적으로 주소 대역이 반영되었는지 확인한다.

 

(2) 위와 같이 정상적으로 반영된 것을 확인할 수 있었다. 

 

 

 

 

 

 

4. Reference

(1) Ansible로 시작하는 인프라 자동화(Infrastructure Automation)

https://www.hanbit.co.kr/store/books/look.php?p_code=B2465301723

 

앤서블로 시작하는 인프라 자동화

“효율적인 IT 자동화를 위한 도구, 앤서블”

www.hanbit.co.kr

 

※ 해당 포스팅에 대해 내용 추가가 필요하다고 생각되면 기존 포스팅 내용에 다른 내용이 추가될 수 있습니다.

개인적으로 공부하며 정리한 내용이기에 오타나 틀린 부분이 있을 수 있으며, 이에 대해 댓글로 알려주시면 감사하겠습니다!

728x90
반응형

댓글