k8s라고도 알려진 쿠버네티스는 컨테이너화된 애플리케이션을 자동으로 배포, 스케일링 및 관리해주는 오픈소스 시스템
쿠버네티스 설치는 우분투 서버 3대로 구성한다.
- master-node
- worker-node1
- worker-node2
그리고 CNI(Container Network Interface) 표준을 지키는 네트워크 플러그인 Calico를 선택하여 구성을 한다.
Calico에 관련된 소개는 링크를 참고한다.
master-node
- OS: Ubuntu Server 20.04 LTS
- type: m2.c2m4 (2vCPU, 4GB)
- HDD: 60 GB
- IP : 192.168.0.100, 133.186.xxx.180
접속방법
ssh -i jdlee-key.pem ubuntu@133.186.xxx.180
서버 설정
#
# 서버이름변경
sudo hostnamectl set-hostname "master-node"
#
# hosts내용 수정
sudo vi /etc/hosts
192.168.0.100 master-node
192.168.0.96 worker-node1
192.168.0.45 worker-node2
install_kubernetes.sh 실행
아래 내용은 master-node, worker-node에서 동일하게 수행한다.
설치 스크립트는 Simplifying Kubernetes Installation on Ubuntu using a Bash Shell Script에 있는 내용을 참고하였다.
스크립트는 모든 서버에서 동일하게 실행하면 된다.
#
# 기본 설치 스크립트 수행
sudo -i
touch install_kubernetes.sh
vi install_kubernetes.sh
#
# ** install_kubernetes.sh 스크립트 내용 시작******
#!/bin/bash
# common.sh
# copy this script and run in all master and worker nodes
#i1) Switch to root user [ sudo -i]
#2) Disable swap & add kernel settings
swapoff -a
sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
#3) Add kernel settings & Enable IP tables(CNI Prerequisites)
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
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 --system
#4) Install containerd run time
#To install containerd, first install its dependencies.
apt-get update -y
apt-get install ca-certificates curl gnupg lsb-release -y
#Note: We are not installing Docker Here.Since containerd.io package is part of docker apt repositories hence we added docker repository & it's key to download and install containerd.
# Add Docker’s official GPG key:
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
#Use follwing command to set up the repository:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install containerd
apt-get update -y
apt-get install containerd.io -y
# Generate default configuration file for containerd
#Note: Containerd uses a configuration file located in /etc/containerd/config.toml for specifying daemon level options.
#The default configuration can be generated via below command.
containerd config default > /etc/containerd/config.toml
# Run following command to update configure cgroup as systemd for contianerd.
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
# Restart and enable containerd service
systemctl restart containerd
systemctl enable containerd
#5) Installing kubeadm, kubelet and kubectl
# Update the apt package index and install packages needed to use the Kubernetes apt repository:
apt-get update
apt-get install -y apt-transport-https ca-certificates curl
# Download the Google Cloud public signing key:
curl -fsSL https://dl.k8s.io/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
# Add the Kubernetes apt repository:
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
# Update apt package index, install kubelet, kubeadm and kubectl, and pin their version:
apt-get update
apt-get install -y kubelet kubeadm kubectl
# apt-mark hold will prevent the package from being automatically upgraded or removed.
apt-mark hold kubelet kubeadm kubectl
# Enable and start kubelet service
systemctl daemon-reload
systemctl start kubelet
systemctl enable kubelet.service
#
# ** install_kubernetes.sh 스크립트 내용 끝 ******
#
# install_kubernetes.sh 실행
sh install_kubernetes.sh
kubeadm init 수행하기
- 해당 작업은
master-node
에서 수행한다. worker-node
에서 진행하지 않는다.
$ sudo kubeadm init --pod-network-cidr=192.168.0.0/16
- pod network cidr을
192.168.0.0/16
` 으로 설정하는 이유는 calico cni 구축 시 사용하기 때문이다. - Calico 기반 구축 블로그 내용 중 참고
kubeadm init이 완료되면 아래와 같은 안내가 나간다.
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
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.0.100:6443 --token z73isr.n7zqe14dji5q8d07 \
--discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
현재 상태가 root이라면 exit명령어로 빠져나와 아래와 같은 명령을 수행한다.
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Calico 구성하기
- calico 설치는 공식 문서도 같이 참고한다. 링크
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.4/manifests/custom-resources.yaml
- Tigera Calico operator 그리고 custom resource definitions을 설치한다.
- 모든 Pod의 상태가 Running이 될 때가지 대기 합니다.
watch kubectl get pods -n calico-system
- 해당 화면을 빠져나가려면 control + c를 누르세요.
ubuntu@master-node:~$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
calico-apiserver calico-apiserver-57444f46d6-bmbzq 1/1 Running 0 62s
calico-apiserver calico-apiserver-57444f46d6-fml7f 1/1 Running 0 62s
calico-system calico-kube-controllers-844f76d6c7-72g75 1/1 Running 0 2m5s
calico-system calico-node-7nf28 1/1 Running 0 2m5s
calico-system calico-typha-66cd8b855f-4zg8v 1/1 Running 0 2m6s
calico-system csi-node-driver-wkk6d 2/2 Running 0 2m5s
kube-system coredns-5dd5756b68-7qz94 1/1 Running 0 4m19s
kube-system coredns-5dd5756b68-bvqnw 1/1 Running 0 4m19s
kube-system etcd-master-node 1/1 Running 1 4m31s
kube-system kube-apiserver-master-node 1/1 Running 1 4m32s
kube-system kube-controller-manager-master-node 1/1 Running 0 4m31s
kube-system kube-proxy-kljdn 1/1 Running 0 4m19s
kube-system kube-scheduler-master-node 1/1 Running 1 4m31s
tigera-operator tigera-operator-7f8cd97876-w9ghv 1/1 Running 0 2m19s
ubuntu@master-node:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-node Ready control-plane 4m42s v1.28.2
- 전체 Pod를 확인했을 때, 아래와 같이 나오면 된다.
- 노드 상태 역시 Ready인 것을 확인 할 수 있다.
- 이제는 worker-node를 mater-node에 조인 시켜본다.
worker-node1
- OS: Ubuntu Server 20.04 LTS
- type: m2.c2m4 (2vCPU, 4GB)
- HDD: 60 GB
- IP : 192.168.0.96
접속방법
ssh -i jdlee-key.pem ubuntu@192.168.0.96
- master-node에서 실행한다.
서버 설정
# 서버이름변경
sudo hostnamectl set-hostname "worker-node1"
# hosts내용 수정
sudo vi /etc/hosts
192.168.0.100 master-node
192.168.0.96 worker-node1
192.168.0.45 worker-node2
- worker-node에서는 install_kubernetes.sh 실행까지 수행하고 kubeadm init는 수행하지 않는다.
- master-node에서 kubeadm init를 수행했을 때 출력된 kubeadm join 메세지를 따로 복사하지 않았다면 아래와 같은 명령어를 수행한다.
# 마스터 조인 토큰 생성
kubeadm token create --print-join-command
- kubeadm join 메세지를 따로 복사했다며 아래와같다.
- 이것을 worker-node에서 실행한다.
kubeadm join 192.168.0.100:6443 --token z73isr.n7zqe14dji5q8d07 \
--discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
# 또는 /etc/hosts 파일을 수정했기 때문에 아랫처럼 입력해도 된다.
sudo kubeadm join master-node:6443 --token z73isr.n7zqe14dji5q8d07 \
--discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
실제로 아래화면처럼 진행된다.
$ sudo kubeadm join master-node:6443 --token z73isr.n7zqe14dji5q8d07 \
> --discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
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에서 아래 명령어를 실행하면 전체노드의 상태를 확인 할 수 있다.
ubuntu@master-node:~$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master-node Ready control-plane 112m v1.28.2 192.168.0.100 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node1 Ready <none> 67s v1.28.2 192.168.0.96 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node2 역시 worker-node1에서 진행했던 작업과 동일하게 설정한다.
kubeadm Reset
간혹, 설정이 망했다면 리셋을 통해 다시 작업을 초기화 할 수 있다.
sudo kubeadm reset
sudo systemctl restart kubelet
sudo reboot
트러블 슈팅
ubuntu@worker-node2:~$ sudo kubeadm join master-node:6443 --token z73isr.n7zqe14dji5q8d07 \
> --discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
[preflight] Running pre-flight checks
error execution phase preflight: couldn't validate the identity of the API Server: could not find a JWS signature in the cluster-info ConfigMap for token ID "z73isr"
To see the stack trace of this error execute with --v=5 or higher
worker-node2를 나중에 join하려고 하니 오류가 발생하였다.
kubeadm join으로 클러스터에 노드 추가(worker)를 참고하여 worker-node2를 join하기 위해 작업을 하였다.
master-node에서 아래와 같이 토큰을 생성한다.
# 토큰 리스트
$ kubeadm token list
# 토큰 생성
$ kubeadm token create
sj8azl.qq377mqc9jq8pmki
# hash 값 조회
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
worker-node2에 접속하여 아래와 같이 입력한다.
# master-node에서 생성했던 토큰 정보와 bash 값을 입력한다.
$ sudo kubeadm join master-node:6443 --token sj8azl.qq377mqc9jq8pmki \
discovery-token-> --discovery-token-ca-cert-hash sha256:1c6e52cac97939c3e62331894399703e6132b72617b0b405b53cc38f894f01ad
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
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에서 노드의 상태를 확인한다.
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master-node Ready control-plane 9d v1.28.2 192.168.0.100 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node1 Ready <none> 8d v1.28.2 192.168.0.96 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node2 NotReady <none> 16s v1.28.2 192.168.0.45 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
# 시간이 지나면 worker-node2의 STATUS가 NotReady -> Ready 으로 변경된 것을 확인 할 수 있다.
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
master-node Ready control-plane 9d v1.28.2 192.168.0.100 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node1 Ready <none> 8d v1.28.2 192.168.0.96 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26
worker-node2 Ready <none> 76s v1.28.2 192.168.0.45 <none> Ubuntu 20.04.6 LTS 5.4.0-165-generic containerd://1.6.26