카테고리 보관물:  IT

리눅스 VM Disk 증설 후 Partition 확장 및 LV 확장

개요

VMware, KVM 등 리눅스 VM Disk 증설 후 OS에서 파티션과 논리 볼륨(LV)을 확장하지 않으면 실제 파일시스템에서 늘어난 용량을 사용할 수 없습니다. Ubuntu LVM 환경에서는 hypervisor에서 디스크를 확장한 뒤 parted로 파티션을 늘리고, pvresizelvextendresize2fs 순서로 실제 마운트 포인트까지 용량을 반영해야 합니다. 이 글에서는 VM 디스크 16G → 30G 증설 후 전체 확장 절차를 단계별로 정리합니다.

LVM 기반 디스크 확장 절차 이해

Ubuntu Server의 기본 설치는 LVM(Logical Volume Manager) 구조를 사용합니다. 하이퍼바이저(VMware, KVM 등)에서 VM 디스크 크기를 늘려도 OS는 즉시 인식하지 못합니다. LVM 환경에서는 물리 디스크 → 파티션 → Physical Volume → Volume Group → Logical Volume → 파일시스템의 순서로 각 계층을 순차적으로 확장해야 합니다.

구체적인 확장 순서는 다음과 같습니다: parted로 파티션을 디스크 끝까지 확장 → pvresize로 Physical Volume이 새 파티션 크기를 인식 → lvextend로 Logical Volume에 여유 공간 추가 → resize2fs로 파일시스템이 새 LV 크기를 인식. 이 절차는 온라인 상태(마운트 해제 없이)에서 진행 가능하여 서비스 중단 없이 디스크를 확장할 수 있습니다.

0단계 — 파일시스템 현재 상태 확인

@:~$ df -h
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              794M   14M  781M   2% /run
/dev/mapper/ubuntu--vg-ubuntu--lv  9.8G  8.2G  1.1G  89% /
tmpfs                              3.9G   84K  3.9G   1% /dev/shm
tmpfs                              5.0M     0  5.0M   0% /run/lock
/dev/sda2                          1.7G  242M  1.4G  15% /boot
tmpfs                              794M  4.0K  794M   1% /run/user/1000

1단계 — VM 디스크 증설 후 lsblk 확인

VM의 디스크를 16G에서 30G로 증설하면 lsblk에서 sda는 30G로 표시되지만, 실제 파티션 sda3와 LV는 아직 이전 크기(14.2G)를 유지합니다.

@:~$ lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0                       7:0    0  63.4M  1 loop /snap/core20/1974
loop1                       7:1    0  63.7M  1 loop /snap/core20/2434
loop2                       7:2    0 111.9M  1 loop /snap/lxd/24322
loop3                       7:3    0  89.4M  1 loop /snap/lxd/31333
loop4                       7:4    0  53.3M  1 loop /snap/snapd/19457
loop5                       7:5    0  44.3M  1 loop /snap/snapd/23258
sda                         8:0    0    30G  0 disk
├─sda1                      8:1    0     1M  0 part
├─sda2                      8:2    0   1.8G  0 part /boot
└─sda3                      8:3    0  14.2G  0 part
  └─ubuntu--vg-ubuntu--lv 253:0    0    10G  0 lvm  /
sdb                         8:16   0    50G  0 disk
sr0                        11:0    1  1024M  0 rom

2단계 — parted로 파티션 확장

@:~$ sudo parted
GNU Parted 3.4
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 32.2GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name  Flags
 1      1049kB  2097kB  1049kB                     bios_grub
 2      2097kB  1881MB  1879MB  ext4
 3      1881MB  17.2GB  15.3GB

(parted) resizepart 3
End?  [17.2GB]? 32.2GB
(parted) print
Model: VMware Virtual disk (scsi)
Disk /dev/sda: 32.2GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End     Size    File system  Name  Flags
 1      1049kB  2097kB  1049kB                     bios_grub
 2      2097kB  1881MB  1879MB  ext4
 3      1881MB  32.2GB  30.3GB

(parted) q
Information: You may need to update /etc/fstab.

3단계 — 파티션 확장 확인

@:~$ lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0                       7:0    0  63.4M  1 loop /snap/core20/1974
loop1                       7:1    0  63.7M  1 loop /snap/core20/2434
loop2                       7:2    0 111.9M  1 loop /snap/lxd/24322
loop3                       7:3    0  89.4M  1 loop /snap/lxd/31333
loop4                       7:4    0  53.3M  1 loop /snap/snapd/19457
loop5                       7:5    0  44.3M  1 loop /snap/snapd/23258
sda                         8:0    0    30G  0 disk
├─sda1                      8:1    0     1M  0 part
├─sda2                      8:2    0   1.8G  0 part /boot
└─sda3                      8:3    0  28.2G  0 part
  └─ubuntu--vg-ubuntu--lv 253:0    0    10G  0 lvm  /
sdb                         8:16   0    50G  0 disk
sr0                        11:0    1  1024M  0 rom

3단계 결과 확인 후 주의사항

lsblk에서 sda3 크기가 28.2G로 늘어난 것을 확인했지만, LVM은 아직 이전 크기를 기억하고 있습니다. pvdisplay 실행 시 PV Size: <14.25 GiB로 표시됩니다. 이는 PV 메타데이터가 파티션 확장 사실을 모르기 때문입니다. pvresize 명령으로 PV 메타데이터를 갱신해야 VG에 여유 공간이 생깁니다.

4단계 — Physical Volume 확장 (pvresize)

@:~$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda3
  VG Name               ubuntu-vg
  PV Size               <14.25 GiB / not usable 0
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              3647
  Free PE               1087
  Allocated PE          2560
  PV UUID               O2p8iY-2Jpm-WNGJ-viUf-nIt6-iw0x-rVgXAo

@:~$ sudo pvscan
  PV /dev/sda3   VG ubuntu-vg       lvm2 [<14.25 GiB / <4.25 GiB free]
  Total: 1 [<14.25 GiB] / in use: 1 [<14.25 GiB] / in no VG: 0 [0   ]

@:~$ sudo pvresize /dev/sda3
  Physical volume "/dev/sda3" changed
  1 physical volume(s) resized or updated / 0 physical volume(s) not resized
@:~$ sudo pvdisplay
  --- Physical volume ---
  PV Name               /dev/sda3
  VG Name               ubuntu-vg
  PV Size               <28.24 GiB / not usable 1.31 MiB
  Allocatable           yes
  PE Size               4.00 MiB
  Total PE              7228
  Free PE               4668
  Allocated PE          2560
  PV UUID               O2p8iY-2Jpm-WNGJ-viUf-nIt6-iw0x-rVgXAo

5단계 — Logical Volume 확장 (lvextend)

@:~$ sudo vgdisplay
  --- Volume group ---
  VG Name               ubuntu-vg
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               28.23 GiB
  PE Size               4.00 MiB
  Total PE              7228
  Alloc PE / Size       2560 / 10.00 GiB
  Free  PE / Size       4668 / 18.23 GiB
  VG UUID               aUI3qM-tbml-FpOz-ccxw-1yk3-4hCo-a35uCK

@:~$ sudo lvdisplay
  --- Logical volume ---
  LV Path                /dev/ubuntu-vg/ubuntu-lv
  LV Name                ubuntu-lv
  VG Name                ubuntu-vg
  LV UUID                gFcvA9-fkuH-rNy8-wVka-93Th-r8X0-FB8giN
  LV Write Access        read/write
  LV Creation host, time ubuntu-server, 2023-12-05 01:04:17 +0000
  LV Status              available
  # open                 1
  LV Size                10.00 GiB
  Current LE             2560
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:0

@:~$ sudo lvextend -l +100%FREE -n /dev/ubuntu-vg/ubuntu-lv
  Size of logical volume ubuntu-vg/ubuntu-lv changed from 10.00 GiB (2560 extents) to 28.23 GiB (7228 extents).
  Logical volume ubuntu-vg/ubuntu-lv successfully resized.
@:~$ sudo vgdisplay
  --- Volume group ---
  VG Name               ubuntu-vg
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               1
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               28.23 GiB
  PE Size               4.00 MiB
  Total PE              7228
  Alloc PE / Size       7228 / 28.23 GiB
  Free  PE / Size       0 / 0
  VG UUID               aUI3qM-tbml-FpOz-ccxw-1yk3-4hCo-a35uCK

@:~$ lsblk
NAME                      MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0                       7:0    0  63.4M  1 loop /snap/core20/1974
loop1                       7:1    0  63.7M  1 loop /snap/core20/2434
loop2                       7:2    0 111.9M  1 loop /snap/lxd/24322
loop3                       7:3    0  89.4M  1 loop /snap/lxd/31333
loop4                       7:4    0  53.3M  1 loop /snap/snapd/19457
loop5                       7:5    0  44.3M  1 loop /snap/snapd/23258
sda                         8:0    0    30G  0 disk
├─sda1                      8:1    0     1M  0 part
├─sda2                      8:2    0   1.8G  0 part /boot
└─sda3                      8:3    0  28.2G  0 part
  └─ubuntu--vg-ubuntu--lv 253:0    0  28.2G  0 lvm  /
sdb                         8:16   0    50G  0 disk
sr0                        11:0    1  1024M  0 rom

6단계 — 파일시스템 확장 및 확인 (resize2fs)

@:~$ sudo resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
resize2fs 1.46.5 (30-Dec-2021)
Filesystem at /dev/mapper/ubuntu--vg-ubuntu--lv is mounted on /; on-line resizing required
old_desc_blocks = 2, new_desc_blocks = 4
The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 7401472 (4k) blocks long.

@:~$ df -h
Filesystem                         Size  Used Avail Use% Mounted on
tmpfs                              794M   14M  781M   2% /run
/dev/mapper/ubuntu--vg-ubuntu--lv   28G  8.2G   19G  31% /
tmpfs                              3.9G   84K  3.9G   1% /dev/shm
tmpfs                              5.0M     0  5.0M   0% /run/lock
/dev/sda2                          1.7G  242M  1.4G  15% /boot
tmpfs                              794M  4.0K  794M   1% /run/user/1000

XFS 파일시스템 환경에서의 차이

위 절차는 ext4 파일시스템 기준입니다. RHEL/Rocky Linux의 기본 파일시스템인 XFS를 사용하는 경우 마지막 단계의 resize2fs 대신 xfs_growfs /를 사용합니다. XFS는 ext4와 달리 마운트된 상태에서만 확장 가능하므로 마운트 해제 후에는 확장할 수 없습니다. LVM과 parted를 이용한 파티션 확장 절차(1~5단계)는 동일하고 마지막 파일시스템 확장 명령만 다릅니다.

또한 lvextend -r 옵션을 사용하면 lvextend와 파일시스템 확장(resize2fs 또는 xfs_growfs)을 한 번에 처리할 수 있습니다. 단, 이 옵션은 파일시스템 타입을 자동 감지하므로 마운트된 상태에서만 정상 동작합니다.

참고

관련 포스트:

참고 문서: parted(8) man page · lvextend(8) man page

GitLab CE install

개요

GitLab CE(Community Edition)는 자가 관리형(self-hosted) 오픈소스 Git 저장소 및 DevOps 플랫폼입니다. GitHub Actions와 유사한 CI/CD 파이프라인(GitLab CI)을 포함하며, 이슈 트래킹, MR(Merge Request), Container Registry, Wiki까지 하나의 서버에서 운영할 수 있습니다.

인터넷 연결이 제한된 내부망 환경이나 코드를 외부에 두기 어려운 보안 요건이 있는 조직에서 GitHub.com 대신 사용하는 사례가 많습니다. 이 글에서는 Ubuntu 22.04 환경에 GitLab CE 17.6.2를 Omnibus 패키지로 설치하는 전체 절차를 정리합니다.

권장 사양: CPU 4코어 이상, RAM 8GB 이상, 디스크 50GB 이상. Omnibus 패키지는 PostgreSQL, Redis, Nginx, Prometheus 등 GitLab의 모든 컴포넌트를 포함하므로 최소 3.7GB의 패키지 다운로드와 디스크 공간이 필요합니다.

OS: Ubuntu 22.04.3 LTS | GitLab: CE 17.6.2

OS 업데이트 및 의존성 패키지 설치

GitLab 설치 전 OS 패키지를 최신 상태로 업데이트하고, GitLab 설치 스크립트에 필요한 의존성 패키지를 설치합니다. ca-certificatescurl은 GitLab 패키지 저장소를 HTTPS로 추가할 때 필요하고, tzdata는 GitLab 내부의 시간대 처리에 사용됩니다.

<admin-user>@<server>:~$ sudo apt-get update
<admin-user>@<server>:~$ sudo apt-get install -y curl openssh-server ca-certificates tzdata perl

sendmail 설치 (선택)

GitLab은 계정 인증, 비밀번호 재설정, 알림 등을 이메일로 발송합니다. 자체 메일 서버(Postfix)를 설치하거나, 나중에 /etc/gitlab/gitlab.rb에서 외부 SMTP 서버(Gmail, AWS SES 등)를 설정하는 방법 중 선택할 수 있습니다. 내부망 환경에서 별도 SMTP 서버가 있다면 이 단계를 건너뛰어도 됩니다.

<admin-user>@<server>:~$ sudo apt-get install -y postfix

GitLab 저장소 추가 및 패키지 설치

GitLab에서 제공하는 공식 설치 스크립트로 apt 저장소를 등록한 뒤 패키지를 설치합니다. EXTERNAL_URL 환경변수는 GitLab이 외부에서 접근되는 URL입니다. 이 값은 설치 후 /etc/gitlab/gitlab.rbexternal_url 항목에 저장되며 CI/CD 파이프라인의 클론 URL, 이메일 링크 등에 전반적으로 사용됩니다. 도메인이 없다면 http://서버IP:포트 형식으로 지정합니다.

패키지 크기가 약 1.3GB이므로 다운로드에 수 분이 소요됩니다. 설치 중 Omnibus Chef 레시피가 실행되면서 PostgreSQL 초기화, Nginx 설정, 서비스 기동까지 자동으로 처리됩니다.

<admin-user>@<server>:~$ curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
<admin-user>@<server>:~$ sudo EXTERNAL_URL="http://x.x.x.x:8081" apt-get install gitlab-ce

gitlab.rb 수정 및 서비스 재기동

설치 후 /etc/gitlab/gitlab.rb는 GitLab의 모든 설정을 관리하는 중앙 설정 파일입니다. external_url 외에도 SMTP 설정, LDAP 연동, 백업 경로, 이메일 발신자 등 수백 가지 옵션을 이 파일 하나에서 제어합니다. 변경 사항을 적용하려면 반드시 gitlab-ctl reconfigure를 실행해야 하며, 이 과정에서 Chef 레시피가 재실행되어 변경된 설정이 각 서비스 설정 파일에 반영됩니다.

vi /etc/gitlab/gitlab.rb
# external_url 항목 수정
external_url 'http://x.x.x.x:8081'

<admin-user>@<server>:~$ sudo gitlab-ctl reconfigure

초기 root 비밀번호 확인

설치 직후 GitLab은 임시 root 비밀번호를 /etc/gitlab/initial_root_password 파일에 저장합니다. 이 파일은 설치 후 24시간이 지나면 자동으로 삭제됩니다. 초기 로그인 후 즉시 Admin > Edit profile > Password에서 비밀번호를 변경하고, 변경 후에는 이 파일을 수동으로 삭제해도 됩니다.

sudo cat /etc/gitlab/initial_root_password

브라우저 접근 확인 및 초기 비밀번호 변경

브라우저에서 http://x.x.x.x:8081로 접속하여 GitLab 로그인 페이지가 표시되면 설치가 완료된 것입니다. root 계정으로 로그인 후 다음 순서로 초기 설정을 진행합니다.

  1. Admin > Edit profile > Password에서 초기 비밀번호 변경
  2. Admin Area > Settings > General에서 Sign-up 제한(내부망이면 비활성화 권장)
  3. 첫 번째 프로젝트(저장소) 생성 확인
GitLab CE 설치 완료 후 웹 브라우저 초기 접속 화면

참고

참고 문서: GitLab 패키지 설치 공식 문서 · GitLab Runner Docker 설치 문서

Kubernetes 기본 설치(Version 1.28)

개요

이 글에서는 Ubuntu 22.04 환경에서 kubeadm을 사용하여 Kubernetes 1.28 클러스터를 구축하는 전체 절차를 정리합니다. Kubernetes 1.24부터 Docker shim이 제거되었기 때문에 Docker 런타임을 계속 사용하려면 cri-dockerd를 컨테이너 런타임 인터페이스(CRI)로 별도 설치해야 합니다. CNI 플러그인은 Calico를 사용하며, 마스터 노드 1개와 워커 노드 2개로 구성하는 것을 기준으로 작성하였습니다.

이 가이드는 단일 마스터 클러스터 기준입니다. HA(고가용성) 멀티 마스터 구성은 HAProxy 로드밸런서와 etcd 클러스터 구성이 추가로 필요합니다.

구성 내역

설치 환경은 다음과 같습니다.

Kubernetes 1.28.2
Ubuntu 22.04.3 LTS
Container : cri-dockerd
CNI : calico
구성용 계정 : <admin-user>
Master node : <master-node>
Worker node : <worker-node-01> ~ <worker-node-02>

시작 전 모든 노드에서 swap을 비활성화해야 합니다. kubelet은 swap이 활성화된 환경에서 기본적으로 동작을 거부합니다.

sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#/g' /etc/fstab

[공통]

cri-docker 설치

Kubernetes 1.24 이후 Docker shim이 제거되면서 Docker를 컨테이너 런타임으로 사용하려면 cri-dockerd를 별도로 설치해야 합니다. cri-dockerd는 Mirantis가 관리하는 오픈소스 프로젝트로, Docker Engine과 kubelet 사이의 CRI(Container Runtime Interface) 어댑터 역할을 합니다. 먼저 Docker Engine을 설치한 뒤 cri-dockerd 바이너리를 받아 systemd 서비스로 등록합니다.

Docker cgroup driver를 systemd로 맞추는 것이 중요합니다. kubelet도 기본적으로 systemd cgroup driver를 사용하므로, driver 불일치 시 노드가 NotReady 상태가 됩니다.

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo systemctl enable --now docker && sudo systemctl status docker --no-pager
sudo usermod -aG docker <admin-user>
sudo docker container ls

# cri-docker Install
VER=$(curl -s https://api.github.com/repos/Mirantis/cri-dockerd/releases/latest|grep tag_name | cut -d '"' -f 4|sed 's/v//g')
echo $VER
wget https://github.com/Mirantis/cri-dockerd/releases/download/v${VER}/cri-dockerd-${VER}.amd64.tgz
tar xvf cri-dockerd-${VER}.amd64.tgz
sudo mv cri-dockerd/cri-dockerd /usr/local/bin/

# cri-docker Version Check
cri-dockerd --version

wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.service
wget https://raw.githubusercontent.com/Mirantis/cri-dockerd/master/packaging/systemd/cri-docker.socket
sudo mv cri-docker.socket cri-docker.service /etc/systemd/system/
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

# cri-docker Active Check
sudo systemctl restart docker && sudo systemctl restart cri-docker
sudo systemctl status cri-docker.socket --no-pager

# Docker cgroup Change Require to Systemd
sudo mkdir /etc/docker
cat <<EOF | sudo tee /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF

sudo systemctl restart docker && sudo systemctl restart cri-docker
sudo docker info | grep Cgroup

환경 설정

Kubernetes 네트워킹이 정상 동작하려면 커널 모듈과 sysctl 파라미터를 설정해야 합니다. br_netfilter 모듈은 Linux Bridge를 통과하는 패킷을 iptables/ip6tables에서 처리할 수 있게 해주며, overlay 모듈은 컨테이너 파일시스템에 사용하는 OverlayFS를 위해 필요합니다. net.ipv4.ip_forward = 1은 노드가 패킷을 다른 노드로 포워딩할 수 있도록 허용합니다. 이 설정은 모든 노드(마스터 + 워커)에 적용해야 합니다.

# Kernel Forwarding
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

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

sudo sysctl --system

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 필요한 sysctl 파라미터를 설정하면, 재부팅 후에도 값이 유지된다.
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

# 재부팅하지 않고 sysctl 파라미터 적용하기
sudo sysctl --system

Package 설치

kubeadm, kubelet, kubectl 세 패키지를 설치합니다. 각 패키지의 역할은 다음과 같습니다.

  • kubeadm — 클러스터 초기화(init)와 노드 합류(join)를 담당하는 부트스트랩 도구
  • kubelet — 각 노드에서 실행되며 Pod 생명주기를 관리하는 에이전트
  • kubectl — 클러스터를 제어하는 CLI 클라이언트

apt-mark hold로 패키지를 고정하면 apt upgrade로 인한 의도치 않은 버전 업그레이드를 방지할 수 있습니다. Kubernetes는 컴포넌트 버전을 맞춰 관리해야 하므로 반드시 hold 설정을 유지하고, 업그레이드 시에는 kubeadm upgrade 절차를 따릅니다.

sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl

sudo curl -fsSLo /etc/apt/keyrings/kubernetes-archive-keyring.gpg https://dl.k8s.io/apt/doc/apt-key.gpg && echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

sudo systemctl daemon-reload
sudo systemctl restart kubelet

위 방법으로 패키지를 찾지 못하는 경우(E: Unable to locate package kubelet), pkgs.k8s.io 신규 리포지토리를 사용합니다.

$ sudo apt-get install -y kubelet kubeadm kubectl
E: Unable to locate package kubelet
E: Unable to locate package kubeadm
E: Unable to locate package kubectl

# kubelet kubeadm kubectl 설치시 위 에러 발생할 경우 아래 방안으로 설치
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gpg

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.28/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.28/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl

sudo systemctl daemon-reload
sudo systemctl restart kubelet

[Master node]

kubeadm init으로 마스터 노드를 초기화합니다. --cri-socket 옵션으로 cri-dockerd 소켓을 명시하지 않으면 kubeadm이 런타임을 자동 감지하는 과정에서 오류가 발생할 수 있습니다. 초기화가 완료되면 출력 마지막에 워커 노드 join 명령어가 표시됩니다. 이 명령어의 토큰은 24시간 후 만료되므로 즉시 복사해 두거나 kubeadm token create --print-join-command로 재발급합니다.

kubeconfig 설정 후 Calico CNI를 설치합니다. CNI가 설치되기 전까지는 노드 상태가 NotReady로 표시되며, calico.yaml 적용 후 수 분 내에 Ready로 전환됩니다.

sudo kubeadm config images pull --cri-socket unix:///run/cri-dockerd.sock
sudo kubeadm init --cri-socket /var/run/cri-dockerd.sock

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

kubectl get nodes -o wide
kubectl get pods -A
kubectl describe node <master-node>

# Calico CNI 설치
curl https://raw.githubusercontent.com/projectcalico/calico/v3.26.1/manifests/calico.yaml -O
kubectl apply -f calico.yaml

kubectl get nodes
kubectl get pod --all-namespaces

[worker node]

워커 노드에서 kubeadm join 명령어를 실행하여 클러스터에 합류합니다. kubeadm init 출력에서 복사한 명령어를 그대로 사용하되, --cri-socket 옵션을 추가해야 합니다. join이 완료된 후 마스터 노드에서 kubectl get nodes를 실행하여 워커 노드가 Ready 상태로 등록되는지 확인합니다.

# kubeadm init 실행시 마지막 출력되는 명령어 사용
sudo kubeadm join x.x.x.x:6443 --token xxxxxxxxxxxx --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxx --cri-socket /var/run/cri-dockerd.sock

kubectl get nodes

kubectl 명령어 자동 완성

kubectl bash completion을 설정하면 Tab 키로 리소스명, 네임스페이스 등을 자동 완성할 수 있어 운영 편의성이 크게 향상됩니다. alias k=kubectl과 함께 설정하면 짧은 명령어로 빠르게 조작할 수 있습니다. 자세한 내용은 kubectl 자동 완성 설정 — Kubernetes 공식 문서를 참고하세요.

echo 'source <(kubectl completion bash)' >> ~/.bashrc
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc
source ~/.bashrc

설치 결과 확인

모든 노드가 정상적으로 등록되고 kube-system 파드들이 Running 상태가 되면 클러스터 구성이 완료된 것입니다. 아래 명령어로 최종 상태를 확인합니다.

# 노드 상태 확인 — 모든 노드 Ready 여야 정상
kubectl get nodes -o wide

# 시스템 파드 상태 확인 — 모두 Running 또는 Completed
kubectl get pods -n kube-system

# 클러스터 정보 확인
kubectl cluster-info

워커 노드가 NotReady로 유지될 경우 해당 노드에서 sudo systemctl status kubeletjournalctl -u kubelet -n 50으로 에러 메시지를 확인합니다. 대부분은 cgroup driver 불일치 또는 cri-dockerd 미기동으로 인한 문제입니다.

참고

참고 문서: kubeadm으로 클러스터 생성 — Kubernetes 공식 문서 · Calico 온프레미스 설치 문서