[Infra] 쿠버네티스(kubernetes)(2) 쿠버네티스 설치(Kubernetes install)

업데이트:

쿠버네티스(2) 쿠버네티스 설치와 환경 설정

참고 링크

0. 인트로

이번 포스팅에서는 쿠버네티스를 설치해 보도록 하겠습니다. 쿠버네티스 설치는 꽤 어렵습니다. 하지만 차근차근 한 스텝씩 나가도록 합시다. 제 환경은 전체 서버 세 대 입니다. 한 대의 마스터노드, 두 대의 워커노드로 구성된 쿠버네티스 클러스터를 구축해보도록 하겠습니다.

1단계. swap disable

쿠버네티스 첫 단계로 swap 기능을 꺼야합니다. 이 때, 스왑(swap)이란 물리 메모리(RAM)의 용량이 부족할 때 하드 디스크의 일부 공간을 메모리 처럼 사용하는 것입니다. 쿠버네티스를 설치하기 위해서는 바로 이 스왑 기능을 꺼야합니다.

1-1. 스왑 가동 중인지 확인하기

먼저 마스터노드에 접속하고 스왑이 가동중인지 알아봅니다.

(마스터노드)$ free -h
              total        used        free      shared  buff/cache   available
Mem:          125Gi       1.0Gi       120Gi       4.0Mi       4.7Gi       123Gi
Swap:         8.0Gi          0B       8.0Gi

위 코드 처럼 ‘free -h’를 입력하면 스왑 영역 8G가 가동중인것을 알 수 있습니다. 스왑이 가동중인지 확인하는 방법은 아래와 같은 방법을 사용해도 됩니다.

(마스터노드)$ cat /proc/swaps
Filename                                Type            Size    Used    Priority
/dev/dm-6                               partition       8388604 0       -2

스왑이 가동하는지 확인하는 또 한가지 방법은 위 코드처럼 ‘cat /proc/swaps’를 입력해서 스왑 영역을 확인하는 것입니다.

1-2. 스왑 기능 중지 시키기

그렇다면 이제 스왑 기능을 중지시켜봅니다.

(마스터노드)$ sudo -i
(마스터노드)# swapoff --all

코드는 위와 같이 간단합니다. sudo 권한으로 ‘swapoff –all’ 커맨드를 입력합니다. 주의할 점은 작대기 1개 아니고 2개 입니다.(–all)

그렇다면 이제 스왑이 중단 뒤었는지 확인해 봅니다.

(마스터노드)# free -h
              total        used        free      shared  buff/cache   available
Mem:          125Gi       1.0Gi       120Gi       4.0Mi       4.7Gi       123Gi
Swap:            0B          0B          0B

‘free -h’ 커맨드로 확인해보니 스왑영역이 없는것을 볼 수 있습니다.

(마스터노드)# cat /proc/swaps
Filename                                Type            Size    Used    Priority

그리고 ‘cat /proc/swaps’ 커맨드로 확인해도 역시 스왑 영역이 없는 것을 볼 수 있습니다.

그리고 /etc/fstab 파일에서 swap 부분을 주석처리 해줍니다.

(마스터노드)# vim /etc/fstab

그리고 재부팅을 해줍니다.

1-3. 각 클러스터 서버마다 모두 스왑 기능 끄기

지금은 마스터 노드의 스왑 기능만 껐습니다. 같은 작업을 워커노드1, 워커노드2에도 해주세요. 모두 스왑 기능을 꺼줍니다.

2단계. hostname 설정

다음은 ‘/etc/hosts’ 파일에 모든 노드(마스터노드, 워커노드1, 워커노드2)를 추가해줍니다. ‘/etc/hosts’파일은 IP주소와 도메인 이름을 매핑하는 파일입니다. 즉, 해당 IP 주소를 alias 이런 이름으로 부르겠다~라고 선언해주는 것입니다.

(마스터노드)# cat /etc/hosts
# /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu20

192.168.200.91  poc-dlinfo-db01
192.168.200.92  poc-dlinfo-web01
192.168.200.93  poc-dlinfo-gpu01

저는 위와 같은 세가지 서버(91,92,93)를 사용하도록 하겠습니다. 마찬가지로 모든 노드에 방문해서 hosts파일을 위와 같이 수정해주세요.

3단계. docker 설치

마스터노드, 워커노드1, 워커노드2에 모두 도커를 설치해 줍니다. 도커 설치 방법은 도커 설치 링크를 참고해주세요.

도커를 설치했다면 버전을 확인합니다.

(마스터노드)# docker version
Client: Docker Engine - Community
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:27 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

4단계. kubernetes 설치

자 이제 쿠버네티스를 설치할 준비가 되었습니다.

4-1. 인증 키 추가

먼저 쿠버네티스를 사용하기 전에 인증키를 추가할것인데 먼저 다음과 같이 사전 업데이트를 해주고 curl 같이 필요한 프로그램을 설치합니다.

(마스터노드)$ sudo -i
(마스터노드)# apt-get update
(마스터노드)# apt-get install -y apt-transport-https curl

위와 같이 준비가 끝났으면 이제 인증 키를 추가합니다.

(마스터노드)# curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
OK

위와 같이 인증키를 추가하는 커맨드를 입력했을 때(주의: 마지막에 -로 끝남) 위와 같이 OK가 뜨면 잘 된 것입니다.

(마스터노드)# vim /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main

위와 같이 vim 으로 /etc/apt/sources.list.d/kubernetes.list 파일 만들어서 위와 같이 한줄 추가해줍니다. (기존에는 kubernetes.list 파일이 없는데 새로 만드는 것입니다.)

(마스터노드)# cat /etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main 

잘 만들어졌는지 위와 같이 cat으로 확인해봅니다.

그리고 마지막으로 다시한번 업데이트 해줍니다.

(마스터노드)# apt-get update
Hit:1 https://download.docker.com/linux/ubuntu focal InRelease
Ign:2 http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  InRelease
Ign:4 http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  InRelease
Hit:5 http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64  Release
Hit:6 http://developer.download.nvidia.com/compute/machine-learning/repos/ubuntu1804/x86_64  Release
Hit:9 http://kr.archive.ubuntu.com/ubuntu focal InRelease
Get:10 http://kr.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Get:3 https://packages.cloud.google.com/apt kubernetes-xenial InRelease [9,383 B]
Get:11 https://packages.cloud.google.com/apt kubernetes-xenial/main amd64 Packages [49.1 kB]
Get:12 http://kr.archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Get:13 http://kr.archive.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:14 http://kr.archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages [1,138 kB]
Get:15 http://kr.archive.ubuntu.com/ubuntu focal-updates/universe amd64 Packages [844 kB]
Fetched 2,369 kB in 3s (698 kB/s)
Reading package lists... Done

아까 업데이트했는데도 뭐가 주루룩 나오는 것을 볼 수 있는데 거의다 쿠버네티스 관련 내용입니다. 이거 apt-get update 안하고 쿠버네티스 설치하려고 하면 설치 안되니까 apt-get update 꼭 해주세요!

4-2. 쿠버네티스 설치

이제 대망의 쿠버네티스를 설치해보겠습니다.

(마스터노드)# apt-get install kubeadm kubectl kubelet kubernetes-cni
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
  conntrack cri-tools ebtables socat
Suggested packages:
  nftables
The following NEW packages will be installed:
  conntrack cri-tools ebtables kubeadm kubectl kubelet kubernetes-cni socat
0 upgraded, 8 newly installed, 0 to remove and 41 not upgraded.
Need to get 73.8 MB of archives.
After this operation, 346 MB of additional disk space will be used.
...(중략)...
Setting up socat (1.7.3.3-2) ...
Setting up cri-tools (1.13.0-01) ...
Setting up kubernetes-cni (0.8.7-00) ...
Setting up kubelet (1.22.0-00) ...
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.
Setting up kubeadm (1.22.0-00) ...
Processing triggers for man-db (2.9.1-1) ...

위와 같이 쿠버네티스가 잘 설치된 것을 볼 수 있습니다. (중간에 Y/N 선택하라는거 나오는데 Y 입력해주세요) 쿠버네티스가 잘 설치 되었는지 확인하기 위해 위 설치 코드를 다음과 같이 한번 더 입력해 봅니다.

(마스터노드)# apt-get install kubeadm kubectl kubelet kubernetes-cni
Reading package lists... Done
Building dependency tree
Reading state information... Done
kubeadm is already the newest version (1.22.0-00).
kubectl is already the newest version (1.22.0-00).
kubelet is already the newest version (1.22.0-00).
kubernetes-cni is already the newest version (0.8.7-00).
0 upgraded, 0 newly installed, 0 to remove and 41 not upgraded.

이미 설치가 되었다고 나오는걸 보니 잘 설치가 된 것 같습니다.

(마스터노드)# kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:03:20Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?
root@poc-dlinfo-gpu01:~# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:02:08Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"}
(마스터노드)#  kubelet --version
Kubernetes v1.22.0 
(마스터노드)#  kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.0", GitCommit:"c2b5237ccd9c0f1d600d3072634ca66cefdf272f", GitTreeState:"clean", BuildDate:"2021-08-04T18:03:20Z", GoVersion:"go1.16.6", Compiler:"gc", Platform:"linux/amd64"}
The connection to the server localhost:8080 was refused - did you specify the right host or port?

위와 같이 버전을 확인해도 잘 나오는 것을 볼 수 있습니다.

5단계: 모든 노드에 1~4단계

지금까지 1단계부터 4단계 까지의 과정을 나머지 노드에도 반복해서 해주세요.

6단계: 마스터노드 설정(kubeadm init)

앞서 세개의 서버에 모두 쿠버네티스를 설정했습니다. 그러나 아직 클러스터가 서로 연결되지 않았습니다. 누가 마스터노드이고 누가 워커노드인지 지정해주지 않았죠. 지금부터 할 작업이 이러한 것들을 지정하는 작업입니다. 마스터노드에 접속해서 니가 마스터다라고 지정해주고 워커노드를 붙여주는거죠. 짧게 요약하면 마스터노드에서 kubeadm init으로 마스터 노드를 초기화 하고, kubeadm join으로 워커노드를 초기화하고 클러스터에 연결합니다.

먼저 마스터노드 설정을 해보겠습니다. 작업을 하기전에 알아야 할게 kubeadm은 클러스터를 실행하는데 필요한 모든 인정서를 생성합니다. 따라서 마스터노드를 설정하기 위한 kubeadm init을 실행하기 전에 인증서를 받아야합니다.

먼저 현재 인증서 상태를 확인해봅니다.

(마스터노드)# kubeadm certs check-expiration
CERTIFICATE                          EXPIRES   RESIDUAL TIME   CERTIFICATE AUTHORITY   EXTERNALLY MANAGED
!MISSING! admin.conf
!MISSING! apiserver
!MISSING! apiserver-etcd-client
!MISSING! apiserver-kubelet-client
!MISSING! controller-manager.conf
!MISSING! etcd-healthcheck-client
!MISSING! etcd-peer
!MISSING! etcd-server
!MISSING! front-proxy-client
!MISSING! scheduler.conf

CERTIFICATE AUTHORITY      EXPIRES   RESIDUAL TIME   EXTERNALLY MANAGED
!MISSING! ca
!MISSING! etcd-ca
!MISSING! front-proxy-ca

위 결과를 보면 뭔가 인증이 하나도 안되어 있는 것을 볼 수 있습니다.
그럼 이제 설정 파일을 받아봅시다.

(마스터노드)# kubeadm config images pull
[config/images] Pulled k8s.gcr.io/kube-apiserver:v1.22.0
[config/images] Pulled k8s.gcr.io/kube-controller-manager:v1.22.0
[config/images] Pulled k8s.gcr.io/kube-scheduler:v1.22.0
[config/images] Pulled k8s.gcr.io/kube-proxy:v1.22.0
[config/images] Pulled k8s.gcr.io/pause:3.5
[config/images] Pulled k8s.gcr.io/etcd:3.5.0-0
[config/images] Pulled k8s.gcr.io/coredns/coredns:v1.8.4

위 코드와 같이 ‘kubeadm config images pull’를 입력하면 설정 이미지를 받을 수 있습니다.

다음으로 kubeadm init을 할 것인데 이는 마스터 노드를 초기화 하는 커맨드 입니다. kubeadm을 통해 만든 클러스터는 CNI(Container Network Interface) 기반의 애드온이 필요합니다. 여기서는 Flannel이라는 Pod 네트워크 애드온을 설치해 사용할 것입니다. 그리고 옵션으로 다음과 같은 것을 사용합니다.

  • –apiserver-advertise-address: 특정 마스터 노드의 API Server 주소를 설정할 때 사용합니다. ifconfig를 통해 마스터노드의 아이피를 확인해 넣습니다.

  • –pod-network-cidr: Pod 네트워크를 설정할 때 사용합니다. 우리는 ‘–pod-network-cidr=10.244.0.0/16’을 사용할 것인데 ‘10.244.0.0/16’은 Flannel에서 권장하는 네트워크 대역입니다.

이제 준비가 끝났습니다. 다음과 같이 커맨드를 입력합니다.

(마스터노드)# kubeadm init --apiserver-advertise-address=192.168.200.93 --pod-network-cidr=10.244.0.0/16
...(중략)...
This can kae up to 4m0s

위와 같이 입력하면 뭔가 주루룩 나옵니다. 그리고 4분정도 걸릴거라고 하네요. 그랬더니 다음과 같은 에러가 나옵니다.

[kubelet-check] It seems like the kubelet isn't running or healthy.  
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp 127.0.0.1:10248: connect: connection refused.

        Unfortunately, an error has occurred:
                timed out waiting for the condition

        This error is likely caused by:
                - The kubelet is not running
                - The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

        If you are on a systemd-powered system, you can try to troubleshoot the error with the following commands:
                - 'systemctl status kubelet'
                - 'journalctl -xeu kubelet'

        Additionally, a control plane component may have crashed or exited when started by the container runtime.
        To troubleshoot, list all containers using your preferred container runtimes CLI.

        Here is one example how you may list all Kubernetes containers running in docker:
                - 'docker ps -a | grep kube | grep -v pause'
                Once you have found the failing container, you can inspect its logs with:
                - 'docker logs CONTAINERID'

error execution phase wait-control-plane: couldn't initialize a Kubernetes cluster
To see the stack trace of this error execute with --v=5 or higher

안되니까 일단 kubeadm을 리셋을 한번 해봅시다. 다음 커맨드를 입력하면 리셋 됩니다.

(마스터노드)# kubeadm reset

6-1. 문제 해결

위와 같은 문제가 나타나면 다음과 같이 입력해줍니다. 참고링크1, 참고링크2

(마스터노드)# sudo mkdir /etc/docker

(마스터노드)# cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

위와 같은 커맨드를 입력하고 다음과 같이 입력합니다.

(마스터노드)# sudo systemctl enable docker
(마스터노드)# sudo systemctl daemon-reload
(마스터노드)# sudo systemctl restart docker

-- kubelet이 실행 중인지 확인
(마스터노드)# sudo systemctl status kubelet

-- 만약 실행 중이 아니라면 다음을 실행
(마스터노드)# sudo systemctl start kubelet

위와 같은 커맨드를 입력했다면 다시한번 시도해봅니다.

(마스터노드)# kubeadm config images pull
(마스터노드)# kubeadm init --apiserver-advertise-address=192.168.200.93 --pod-network-cidr=10.244.0.0/16
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

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.200.93:6443 --token 1rnf72.myfkkr8q109ugylr \
        --discovery-token-ca-cert-hash sha256:8a5130aa0992e920a7756f8abea8be391ae444c6ecd2433e4eeb1d2c71885c09

오 드디어 kubeadm 성공했습니다.

6-2단계. kubeadm init 마무리

kubeadm init을 성공했다면 다음으로 위 성공 창의 안내문과 같이 다음 커맨드를 입력합니다.

(마스터노드)# mkdir -p $HOME/.kube
(마스터노드)# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
(마스터노드)# sudo chown $(id -u):$(id -g) $HOME/.kube/config

7단계. pod 네트워크 설정

(마스터노드)# sudo kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
Warning: policy/v1beta1 PodSecurityPolicy is deprecated in v1.21+, unavailable in v1.25+
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created

8단계. 설치 확인!

(마스터노드)# kubectl get pods --all-namespaces
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   coredns-78fcd69978-52cnq                   0/1     Pending   0          27m
kube-system   coredns-78fcd69978-b8lj6                   0/1     Pending   0          27m
kube-system   etcd-poc-dlinfo-gpu01                      1/1     Running   1          27m
kube-system   kube-apiserver-poc-dlinfo-gpu01            1/1     Running   1          27m
kube-system   kube-controller-manager-poc-dlinfo-gpu01   1/1     Running   1          27m
kube-system   kube-flannel-ds-f72sp                      1/1     Running   0          13s
kube-system   kube-proxy-xscx7                           1/1     Running   0          27m
kube-system   kube-scheduler-poc-dlinfo-gpu01            1/1     Running   1          27m

잘 설치 된거 같은데 위 두개의 네임스페이스가 Pending이네요. 몇분 기다렸다가 다시 확인하면 Running으로 잘 나옵니다.

(마스터노드)# kubectl get pods --all-namespaces
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   coredns-78fcd69978-52cnq                   1/1     Running   0          29m
kube-system   coredns-78fcd69978-b8lj6                   1/1     Running   0          29m
kube-system   etcd-poc-dlinfo-gpu01                      1/1     Running   1          30m
kube-system   kube-apiserver-poc-dlinfo-gpu01            1/1     Running   1          30m
kube-system   kube-controller-manager-poc-dlinfo-gpu01   1/1     Running   1          30m
kube-system   kube-flannel-ds-f72sp                      1/1     Running   0          2m44s
kube-system   kube-proxy-xscx7                           1/1     Running   0          29m
kube-system   kube-scheduler-poc-dlinfo-gpu01            1/1     Running   1          30m

9. 옵션(마스터 노드에도 Pod생성하고 싶을때)

디폴트는 마스터노드에는 pod 스케쥴링을 하지 않습니다. 그러나 만약 자신이 마스터 노드에도 pod를 생성하고 싶다면 다음과 같이 입력합니다.

(마스터노드)# kubectl taint nodes --all node-role.kubernetes.io/master- 
node/poc-dlinfo-gpu01 untainted

10. Join 워커노드

(마스터노드)# kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash>