1. Stop firewalld service and Time synchronization
# firewalld 서비스 중지
sudo systemctl stop firewalld
# firewalld 서비스 자동 실행 중지
sudo systemctl disable firewalld
# 표준 시간대 설정 (서울)
sudo timedatectl set-timezone Asia/Seoul
# chrony 설치 및 NTP 동기화 활성화
sudo dnf install -y chrony
sudo systemctl enable --now chronyd
# 동기화 상태 확인
chronyc tracking
chronyc sources -v
2. swap 기능 비활성화
# swap 끄기
sudo swapoff -a
# swap 자동 마운트 끄기
sudo vi /etc/fstab
# /swap 라인 주석 처리
3. containerd(docker) 설치
# 패키지 업데이트
sudo yum update -y
# 필수 패키지 설치
sudo yum install -y yum-utils iproute-tc
# docker 저장소 추가
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# containerd 설치
sudo yum install containerd.io.x86_64 -y
# containerd 자동 시작하도록 설정
sudo systemctl enable --now containerd
# containerd 설정 파일 생성
sudo bash -c "containerd config default > /etc/containerd/config.toml"
# Cgroup을 Systemd를 통해 관리하도록 설정
sudo sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml
4. 쿠버네티스 설치
# kubernetes 저장소 설정
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
EOF
참고링크 : install-kubeadm
# SELinux 를 permissive mode로 변경
# 즉시 변경 (재부팅시 적용 X)
sudo setenforce 0
# 설정 파일 수정 (재부팅 후 적용)
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# kubelet kubeadm kubectl 설치
sudo yum install kubelet kubeadm kubectl --disableexcludes=kubernetes -y
# kubelet 자동 시작하도록 설정
sudo systemctl enable --now kubelet
# net.ipv4.ip_forward=1 로 설정
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
# bridge 모듈 로드
sudo modprobe br_netfilter
# net.bridge.bridge-nf-call-iptables = 1 로 설정
echo "net.bridge.bridge-nf-call-iptables = 1" | sudo tee -a /etc/sysctl.conf
# 변경 사항 적용
sudo sysctl -p
# containerd 재시작
sudo systemctl restart containerd
5. kubeadm init (master node)
sudo kubeadm init --pod-network-cidr=10.10.0.0/16 --apiserver-advertise-address 192.168.1.71
[조금 기다리다 보면 ....]
[앞부분 생략]
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.71:6443 --token fx8wwi.h1sg517qd62hft7e \
--discovery-token-ca-cert-hash sha256:62133cfdf41b98d1f45d0a42a9f72af146b632c50c0bda7044461f7e41c1cc1c
# 인증 정보 복사 (위에서 제시한 가이드)
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# calico 설치 (network cni 플러그인 중 하나)
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/master/manifests/tigera-operator.yaml
# custom-resources.yaml 파일은 수정이 필요해서 다운로드 먼저
curl -O https://raw.githubusercontent.com/projectcalico/calico/master/manifests/custom-resources.yaml
# custom-resoures.yaml 편집
vi custom-resources.yaml #cidr 정보를 변경 (-> 10.10.0.0/16)
# 설치
kubectl apply -f custom-resources.yaml
참고링크 : calico 설치가이드
# /etc/resolve.conf 소프트 링크 (혹은 copy) (master node)
# 쿠버네티스 dns 질의 시 /run/systemd/resolve/resolv.conf 파일을 참조 함
sudo mkdir -p /run/systemd/resolve
sudo ln -s /etc/resolv.conf /run/systemd/resolve/resolv.conf
# 설치 확인하기
kubectl get pods -A
[STATUS : All Pending --> All Running]
-
추후 worker를 추가할 경우 유효기간 경과(24시간)로 인해 token 발행 및 해쉬값 확인이 필요함. worker 바로 연결 시에는 아래 단계 생략 하고 “5. kubeadm init (master node) 단계”에서 복사해둔 kubeadm join 문 사용.
# token 재발행 (Master node after 24 hours)
kubeadm token create
[token #1]
# token 해쉬값 확인하기 (Master node after 24 hours)
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
[token #2]
6. kubeadm join (worker Node)
“5. kubeadm init (master node) 단계”에서 복사해둔 kubeadm join 문 사용.
# kubeadm join (worker node) (node 추가하기)
sudo kubeadm join 192.168.1.71:6443 --token [token #1] \
--discovery-token-ca-cert-hash sha256:[token #2]
# master node의 config 파일 복사 (worker node)
mkdir -p $HOME/.kube
scp totoli@192.168.1.71:/home/totoli/.kube/config /home/totoli/.kube
sudo chown $(id -u):$(id -g) $HOME/.kube/config
7. hosts 편집 (all node)
# hostname추가
hostnamectl set-hostname k8s-master
# /etc/hosts 추가
sudo echo "192.168.1.71 k8s-master" >> /etc/hosts
sudo echo "192.168.1.72 k8s-worker1" >> /etc/hosts
sudo echo "192.168.1.73 k8s-worker2" >> /etc/hosts
sudo echo "192.168.1.74 k8s-worker3" >> /etc/hosts
127.0.1.1 k8s-worker3 <----- 필요 시 sudo vi /etc/hosts
# master & workers node 연결 확인
kubectl get nodes
8. Matal LoadBalancer 설치
# MetalLB Manifest 적용
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.8/config/manifests/metallb-native.yaml
#MetalLB Pod 확인
kubectl -n metallb-system get pods
#모두 Running 상태면 OK.
# IPAddressPool & L2Advertisement 설정
# 예시: 192.168.1.240 ~ 192.168.1.250 구간을 외부 IP 대역으로 사용
cat <<EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default-adv
namespace: metallb-system
spec:
ipAddressPools:
- default-pool
EOF
# 정상 설치 확인
kubectl -n metallb-system get ipaddresspool,l2advertisement
kubectl -n metallb-system get pods
9. Portainer Environments 연결
# Portainer 이름영역 생성
kubectl create namespace portainer
#Portainer agent 설치 (portainer-agent-k8s-lb manifest 적용)
kubectl apply -n portainer -f https://downloads.portainer.io/ce2-33/portainer-agent-k8s-lb.yaml
#위 YAML은 자동으로 LoadBalancer 서비스를 생성하므로 MetalLB가 설치되어 있다면 자동으로 IP를 할당받음.
# 서비스 확인
kubectl -n portainer get svc
kubectl -n portainer get pods -o wide
# Portainer UI에서 Agent 연결
> 좌측 메뉴 → Environments → Add Environment
> Kubernetes Agent 선택
> 주소 입력: 192.168.1.240:9001
10. LoadBalancer controller 고정 IP 설정
# Agent 서비스에 고정 IP(192.168.1.240) 지정함
kubectl -n portainer patch svc portainer-agent -p '{"spec":{"type":"LoadBalancer","loadBalancerIP":"192.168.1.240"}}'
# 최종 확인
kubectl -n metallb-system get ipaddresspool,l2advertisement
kubectl -n portainer get pods -o wide
kubectl -n portainer describe svc portainer-agent
11. Kubernetics-dashboard 설치 및 LoadBalancer 연결 설정
# 쿠버네티스 대시보드 배포
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# 설치확인
kubectl -n kubernetes-dashboard get pods -o wide
# Running 상태가 되면 성공
# 접근용 계정(ServiceAccount) 및 ClusterRole 생성
cat <<EOF | tee dashboard-adminuser.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: totoli
namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: totoli
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: totoli
namespace: kubernetes-dashboard
EOF
# 관리자 유저 생성
kubectl apply -f dashboard-adminuser.yaml
# 계정 인증 토큰 발급
kubectl -n kubernetes-dashboard create token totoli
12. MetalLB를 통한 외부 접근 연결
# kubernetes-dashboard 서비스 타입을 LoadBalancer로 변경.
kubectl -n kubernetes-dashboard patch svc kubernetes-dashboard -p '{
"spec": {
"type": "LoadBalancer",
"loadBalancerIP": "192.168.1.241"
}
}'
# 정상 설치 시 환경 값 요약
clear
echo "=== Portainer Agent ==="
kubectl -n portainer get svc portainer-agent -o wide
echo
echo "=== Dashboard ==="
kubectl -n kubernetes-dashboard get svc kubernetes-dashboard -o wide
echo
echo "=== ServiceAccount totoli ==="
kubectl get clusterrolebinding | grep totoli
# Portainer Agent 192.168.1.240:9001
# Dashboard 192.168.1.241 (MetalLB)
# ServiceAccount totoli (cluster-admin)
# Token 재발급 kubectl -n kubernetes-dashboard create token totoli
13. Kubernetics-dashboard Skip-Login 활성화 (Option)
# 컨테이너 args에 --enable-skip-login 추가
kubectl -n kubernetes-dashboard patch deployment kubernetes-dashboard \
--type=json \
-p='[{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--enable-skip-login"}]'
# 기본은 대시보드의 SA(kubernetes-dashboard) 권한으로 동작함 → 권한이 제한적임
# 관리자처럼 쓰려면 아래처럼 cluster-admin 부여함(보안 주의)
kubectl create clusterrolebinding kubernetes-dashboard-admin \
--clusterrole=cluster-admin \
--serviceaccount=kubernetes-dashboard:kubernetes-dashboard
# 되돌리기(롤백)
# 플래그 제거
kubectl -n kubernetes-dashboard patch deployment kubernetes-dashboard \
--type=json \
-p='[{"op":"remove","path":"/spec/template/spec/containers/0/args"}]'
# 또는 kubectl edit로 args에서 --enable-skip-login만 삭제
# 과권한 바인딩 제거(만약 부여했으면)
kubectl delete clusterrolebinding kubernetes-dashboard-admin
14. Autoscaling policy defined. (Option)
metrics-server 설치
# 마스터 노드에서 다음 명령만 실행하면 됨
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# metrics-server에 TLS 완화 옵션 추가
kubectl -n kube-system patch deploy metrics-server --type='json' -p='[
{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-insecure-tls"},
{"op":"add","path":"/spec/template/spec/containers/0/args/-","value":"--kubelet-preferred-address-types=InternalIP,Hostname,ExternalIP"}
]'
# 롤아웃 완료 확인
kubectl -n kube-system rollout status deploy/metrics-server
#deployment "metrics-server" successfully rolled out 결과나오면 OK
# 배포 상태 확인
kubectl -n kube-system get pods -l k8s-app=metrics-server
# API 서비스 등록 확인
kubectl get apiservices | grep metrics
# v1beta1.metrics.k8s.io 가 True 상태여야 함.
kubectl top nodes
# cpu 사용률과 memory 사용률 표출여부 확인하면 완료