Overview

0. 목차

1. Multus CNI

Multus CNI는 Kubernetes Pod에 복수개의 NIC를 등록할 수 있는 CNI 입니다.

일반적으로 각 Kubernetes Pod는 loopback을 제외한 하나의 Network Interface를 가지고 있습니다. 그러나 Multus를 사용하면 복수개의 Interface를 가진 Multi-homed Pod를 생성할 수 있습니다. 이는 다른 CNI 플러그인을 호출할 수 있는 Multus의 "Meta-plugin"을 통해 이루어집니다.

따라서 Kubernetes에서는 기본적으로 단일 CNI 플러그인(Calico, Cilium, Flannel...)만 사용이 가능하나, Multus CNI를 사용하게 되면 Pod 내의 여러개 NIC를 추가할 수 있습니다.

1.1 Multi-homed Pod

아래 사진은 Multus CNI를 통해 프로비저닝된 Pod의 CNI 아키텍처 입니다.

위 아키텍처는 Pod가 3개의 Interface를 가진것을 보여주는데, 각각 eth0, net0, net1 입니다.

  1. eth0 : Kubernetes의 API-Server, kubelet과 같은 K8s 서비스, 서버와 통신하기 위한 Interface
  2. net0, net1 : 추가적으로 생성된 Network Interface이며, VLAN, VXLAN, PTP와 같은 다른 CNI 플러그인을 사용하여 다른 네트워크에 연결됩니다.

상세 Multus Plugin 구성은 다음과 같습니다.

Multus Plugin을 통해 Flannel CNI와 IPVLAN을 사용하게끔 설정합니다. 해당 설정은 NetworkAttachmentDefinition(줄여서 net-attach-def)를 통해 이루어지며, 이는 Kubernetes에서 추가적인 네트워크 인터페이스를 정의하는 객체입니다.

Pod 첫번째 NIC eth0 :

  • Flannel CNI를 사용하여 pod CIDR로 IP대역을 할당 받고, vxlan overlay 통신을 사용합니다. 노드의 enp0s8과 매핑됩니다.
  • Pod 두번째 NIC net1 :*
  • IPVLAN plugin 사용으로 net-attach-def에서 설정한 IP 대역을 할당 받고 VLAN L2통신을 사용합니다. 노드의 enp0s9와 매핑됩니다.

2. 기능 List

아래 명시된 기능은 NetworkAttachmentDefinition 를 정의하여 사용이 가능합니다.

2.1 Multus에서 지원하는 CNI List

참고 Link-CNI

  • bridge plugin : 브릿지 환경 제공
  • host-device : dpdk driver 를 컨테이너에 binding
  • ipvlan plugin : L2/L3 모드 제공, 노드에 파드들은 모두 동일한 MAC 주소 사용, DHCP 사용 불가
  • macvlan plugin : L2 모드 제공, 노드에 파드별로 각기 다른 MAC 주소 사용, DHCP 사용 적합
  • ptp plugin : 컨테이너 끼리 1:1 연결
  • win-bridge plugin (windows specific) : 브릿지 환경 제공
  • win-overlay plugin (windows specific) : 오버레이 환경 제공

2.2 IPAM Plugin

Pod에 IP 주소 할당을 관리합니다.

참고 Link

  • dhcp plugin : DHCP 데몬(서비스)를 통해서 파드에 IP를 자동 할당
  • host-local IP address management plugin : host-local databases 에서 파드에 IP 할당
  • static IP address management plugin : 컨테이너에 IPv4/IPv6 를 직접 설정
    → 3rd party IPAM 사용 가능 : Whereabout IPAM 등

2.3 ETC

  • tuning : sysctl parameters 값 변경 설정
  • portmap : An iptables-based portmapping plugin , 컨테이너의 통신에 관련하는 일부 iptables rules 설정
  • bandwidth : traffic control tbf (ingress/egress) 를 통한 대역폭 제한(bandwidth-limiting)
  • sbr : source based routing, 소스 기반 라우팅 관련 설정 → 트래픽 통신 경로 분리에 유리 ⇒ 추후에는 VRF 기능으로 발전 예정
  • firewall : iptables or firewalld 에 rules 추가를 통한 컨테이너 in/out 트래픽 통제

3. Multus 사용 방법

Multus는 위 기능 List에 명시된 기능을 사용하기 위해 아래와 같은 WorkFlow를 가집니다.

  1. NetworkAttachmentDefinition 생성
  2. Pod에 Annotation으로 NetworkAttachmentDefinition 등록

3.1 예시

MACVLAN을 사용하여 Pod에 추가 NIC를 설정하는 NetworkAttachmentDefinition

  • type: "macvlan" → Multus를 통해 MACVLAN CNI 플러그인을 사용
  • master: "eth0" → 물리 네트워크 인터페이스와 연결
  • mode: "bridge" → MACVLAN을 브릿지 모드로 설정
  • ipam → IP 주소 할당을 위해 Static IP 사용
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: macvlan-net
spec:
  config: '{
    "cniVersion": "0.3.1",
    "type": "macvlan",
    "master": "eth0",
    "mode": "bridge",
    "ipam": {
      "type": "static",
      "addresses": [
        {
          "address": "192.168.1.100/24",
          "gateway": "192.168.1.1"
        }
      ]
    }
  }'

Pod에서 생성한 NetworkAttachmentDefinition를 사용하도록 annotation 추가

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  annotations:
    k8s.v1.cni.cncf.io/networks: macvlan-net
spec:
  containers:
    - name: my-container
      image: busybox
      command: ["sleep", "3600"]

4. Calico vs. Multus: 역할과 차이점

calico와 Multus를 비교하는 것은 기능별 관점이 너무 상이하여 기능별 비교는 의미가 없습니다. 그러나 함께 사용되는 주체로써 이해를 돕기 위해 비교해 보면 다음 표와 같습니다.

Calico Multus
주요 역할 네트워크 정책(보안) 및 라우팅 제공 여러 개의 CNI 플러그인을 Pod에 연결
CNI 플러그인 유형 기본 CNI (Primary CNI) 메타 CNI (Meta CNI)
주 기능 - Pod 네트워크 제공 (IP 할당)
- 네트워크 정책 (NetworkPolicy) 적용
- BGP를 통한 클러스터 외부와 연결
- 한 개 이상의 네트워크 인터페이스를 Pod에 추가할 수 있도록 함
- Bridge, IPVLAN, MACVLAN 등의 CNI 플러그인을 함께 사용할 수 있게 해줌
Pod 인터페이스 eth0 하나만 생성 (단일 네트워크) 여러 개의 인터페이스(eth0, net1, net2 등)를 Pod에 추가 가능
사용 예시 - Kubernetes에서 기본 네트워크 설정
- 네트워크 정책을 적용하여 보안 강화
- BGP/Overlay 모드를 활용하여 노드 간 트래픽 관리
- Multi-Homed Pod (여러 네트워크 인터페이스 필요할 때)
- SR-IOV, DPDK, MACVLAN, IPVLAN 같은 특정 CNI 플러그인 사용
사용 방식 단독으로 사용 가능 (기본 네트워크 플러그인) Calico, Flannel 등과 함께 사용 (추가 네트워크용)
추가 설명 Kubernetes 클러스터에서 가장 많이 사용되는 기본 CNI 플러그인 중 하나 Pod 내 여러 네트워크 인터페이스를 추가할 수 있도록 보조 역할 수행

Calico는 기본 CNI로 사용하며, Multus는 여러 CNI를 추가할 수 있도록 도와주는 메타 CNI
Multus는 자체적으로 네트워크를 제공하지 않고, 다른 CNI(예: Calico, Flannel, MACVLAN 등)를 사용함
따라서 Multus는 Calico와 경쟁하는 것이 아니라, 함께 사용할 수 있음

5. 사용 사례

  1. 호스트의 다른 Network Interface에 접근해야 할 때
  2. Pod 별 IP 대역을 분리하는 등의 고급 네트워킹 정책이 필요할 때(타 CNI도 지원할 수 있으니 요구사항 정제하여 확인필요)
  3. 사내 컴플라이언스를 지키기 위해 외부 네트워크 통신과 내부 통신을 격리시켜야 할 때

6. 클라우드 별 Multus 사례

Multus CNI는 Kubernetes 환경에서 단일 Pod에 여러 네트워크 인터페이스를 연결하여 고급 네트워크 구성을 가능하게 하는 오픈 소스 CNI 플러그인입니다. 이는 특히 트래픽 분리, 패킷 가속화, 그리고 특정 네트워크 요구 사항을 충족시키기 위해 사용됩니다. 아래는 Multus CNI를 활용한 몇 가지 실제 사례입니다.

  1. AWS EKS에서 Multus 지원
    Amazon Elastic Kubernetes Service(EKS)는 Multus CNI 플러그인을 지원하여 Pod에 다중 네트워크 인터페이스를 첨부할 수 있도록 합니다. 이는 5G 및 스트리밍 네트워크와 같은 고급 네트워킹 구성이 필요한 사용 사례에서 유용합니다.

  2. Oracle OKE에서 SR-IOV와의 통합
    Oracle Kubernetes Engine(OKE)은 Multus와 SR-IOV(Single Root I/O Virtualization) CNI 플러그인을 활용하여 Pod에 고성능 네트워크 인터페이스를 제공합니다. 이를 통해 네트워크 집약적인 워크로드에서 성능을 향상시킬 수 있습니다.

  3. Red Hat OpenShift에서 Multus 활용
    Red Hat의 OpenShift는 Multus CNI를 사용하여 Pod에 여러 네트워크 인터페이스를 연결하는 기능을 제공합니다. 이를 통해 다양한 네트워크 요구 사항을 가진 애플리케이션을 효과적으로 지원할 수 있습니다.

일시 : 20250319

대상 : 전사 임직원

주제 : CI/CD 소개와 사례

위치 : 회사 사옥

발표 시간 : 20분


우리 회사는 매주 수요일마다 전 사원이 참석하는 교육 발표 시간이 있다

 

발표 시간은 총 1시간 정도로,, 사내 임직원이 모두 발표자 혹은 청중이 되는 자리다.

*발표자가 몇 명이냐에 따라 1시간을 나눠서 쓴다. 대부분 20분 정도 되는 듯하다

 

전국 모든 지사 직원들과, 임원이 참여하는 자리이니만큼 주제 선정과 발표 자료 작성에 공을 들인다.

 

엔지니어부터 영업, 컨설팅 등 많은 직무의 인원이 참석한다.

그래서 너무 기술적인 내용보단, 기술을 바탕으로 한 비즈니스적 측면과 사례에 중심을 두는 편이다.

 

좋은 기회로, 발표를 진행했다.

 

CI/CD의 개념, MSA와의 상관관계, 팀내 프로젝트 주요 사례 등을 소개하였으며 비즈니스적으로 어떠한 부분을 고려해야 할지도 전달했다.

*팀의 비전과 목표도 추가했다

 

사실, 초기 발표 자료 작성 시 나름 기술적 내용을 제외한다고 했으나,, 몇 번을 반려당했다.

 

지금 생각해 보면, 듣는 청중과 PT의 목적을 정확히 파악하고 핵심 주제를 넣엇어야 하나,, 너무 개요와 이론 부분이 주저리주저리였다.

 

그렇게 몇 번을 다시 만들어서, 깔끔해진 자료 하나를 만들었다.

 

내가 어떤 내용을 전달해야 하는지, 어떤 부분을 설득해야 하고 어떤 사람들이 듣는지를 먼저 파악해야 좋은 자료가 나올 수 있다는 걸 깨달았다.

최근 좋은 계기로 많은 고객사를 만나며 많은 것을 생각하게 된다.

 

내가 가진 지식을 전파하기 위해서 사용하거나,, 타 업체의 사람들을 설득하기 위해 PT를 진행하는 등 

 

근 4년 정도의 경력 중 짧은 시간에 많은 경험을 하고 있다 느끼고 있다.

 

과거에는 업무시간 동안 콘솔 혹은 IDE와 하루종일 씨름하며 일하던 내 모습과, 지금의 내 모습은 많이 달라졌다.

 

컴퓨터랑 일하는 시간보다,, 전화통을 붙잡고 누군가와 이야기하는 시간이 더 길어진듯 하다.(콘솔은 잡아야 해서, 그만큼 일이 많아진 기분이다)

 

엔지니어로써의 색이 옅어지는 걸까 생각이 들기도 하지만,, 직접 고객과 기술미팅하며 특정 기능을 조율하기 위해서 아키텍처를 고심하며 공부할 때는 또 아닌 것 같기도 하다..

 

이런저런 생각이 많아져서 미루고 미루던 블로그를 제대로 시작하기로 했다

 

단순히 기술적 내용을 정리해 둔 걸 넘어서,, 내 생각을 가미하기로 했다.

 

화이팅

가상화 기술과 VM(Virtual Machine)

목차

1. 개요

2. 가상화 기술

3. 가상화 vs 가상 머신

4. 가상 머신을 사용하는 이유

5. 가상 머신과 Hypervisor

6. 가상 머신의 문제점

7. 가상머신과 클라우드

8. 가상머신과 컨테이너, Hypervisor vs Docker Engine

9. 참고자료

1. 개요

가상 머신은 일종의 컴퓨팅 환경으로, 격리된 시스템으로 작동하며 하드웨어 리소스 풀에서 만들어진 자신의 CPU, Memory, network interface, storage를 포함합니다. Hypervisor라 불리는 소프트웨어가 필수 컴퓨팅 리소스를 격리하고 VM 생성과 관리를 지원합니다.

가상화 기술을 통해 물리적 하드웨어 상에서 생성된 논리적 컴퓨터입니다.

2. 가상화 기술

가상화는 서버, 스토리지, 네트워크 및 기타 물리적 시스템을 논리적으로 분리하여 여러 운영체제나 애플리케이션이 하나의 물리적 하드웨어에서 독립적으로 동작할 수 있도록 하는 기술입니다.

물리 자원의 효율적 사용과 확장성, 비용 절감을 가능하게 합니다.

2.1 종류

1. 하드웨어 가상화:

컴퓨터 및 VM(운영체제) 버전을 포함한 하드웨어를 가상화하면 하나의 가상화된 통합 기본 서버가 생성됩니다.

2. 소프트웨어 가상화:

하나 이상의 게스트 OS가 물리적 호스트 시스템에서 실행될 수 있도록 하는 하드웨어를 포함한 컴퓨터 시스템을 만듭니다.

3. 스토리지 가상화:

여러 개의 물리적 스토리지 디바이스를 통합하여 스토리지를 가상화합니다. 이 장치는 단일 스토리지 단위로 제공되므로 성능 향상과 속도를 높일 수 있습니다.

4. 네트워크 가상화:

물리적 네트워크 인프라에서 분리된, 전적으로 분산된 시스템 세트에 걸쳐 애플리케이션 기반 클라우드 가상 네트워킹을 지원합니다. 네트워크 가상화는 채널 간 대역폭을 할당하여 서버 및 장치에 실시간으로 리소스를 제공합니다.

5. 데스크톱 가상화:

데스크탑 환경을 물리적 장치에서 분리하고 원격 서버에 데스크탑을 저장하여 모든 장치에서 액세스할 수 있도록 합니다.

2.2 장점

1. 효율적 리소스 사용

하나의 컴퓨터 시스템에서 하나의 서버를 실행하는 대신 필요에 따라 서버를 생성하고 풀로 반환하여 동일한 컴퓨터 시스템에 가상 서버 풀을 생성할 수 있습니다.

또한 여러 개의 물리적 서버를 사용하는 대신 하나의 물리적 서버로 통합함으로써 서버의 유지관리 비용을 줄일 수 있습니다.

2. 자동화된 IT 관리

물리적 컴퓨터가 가상화되었기 때문에 소프트웨어 도구로 관리가 가능합니다. 가상 머신 템플릿을 정의하여 반복적이고 일관된 방식으로 인프라 복제가 가능하기에 수동 작업 시 발생 가능한 휴먼에러를 줄일 수 있습니다.

3. 신속한 재해복구

자연재해, 사이버 공격과 같은 문제가 발생하여 IT 인프라를 교체하거나 고치기 위한 시간을 줄일 수 있습니다.

물리적 서버를 사용한 경우엔 교체하거나 고치기 위한 시간이 몇 시간에서 며칠까지 늘어날 수 있지만, 물리 서버가 가상화된 경우엔 이러한 작업을 몇 분 안에 완료할 수 있습니다.

2.3 예시

Hypervisor(ex: VMware, KVM, Hyper-V)

  • 여러 운영체제를 하나의 물리 서버에서 동시에 실행합니다.

컨테이너 가상화(Docker 등)

  • 애플리케이션을 격리하여 독립적 실행 환경을 제공합니다.

3. 가상화 vs 가상 머신

요약하자면 가상화는 물리적 하드웨어 환경을 논리적으로 분리하여 여러 환경으로 만들 수 있게 하는 기술이며, 가상 머신은 가상화 기술로 생성된 독립적인 컴퓨터 환경을 의미합니다.

4. 가상 머신을 사용하는 이유

호스트 하드웨어에 별도의 머신처럼 작동하는 격리된 환경을 만들 수 있습니다. 따라서 다음과 같은 이점이 있습니다.

1. 서버 통합

서버를 가상화하여 사용한다면 하나의 물리 서버에 여러 개의 가상 서버를 배치하여 하드웨어 성능을 높힐 수 있습니다.

2. 비용 절감

서버 통합의 이점을 통해서 관리할 물리 서버를 줄임으로써 비용을 절감할 수 있습니다.

3. 안정성

가상 머신과 가상 머신 구성요소는 가상으로 존재하며 다른 가상 머신과 격리됩니다. 다른 가상 머신에 문제가 발생하더라도, 다른 게스트 VM(가상 머신)은 정상 작동합니다. 또한 물리적 호스트 OS는 영향을 받지 않습니다.

5. 가상 머신과 Hypervisor

가상 머신은 Hypervisor라는 소프트웨어를 통해 가상화 기술로 만들어진 논리적인 물리 컴퓨터입니다. 여러 개의 가상 머신(VM)을 하나의 물리 서버(호스트 OS)에서 실행할 수 있습니다.

Hypervisor는 가상 머신을 호스트 컴퓨터에서 실행하고 모든 VM에 프로세서, 메모리 및 스토리지를 배포할 수 있도록 해주는 소프트웨어 계층입니다. 물리적 자원을 가상 머신에 할당하고, 각각의 가상 머신이 독립적으로 운영체제를 실행할 수 있도록 지원합니다.

5.1 Hypervisor 유형

1. type 1 (네이티브 또는 베어메탈 Hypervisor)

물리적 하드웨어 위에서 바로 실행되며, 가상머신을 바로 관리합니다. 성능이 높고, 대규모 서버 가상화에 적합합니다. (ex: VMware ESXi, Microsoft Hyper-V, KVM)

2. type 2 (호스트형 Hypervisor)

기존 호스트 OS의 운영체제 위에서 실행되며, 그 위에서 가상 머신을 관리합니다. 개발자 테스트 환경이나 데스크톱 가상화에 주로 사용됩니다. (ex: VMware Workstation, Oracle VirtualBox)

6. 가상 머신의 문제점

가상 머신을 사용할 경우, 호스트 OS 성능에 매우 의존적이라는 문제점이 있습니다.

여러 운영체제와 Hypervisor 레이어를 실행하기 때문에 성능을 높이기 위한 비용이 발생할 수 있습니다.

7. 가상머신과 클라우드

기본적으로 가상화 기술은 클라우드 컴퓨팅을 가능하게 합니다.

클라우드 제공 업체는 자체 데이터센터를 설정하고 유지 관리합니다. 이들은 기반 하드웨어 리소스를 사용하는 서로 다른 가상 환경을 생성하여, 사용자로 하여금 API를 사용해서 이 클라우드 리소스에 엑세스 하도록 합니다.

따라서 둘 다 물리적 리소스에서 기능적 환경을 만드는 데 중점을 둡니다. 때문에 동일하다고 혼동할 수 있습니다. 그러나 둘은 차이점이 명확합니다.

가상화를 통한 가상 머신은 단일 하드웨어에서 여러 가상 시스템을 실행하는 기술입니다. 그러나 클라우드는 네트워크에서 확장 가능한 리소스를 추상화하여 공유하는 환경입니다.

확장 가능한 리소스의 추상화?

이 말은 클라우드의 핵심 특징에 관련이 있습니다.

확장 가능한: 클라우드는 사용자의 수요에 따라 CPU, Memory, 스토리지를 동적으로 확장, 축소합니다. 

추상화: 물리적 하드웨어와 인프라 복잡성을 숨기고 가상의 자원을 서비스처럼 제공하는데, 이때 리소스는 물리적 자원이 아닌 "추상화"된 형태로 제공됩니다.

8. 가상머신과 컨테이너, Hypervisor vs Docker Engine

컨테이너 기술 또한 가상화 기술의 한 종류입니다. 리소스를 격리한다는 차원에서 보면 둘은 비슷해 보이지만, 그렇지 않습니다.

Hypervisor로 가상화된 가상 머신(VM)은 각각 독립적인 운영 체제를 가지고 있으며 물리적 하드웨어 자원을 직접 할당받아 작동합니다. (이는 각 VM마다 커널을 갖고 있다는 것을 의미합니다.) 따라서 Hypervisor로 격리된 가상 머신(VM)은 하드웨어 차원에서 격리됩니다.

컨테이너 또한 가상화 기술에 일부입니다. 그러나 호스트 운영체제의 커널을 공유하고, 각 컨테이너는 독립된 애플리케이션 환경을 제공합니다. 따라서 컨테이너, Docker Engine은 OS 레벨에서의 격리만 지원합니다.

Hypervisor는 격리된 가상 머신마다 OS를 가지기 때문에 무겁고 성능 오버헤드가 상대적으로 크다는 단점이 있지만, 하드웨어 차원에서 격리되기 때문에 안정성과 보안적 이점이 컨테이너보다 높습니다.

컨테이너는 호스트 운영 체제와 커널을 공유하고 애플리케이션만 격리하여 경량화되어 가볍지만, 격리 수준이 Hypervisor보다 낮기 때문에 호스트 커널에 의존적이라는 단점이 있습니다.

결론으로 Docker Engine은 컨테이너 기반 가상화를 관리하고, Hypervisor는 가상 머신(VM) 기반 가상화를 관리합니다.

9. 참고자료

  • CloudNet@ 팀 gasida님의 a101(Ansible 101 study) 스터디를 진행하며 작성한 글 입니다.

Semaphore_Ansible UI

Semaphore란 Ansible Playbook UI 입니다.

Task별로 버전관리를 수행해 주거나 , Inventory , env , key 들을 잘 저장해서 편하게 사용할 수 있게끔 도와주는 Tool 입니다.

Semaphore 설치

Semaphore는 4가지 설치방안을 지원합니다.

  1. snap
  2. package manager
  3. docker
  4. binary file

1. package manager 설치 방안

위 설치 방안중 package manager 방안을 통해 설치합니다.

먼저 wget으로 package manager deb 파일을 가져옵니다.

wget https://github.com/ansible-semaphore/semaphore/releases/download/v2.9.45/semaphore_2.9.45_linux_amd64.deb

이후 semaphore의 config.json 파일을 성상하기 위한 셋업 과정을 진행합니다.
먼저 DB를 선택합니다.

# Setup Semaphore by using the following command
semaphore setup
1. Set up configuration for a MySQL/MariaDB database
2. Set up a path for your playbooks (auto-created)
3. Run database Migrations
4. Set up initial semaphore user & password

# 사용할 백엔드 database 선택
## 테스트할땐 내장 BoltDB 사용하는데, 실무에서 사용할때는 외부 DB 사용,
What database to use:
   1 - MySQL
   2 - BoltDB
   3 - PostgreSQL
 (default 1): 2

이후 Semaphore 관련 설정을 진행합니다.

# Semaphore가 사용할 db 파일의 경로와 이름 설정
db filename (default /home/ubuntu/database.boltdb): 

# Semaphore 작업 실행 시 사용될 Ansible 플레이북의 기본 저장 위치를 설정
Playbook path (default /tmp/semaphore): 

# Semaphore 서버에 접근하기 위한 public domain 설정. 설정하지 않으면 private network로만 접근이 가능함
Public URL (optional, example: https://example.com/semaphore): 

# email 알람 설정 
Enable email alerts? (yes/no) (default no): 

# telegram 알람 설정
Enable telegram alerts? (yes/no) (default no): 

# slack 알람 설정
Enable slack alerts? (yes/no) (default no): 

# LDAP 인증 설정
Enable LDAP authentication? (yes/no) (default no): 

# Semaphore 설정 완료 이후 작성되는 config.json 파일의 저장 위치 설정
Config output directory (default /home/ubuntu): 

...

> Username:    # 닉네임
> Email:  # 이메일
> Your name:    # 이름
> Password: # 비밀번호

...

설정 완료 시 config.json 파일이 생성되는것을 확인할 수 있습니다.

cat ./config.json 

Semaphore server를 아래 명령어로 실행합니다.

  • config.json을 직접 생성해서 실행할 수 도 있습니다.
$ semaphore service --config=./config.json
Loading config
Validating config
BoltDB /home/ubuntu/database.boltdb
Tmp Path (projects home) /tmp/semaphore
Semaphore v2.9.45
Interface 
Port :3000
Server is running

Semaphore를 package manager 또는 binary file로 설치했을 경우, Semaphore Deamon service를 수동으로 생성할 수 있습니다.

먼저 systemd service file을 생성합니다.

# 아래 /path/to/config.json 설정부분을 실제 config.json 파일의 경로로 변경해야 합니다.
sudo cat > /etc/systemd/system/semaphore.service <<EOF
[Unit]
Description=Semaphore Ansible
Documentation=https://github.com/ansible-semaphore/semaphore
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/path/to/semaphore service --config=/path/to/config.json
SyslogIdentifier=semaphore
Restart=always
RestartSec=10s

[Install]
WantedBy=multi-user.target
EOF

Semaphore service를 실행합니다.

sudo systemctl daemon-reload
sudo systemctl start semaphore
sudo systemctl enable semaphore

생성한 Semaphore service의 상태를 확인합니다.

sudo systemctl status semaphore

Semaphore를 설치한 서버에서, 아래 명령어를 수행하여 설치가 잘 되었는지 확인합니다.

# CLI 확인
semaphore -h
semaphore version
semaphore user list

Semaphore는 3000번 포트로 open됩니다. 웹에 접근하여 설치 결과를 확인합니다.

  • Semaphore를 웹을 통해 이용할 수 도 있지만, CLI를 통해 사용하는것 또한 가능합니다.

설치 시 설정했던 ID , PWD 를 통해 웹에 로그인 합니다.

기본적으로 Semaphore는 프로젝트 단위의 격리를 지원합니다.

따라서 , 가장 먼저 프로젝트를 생성해야 합니다.

프로젝트를 생성하면 다음과 같은 페이지로 이동합니다.

2. Docker 설치 방안

Semaphore를 Docker로 설치하기 위해서 docker-compose file을 사용합니다.

아래는 Semaphore 공식 문서에 등록된 compose file입니다.

env 설정을 통해 config.json 파일을 생성하게 되며 , 아래 설정값은 필수로 설정해야만 합니다.

  • MYSQL_PASSWORD and SEMAPHORE_DB_PASS
    — password for the MySQL user.
  • SEMAPHORE_ADMIN_PASSWORD
    — password for the Semaphore's admin user.
  • SEMAPHORE_ACCESS_KEY_ENCRYPTION
    — key for encrypting access keys in database. It must be generated by using the following command: head -c32 /dev/urandom | base64.

또한 기본적으로 BackEnd DB는 MySQL로 설정되어 있습니다. 이는 변경 가능하며, 주석으로 되어있는 postgrese로 변경할 수 있습니다.

services:
  # uncomment this section and comment out the mysql section to use postgres instead of mysql
  #postgres:
    #restart: unless-stopped
    #image: postgres:14
    #hostname: postgres
    #volumes: 
    #  - semaphore-postgres:/var/lib/postgresql/data
    #environment:
    #  POSTGRES_USER: semaphore
    #  POSTGRES_PASSWORD: semaphore
    #  POSTGRES_DB: semaphore
  # if you wish to use postgres, comment the mysql service section below 
  mysql:
    restart: unless-stopped
    image: mysql:8.0
    hostname: mysql
    volumes:
      - semaphore-mysql:/var/lib/mysql
    environment:
      MYSQL_RANDOM_ROOT_PASSWORD: 'yes'
      MYSQL_DATABASE: semaphore
      MYSQL_USER: semaphore
      MYSQL_PASSWORD: semaphore
  semaphore:
    restart: unless-stopped
    ports:
      - 3000:3000
    image: semaphoreui/semaphore:latest
    environment:
      SEMAPHORE_DB_USER: semaphore
      SEMAPHORE_DB_PASS: semaphore
      SEMAPHORE_DB_HOST: mysql # for postgres, change to: postgres
      SEMAPHORE_DB_PORT: 3306 # change to 5432 for postgres
      SEMAPHORE_DB_DIALECT: mysql # for postgres, change to: postgres
      SEMAPHORE_DB: semaphore
      SEMAPHORE_PLAYBOOK_PATH: /tmp/semaphore/
      SEMAPHORE_ADMIN_PASSWORD: changeme # Admin User 비밀번호
      SEMAPHORE_ADMIN_NAME: admin # Admin User 이름
      SEMAPHORE_ADMIN_EMAIL: admin@localhost # Admin User Email
      SEMAPHORE_ADMIN: admin
      SEMAPHORE_ACCESS_KEY_ENCRYPTION: gs72mPntFATGJs9qK0pQ0rKtfidlexiMjYCH9gWKhTU=
      SEMAPHORE_LDAP_ACTIVATED: 'no' # if you wish to use ldap, set to: 'yes' 
      SEMAPHORE_LDAP_HOST: dc01.local.example.com
      SEMAPHORE_LDAP_PORT: '636'
      SEMAPHORE_LDAP_NEEDTLS: 'yes'
      SEMAPHORE_LDAP_DN_BIND: 'uid=bind_user,cn=users,cn=accounts,dc=local,dc=shiftsystems,dc=net'
      SEMAPHORE_LDAP_PASSWORD: 'ldap_bind_account_password'
      SEMAPHORE_LDAP_DN_SEARCH: 'dc=local,dc=example,dc=com'
      SEMAPHORE_LDAP_SEARCH_FILTER: "(\u0026(uid=%s)(memberOf=cn=ipausers,cn=groups,cn=accounts,dc=local,dc=example,dc=com))"
    depends_on:
      - mysql # for postgres, change to: postgres
volumes:
  semaphore-mysql: # to use postgres, switch to: semaphore-postgres

설정이 완료되면 docker compose 명령어로 실행합니다.

docker compose up -d

Semaphore 사용

Semaphore 또한 Ansible Playbook을 편리하게 사용하기 위한 UI 이기 때문에, 대상이되는 서버에 ssh 연결이 무조건 되어야만 합니다.

1. Key Store 설정

Semaphore dashboard의 좌측 버튼중 Key Store에 접근합니다.

여기서 Key를 설정하는것은 다음과같은 목적이 있습니다.

  1. Playbook 대상 hosts들에게 ssh 연결을하기 위해 사용
  2. Repository에 remote 연결하기 위해 사용
  3. sudo 권한을 갖기위해 사용
  4. Ansible vault로 암호화된 파일을 복호화하기위해 사용

따라서 Key 를 생성할 때, 다음 Type들을 지원합니다.

  1. SSH Key
    • host ssh 연결 및 remote repository 에 ssh 연결 . 시사용
  2. Login With Password
    • 로그인 계정에 대한 암호 또는 access token
    • remote hosts 로그인 시 암호
    • remote hosts 에 sudo 사용 시 암호
    • remote Repo over HTTPS 로그인 시 암호
    • Ansible vaults 의 Unlock
  3. None
    • remote repository 에 암호가 없는 경우
    • local repository에 접근하거나, public repository에 접근할 때 사용. public 일 경우 인증정보가 없기에.

먼저 SSH Key file을 등록합니다.

  • 각 host Node에 SSH 연결이 가능하다면, ansible server에 위치한 ssh private key가 있을것입니다. 이를 넣어줍니다.
# private key 확인
cat /home/ubuntu/.ssh/id_rsa
-----BEGIN OPENSSH PRIVATE KEY-----
.....
-----END OPENSSH PRIVATE KEY-----

key를 생성합니다.

sudo 권한을 위한 root 계정의 Login 정보도 등록합니다.

remote repository 에 연결하기 위한 정보도 등록합니다.

  • repo에 접근할 때 정보가 필요하지않기에 none으로 생성

2. Repositories 생성

Semaphore dashboard의 좌측 버튼중 Repositories에 접근합니다.

Repositories 는 Playbook과 role들이 위치한곳을 등록합니다.

3가지 저장소를 지원합니다.

  1. 로컬 Git Repo : git://
  2. 로컬 파일시스템 : file://
  3. 리모트 Git Repo : accessed over HTTPS(*https://*) , or SSH(*ssh://*)
    • 인증 필요 : SSH 사용 시 SSH Key store , 인증 없을 경우 None type Key

테스트를 위해 로컬 파일시스템에 role이나 playbook을 가져오도록 세팅합니다.

먼저 Semaphore가 설치된 서버에 아래 경로를 생성합니다.

mkdir /tmp/semaphore

이후 생성한 로컬 경로를 바라보는 Repository를 생성합니다.

  • 이때 Branch가 자동으로 비활성화되고 URL or path 창의 구분이 자동으로 local path로 적용되는것을 확인할 수 있습니다.

3. Environment 생성

Semaphore dashboard의 좌측 버튼중 Environment에 접근합니다.

인벤토리에 추가 변수를 저장하는 곳으로 JSON 포멧으로 작성합니다.

빈 값과 user 정보 2가지 변수를 생성합니다.

1. 빈 값

변수 이름을 Empty 로 두고 Extra variables 에 아래 빈 값을 넣어줍니다.

{}

2. user 정보

변수 이름을 User-cloudneta 으로 두고 Extra variables 에 아래 값을 넣어줍니다.

{
  "user" : "cloudneta"
}

이렇게 설정해두면, Playbook을 수행할 때 User-cloudneta 을 통해서 "user" : "cloudneta" 변수를 가져올 수 있을것 입니다.

4. Inventory 설정

Semaphore dashboard의 좌측 버튼중 Inventory에 접근합니다.

Ansible Inventory를 설정하는곳으로, Yaml , Json , Toml 포멧을 지원합니다.

Inventory를 설정할 땐 , Static , Static Yaml , File Type을 지원하기 때문에 다양한 형태로 Inventory를 지정할 수 있습니다. 또한 해당 Host를 접근할 때 어떤 Credential을 사용해야할지 이전에 Key Store에서 생상한 Key를 선택하며 , Playbook 상황에 따라 Sudo가 필요할 경우 Sudo 권한을 위한 Credentials도 선택이 가능합니다.

먼저 Static Type으로 Host를 단순 나열하는 형태로 Inventory를 생성합니다.

두번째로 env라는 이름의 Inventory를 생성합니다.

  • 특이점이 있는데, 해당 Inventory는 user=study 라는 변수를 가집니다. 위에 Environment 를 생성할 때도 변수를 만들어주었는데, 우선순위는 Environment가 최상위고, 그다음이 Inventory 입니다.
[web]
tnode1
tnode2

[db]
tnode3

[all:children]
web
db

[all:vars]
user=study

5. Task Templates 설정

Semaphore dashboard의 좌측 버튼중 Task Templates에 접근합니다.

실제 Playbook을 생성하는 부분입니다. 특장점으로 Semaphore는 Cron을 지원하기때문에 따로 스크립트를 만들지 않더라도 Playbook을 주기별 자동실행할 수 있습니다.

3가지 Type을 지원합니다.

1. Task

단순하게 특정 playbook을 특정 파라미터들로 실행

2. Build

Semaphore에서 각 Playbook Task 별 버전관리를 수행하는 타입

버전관리는 지원하지만 Semaphore가 기본적으로 빌드 결과물이나 실행 파일 같은 아티팩트를 생성하고 관리하는 기능을 내장하고 있지 않습니다. 따라서 사용자가 생성된 아티팩트들을 관리하기 위해서 추가적인 작업을 수행해야만 합니다.

3. Deploy

Semaphore에서 Build 에서 생성된 특정 아티팩트 버전을 파라미터들로 실행하는 타입

간단한 Test를 위해서 Task Type으로 진행합니다.

Repo 생성 시 만들어준 /tmp/semaphore 경로에 아래 Playbook을 생성합니다.

  • Facts 확인
cat << EOT > /tmp/semaphore/fact.yml
---

- hosts: all

  tasks:
  - name: Print all facts
    ansible.builtin.debug:
      msg: >
        The default IPv4 address of {{ ansible_facts.fqdn }}
        is {{ ansible_facts.default_ipv4.address }}
EOT
  • user 확인
cat << EOT > /tmp/semaphore/user.yml
---

- hosts: web
  tasks:
  - name: Create User {{ user }}
    ansible.builtin.user:
      name: "{{ user }}"
      state: present
EOT

첫번째 fact.yml Playbook을 사용하는 Task를 생성합니다.

  • 위에 생성했었던 정보들을 바탕으로 대상 Inventory , target Repository , Environment 를 설정하고 생성합니다.
    • CronTab 을 통해 주기를 설정합니다. (매 5분주기)

두번째 user.yml Playbook을 사용하는 Task를 생성합니다.

  • 특징으로 users Playbook에는 user 변수를 사용합니다. 그런데 , Environment , Inventory 모두 user 변수를 갖고있습니다. 이때 우선순위는 Environment 입니다.

RUN 버튼을 클릭하여 생성한 Task를 실행합니다. Task Debug 창이 보이게 됩니다.

Task 기록또한 각 task를 클릭하여 확인할 수 있습니다.

또한 Task가 수행될 때 마다 Inventory 정보가 파일로 생성됩니다.

$ pwd
/tmp/semaphore

$ ls -l
total 20
-rw-rw-r-- 1 ubuntu ubuntu 207 Feb 11 01:52 fact.yml
-rw-rw-r-- 1 ubuntu ubuntu  32 Feb 11 02:00 inventory_2147483644
-rw-rw-r-- 1 ubuntu ubuntu  32 Feb 11 02:00 inventory_2147483645
-rw-rw-r-- 1 ubuntu ubuntu  78 Feb 11 01:59 inventory_2147483646
-rw-rw-r-- 1 ubuntu ubuntu 132 Feb 11 01:52 user.yml

두번째 user.yml Task를 수행합니다.

  • Fail 되게 됩니다. 그러한 이유는 env를 생성할 때, root 유저에 대한 user명을 설정해주지 않았기 때문

Key Store에 돌아가서, 설정한 login-root key를 수정합니다.

  • Override 버튼 클릭하면 덮어씌워집니다.

Task를 재 실행하면, 성공하고 변수는 Environment 가 더 높은 우선순위를 갖기 때문에 cloudneta 으로 등록된것을 확인할 수 있습니다.

두번째 Task를 수정해서 , 추가변수를 생성해 봅니다.

  • Semaphore에서는 추가변수를 설정할 때, 아래처럼 Allow CLI args in Tasks 버튼을 클릭하고 ["-e", ~~] 형태로 추가 변수를 설정해야만 합니다.

Save 하고 재 실행하면, 가장높은 우선순위를 가지는 추가 변수 (-e) 가 변수로 들어가는것을 확인할 수 있습니다.

'스터디 기록 > Ansible' 카테고리의 다른 글

Ansible 시스템 구축 자동화 도전과제풀이  (0) 2024.02.03
Ansible 연산자  (0) 2024.01.20
Ansible의 소개 및 기본 사용  (1) 2024.01.13

+ Recent posts