- docker swarm - 다수의 호스트(manger, worker), 여러종류의 컨테이너
- 오케스트레이션 - 여러개의 컨테이너를 관리하는 기술(스케일링, 헬스체크, 트래픽제어=배포)
쿠버네티스
컨테이너 오케스트레이션 툴, CNCF(Cloud Native Computing Foundation)의 오픈소스 컨테이너 오케스트레이션 플랫폼
kubeadm을 통한 온프레미스 클러스터 구성


1. docker 설치 - 이미지빌드를 하기 위한 도구로 사용하기 위해서
- 도커 설치
curl -fsSL https://get.docker.com -o get-docker.sh
chmod +x get-docker.sh
./get-docker.sh
- 도커 재시작 스크립트 스케쥴링
sudo tee /root/check_ip_and_restart_docker.sh<<EOF #!/bin/bash if ! ip add | grep -q 172.17; then systemctl restart docker fi EOF |
- 스케쥴 관리 → 2번 기본 vim 편집기
chmod 777 /root/check_ip_and_restart_docker.sh
crontab -e
* * * * * /root/check_ip_and_restart_docker.sh
2. 디스크 40GB 추가확장

vgextend ubuntu-vg /dev/sdb
lvextend -l +100%FREE -n /dev/mapper/ubuntu--vg-ubuntu--lv
resize2fs /dev/mapper/ubuntu--vg-ubuntu--lv
3. yaml 수정도구
vi ~/.vimrc
" Enable file type detection filetype on " Enable syntax highlighting syntax on " Enable auto-indentation for YAML files autocmd FileType yaml setlocal autoindent smartindent expandtab shiftwidth=2 tabstop=2 autocmd FileType yml setlocal autoindent smartindent expandtab shiftwidth=2 tabstop=2 |
설정 끝 !
이제 init 0 후 "k8s-tem" full clone으로 생성해두자 !
- ubun-tem clone → master
- master clone → k8s-tem
- master clone → worker-1, worker-2
- k8s-tem 제작

- worker-1, 2 노드를 복제


# 각각 .100 .110 .120으로 변경
vi /etc/netplan/00-installer-config.yaml
netplan apply
# 각각 vm 이름과 동일하게 호스트네임 설정
hostnamectl set-hostname master
hostnamectl set-hostname worker-1
hostnamectl set-hostname worker-2
클러스터 공통 설정(master, worker-1, worker-2)
1. 네트워크 설정

- 네트워크 관련 모듈을 불러오는 명령어
modprobe overlay
modprobe br_netfilter
- 쿠버네티스와 컨테이너런타임의 네트워크 트래픽을 제어하기위한 설정 파일 생성
tee /etc/sysctl.d/kubernetes.conf<<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF |
tee /etc/modules-load.d/containerd.conf <<EOF overlay br_netfilter EOF |
- 설정 반영
sysctl --system
2. 가상메모리 중지 및 비활성화
가상 메모리(swap) → RAM 부족할때 hard 땡겨다 쓰는데...
쿠버네티스 클러스터는 가상메모리가 활성화 되어있으면 클러스터가 구성이 안된다 !
- 가상메모리 중지
swapoff -a
- 클러스터가 재시작됐을때도 스왑이 off 상태여야 하므로, 자동마운트 해제
vi /etc/fstab

- 직접 들어가서 수정하지 않고 sed로 변경하는 법(복붙하다보면 안될수도 있음)
sed -i '/^\/swap.img/s/^/#/' /etc/fstab

3. CRI(Container Runtime Interface) 설치 - containerd
- pod - 쿠버네티스 기본단위, 최소단위
- CRI - pod 안에 들어갈 container를 어떤 것으로 만들지 → containerd 사용

- gpg키 다운로드
gpg키 - 내가 설치할 패키지의 무결성을 검증하기 위한 키
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
- 레포지토리에 목록 추가
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
- 레포 갱신
apt-get update -y
- CRI(containerd) 설치
apt-get install -y containerd.io
- containerd 설정파일 디렉토리 생성
mkdir -p /etc/containerd
- 기본 설정을 포함한 설정파일 생성
containerd config default>/etc/containerd/config.toml
- 설정 후 재시작
systemctl restart containerd
systemctl enable containerd
4. 쿠버네티스 v1.30 설치(kubectl, kubelet, kubeadm)
쿠버네티스 클러스터 명령어
- kubectl - k8s 클러스터에 REST API 요청(https로 api 요청)하기 위한 명령어
이 명령어와 인증/인가 파일만 있다면 어디서든 내 클러스터에 요청 가능함
클러스터에 요청하기 위한 명령어 - kubelet - 노드 관리자
- kubeadm - 클러스터 자체를 구성하고 관리하는 도구
- 설치 방법
https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
kubeadm 설치하기
이 페이지에서는 kubeadm 툴박스 설치 방법을 보여준다. 이 설치 프로세스를 수행한 후 kubeadm으로 클러스터를 만드는 방법에 대한 자세한 내용은 kubeadm으로 클러스터 생성하기 페이지를 참고한다.
kubernetes.io
- 필요한 패키지 설치
apt-get install -y apt-transport-https ca-certificates curl
- 아래 경로가 없으면 생성
mkdir -p /etc/apt/keyrings
- gpg키 다운
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/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.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
- 레포 목록 업데이트
apt-get update -y
- 명령어 3가지 설치
apt-get install -y kubelet kubeadm kubectl
- 버전이 업데이트 되더라도 고정
apt-mark hold kubelet kubeadm kubectl
- kubelet 재시작
systemctl restart kubelet
systemctl enable kubelet
공통 설정 끝 !
벤 먹으면 도커 로그인 !
master 노드 구성
- 클러스터 설치를 위한 이미지 풀링
kubeadm config images pull --cri-socket unix:///run/containerd/containerd.sock --kubernetes-version v1.30.3

- DNS - IP를 영문주소로 대체
- kube-proxy - 수직적 트래픽, 클러스터 내 서비스의 트래픽을 적절한 Pod로 라우팅(트래픽 분산과 라우팅)
- coredns - 수평적 트래픽, Pod 수를 늘려서 수평 확장(horizontal scaling)
요청이 많아지면 CoreDNS 인스턴스를 여러 개 띄워서 DNS 요청을 나눠 처리
- 릴리스된 버전 목록 확인 가능
https://github.com/kubernetes/kubernetes/releases
Releases · kubernetes/kubernetes
Production-Grade Container Scheduling and Management - kubernetes/kubernetes
github.com
- 클러스터 초기화 + control plane 구성
kubeadm init --pod-network-cidr=10.244.0.0/16 --upload-certs --kubernetes-version=v1.30.3 --cri-socket unix:///run/containerd/containerd.sock --ignore-preflight-errors=all
# --ignore-preflight-errors=all : 에러 생기면 무시
# --pod-network-cidr=10.244.0.0/16 : 나중에 네트워크애드온의 대역과 맞춰줘야 함. 10.244.0.0/16 대역은 flannel이라는 네트워크애드온의 대역
# --upload-certs : 인증, 인가하기 위한 파일을 자동으로 배포할 수 있게 해주는 옵션

- init했을때 나오는 토큰을 복붙 (나중에 워커노드가 말썽을 일으키면 초기화 해야하는데, 다시보기 힘듬)
vi token.txt


# kubectl이라는 명령을 치면, ~/.kube/config 파일에 있는 정보를 토대로 클러스터에 API 요청을 한다.
# ~/.kube/config 파일에는 "클러스터의 주소 + 인증/인가"에 대한 정보가 들어있다.
# kubectl 명령을 치려면 결국 kubectl 명령어 설치는 물론 config 파일도 구성해야 한다.
- config 설정 전

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

- 설정 후

worker 노드 구성
- join 명령을 워커노드(worker-1, worker-2)에 복붙
kubeadm join 211.183.3.100:6443 --token bwffkx.fn37f426xuuisikp --discovery-token-ca-cert-hash sha256:22040a00b0c4565065b14a4616dc8146bd0919025c916acdf7ab38666e371de8 --cri-socket unix:///run/containerd/containerd.sock

♨ 혹시 클러스터 깨지거나 했을때, 아래 명령을 통해 3노드를 전부 리셋하고 다시 init 해서 클러스터를 재구성(최악의 경우)
kubeadm reset --cri-socket unix:///run/containerd/containerd.sock
쿠버네티스 클러스터 트러블슈팅
- 모든 pod 삭제
kubectl delete pod --all
- test1, test2 pod 생성
kubectl run test1 --image=public.ecr.aws/docker/library/nginx:alpine
kubectl run test2 --image=public.ecr.aws/docker/library/nginx:alpine
kubectl create deploy test --replicas=2 --image=public.ecr.aws/docker/library/nginx:alpine




♨ 만약 0/1이 뜬다면
0/1 뜨는 pod descibe → flannel 원인임을 확인 → 다시 적용 → 확인
kubectl describe pod -n kube-system coredns-55cb58b774-54mxh
kubectl apply -f ~/kube-flannel.yml
kubectl get pod -n kube-flannel
- 모든 파드를 삭제
root@master:~# kubectl delete pod --all -n kube-system
- 다시 비정상 파드주소에 curl

- 그래도 안되면 일단 모든 노드 재부팅
init 6

그래도 안된다면 최악의 상황
- kubectl delete -f kube-flannel.yml로 flannel CNI 삭제
- 모든 노드에서 kubeadm reset으로 클러스터 리셋
- 재부팅을 해서 CNI 관련된 호스트의 설정값들을 초기화
- kubeadm init 및 kubeadm join으로 클러스터 재구성

네트워크 애드온의 종류 = calico , flannel 등
이런 애드온들을 CNI(Container Network Interface) 라고도 부른다.
CNI 설치(master)

# 원하는 상태(Desired state) = 바람 = 매니페스트 파일
- 파일(-f)에 담긴 나의 바램(yml 파일)을 내 클러스터에 반영(apply)
root@master:~# kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
- wget으로 웹에서 받아오는 것도 가능
나중에 클러스터에 네트워크 문제가 생겼을 경우 재설치 할 수도 있기 때문에 파일도 저장해두기
wget https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

vi kube-flannel.yml

# kubeadm에서 파드네트워크를 정한 이유
: 만약에 내가 calico같은 애드온을 설치해야한다면, 실제 내 pod-network와 CNI의 대역을 맞춰줘야한다.
# calico의 경우를 정한 이유
: calico의 경우 일반적으로 설치 매니페스트파일 상의 기본 대역이 192.168.0.0/16으로 되어있다.
- kubectl get 명령어 사용해 설치 확인
root@master:~# kubectl get pod -n kube-system
root@master:~# kubectl get pod -n kube-flannel

쿠버네티스 컴포넌트 ★

♨ 트래픽이 어떻게 흘러가는지, 컴포넌트 별로 무슨 역할을 하는지
api(apllication programming interfacer) - 인터페이스, 매개체 역할(외부 요청, 명령어를 받아옴)
- kube-apiserver - 외/내부 요청을 받는 서버(관리자 역할, 조율), controller나 scheduler의 주시대상 + 인증/인가 정보
ex. 호텔지배인 - etcd - 클러스터 및 모든 리소스에 대한 정보를 <key>:<value> 형태로 저장하는 일종의 데이터베이스
ex. 장부 - kube-scheduler - 생성될 리소스들을 어떤 노드에 배치할지 결정하는 역할(스케쥴링)
ex. 호텔 로비 직원 - kube-controller - 다양한 컨트롤러들이 존재, 원하는 상태(desired state, 바람)에 현재상태(status)가 수렴하도록 계속 모니터링, 문제가 생기면 고치거나 리소스 재생성
ex. 하우스키퍼

노드에 존재하는 컴포넌트
- kubelet - 노드 관리자, 실질적으로 각 노드에 리소스를 관리
- kube-proxy - 노드 안과 밖을 넘나드는 수직적인 트래픽을 관리
네트워크 애드온(CNI) - 네트워크에 관련된 coredns와 kube-proxy를 위해 필요한 부가 기능
- test-pod라는 이름을 갖는 pod를 생성
root@master:~# kubectl run test-pod --image public.ecr.aws/docker/library/nginx:alpine
- pod 정보를 보고싶을때 (get)
root@master:~# kubectl get pod

- pod 정보 실시간 모니터링
root@master:~# watch kubectl get pod


- test-pod라는 이름을 갖는 pod를 삭제
root@master:~# kubectl delete pod test-pod
root@master:~# kubectl delete pod watch-pod


- 아웃풋(-o)을 좀 폭넓게 보고싶을때 (배치된 노드, IP 확인)
root@master:~# kubectl get pod -o wide

# 오버레이네트워크가 구성되어 있고, 노드들이 pod 네트워크를 알고있기 때문에, master 노드에서 worker1 노드에 있는 pod와 통신이 가능함
# kubectl get pod -n kube-system을 쳤을때, 0/1 이런 pod들이 존재한다면, 클러스터가 비정상일 확률이 높고, 위와 같은 방법으로도 클러스터의 정상여부 확인 가능함
# 쿠버네티스 수업에서 '클러스터 키세요~' 하면 일단 저걸 확인
- 완전 자세히 묘사
root@master:~# kubectl describe pod test-pod

- 존재하지 않는 이미지로 pod를 생성 후 확인
root@master:~# kubectl run bad-pod --image=pcmin-jjang
root@master:~# kubectl describe pod bad-pod
- pod 삭제
root@master:~# kubectl delete pod test-pod bad-pod
- pod 생성
root@master:~# kubectl run test-pod --image public.ecr.aws/docker/library/nginx:alpine --dry-run=client -o yaml > test-pod.yml
# --dry-run=client : 서버엔 전달을 안하고 리허설을 해보겠다(가짜)
# -o yaml : yaml형태로 출력해서
# test.pod.yml이라는 매니페스트(명세표) 파일로 리다이렉션해서 만들겠다.

root@master:~# vi test-pod.yml


# status는 매니페스트에는 존재하지 않고, etcd 같은곳에 존재한다.
# x친 부분들을 삭제
매니페스트 파일의 필수항목

# apiVersion: '과자'라는 카테고리
# kind: '새우깡'. 새우깡은 '과자'라는 카테고리에 속함,
- test-pod.yml 파일(-f) 에 담겨있는 나의 바람이 클러스터에 반영(apply)
root@master:~# kubectl apply -f test-pod.yml
root@master:~# kubectl delete -f test-pod.yml

실습1)
worker1 노드에서 kubectl로 master노드의 apiserver에 요청 가능한 상태를 만들어보세요. 요청이 가능하다면,
- cli명령으로 ECR갤러리의 httpd:latest 이미지로 구성된 pod를 한번 띄워보세요.
- --dry-run으로 ECR갤러리의 httpd:latest 이미지로 구성된 pod를 생성하기위한 매니페스트 파일(my-httpd.yml)을 만들어보세요.
- my-httpd.yml파일을 적절하게 수정하여 pod의 이름이 test인 파드를 만들어보세요.

풀이1)
scp 사용 - best
- IP로 master 접근 가능한지 확인
root@worker-1:~# curl -k https://211.183.3.100:6443/version

- .kube 디렉토리 생성
root@worker-1:~# mkdir -p /root/.kube
- 마스터에서 kubeconfig 복사
root@master:~# scp /root/.kube/config root@211.183.3.110:/root/.kube/config

root@worker-1:~# kubectl get nodes

1. cli명령으로 ECR갤러리의 httpd:latest 이미지로 구성된 pod를 한번 띄워보세요.
root@worker-1:~# kubectl run test-pod1 --image public.ecr.aws/docker/library/httpd:latest

2. --dry-run으로 ECR갤러리의 httpd:latest 이미지로 구성된 pod를 생성하기위한 매니페스트 파일(my-httpd.yml)을 만들어보세요.
root@worker-1:~# kubectl run test-pod2 --image public.ecr.aws/docker/library/httpd:latest --dry-run=client -o yaml > my-httpd.yml
root@worker-1:~# vi my-httpd.yml

root@worker-1:~# kubectl apply -f my-httpd.yml

3. my-httpd.yml파일을 적절하게 수정하여 pod의 이름이 test인 파드를 만들어보세요.
root@worker-1:~# vi my-httpd.yml

root@worker-1:~# kubectl apply -f my-httpd.yml

풀이2)
복붙
root@master:~# cat ~/.kube/config
# 이 파일의 내용만 worker1로 옮기고, kubectl 명령을 설치만 하면 된다.

# worker-1에서 kubectl 명령을 쳐보면 요청에 제대로 안간다.
root@worker-1:~# mkdir -p ~/.kube
root@worker-1:~# vi ~/.kube/config
root@worker-1:~# chown (id−u):(id -g) $HOME/.kube/config
# 아까 마스터에서 복사한 config 파일의 내용을 붙여넣기

1. pod 생성
kubectl run my-httpd --image public.ecr.aws/docker/library/httpd:latest

1-2. 드라이런
kubectl run my-httpd --image public.ecr.aws/docker/library/httpd:latest --dry-run=client -o yaml > my-httpd.yml

vi my-httpd.yml
apiVersion: v1 kind: Pod metadata: name: my-httpd spec: containers: - image: public.ecr.aws/docker/library/httpd:latest name: my-httpd |

3. pod의 이름 수정
apiVersion: v1 kind: Pod metadata: name: test spec: containers: - image: public.ecr.aws/docker/library/httpd:latest name: test-con |
root@worker-1:~# kubectl apply -f my-httpd.yml

kubectl run = docker run
# cli로 명령 전달
kubectl apply -f = docker compose up, docker stack deploy
# 내가 원하는 상태(Desired state)가 미리 정의된 매니페스트 파일(yml)을 미리 구성해놓고 apply 해서 반영
# run에 비해 편한점 : 매니페스트 파일을 업데이트 후 다시 apply를 하면 지웠다가 다시 만들 필요없이 변경사항만 반영할 수 있다.
root@master:~# kubectl delete pod --all
# 모든 파드 삭제