

일단 프로메테우스를 설치하는데, 헬름이 설치되어 있지 않아서(helm version 했을 때 찾을 수 없었다.)
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
위 명령어를 통해 헬름을 설치해줬다.
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

helm repo update

sudo kubeadm reset -f
sudo systemctl stop kubelet
sudo systemctl stop containerd
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/etcd
sudo rm -rf /var/lib/kubelet
sudo systemctl start containerd
sudo kubeadm init --pod-network-cidr=192.168.0.0/16

하면 이렇게 join할 수 있는 명령어가 뜬다.
이 작업은 kubectl 명령어를 쓸 수 있게 admin.conf 를 내 홈디렉토리에 등록하는 작업이다.
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
하면
master 1개가 NotReady로 뜨게 된다.

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/calico.yaml
명령어를 실행한다.

그럼 다음과 같이 created 되는 것을 확인할 수 있는데,
kubectl get pods -n kube-system
kubectl get nodes
해서 보면 노드가 Ready로 바뀌는 것을 확인할 수 있다.

워커용 새 노드에서 다음과 같이 명령어를 실행한다.
sudo kubeadm reset -f
sudo systemctl stop kubelet
sudo systemctl stop containerd
sudo rm -rf /etc/kubernetes /var/lib/kubelet /var/lib/etcd
sudo systemctl start containerd (필요 시)
ping -c 3 192.168.174.132
했을 때

다음과 같이 되는 것을 확인할 수 있다.
나의 경우에는 join하려는 워커 노드 hostname이 doram인데,
그런데 클러스터 안에 이미 마스터 노드 이름도 doram 이라서
에러가 떴다. 그래서 워커의 hostname을 바꿔주었다.
sudo hostnamectl set-hostname worker1
그런 다음,
sudo nano /etc/hosts

이렇게 /etc/hosts 안에서 doram -> worker1로 바꿔주었다.
그런 다음 다시, kubelet 데이터를 완전 삭제해주었다.
sudo kubeadm reset -f
sudo systemctl stop kubelet
sudo systemctl stop containerd
sudo rm -rf /etc/kubernetes /var/lib/kubelet /var/lib/etcd
sudo systemctl start containerd
sudo kubeadm join 192.168.174.132:6443 --token mnugb9.h4zqi87hdb165l38 \
--discovery-token-ca-cert-hash sha256:5c84587d1772dbdad74ee30f3444ebf7cced2a35a3ea371bfdc82a4f725b964e

이제 조인이 완벽하게 되는 것을 확인할 수 있다.

이제 마스터 노드에서 2개의 노드가 뜨는 것을 확인할 수 있다.
이제 컨트롤 플레인에서 프로메테우스를 설치하면 된다.
helm install prometheus prometheus-community/prometheus \
--set pushgateway.enabled=false \
--set alertmanager.enabled=false \
--set server.service.type="LoadBalancer" \
--set server.global.scrape_interval="15s" \
--set server.global.evaluation_interval="15s" \
--set server.extraFlags[0]="web.enable-lifecycle" \
--set server.extraFlags[1]="storage.tsdb.no-lockfile" \
--namespace=monitoring \
--create-namespace
위 명령어를 실행하여 프로메테우스를 설치해준다.

kubectl get pods -n monitoring

kubectl get svc -n monitoring

이제 프로메테우스 설치가 성공적으로 끝이난 줄 알았다.
알고보니 프로메테우스 서버에서 external ip가 pendding이 아니라 할당이 되어야 하는 것이었다.
사유는 다음과 같았다.
external ip가 계속 pending 뜨는 이유는 100% 확률로
너 지금 사용하는 환경(VMware / Fusion / VirtualBox / Parallels 등)은
LoadBalancer 타입의 서비스를 자동으로 할당해주는 클라우드가 아니기 때문이다.
즉:
- AWS → ELB 자동 생성됨
- GCP → GLB 자동 생성됨
- Azure → LB 자동 생성됨
- VM 방식의 로컬 쿠버네티스 → LB 없음 → pending 뜸
따라서 로드밸런서 기능을 쓰기위해 MetalLB를 설치하기로 했다.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
네트워크가 192.168.174.0/24라면
파일 명 : metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
namespace: metallb-system
name: default-pool
spec:
addresses:
- 192.168.174.200-192.168.174.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
namespace: metallb-system
name: l2
spec:
ipAddressPools:
- default-pool
적용 명령어
kubectl apply -f metallb-config.yaml
했는데 에러가 떴다.

그래서 MetalLB상태를 확인하고 기존 MetalLB를 삭제하고 다시 설치하기로 했다.
kubectl delete ns metallb-system
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.3/config/manifests/metallb-native.yaml
kubectl get pods -n metallb-system

이렇게 Running 상태가 떠야 하는데, evicted 상태가 떴다.
메모리나 디스크가 부족하기 때문에 뜬 것이다.

/etc/netplan/*.yaml열고 내용을 수정해준다.
sudo nano /etc/netplan/00-installer-config.yaml
network:
version: 2
ethernets:
enp2s0:
dhcp4: false
addresses:
- 192.168.174.132/24
routes:
- to: 0.0.0.0/0
via: 192.168.174.2
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1
sudo chmod 600 /etc/netplan/00-installer-config.yaml
그리고 해당 명령을 실행해서 퍼미션 문제를 해결한다.
DHCP 클라이언트를 종료해준 후 , 적용해준다.
sudo dhclient -r enp2s0
sudo netplan apply
마지막으로 인터페이스를 재시작해준다.
sudo ip link set enp2s0 down
sudo ip link set enp2s0 up
sudo ip link set enp2s0 down 하면 통신이 끊겨서
가상환경 안에서 코드를 쳐줘야 한다.

이렇게 완벽하게 올라온 것을 확인할 수 있다.
클러스터가 정상인지 확인해준다.

정상인 것을 확인할 수 있으며, 다시 MetalLB 삭제 후 재설치해준다.
그런 후 에러가 생겼다.
Ubuntu는 systemd-resolved 때문에 /etc/resolv.conf 를 직접 수정해도 무효일 때가 많다.
따라서 resolv.conf 직접 수정 후 systemd-resolved 재시작해준다.
sudo bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
sudo systemctl restart systemd-resolved
이후 ping 테스트를 하여 답이 오면 해결된 것이다.
ping -c 3 raw.githubusercontent.com
했는데 네임스페이스가 망가지고 Ping테스트도 안되어 근본부터 고치기로 했다.
현재 나의 상태는
➡ default route(인터넷으로 나가는 길) 이 사라지고,
➡ 그래서 8.8.8.8도 못 나가고, github도 못 나간다.
➡ NAT 게이트웨이(192.168.174.2)로 나가는 경로가 없다.
이 3가지의 상태이며 즉, LAN안에서는 통신이 가능한 상태이며 인터넷은 안되는 상태이다.
그래서 default route추가하여 해결하기로 했다.
sudo ip route add default via 192.168.174.2 dev enp2s0
하여 디폴트 루트를 추가하였다.

이제 디폴트 루트도 성공적으로 추가되고 ping도 제대로 되는 것을 확인할 수 있다.

그런데 깃허브로의 ping test는 성공하지 못한 것을 확인할 수 있다.
이제 인터넷 자체는 복구되었는데
DNS만 고장난 상태이다.
이제 DNS만 고치면 된다.
일단 resolv.conf를 재생성해준다.
/etc/resolv.conf 는 systemd-resolved가 관리해야 해야하기 때문에
다음과 같이 명령어를 실행해준다.
sudo rm -f /etc/resolv.conf
sudo ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
sudo systemctl restart systemd-resolved
그런 다음, 확인해준다.

정상인 것을 확인할 수 있다.
또한,
Ubuntu의 기본 DNS가 깨졌기 때문에
강제로 8.8.8.8을 넣어주면 해결할 수 있다.
sudo mkdir -p /etc/systemd/resolved.conf.d
echo -e "[Resolve]\nDNS=8.8.8.8\nFallbackDNS=1.1.1.1" | sudo tee /etc/systemd/resolved.conf.d/dns.conf
sudo systemctl restart systemd-resolved
후, DNS를 확인해준다.
resolvectl status

이제 DNS가 정상인 것을 확인할 수 있으며 정말 마지막으로 ping 테스트를 진행해준다.
ping -c 3 raw.githubusercontent.com

실패를 했다.
이정도까지 되니 머리가 점점 아파져왔지만
원인을 찾아보니 resolv.conf 링크 상태 확인을 해야한다고 나와 있어서, 다시 점검해보기로 했다.

나의 경우 이렇게, 정상으로 나와서 이것은 문제가 아닌 것으로 판별되었다.
시원하게 어댑터를 리셋시키기로 했다.

여기에서

Autodetect로 바꾸고, vm을 재부팅해야한다.
바꾼 후,
sudo reboot
명령어를 쳐서 재부팅시켜준다.
그래도 해결이 안됐다.

현재 이렇게 디폴트 라우트가 두개라 삭제해주기로 했다.
sudo ip route del default via 192.168.219.1 dev enp2s0
sudo ip route del 192.168.219.0/24 dev enp2s0
그리고 추가로
sudo ip route del 168.126.63.1 dev enp2s0
얘도 삭제를 한다.(219 대역이 만든 잘못된 라우트다.)
sudo nano /etc/netplan/00-installer-config.yaml
netplan 고정 IP 설정을 열고 내용을 다음과 같이 바꿔준다.
network:
version: 2
ethernets:
enp2s0:
dhcp4: false
addresses:
- 192.168.174.132/24
routes:
- to: default
via: 192.168.174.2
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1
이제 퍼미션 오류를 해결하기 위해
다음 명령어를 쳐준다.
sudo chmod 600 /etc/netplan/00-installer-config.yaml
그리고 netplan 파일을 확인해보았다.
sudo cat /etc/netplan/00-installer-config.yaml

이렇게 결과가 떴다.
/etc/netplan/00-installer-config.yaml 파일 자체가 없다는 뜻이며,
그래서 netplan이 DHCP 기본 설정으로 자동 revert 돼서
192.168.219.x 경로가 자꾸 생겨난 것이었다.
그래서 netplan 디렉토리 안 상태를 확인해보기로 했다.

이렇게 현재 두개가 나오는데, 50-cloud-init.yaml은 cloud-init 기본 설정이 계속 네트워크를 덮어쓰는 원인이며
파일 이름 변경해서 netplan이 무시하도록 만들기로 하였다.
sudo mv /etc/netplan/50-cloud-init.yaml /etc/netplan/50-cloud-init.yaml.bak
또한 다음 명령어를 통해 00-installer-config.yaml 파일을 수정한다.
sudo nano /etc/netplan/00-installer-config.yaml
network:
version: 2
renderer: networkd
ethernets:
enp2s0:
dhcp4: false
addresses:
- 192.168.174.132/24
routes:
- to: default
via: 192.168.174.2
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1
또한 퍼미션을 수정한 뒤 설정을 적용한다.
sudo chmod 600 /etc/netplan/00-installer-config.yaml
sudo netplan apply

이렇게 정상적용된 것을 확인할 수 있다.
마지막으로 ip와 라우터를 확인해준다.
ip a
ip route

그리고 제일 문제가 많았던 ping 테스트도 해준다.
ping -c 3 192.168.174.2
ping -c 3 8.8.8.8
ping -c 3 google.com

실패했다. 실패 원인은,
ip도 붙어있고, 라우팅 테이블도 정상이고, DNS도 설정되어 있ㅋ는데
게이트웨이가 죽어 있어서 문제가 생긴 것이다.
일단 vm을 재부팅 한 후 ip a 명령어를 통해 다시 ip와 게이트웨이를 확인한다.
sudo reboot
ip a
ip route
재부팅을 하고 확인을 하니 이렇게 나왔다.

network 설정에 들어가서 브릿지 -> wifi로 선택하기로 했다.

다음과 같이 설정했다.
그리고 vmWare을 끄고 다시 대역을 확인했다.

그런데 공유기 대역이 특이해서 브릿지가 꼬여서 맥이랑 NAT으로 연결로 설정을 바꾸기로 했다.

ip a
ip route
ping -c 3 8.8.8.8
ping -c 3 google.com
한 결과이다.

인터넷과 모든것이 정상이 되었다.
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.3/config/manifests/metallb-native.yaml
또한 MetalLB config 파일은 다음과 같이 설정해준다.
파일 명 :metallb-config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 192.168.174.200-192.168.174.220
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: advert
namespace: metallb-system
그런 다음 확인해준다.
kubectl get pods -n metallb-system


kubelet 서버가 제대로 안 올라온 상태인것이다.
또한 k8s 클러스터를 제대로 설치해준다.
다음과 같이 실행한다.
sudo swapoff -a
sudo apt update && sudo apt upgrade -y
sudo apt install containerd -y

그다음 컨테이너 기본 설정을 해준다.
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
sudo apt-get install -y apt-transport-https ca-certificates curl
sudo curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg \
https://packages.cloud.google.com/apt/doc/apt-key.gpg

echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] \
https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt update
sudo apt install -y kubeadm kubelet kubectl
sudo systemctl enable kubelet

설치가 잘 되었다.
sudo kubeadm init \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=192.168.174.132
이제 해당 명령어를 실행하면 kubectl이 동작하게 된다.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.2/manifests/calico.yaml

이렇게 떴는데, 이는 kubeadm init을 안 해서 그렇게 된 것이다.
저장소 잘못된 파일 제거를 한 후 init을 진행한다.
sudo rm /etc/apt/sources.list.d/kubernetes.list
sudo apt update
그다음 kubeconfig를 설정해준다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
과거 kubeletdl 10250 프로세스를 잡고 있어서 실패를 했다.
그래서 문제 프로세스를 종료 후, 이전 kubernetes 데이터를 완전 삭제 후, 재시작 준비 및 다시 init을 실행했다.
sudo systemctl stop kubelet
sudo kill -9 864
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/kubelet
sudo rm -rf /var/lib/etcd
sudo rm -rf /etc/cni/net.d
sudo kubeadm init \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=192.168.174.132
sudo kubeadm init \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=192.168.174.132

거의 다 됐는데 마지막에 에러가 떴다.


로그를 확인해보니, 로그가 반복해서 뜨고 있는데
예전에 실패했던 kubeadm init 의 잔여 컨테이너·샌드박스가 containerd 안에 남아 있어서
새로운 etcd / apiserver / scheduler static pod 를 만들려고 하면
containerd 가 이름이 중복됐다고 거부하는 상황이다.
그래서 excd sandbox 를 못 만드는 것이다.
해결 절차는 다음과 같다.
containered 에 있는 모든 kube관련 컨테이너를 조회하고 전부 삭제한다.
그리고 kubeadm 잔여 파일들을 삭제한다.
sudo crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -a | grep kube
sudo crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock rm -f $(sudo crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock ps -aq)
sudo crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock sandboxes
sudo rm -rf /etc/kubernetes
sudo rm -rf /var/lib/kubelet
sudo rm -rf /var/lib/etcd
sudo rm -rf /etc/cni/net.d
sudo rm -rf /run/kubeadm
1) containered 정리 및 재시작
sudo systemctl restart containerd
2) 현재 Sandbox / Pod 상태 다시 확인
sudo crictl --runtime-endpoint unix:///var/run/containerd/containerd.sock pods
sudo crictl ps -a

1) /etc/kubernetes/manifests 내부 파일 존재 확인
ls -l /etc/kubernetes/manifests
했을 때, 밑 4개가 있어야 한다.
etcd.yaml
kube-apiserver.yaml
kube-controller-manager.yaml
kube-scheduler.yaml

다행히도, 존재했다.
2) kube-apiserver 실제 오류 로그 확인
sudo crictl logs d330a96a930dd
여기서 apiserver가 왜 죽었는지 로그가 보인다.

3) etcd 오류 로그 확인
sudo crictl logs 3c5ada0e23417

로그를 보니 문제가 보였다. 인증서 문제였다.
1) apiserver에서 사용하는 etcd 인증서 실제로 존재하는지 확인
sudo grep -R "etcd" -n /etc/kubernetes/manifests/kube-apiserver.yaml

확인해보니 apiserver 인증서 경로가 잘못되었다.
그래서 인증서를 재생성 하기로 했다.
sudo kubeadm init phase certs etcd
sudo kubeadm init phase certs apiserver-etcd-client
인증서가 잘 생성되었는지 다음 명령어를 통해 확인할 수 있다.
sudo ls -l /etc/kubernetes/pki/ | grep apiserver-etcd-client

이 두개가 떠있는 것을 확인하여 정상 생성된 것을 확인할 수 있다.
그런데 확인해보니

apiserver 가 계속 죽는 이유는, etcd 연결 주소가 잘못되어서 붙을 수 있도록 ip를 변경해준다.
sudo nano /etc/kubernetes/manifests/kube-apiserver.yaml
를 통해 컨피그 파일을 열어준 후,

여기에서
--etcd-servers=https://127.0.0.1:2379 이 줄을,
--etcd-servers=https://192.168.174.132:2379
이렇게 수정해준다.
그런 다음 조금 기다린 후,
sudo crictl ps -a | grep kube-apiserver
journalctl -u kubelet -f
kubectl get nodes
해당 명령어를 치고 apiserver가 running상태가 되는 것을 확인한다.
evicted가 떴다.
poweroff 후, 메모리랑 cpu를 늘려줬다.
vm 을 재부팅해준다.
1)kubelet 상태 확인
sudo systemctl status kubelet
active (running) 떠야한다.
2)노드 상태 확인
kubectl get nodes -o wide
여기서 ready가 떠야 하는데, 응답 불가 상태가 나왔다.
3) kube-apiserver 파드 컨테이너 로그 확인
sudo crictl ps -a | grep kube-apiserver

4) 가장 최근 kube-apiserver 컨테이너 로그 확인
sudo crictl logs 90aa9e1ae7f8e

5) etcd 컨테이너 확인
sudo crictl ps -a | grep etcd

하고 나온 컨테이너 id(3c5ada0e23417)로
sudo crictl logs 3c5ada0e23417 | head -n 40
하여 로그를 확인해준다.
확인해보니 인증서 재발급이 필요한 상황으로 판단되었다.
sudo kubeadm init phase certs apiserver-etcd-client --v=5

재발급을 하려는데 이미 있다고 재생성이 되지 않는다.
따라서 강제로 기존 인증서를 백업 후 삭제해준다.
1) 기존 인증서 강제로 백업 후 삭제
sudo mv /etc/kubernetes/pki/apiserver-etcd-client.crt /etc/kubernetes/pki/apiserver-etcd-client.crt.bak
sudo mv /etc/kubernetes/pki/apiserver-etcd-client.key /etc/kubernetes/pki/apiserver-etcd-client.key.bak
2) 삭제되었는지 확인
ls -l /etc/kubernetes/pki/ | grep apiserver-etcd-client
3) 인증서 강제로 재생성
sudo kubeadm init phase certs apiserver-etcd-client

4) 인증서 확인

오늘 날짜로 생성된 것을 확인할 수 있다.
sudo systemctl restart kubelet
sudo crictl ps -a | grep kube-apiserver


이렇게 에러가 떴다. kube-apiserver 컨테이너는 Running 상태인데, kubectl 이 6443 포트 접속 불가라고 나온다.
따라서 kube-apiserver 컨테이너 로그를 확인한다.
sudo crictl ps -a | grep kube-apiserver

여기에서 running 상태인 것의 로그를 확인한다.
sudo crictl logs f30b907104c4e | head -n 50
근데 컨테이너는 재시작되면서 계속 죽고 재시작되고 반복되어서
로그를 보려는 순간 죽어서
최근에 생성된 kube-apiserver 컨테이너 id를 확인하고 바로 2초 안에 로그를 찍어야 한다.

로그를 본 결과,
etcd가 죽어있어서 Kube-apiserver가 포트 6443을 못 열고 죽고 있다.
1) etcd 컨테이너 상태 확인
sudo crictl ps -a | grep etcd
2) etcd 로그 확인
sudo crictl logs 3c5ada0e23417 | head -n 50

이렇게 결과가 나왔다.
결론적으로는 etcd는 잘 떴는데, 재부팅 하는 과정에서 ip충돌이 생겼고 kube-apiserver가 etcd에 접속을 못하는 상황이다.
1) enp2s0 인터페이스 IP 중 하나만 남기고 나머지 제거
현재 enp2s0 상태 확인 후, 174.133/24 하나만 남겨야 한다.
ip a show enp2s0

따라서 secondary IP(192.168.174.133)를 제거해준다.
sudo ip addr del 192.168.174.133/24 dev enp2s0

2) netplan 확인 및 제거
sudo cat /etc/netplan/*.yaml

rm 및 vim으로 파일 삭제 및 다시 생성하기로 했다.
sudo rm -f /etc/netplan/*.yaml
sudo vim /etc/netplan/01-netcfg.yaml
network:
version: 2
renderer: networkd
ethernets:
enp2s0:
dhcp4: false
addresses:
- 192.168.174.132/24
routes:
- to: default
via: 192.168.174.2
nameservers:
addresses:
- 8.8.8.8
- 1.1.1.1
그런 다음, 네트워크를 끈다.
echo "network: {config: disabled}" | sudo tee /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg
그런 다음, 적용해준다.
sudo netplan apply
그리고 남아 있는 DHCP IP를 삭제해준다.
sudo ip addr del 192.168.174.133/24 dev enp2s0 2>/dev/null
그리고 재부팅해준다.
그리고 ip를 확인해준다.

1) Kubelet 재시작
sudo systemctl restart kubelet
2) apiserver 컨테이너 상태 확인
sudo crictl ps -a | grep kube-apiserver
api server Running인 것까지 확인했는데,
3) apiserver 로그 확인
sudo crictl logs 52479dc8eb402 | head -n 50
4) etcd 붙었는지 확인
sudo crictl ps -a | grep etcd

왜 에러가 떴는지 로그는 정상적으로 나와서
sudo systemctl stop kubelet
sudo rm -rf /var/lib/etcd
sudo systemctl start kubelet
sudo crictl ps -a | grep etcd
다음 명령어를 실행해보기로 했다.

1) etcd manifest 실제 존재 확인
sudo ls -l /etc/kubernetes/manifests/

여기에 etcd.yaml 파일이 있으므로 내용을 확인해본다.
2) etcd manifest 내용 확인
sudo cat /etc/kubernetes/manifests/etcd.yaml
doram@doram:~$ sudo cat /etc/kubernetes/manifests/etcd.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
kubeadm.kubernetes.io/etcd.advertise-client-urls: https://192.168.174.132:2379
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://192.168.174.132:2379
- --cert-file=/etc/kubernetes/pki/etcd/server.crt
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --experimental-initial-corrupt-check=true
- --experimental-watch-progress-notify-interval=5s
- --initial-advertise-peer-urls=https://192.168.174.132:2380
- --initial-cluster=doram=https://192.168.174.132:2380
- --key-file=/etc/kubernetes/pki/etcd/server.key
- --listen-client-urls=https://127.0.0.1:2379,https://192.168.174.132:2379
- --listen-metrics-urls=http://127.0.0.1:2381
- --listen-peer-urls=https://192.168.174.132:2380
- --name=doram
- --peer-cert-file=/etc/kubernetes/pki/etcd/peer.crt
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd/peer.key
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.crt
image: registry.k8s.io/etcd:3.5.15-0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 8
httpGet:
host: 127.0.0.1
path: /health?exclude=NOSPACE&serializable=true
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
name: etcd
resources:
requests:
cpu: 100m
memory: 100Mi
startupProbe:
failureThreshold: 24
httpGet:
host: 127.0.0.1
path: /health?serializable=false
port: 2381
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 15
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priority: 2000001000
priorityClassName: system-node-critical
securityContext:
seccompProfile:
type: RuntimeDefault
volumes:
- hostPath:
path: /etc/kubernetes/pki/etcd
type: DirectoryOrCreate
name: etcd-certs
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
status: {}
doram@doram:~$
현재 이렇게 되어있다.
yaml 파일은 아주 멀쩡하다.
1) kubelet 완전히 멈추기
sudo systemctl stop kubelet
2) etcd 데이터 디렉터리 완전히 삭제
sudo rm -rf /var/lib/etcd
3) 디렉터리 다시 생성 + 권한 맞게 설정
sudo mkdir -p /var/lib/etcd
sudo chown root:root /var/lib/etcd
sudo chmod 700 /var/lib/etcd
싱글 노드 kubeadm etcd는 700 root:root 여야 정상 작동한다.
권한이 틀리면 etcd가 db 초기화를 못 해서 바로 죽는다.
4) kubelet 재시작
sudo systemctl start kubelet
5) etcd 컨테이너 생성 확인
sudo crictl ps | grep etcd
여기서
Running 이 떠야 한다.
6) kube-apiserver도 자동으로 살아날 것
etcd가 살아야 kube-apiserver도 연결된다.
sudo crictl ps | grep kube-apiserver
7) 확인하기
sudo crictl ps | grep etcd
sudo crictl ps | grep kube-apiserver

sudo systemctl start kubelet
그런 다음 , 오랜 시간 기다린 후 다음 명령어를 실행해준다.
sudo crictl ps | grep etcd
sudo crictl ps | grep kube-apiserver

sudo journalctl -u kubelet -n 50 --no-pager

로그를 보니 containerd 내부에 “이전 static pod sandbox”가 남아 있어 이름이 충돌된다.
따라서 kubelet 끄고 containered 모든 컨테이너를 삭제해준다.
1) kubelet 끄기
sudo systemctl stop kubelet
2) containerd 모든 컨테이너 삭제
sudo crictl ps -a
sudo crictl pods -a
3) static pod 디렉토리 확인
ls -l /etc/kubernetes/manifests
4) kubelet 재시작
sudo systemctl start kubelet
5) 다시 상태 확인
sudo crictl ps | grep etcd
sudo crictl ps | grep kube-apiserver
1) kubelet 완전히 중지
sudo systemctl stop kubelet
2) 모든 컨테이너 제거
sudo crictl rm -f $(sudo crictl ps -aq)
삭제 후 다시 확인:
sudo crictl ps -a
→ 아무것도 안 나와야 정상이다.
3)모든 pod(sandbox) 제거
crictl은 -a 옵션 없으니까 이렇게 해야한다.
파드 ID만 출력:
sudo crictl pods -q
삭제:
sudo crictl rmp -f $(sudo crictl pods -q)
확인:
sudo crictl pods
→ 비어 있어야 정상.
4) 남은 파드 전부 강제삭제
sudo crictl rmp -f $(sudo crictl pods -q)
sudo crictl pods
했을 때 아무것도 안 나와야 한다.
5) 컨테이너도 다 삭제
sudo crictl rm -f $(sudo crictl ps -aq)
그리고 확인해준다.
sudo crictl ps -a
6) kubelet 재시작
sudo systemctl restart kubelet
그리고 확인해준다.
sudo crictl ps | grep etcd
sudo crictl ps | grep kube-apiserver
sudo crictl ps | grep scheduler
sudo crictl ps | grep controller

드디어 정상작동하는 것을 확인할 수 있다.

노드를 확인하려는데 kubeconfig가 깨져서 권한이 없다는 메세지가 뜨는 것이다.
이유를 확인하니 config가 깨졌다.
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
그리고 다시 확인해준다.
kubectl get nodes
kubectl get pods -A

이렇게 떴는데, API server가 안 떠 있어서 그런것이었다.
1) apiserver / etcd 상태 다시 확인
sudo crictl ps | grep kube-apiserver
sudo crictl ps | grep etcd
2) 6443 포트 열려있는지 확인
sudo ss -tlnp | grep 6443
3) apiserver 로그 직접 보기
sudo crictl logs $(sudo crictl ps -q --name kube-apiserver)

etcd 데이터 날렸는데
kubelet이 Node 다시 등록하기 전에 RBAC/토큰/인증이 꼬여서 해당 일이 일어났다.
1) kubelet 인증 파일 삭제
sudo systemctl stop kubelet
sudo rm -f /var/lib/kubelet/pki/kubelet-client*
sudo rm -f /var/lib/kubelet/pki/kubelet.crt
sudo rm -f /var/lib/kubelet/kubeconfig
2) kubelet 재시작
sudo systemctl start kubelet
sudo systemctl restart kubelet
3) 30초 기다린 뒤 Node 확인
kubectl get nodes

아직도 안되었다.
그래서 다음 행동을 하였다.
4) kubeadm 클러스터 자격증명 재생성
sudo kubeadm init phase kubeconfig kubelet
sudo systemctl restart kubelet

확인해보니, kube-apiserver나 kubelet 문제가 아니라
RBAC가 날아간 상태라 다시 만들어주어야 한다.
sudo kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubernetes-admin-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes-admin
EOF

위와같이 뜨는데, 지금 admin.conf 자체가 ‘kubernetes-admin’으로 인식되지 않고 있다는 뜻이다.
따라서 kubeadm init을 재실행 시켜서 관리자 권한을 복구한다.
sudo kubeadm init phase upload-config kubeadm
그다음,
sudo kubeadm init phase upload-config kubelet
그리고
sudo kubeadm init phase kubeconfig all

이렇게 아직까지는 정상적으로 진행되었다.
sudo kubeadm init phase addon all
그런 다음,
kubectl get nodes
를 실행해준다.

NotReady는 Calico가 설치되지 않아서 그런것이라
Calico를 설치한다.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
그 후, 다시 상태를 확인한다.
kubectl get nodes
kubectl get pods -A | grep calico

아무것도 안 뜨는 것은 네트워크 애드온 설치가 실제로 적용이 안됐다. 그래서
cni가 제대로 설치가 아직 안 했거나 중간에 실패한 경우이다.
아무 설정이 안 나오는것을 보니 네트워크 CIDR 빠진 것이다.
그래서 클러스터 초기화를 하기로 결정했다.
sudo kubeadm reset -f
sudo rm -rf /etc/cni/net.d
sudo kubeadm init --pod-network-cidr=192.168.0.0/16
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

NotReady지만 괜찮다.
Calico가 오류가 많이 나서 Flannel로 설치하기로 했다.
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubectl get pods -n kube-system
kubectl get nodes
하고나서 모든 pod가 Running이 되고,
node가 running 상태가 되어야 하는데 다음과 같이 떴다.

실제 집 네트워크가 불안정하여 그런 것 같다.
caclico 설치하다 잘 안되어 flannel을 설치하기로 했는데, flannel도 에러떠서
그냥 calico를 다시 설치하기로 했다.
1) 과거 설치했던 설정들, 리소스 삭제
sudo rm -rf /etc/cni/net.d/*
kubectl delete -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
2) kubelet 재시작
sudo systemctl restart kubelet
3) calico 재설치
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
4) 상태 확인
kubectl get pods -n kube-system | grep calico
kubectl get nodes

CrashLoopBackOff, running 상태가 반복적으로 나타나서

일단 기다려보기로 했다.
중간에 네트워크가 끊긴 것 같아서 오류가 뜬 것 같았다.

tunl0 인터페이스가 다시 살아났다.
5) Calico 먼저 완전히 삭제 및 다시 설치 하기로 했다.
sudo rm -rf /etc/cni/net.d/*
kubectl delete -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml
kubectl delete daemonset calico-node -n kube-system --force --grace-period=0
kubectl delete deployment calico-kube-controllers -n kube-system --force --grace-period=0
caclico crd도 싹 삭제해준다.
kubectl delete crd bgpconfigurations.crd.projectcalico.org \
bgppeers.crd.projectcalico.org \
felixconfigurations.crd.projectcalico.org \
ippools.crd.projectcalico.org \
clusterinformations.crd.projectcalico.org \
kubecontrollersconfigurations.crd.projectcalico.org \
networkpolicies.crd.projectcalico.org --force --grace-period=0
그런 다음 kubelet 을 재시작해주고 kubectl get nodes 하여 notReady 상태인 것을 확인한다.
마지막으로 calico maifest 버전을 설치해준다.
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml

자꾸 api server 가 끊겼다 안 끊겼다 해서 봤더니 CPU 및 메모리가 꽉차서 문제가 된 로그를 확인할 수 있었다. 따라서 가상환경을 끈 후,
다시 리소스를 늘렸다.
그런 후, 네임스페이스 및 찌꺼기 파일들을 삭제하였으며
헬름 및 프로메테우스 재설치를 했더니 설치가 성공적으로 된 것을 확인할 수 있었다.