각 노드끼리 Timezone이 일치하는지, 시간은 동기화 되어 있는지 확인합니다. 상술하였듯 kube-apiserver 는 HTTPS 를 통신에 사용합니다. 이 때문에 보안 인증서를 자동으로 발급받게 되는데, Master 와 Node 사이에 시간 차이가 있을 경우 Issue Date 검증 과정에 실패하여 Node Join 이 실패할 수 있습니다.
hostnamectl 명령어를 입력하여 Machine ID 가 서로 다른지, Hostname 은 서로 다르게 설정되었는지 확인합니다.
Kubernetes 는 Machine ID 를 이용하여 각 노드를 구분하므로 Machine ID 가 동일할 경우 정상적으로 노드가 추가되지 않거나 먼저 등록된 노드의 동작을 교란할 수 있습니다.
sudo rm /etc/machine-id 를 입력하여 Machine ID를 지우고 sudo systemd-machine-id-setup 를 입력하여 Machine ID 를 재생성 하거나 랜덤한 UUID를 /etc/machine-id 에 저장합니다.
Docker 설치 (모든 노드)
Kubernetes 는 Docker, cri-o 등 여러 Runtime 과 같이 사용 할 수 있습니다. 여기서는 Docker 를 사용하겠습니다.
# 항상 root 유저로 작업합니다.
su
# Docker CE 설치
# 출처: https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes
## Swap 끄기
swapoff -a
# 그리고 /etc/fstab 파일을 선호하는 편집기로 열어서 swap 영역을 지워줍니다.
# swap 이라고 적혀있는 라인을 지워주면 됩니다.
# 이 작업을 하지 않으면 재부팅시 swap 영역이 살아나 Kubernetes 실행에 실패합니다.
vim /etc/fstab
## 리포지터리 설정
### apt가 HTTPS 리포지터리를 사용할 수 있도록 해주는 패키지 설치
apt-get update && apt-get install -y \
apt-transport-https ca-certificates curl software-properties-common gnupg2
### Docker의 공식 GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
### Docker apt 리포지터리 추가.
add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
## Docker CE 설치.
apt-get update
apt-get install containerd.io docker-ce docker-ce-cli
# 데몬 설정.
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# Docker 재시작.
systemctl daemon-reload
systemctl restart docker
kubeadm toolbox 설치 (모든 노드)
Kubernetes 설치를 위해 사용하는 kubeadm, Kubernetes 관리를 위해 사용하는 kubectl 등을 이용하기 위해 설치합니다.
# 항상 root 유저로 작업합니다.
su
# 출처: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
# 네트워크 관련 기능을 켭니다.
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
sysctl --system
# kubeadm toolbox 를 설치합니다
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" | tee /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
Kubernetes 설치
### Master Node를 초기화 합니다.
# 항상 root 유저로 작업합니다.
su
# calico 에서 사용할 IP CIDR 를 지정하여 초기화 합니다.
# 기본값은 192.168.0.0/16 (192.168.0.1 ~ 192.168.255.254) 이나, 한국에서는 주로 ipTIME 라우터 등에서 사용되는 기본값이므로 IP 충돌 우려가 있어 변경합니다. 네트워크 상황에 따라 수정 해 주십시오.
# 작업은 최대 4분 까지 걸릴 수 있으며, 시스템 사양에 따라 다릅니다.
# 4분 이상 초기화에 시간이 걸린다면 오류가 발생합니다.
kubeadm init --pod-network-cidr=10.96.0.0/16
## 아래와 같은 로그가 출력되면 Master Node 의 초기화가 성공 한 것 입니다.
## 중간의 `To start using your cluster` 부분의 명령어를 Master Node 에서 입력하십시오.
## 이 명령어는 kubectl 을 이용해 Cluster 를 관리 하기 위해 필요합니다.
## 그 후, 맨 아래 kubeadm join 명령어를 각 노드에 root 유저 상태에서 입력하십시오.
##
# ~ 생략 ~
# Your Kubernetes control-plane has initialized successfully!
#
# 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
#
# 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.0.218:6443 --token ttq3wo.s6n45xjqpjygx452 \
# --discovery-token-ca-cert-hash sha256:02d0425add47b5a409c39f7e36b6fe51496a47f5c1e56fefb5292bfe3b541945
#
# Kubernetes Admin 정보를 현재 유저 (root)에 적용합니다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
### Worker Node를 초기화 합니다.
# 항상 root 유저로 작업합니다.
su
# Kubernetes Cluster 에 Worker Node를 Join 합니다.
# Master Node 에서 발급된 토큰을 이용해 조인합니다. 아래 명령어는 샘플이니 사용하지 마십시오.
# 토큰의 유효기간은 24시간 이므로 24시간 이후에 새 노드를 추가하시려면 Token을 신규 발급 하셔야 합니다.
kubeadm join 192.168.0.218:6443 --token ttq3wo.s6n45xjqpjygx452 \
--discovery-token-ca-cert-hash sha256:02d0425add47b5a409c39f7e36b6fe51496a47f5c1e56fefb5292bfe3b541945
## 아래와 같은 로그가 출력되면 Join 에 성공 한 것 입니다.
# ~ 생략 ~
# This node has joined the cluster:
# * Certificate signing request was sent to apiserver and a response was received.
# * The Kubelet was informed of the new secure connection details.
#
# Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
### Master Node 에서 작업 합니다.
# Worker Node Join 에 성공하였는지 Master Node 에서 확인합니다.
kubectl get nodes
## 아래와 같이 출력되면 정상적으로 Join 된 것입니다.
# NAME STATUS ROLES AGE VERSION
# kubernetes-218 NotReady master 10m v1.18.0
# kubernetes-219 NotReady <none> 4m14s v1.18.0
# kubernetes-220 NotReady <none> 4m10s v1.18.0
#
# 현재 이 상태에서는 CNI 플러그인이 설치되지 않아 노드끼리 통신이 불가능하여 CoreDNS 라는 Kubernetes Core Module 중 하나가 Running 상태로 진입하지 못하고 있을 것입니다.
# 이는 `kubectl get all --all-namespaces` 명령어와 `kubectl describe pod <Pod 명> -n <namespace>` 명령어로 확인할 수 있습니다.
# CNI 플러그인을 설치 하되, 아까 설정하였던 IP CIDR를 수정해야 한다는 점을 유념하여 작업합니다.
# 우선, CNI 플러그인인 Calico 의 설정 파일을 받아 수정합니다.
curl -O https://docs.projectcalico.org/manifests/calico.yaml
# 선호하는 편집기를 이용해 calico.yaml 을 열어 아래와 같이 수정합니다.
vim calico.yaml
# ---------------------------------------------------------------
### calico.yaml
## 주석처리 되어 있는 '- name: CALICO_IPV4POOL_CIDR' 부분을 찾아 name 과 value 의 주석을 해제하고 값을 수정합니다.
# ~ 생략 ~
# The default IPv4 pool to create on startup if none exists. Pod IPs will be
# chosen from this range. Changing this value after installation will have
# no effect. This should fall within `--cluster-cidr`.
- name: CALICO_IPV4POOL_CIDR
value: "10.96.0.0/16"
# ~ 생략 ~
# ---------------------------------------------------------------
# 수정을 마치고 저장 한 후 Kubernetes Cluster 에 Deploy 합니다.
kubectl apply -f calico.yaml
# 정상적으로 Deploy 되었는지 확인 합니다.
kubectl get all --all-namespaces
## 아래와 같이 출력 로그에 calico 가 보인다면 Deploy 에 성공한 것입니다.
# NAMESPACE NAME READY STATUS RESTARTS AGE
# kube-system pod/calico-kube-controllers-5b8b769fcd-zclkf 0/1 Pending 0 32s
# kube-system pod/calico-node-h8krd 0/1 Init:0/3 0 33s
# kube-system pod/calico-node-js4nn 0/1 Init:0/3 0 33s
# kube-system pod/calico-node-wsdc7 0/1 Init:0/3 0 33s
# kube-system pod/coredns-66bff467f8-nb2x4 0/1 Pending 0 44m
# kube-system pod/coredns-66bff467f8-tbfsb 0/1 Pending 0 44m
# ~ 이하 생략 ~
## 다만 Init 상태나 Pending 상태라면 아직 초기화가 진행중 이므로 이 상태가 해소될 때까지 기다립니다. 몇 분에서 몇 십분 정도 걸릴 수 있습니다.
## 너무 오랜 시간 동안 상태에 변화가 없다면 `kubectl describe pod <Pod 명> -n <namespace>` 명령어로 원인을 찾아 해결을 시도하십시오.
# 노드의 Status 가 Ready 가 되었는지 확인합니다.
kubectl get nodes
# 클러스터의 API Endpoint 주소를 확인합니다.
kubectl cluster-info