인프런 일프로님의 쿠버네티스 어나더 클래스 강의를 수강하며, 저희 사내 환경에 맞게 쿠버네티스를 설치하는 내용을 다루도록 하겠습니다.

 

환경

PC: Windows 10

IDE: vscode

HCI: Proxmox VE v8.1.4

IaC: Terraform

OS: Rocky linux 8.10

 

우선, 제가 구축할 환경은 아래와 같습니다. (빨간색 점선 부분이 추가 부분)

 

강의에서는 VirtualBox를 사용하였으나, 현재 저는 사내 데스크탑에 Proxmox 서버를 구축해 둔 관계로, 제공해주신 스크립트를 Proxmox에 맞춰 변경하는 작업이 필요합니다. 저는 굳이 VirtualBox를 사용하지 않기 때문에, Terraform을 이용하여 스크립트를 다시 작성하도록 하겠습니다.

 

Terraform은 아래의 과정을 수행합니다.

  1. 템플릿을 기반으로 VM 생성 (CPU, 메모리, SSH Key 등..)
  2. SSH key를 이용하여 서버에 접속한 후 쉘 스크립트로 쿠버네티스 설치 진행

 

1. Proxmox Template 생성

제가 작성한 아래 게시물의 링크를 참조합니다.

https://ratril.tistory.com/42

 

2. Proxmox API Key 생성

Proxmox 관리 UI 접속 이후 아래 과정을 따릅니다.

- Datacenter 클릭 -> API Tokens 클릭 -> Add 클릭 -> Token ID에 식별할 수 있는 값 자유롭게 입력 -> Priveilege Separation 체크 해제 -> Add 버튼 클릭

 

이후 표출되는 Secret 값을 복사한 후 잘 저장해둡니다. (생성 시에만 확인 가능)

 

3. Terraform 코드 작성

일프로님이 작성하신 Vagrant 스크립트를 기반으로 하여 테라폼으로 배포할 수 있도록 스크립트를 아래와 같이 작성하였습니다. 테라폼을 제대로 처음 작성해보는 관계로 코드가 좋지 않을 수 있어 양해 부탁드립니다.

 

스크립트를 그대로 사용하실 경우 유의하실 점은

  1. terraform.tfvars 파일을 자신의 환경에 맞게 적절히 수정
  2. ssh private key와 public key를 모두 같은 폴더에 넣고 파일명에 맞춰 terraform.tfvars 내 변수 수정
  3. install_k8s.sh 의 경우 파일명을 그대로 유지하며 같은 폴더에 넣을 것

윈도우와 vscode 환경에서 테라폼 구성 시에는 잘 모르시겠다면 아래 제가 진행하다가 작성한 링크를 참고해주세요.

https://ratril.tistory.com/category/IaC/Terraform

 

A. backend.tf

terraform {
  required_providers {
    proxmox = {
      source  = "Telmate/proxmox"
      version = "3.0.1-rc4"
    }
  }
  backend "local" {
  }
}

 

B. provider.tf

provider "proxmox" {
  pm_api_url = var.proxmox_endpoint
  pm_api_token_id = var.proxmox_api_token_id
  pm_api_token_secret = var.proxmox_api_secret
  pm_tls_insecure = true  # TLS 검증 비활성화

  # debug
  pm_log_enable = true
  pm_log_file = "terraform-plugin-proxmox.log"
  pm_debug = true
  pm_log_levels ={
    _default = "debug"
    _capturelog = ""
  }
}

 

C. main.tf

# 마스터 노드 설정
resource "proxmox_vm_qemu" "master_node" {
  name        = "k8s-master"
  target_node = "vm"
  vmid        = 600
  cores       = 4
  memory      = 6144
  scsihw      = "virtio-scsi-pci"
  bootdisk = "order=scsi0"
  clone = var.template_name
  os_type = "cloud-init"
  cpu = "host"
  ipconfig0 = "ip=${var.k8s_ip},gw=${var.k8s_gw}"
  sshkeys = file("${path.module}/${var.pub_ssh_key}")

    disks {
        ide {
            ide2 {
                cloudinit {
                    storage = "main-hdd"
                }
            }
        }

        scsi {
            scsi0 {
                disk {
                    size            = 50
                    storage         = "main-hdd"
                    iothread        = true
                    discard         = true
                }
            }
        }
    }


  # 네트워크 설정
  network {
    model  = "virtio"
    bridge = "vmbr0"
    tag = 56
    firewall = false
    link_down = false
  }

  # 시리얼 포트 추가
  serial {
    id   = 0
    type = "socket"
  }

  connection {
    host = replace(var.k8s_ip, "/24", "")
    type = "ssh"
    user = "rocky"
    private_key = file(var.pri_ssh_key)
  }

  # install_k8s.sh 파일 업로드 및 실행
  provisioner "file" {
    source      = "install_k8s.sh"  # 로컬의 스크립트 경로
    destination = "/tmp/install_k8s.sh"  # 원격 VM 내 저장 경로
  }

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/install_k8s.sh",  # 실행 권한 부여
      "/tmp/install_k8s.sh"            # 스크립트 실행
    ]
  }
}

 

D. variables.tf

variable "proxmox_endpoint" {
  description = "Proxmox API endpoint URL"
}

variable "proxmox_api_token_id" {
  description = "Proxmox API token id"
}

variable "proxmox_api_secret" {
  description = "Proxmox password or API token"
}

variable "proxmox_node" {
  description = "Proxmox node name"
}

variable "template_name" {
  description = "Proxmox template name"
  type = string
}

variable "pub_ssh_key" {
  description = "Public SSH Key file Name"
}

variable "pri_ssh_key" {
  description = "Private SSH Key file Name"
}

variable "k8s_ip" {
  description = "K8s Master Node IP and subnet"
}

variable "k8s_gw" {
  description = "K8s Master Node GW"
}

 

F. terraform.tfvars (직접 환경에 맞는 변수를 입력하셔야 합니다)

proxmox_endpoint = "https://[Proxmox IP]:8006/api2/json"
proxmox_api_token_id = "[계정명]@pam![토큰 ID] ex)root@pam!terraform"
proxmox_api_secret = "[토큰 secret]"
proxmox_node = "[proxmox node명 입력] ex)pxe"
template_name = "[proxmox template 이름 입력] ex) rocky-8-10-server-template"
pri_ssh_key = "[ssh private key 파일명 입력] ex) proxmox_key"
pub_ssh_key = "[ssh public key 파일명 입력] ex) proxmox_key.pub"
k8s_ip = "[k8s 마스터 노드 IP/Subnet 입력] ex)192.168.56.30/24"
k8s_gw = "[k8s 마스터 노드 gw 입력] ex)192.168.56.1"

 

G. install_k8s.sh

(테라폼 숙련도 이슈로 root 권한 자체로 스크립트 실행하는 방법을 몰라 일프로님의 스크립트에서 sudo 명령어를 추가 및 이외 수정 작업 진행)

* kubectl 명령어에서는 앞에 sudo 입력 시 아래 에러 표출됨

[rocky@k8s-master ~]$ sudo kubectl create -f [URL]
The connection to the server localhost:8080 was refused - did you specify the right host or port?

#!/bin/bash

echo '======== [4] Rocky Linux 기본 설정 ========'
echo '======== [4-1] 패키지 업데이트 ========'
# 강의와 동일한 실습 환경을 유지하기 위해 Linux Update 주석 처리
# yum -y update

echo '======== [4-2] 타임존 설정 ========'
sudo timedatectl set-timezone Asia/Seoul

echo '======== [4-3] Disk 확장 / Bug: soft lockup 설정 추가========'
sudo yum install -y cloud-utils-growpart
sudo growpart /dev/sda 4
sudo xfs_growfs /dev/sda4
sudo echo 0 > /proc/sys/kernel/hung_task_timeout_secs
sudo echo "kernel.watchdog_thresh = 20" >> /etc/sysctl.conf

echo '======== [4-4] tc 관련 패키지 설치 ========'
sudo yum install -y yum-utils iproute-tc

echo '======= [4-4] hosts 설정 =========='
sudo cat << EOF >> /etc/hosts
192.168.56.30 k8s-master
EOF

echo '======== [5] 방화벽 해제 ========'
sudo systemctl stop firewalld && systemctl disable firewalld

echo '======== [5] Swap 비활성화 ========'
sudo swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab

echo '======== [6] 컨테이너 런타임 설치 ========'
sudo touch /etc/modules-load.d/k8s.conf
sudo cat <<EOF |sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

sudo touch /etc/sysctl.d/k8s.conf
sudo cat <<EOF |sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install -y containerd.io-1.6.21-3.1.el8
sudo systemctl daemon-reload
sudo systemctl enable --now containerd

sudo bash -c "containerd config default > /etc/containerd/config.toml"
sudo sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd

echo '======== [7] kubeadm 설치 ========'
sudo cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF

sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
sudo yum install -y kubelet-1.27.2-150500.1.1.x86_64 kubeadm-1.27.2-150500.1.1.x86_64 kubectl-1.27.2-150500.1.1.x86_64 --disableexcludes=kubernetes
sudo systemctl enable --now kubelet

echo '======== [8] kubeadm으로 클러스터 생성 ========'
sudo kubeadm init --pod-network-cidr=20.96.0.0/16 --apiserver-advertise-address 192.168.56.30

sudo mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml
kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane-

echo '======== [9] 쿠버네티스 편의기능 설치 ========'
sudo echo "source <(kubectl completion bash)" >> ~/.bashrc
sudo echo 'alias k=kubectl' >>~/.bashrc
sudo echo 'complete -o default -F __start_kubectl k' >>~/.bashrc

kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/dashboard-2.7.0/dashboard.yaml
kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/metrics-server-0.6.3/metrics-server.yaml

 

4. Terraform으로 배포 진행

A. vscode를 연 뒤 테라폼 코드를 저장한 폴더를 열고 Open in integrated Terminal 버튼을 클릭합니다.

 

B. 아래 명령어를 입력하여 테라폼으로 배포를 시작합니다.

> terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of telmate/proxmox from the dependency lock file
- Using previously-installed telmate/proxmox v3.0.1-rc4

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

> terraform plan
각종 정보 확인..

> terraform apply

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: -> yes 입력 후 진행

 

C. 완료되었는지 확인합니다. 정상적일 경우 아래와 같이 메세지가 표기됩니다.

 

D. 쿠버네티스 대시보드로 접속하여 잘 설치되었는지 확인합니다. ex) https://192.168.56.30:30000

(테라폼 완료 후에도 약간의 시간 소요되니 대기 필요)

일프로님의 쿠버네티스 강의 수강 중, 192.168.56.1/24 대역을 사용해야 하는데 사내 인프라 구성 상 약간의 구성 변경이 필요함을 느껴 구성 변경 작업을 진행하였다. (정말 귀찮다..) 이에 따라 FortiSwitch의 Trunk Port 설정 및 Proxmox의 VLAN 인터페이스 설정 방법을 아래에 정리한다.

 

주의사항) 네트워크 구성 변경이기에, 서버의 설정과 네트워크 설정의 순서를 올바르게 하지 않으면 직접 서버에 모니터를 연결, 또는 중간에 설정을 원복하고 다시 접속해야 하는 불상사가 있을 수 있습니다.

네트워크 구성은 어느정도 비슷하나, IP는 사내 실제 환경이 아님을 미리 밝힙니다.

 

기존 환경 (AS-IS)

변경 후 환경 (TO-BE)

1. Proxmox 설정 변경

A. /etc/network/interfaces 설정으로 진입한다. (vim이 익숙하지 않아 우선 nano를 사용..)

nano /etc/network/interfaces

 

B. 아래와 같이 설정 파일을 적절하게 수정한다.

auto lo
iface lo inet loopback

iface enp6s0 inet manual

auto vmbr0
iface vmbr0 inet static
        bridge-ports enp6s0
        bridge-stp off
        bridge-fd 0
        bridge-vlan-aware yes
        bridge-vids 50,56

# VLAN ID가 50이므로..
auto vmbr0.50
iface vmbr0.50 inet static
        address 192.168.50.2/24
        gateway 192.168.50.1

# VLAN ID가 56이므로..
auto vmbr0.56
iface vmbr0.56 inet static
        address 192.168.56.2/24
        gateway 192.168.56.1


source /etc/network/interfaces.d/*

 

C. 컨트롤+O 누른 뒤 엔터를 누르고 저장하고 컨트롤+X로 나온다.

D. 아래 명령어를 입력하여 설정을 적용한다.

(해당 명령어 적용할 경우 네트워크 환경이 맞지 않으면 원격 접속 불가하니 주의)

ifup -a

2. FortiSwitch 설정 변경 (Proxmox 연결 포트 Trunk로 변경)

A. FortiSiwtch CLI에 접속한다.

B. 접속한 후 아래 CLI 명령어를 입력한다.

    config switch trunk
    edit "proxmox"
        set members "port23"    # Trunk mode로 변경할 포트 지정     
    end
    
    config switch interface
        edit "proxmox"
        set allowed-vlans 1,50,56 # 허용할 VLAN 설정
    end

 

3. FortiGate VLAN 인터페이스 생성

A. Network -> Interface -> Create New -> Interface 클릭하여 생성 창으로 진입합니다.

B. 아래와 같이 인터페이스 설정을 추가한다.

  • Name: 인터페이스 이름
  • VLAN ID: 위 Proxmox에서 설정한 VLAN ID ex) vmbr0.56 -> 56
  • IP/Netmask: IP 대역
  • 이외 접속 허용 및 DHCP Server 설정은 자유

 

C. OK 버튼을 눌러 인터페이스를 생성한 후, Policy & Objects에서 방화벽 정책을 적절히 생성한다. (과정 생략)

D. IPsec VPN이 연결되어 있을 경우, 잊지 않고 신규 대역에 대한 라우팅 및 정책 설정을 해준다.

 

4. 기존 Proxmox VM의 VLAN 설정 변경

- 변경할 VM 클릭 -> Hardware 클릭 -> Network Device 클릭 -> VLAN Tag 값을 적절히 변경 -> OK 버튼을 클릭한다.

 

이후 기존 서비스에 이상이 없는지 체크하고 안도의 한숨을 내쉬며 작업을 완료한다.


24.10.27 추가

리부팅 이후 FortiSwitch에 설정된 Trunk 설정이 날아가는 듯 하다.. 이거에 대해서 추가적인 해결책을 찾아볼 필요가 있음.

'Cloud, 가상화 > Proxmox' 카테고리의 다른 글

[Proxmox] Rocky Linux Template 생성  (0) 2024.10.06

일프로님의 인프런 쿠버네티스 강의를 수강하며 테라폼으로 쿠버네티스를 설치하려는 중, 템플릿이 있으면 편할 것 같아 Proxmox에서 Rocky Linux 탬플릿을 생성하는 과정을 아래에 작성합니다.

 

1. VM 생성

A. 우측 상단 Create VM 클릭 -> VM ID를 800으로 입력하고 Name 적당히 입력 -> Next 클릭

 

B. 클라우드 이미지를 활용하기에 Do not use any media 클릭 -> Next 클릭

 

C. Qemu Agent 체크 후 Next 클릭

D. 디스크를 휴지통 버튼 클릭하여 제거 이후 Next 클릭

E. 별도 설정 변경 없이 Next 클릭

F. 램을 1024MB로 변경 후 Next 클릭

G. 각자 환경에 맞게 네트워크 설정 후 Next를 클릭

H. Finish 버튼을 클릭하여 완료

2. CloudInit 설정

A. 생성된 VM 클릭 -> Hardware 탭 클릭 -> Add 클릭 -> CloudInit Drive 클릭

B. Storage를 적절히 선택한 후 Add 클릭

 

C. SSH key 생성 (저는 cmd 창에서 진행하였습니다)

> ssh-keygen -t rsa -C proxmox

Generating public/private rsa key pair.
Enter file in which to save the key (C:\Users\JJ/.ssh/id_rsa): C:\proxmox_key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\proxmox_key.
Your public key has been saved in C:\proxmox_key.pub.
The key fingerprint is:
SHA256:GoMoV9XZuV1u2WHqxinUAi85xAMnypQvLZeOlWwBgAw proxmox
The key's randomart image is:
+---[RSA 3072]----+
|E ...o++o+ .     |
| o  oo..==o   .o |
|    .o+ = =o.ooo.|
|   o + X +.+.o+ .|
|. o . @ S + +..  |
| o   . =   . =   |
|      .     o    |
|                 |
|                 |
+----[SHA256]-----+

 

D. Cloud-Init -> SSH public key 더블클릭 후 생성된 public key를 붙여넣기 (생성된 .pub 확장자 파일 내용 복사)

E. IP config 더블클릭 -> DHCP를 클릭한 후 OK 클릭

 

3. Cloud image 다운로드 및 설정 및 탬플릿 생성

A. SSH를 통해 Proxmox CLI 접속 후 아래 명령어 입력하여 rocky linux 클라우드 이미지를 다운로드합니다.

# wget https://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-GenericCloud-Base.latest.x86_64.qcow2

 

B. 아래 명령어를 입력합니다.

# qm set 800 -serial0 socket -vga serial0 // 800은 vm ID

 

C. 아래 명령어를 입력하여 Cloud image를 추가합니다.

// 800은 vm ID, Rocky-8.. 은 wget으로 받은 파일명, main-hdd는 디스크 이름
qm importdisk 800 Rocky-8-GenericCloud-Base.latest.x86_64.qcow2 main-hdd

 

D. GUI로 돌아와 생성한 VM 클릭 -> Hardware 클릭 -> Unused Disk 0 클릭 -> Edit 클릭합니다.

E. Discard를 체크한 후 Add를 클릭합니다.

F. Options -> Boot Order를 더블클릭 후 scsi0의 enabled 체크, 순서를 아래 이미지와 같이 맞추고 OK 버튼을 클릭합니다.

G. Start at boot 더블클릭 -> start at boot에 체크 -> OK 버튼을 클릭합니다.

H. 우클릭 -> Convert to template를 클릭하여 탬플릿을 생성을 완료합니다.

4. 탬플릿 테스트

A. 탬플릿화 된 vm을 우클릭 후 Clone 버튼을 클릭합니다.

B. Mode를 Full Clone으로 변경하고 VM ID와 Name을 적절히 입력한 후 Clone 버튼을 클릭합니다.

C. 몇몇 작업이 완료된 후 정상 접속이 확인됩니다.

(AWS EC2 접속하는 것과 같이 생성한 인증서를 통해 자동으로 할당받은 IP를 입력하여 접속)

* ID는 rocky로 접속합니다

 

유의사항

1. 위의 인증서를 통한 접속 과정을 밟을 경우, Proxmox에서 ID/PW 입력으로는 접속이 불가합니다.

2. 따라서 위의 과정을 적절히 환경에 따라 바꿉니다.

3. 저의 경우 FortiGate 방화벽을 통해 탬플릿으로 생성된 서버의 IP를 확인하였습니다.

+ Recent posts