Install Kubernetes Cluster on Ubuntu 20.04 with kubeadm

설치환경

- OS : Ubuntu 20.04 LTS(2 CPU, 4GB Memory, 20GB Disk 이상)

- master node : 1대(hostname : master)

- worker node : 2대(hostname : worker-1, worker-2)

 

설치순서

master node

- containerd 만 설치

master node에도 내부적으로 관리하는 pod들이 있으며, 이를 위해서는 containerd 가 필요함

sudo apt-get update

sudo apt-get install ca-certificates curl gnupg lsb-release -y

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  
sudo apt-get update
sudo apt-get install containerd.io

 

kubernetes.io 사이트를 참조하여 설치

1) kubernetes 설치 전 환경설정

br_netfilter 모듈이 로드되었는지 확인한다. 

lsmod | grep br_netfilter 를 실행하면 된다.

명시적으로 로드하려면 sudo modprobe br_netfilter 를 실행한다.

- iptables가 브리지된 트래픽을 보게 하기

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
sudo sysctl --system

- swap off

$ sudo swapoff -a

- port 확인

master node에 6443, 8080 port 가 사용중인지 확인합니다. 사용 중인 서비스가 없어야 합니다.

쿠버네티스 API 서버는 2개의 포트에서 HTTP를 서비스합니다.

- 8080 port : 스트 및 부트스트랩을 하기 위한 것이며 마스터 노드의 다른 구성요소 (스케줄러, 컨트롤러 매니저)가 API와 통신

- 6443 port : TLS를 사용한다. --tls-cert-file 플래그로 인증서를 지정하고 --tls-private-key-file 플래그로 키를 지정한다.

telnet 10.10.1.15(예시, master node IP Address) 6443

 

- 방화벽 open(서버 방화벽 disable)

방화벽이 설정을 확인한 다음 방화벽이 enable되어 있으면 방화벽을 disable 합니다. 

## 방화벽 설정 확인
sudo ufw status

## 방화벽 disable
sudo ufw disable

 

 

- kubectl, kubeadm, kubelet 설치

sudo apt-get update
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-get update
sudo apt-get install -y kubelet kubeadm kubectl

sudo apt-mark hold kubelet kubeadm kubectl

 

- ip_forward 설정

echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

 

 

 

- control plane 구성

control plane 구성은 master node에서만 실행합니다.

아래 명령어로 control plane 을 구성합니다. 명령어 수행 제일 하단에 아래와 같이 kubeadm join 으로 시작하는 정보가 표시됩니다. 이 명령어는 나중에 worker node 에서 수행하여 cluster를 구성하는 명령어입니다. 별도로 저장해 놓습니다.

kubeadm init

......
kubeadm join 10.10.1.20:6443 --token x8g6zc.1yb94eh1u1940rrj \
	--discovery-token-ca-cert-hash sha256:996f5ea00339533897cd991fb005349eeb366af000b13c8458f9743d5ada230c

 

root와 일반 user가 쿠버네티스 명령어를 사용할 수 있도록 환경 설정(master node에 설정)

 

root 유저로 수행하려면 아래를 설정합니다. root 유저로 실행합니다.

export KUBECONFIG=/etc/kubernetes/admin.conf

 

일반 유저로 kubectl 명령어를 수행하기 위해 설정합니다. 일반 유저로 실행합니다.

mkdir -p $HOME/.kube

## admin.conf 파일은 kubelet 설치 시 생성
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

 

 

 

2) CNI 설치(master node에 설정)

Pod network add-on 설치

pod 네트워크 애드온 종류는 많습니다(calico, canal, flannel, romana, weave net 등).

원하는 네트워크 애드온을 설치합니다.

본 문서에서는 weave network add on 을 설치합니다. 

Weave Net을 설치하기 전에 TCP 6783 및 UDP 6783/6784 포트가 방화벽에 의해 차단되지 않았는지 확인해야 합니다.

아래 명령어로 weave network add-on을 설치합니다.

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

## 실행결과
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created

[참고]

flannel add-on 설치

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

아래 오류가 발생하면

Warning  FailedCreatePodSandBox  22s   kubelet            
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "...": 
open /run/flannel/subnet.env: no such file or directory

 

 

 

- kubectl auto completion

echo "source <(kubectl completion bash)" >> ~/.bashrc
echo "source <(kubeadm completion bash)" >> ~/.bashrc

 

 

worker node

- worker node join

master node 에서 수행한 kubeadm init 명령어의 실행 결과창에서 보여진 kubeadm join으로 시작되는 부분을 실행해 줍니다.

kubeadm join 10.10.1.15:6443 --token 2gcmlw.zfvrc2b42j3q30zk \
	--discovery-token-ca-cert-hash sha256:aeb530a1ee53667a603d53d9d9abe12a32009b9f432b0fbca40fa1116c1fcc46

 

 

런타임 설치

아래는 여러 종류의 container runtime입니다. 본 문서에서는 containerd runtime을 설치합니다.

[ RuntimePath to Unix domain socket ]

runtime 종류  
containerd unix:///var/run/containerd/containerd.sock
CRI-O unix:///var/run/crio/crio.sock
Docker Engine (using cri-dockerd) unix:///var/run/cri-dockerd.sock or
/var/run/docker.sock
Mirantis Container Runtime  

/var/run/docker.sock 파일은
Docker 데몬이 기본적으로 수신 대기하는 Unix 소켓이며 컨테이너 내에서 데몬과 통신하는 데 사용합니다.

 

 

 

# Docker와 Containerd가 모두 감지되면 Docker가 우선합니다.

# 이외에 다른 두 개 이상의 컨테이너 런타임이 감지되면 kubeadm은 오류 메시지를 출력하고 종료됩니다.

 

파드에서 컨테이너를 실행하기 위해, 쿠버네티스는 컨테이너 런타임을 사용합다.

 

containerd : 

다음 명령을 사용하여 시스템에 containerd를 설치한다.

공식 도커 리포지터리에서 containerd.io 패키지를 설치한다. 각 리눅스 배포판에 대한 도커 리포지터리를 설정하고 containerd.io 패키지를 설치하는 방법은 도커 엔진 설치에서 찾을 수 있다.

 

apt 패키지 인덱스를 업데이트하고 apt가 HTTPS를 통해 리포지토리를 사용할 수 있도록 패키지를 설치합니다.

sudo apt-get update

sudo apt-get install ca-certificates curl gnupg lsb-release

도커 공식 GPG 키를 추가합니다.

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

다음 명령어를 사용하여 저장소를 설정합니다. 

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

 

containerd.io 설치

apt 패키지 인덱스를 업데이트하고 최신 버전의 Docker Engine, containerd 및 Docker Compose를 설치합니다.

 

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
  • containerd.io - daemon to interface with the OS API (in this case, LXC - Linux Containers), essentially decouples Docker from the OS, also provides container services for non-Docker container managers
  • docker-ce - Docker daemon, this is the part that does all the management work, requires the other two on Linux
  • docker-ce-cli - CLI tools to control the daemon, you can install them on their own if you want to control a remote Docker daemon

containerd 설정

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

systemd cgroup 드라이버의 사용

/etc/containerd/config.toml 의 systemd cgroup 드라이버를 runc 에서 사용하려면, 다음과 같이 설정한다.

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

이 변경 사항을 적용하는 경우 containerd를 재시작한다.

sudo systemctl restart containerd

kubeadm을 사용하는 경우, kubelet용 cgroup 드라이버를 수동으로 구성한다.(???)

 

 

 

Step 1: Kubernetes Servers update & upgrade

설치 되어있는 패키지들의 새로운 버젼이 있는지 확인(update)하고 업그레이드 합니다. 업그레이드 후 리부팅을 합니다.

upgrade를 해야 되나?

sudo apt update
sudo apt -y full-upgrade
[ -f /var/run/reboot-required ] && sudo reboot -f

 

참고) pod 생성 시 네트워크 대역을 설정할 수 있습니다.

kubeadm init --pod-network-cidr=10.244.0.0/16;

 

kubeadm init 실행시 에러 : 'curl -sSL http://localhost:10248/healthz' failed with error

발생 시

/etc/docker 디렉토리에 daemon.json 파일을 아래와 같이 만들어줍니다.

{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}

 

daemon.json 파일 생성 후 아래 명령어를 실행해 줍니다.
sudo systemctl enable docker
sudo systemctl daemon-reload
sudo systemctl restart docker

 

위 조치 방법은 쿠버네티스 공식 홈페이지에 나와 있는 내용 그대롭니다.

  => https://kubernetes.io/docs/setup/production-environment/container-runtimes/#docker

 

사실은, 원래 쿠버네티스 설치전에 Container runtime 을 먼저 설치해줘야 하는데(여기서는 docker 부분..)

이 부분을 빠뜨리고 진행한 경우 이런 에러상황을 만나게 되는 겁니다.

위와 같이 daemon.json 파일을 만들어주고나서, kubeadm reset 하고 init 해주니 정상적으로 잘 되네요~

kubeadm reset
kubeadm init

 

에러 유형 3) 

init] Using Kubernetes version: v1.24.0
[preflight] Running pre-flight checks
	[WARNING SystemVerification]: missing optional cgroups: blkio
error execution phase preflight: [preflight] Some fatal errors occurred:
	[ERROR CRI]: container runtime is not running: output: time="2022-05-04T10:21:27Z" level=fatal msg="getting status of runtime: rpc error: code = Unimplemented desc = unknown service runtime.v1alpha2.RuntimeService"
, error: exit status 1

조치내용 : config.toml 파일 삭제, 컨테이너 엔진 재실행 후 kubeadm init 를 실행합니다.(????)

sudo rm /etc/containerd/config.toml
sudo systemctl restart containerd
sudo kubeadm init

kubeadm init 이 완료되면 제일 아래 줄에 아래와 같이 token 이 나타납니다. master node와 연결 시 필요하므로 별도로 저장해 둡니다.

## kubeadm init 실행 결과
......
kubeadm join 10.10.1.21:6443 --token j0vdns.lqbq17k0rwbuvwqj \
        --discovery-token-ca-cert-hash sha256:acfc34d9d77a3b0b326de55f969f95f34779853ac34720526eef99357982750d

kubectl get nodes 명령어를 수행해 봅니다. 오류가 발생하는데, 

# kubectl get nodes

The connection to the server localhost:8080 was refused - did you specify the right host or port?


오류 발생 시 아래 내용을 참조해서 명령어를 수행합니다.

cluster 를 일반 유저로 실행하려면 일반 유저 계정에서 아래를 실행합니다.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

일반 유저로 다시 node를 조회해 봅니다.

kubectl get nodes

NAME     STATUS     ROLES           AGE     VERSION
master   NotReady   control-plane   4m11s   v1.24.0

 

 

root 유저로 수행하려면 아래를 설정합니다.

# export KUBECONFIG=/etc/kubernetes/admin.conf
root@instance-2:~# kubectl get nodes
NAME         STATUS     ROLES                  AGE     VERSION
instance-2   NotReady   control-plane,master   9m30s   v1.23.6

위에서 STATUS 를 보변 NotReady 인데 이는 CNI(Container Network Interface)가 설치가 안되어 있어서 그렇습니다. CNI 설치 후 node 정보를 조회하면 STATUS 가 Ready 상태로 변경됩니다.

 

Pod network add-on 설치

pod 네트워크 애드온 종류는 많습니다(calico, canal, flannel, romana, weave net 등).

본 문서에서는 weave network add on 을 설치합니다. 

Weave Net을 설치하기 전에 TCP 6783 및 UDP 6783/6784 포트가 방화벽에 의해 차단되지 않았는지 확인해야 합니다.

아래 명령어로 weave network add-on을 설치합니다.

kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

## 실행결과
serviceaccount/weave-net created
clusterrole.rbac.authorization.k8s.io/weave-net created
clusterrolebinding.rbac.authorization.k8s.io/weave-net created
role.rbac.authorization.k8s.io/weave-net created
rolebinding.rbac.authorization.k8s.io/weave-net created
daemonset.apps/weave-net created

참고) weave network를 삭제 방법

kubectl delete -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"

serviceaccount "weave-net" deleted
clusterrole.rbac.authorization.k8s.io "weave-net" deleted
clusterrolebinding.rbac.authorization.k8s.io "weave-net" deleted
role.rbac.authorization.k8s.io "weave-net" deleted
rolebinding.rbac.authorization.k8s.io "weave-net" deleted
daemonset.apps "weave-net" deleted

 

weave network 가 설치되었는지 확인합니다. 아래 결과를 보면 weave-net-s6g8g 처럼 CNI가 설치된 것을 확인할 수 있습니다.

$ kubectl get pod --all-namespaces

## 명령어 수행결과
NAMESPACE     NAME                               READY   STATUS    RESTARTS   AGE
kube-system   coredns-6d4b75cb6d-h4bnk           1/1     Running   0          129m
kube-system   coredns-6d4b75cb6d-qdzst           1/1     Running   0          129m
kube-system   etcd-master-1                      1/1     Running   0          129m
kube-system   kube-apiserver-master-1            1/1     Running   0          129m
kube-system   kube-controller-manager-master-1   1/1     Running   0          129m
kube-system   kube-proxy-vgvxd                   1/1     Running   0          129m
kube-system   kube-scheduler-master-1            1/1     Running   0          129m
kube-system   weave-net-j92zv                    2/2     Running   1          30s

 

 

kubectl get nodes 명령어를 수행하면 status 가 Ready 상태가 됩니다.

kubectl get nodes
NAME         STATUS   ROLES                  AGE   VERSION
master-1     Ready    control-plane,master   14m   v1.23.6

 

worker node 구성

위에서 설명한 순서대로 환경설정 및 설치를 수행합니다. 제일 마지막 부분의 kubeadm init 명령어는 수행하지 않습니다.

위에서 저장한 token.txt 내용을 복사한 후 worker node에서 수행합니다.

 

 

 

에러 1) 처음 worker node 구성 시 아래와 같은 오류가 발생했는데, 이는 방화벽 때문에 발생한 오류입니다. 마스터 노드와 6443 port로 통신할 수 있는지 확인해 봅니다. 통신이 안될 경우 통신이 되도록 방화벽을 해제합니다.

sudo kubeadm join 10.10.10.210:6443 --token j0vdns.lqbq17k0rwbuvwqj \
>         --discovery-token-ca-cert-hash sha256:acfc34d9d77a3b0b326de55f969f95f34779853ac34720526eef99357982750d
[preflight] Running pre-flight checks
        [WARNING SystemVerification]: missing optional cgroups: hugetlb
error execution phase preflight: couldn't validate the identity of the API Server: Get "https://10.10.1.21:6443/api/v1/namespaces/kube-public/configmaps/cluster-info?timeout=10s": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
To see the stack trace of this error execute with --v=5 or higher

 

에러 2) woker node를 master node에 join 시 아래 오류가 발생하고,

kubeadm token list 명령어 수행 시 아무런 데이터가 조회되지 않을 경우에 대한 해결 방법입니다.

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 "j0vdns"

해결방법 1) kubeadm reset 후 kubeadm init을 실행하여 token을 다시 생성한다.

$ kubeadm reset
$ kubeadm init

kubeadm join 10.10.1.21:6443 --token j0vdns.lqbq17k0rwbuvwqj \
        --discovery-token-ca-cert-hash sha256:acfc34d9d77a3b0b326de55f969f95f34779853ac34720526eef99357982750d

## token list 확인
$ kubeadm token list
 TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
b962zm.9d6jh1g9dq0oroaq   23h         2022-05-03T14:00:04Z   authentication,signing   The default bootstrap token generated by 'kubeadm init'.   system:bootstrappers:kubeadm:default-node-token

재생성된 token으로 다시 worker node에서 실행합니다.

sudo kubeadm join 10.10.1.21:6443 --token j0vdns.lqbq17k0rwbuvwqj \
        --discovery-token-ca-cert-hash sha256:acfc34d9d77a3b0b326de55f969f95f34779853ac34720526eef99357982750d

 

해결방법 2) token 생성 후 hash 값을 확인한 다음 worker node를 join 합니다.

## token 생성
$ kubeadm token create

## hash 확인
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

## node 조인
kubeadm join <Kubernetes API Server:PORT> --token <Token 값> --discovery-token-ca-cert-hash sha256:<Hash 값>

 

worker node를 master에 join 시키기. 

필요한 수 만큼 worker node를 추가합니다. 단, 위에서 설치한 순서대로 설치를 하고 worker node를 추가합니다.

kubeadm join 10.10.1.21:6443 --token b962zm.9d6jh1g9dq0oroaq \
        --discovery-token-ca-cert-hash sha256:fc41fdaa4dfebf0d2c37a67aef3f3d69e88d9f6e3c9c73b510983dc7eb474276
[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.

 

설치 확인

마스터 노드(control-plane 노드)에서 kubectl get nodes 로 node 정보를 확인합니다. 아래와 같이 조회되면 정상입니다.

$ kubectl get nodes
NAME         STATUS   ROLES                  AGE     VERSION
instance-2   Ready    control-plane,master   10h     v1.23.6
instance-3   Ready    <none>                 9h      v1.23.6
instance-4   Ready    <none>                 2m40s   v1.23.6

 

 

선택사항으로 kubectl 명령어 자동완성 기능을 설정합니다. 명령어의 일부 글자만 타입핑한 후 "탭키"를 누르면 명령어가 완성되는 기능입니다.

echo "source <(kubectl completion bash)" >> ~/.bashrc
echo "source <(kubeadm completion bash)" >> ~/.bashrc

 

 

 

 

 

 

 

 

 

container runtime 설치

아래와 같이 여러 종류의 컨테이너 런타임이 있습니다. 본 문서에서는 containerd 런타임을 설치합니다.

 

 

docker 설치

docs.docker.com 참조하여 설치합니다. 참고로, 현재 도커 엔진 패키지는 docker-ce라고 부릅니다.

구버전 도커 Uninstall

이전 버전의 Docker는 docker, docker.io 또는 docker-engine이라고 했습니다. 이러한 항목이 설치된 경우 제거합니다.

sudo apt-get remove docker docker-engine docker.io containerd runc

저장소를 사용하여 설치

Docker 저장소를 설정해야 합니다. 그런 다음 저장소에서 Docker를 설치하고 업데이트할 수 있습니다.

저장소 설정

apt 패키지 인덱스를 업데이트하고 apt가 HTTPS를 통해 리포지토리를 사용할 수 있도록 패키지를 설치합니다.

$ sudo apt-get update

$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

도커 공식 GPG 키를 추가합니다.

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.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

 

Docker Engine 설치

apt 패키지 인덱스를 업데이트하고 최신 버전의 Docker Engine, containerd 및 Docker Compose를 설치합니다.

$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
or
$ sudo apt-get install docker-ce docker-ce-cli containerd docker-compose-plugin

 

containerd 설정 작업

containerd를 실행하기 전에 containerd의 기본 설정을 정의해줍니다. containerd config default 를 수행하면 기본적으로 제공하는 설정값들을 얻을 수 있습니다. tee 명령어를 통해 화면으로도 출력하고, config.toml 파일로도 저장합니다.

$ sudo mkdir -p /etc/containerd
$ containerd config default | sudo tee /etc/containerd/config.toml

systemd를 cgroup driver로 사용하기

systemd를 cgroup driver로 사용하려면 /etc/containerd/config.toml에 다음 설정을 추가합니다. 참고로, 아래 설정은 config.toml 파일에 사전 정의되어 있지 않으니 직접 추가하셔야 합니다.

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  ...
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

위 과정을 잘못 수행하는 경우 정상적으로 containerd가 실행되지 않습니다.

containerd 재시작

위 단계를 모두 마쳤다면 이제 containerd를 재시작할 차례입니다. 아래 명령어로 containerd를 재시작합니다.

$ sudo systemctl restart containerd

 

 

쿠버네티스 설정

kubernetes.io 사이트에 접속하여 각자의 OS에 맞는 설치 방법에 따라 설치한다.

document에서 "Set up cluster"를 클릭한다. install the kubeadm setup tool 를 클락한 후 설명대로 진행한다.

  • 설치전 환경 설정 : 위에서 설명
  • kubeadm, kubectl, kubelet
  • control plane 구성
  • worker node 구성
  • 설치 확인

kubeadm, kubelet 및 kubectl 설치

모든 머신에 다음 패키지들을 설치한다.

  • kubeadm: 클러스터를 부트스트랩하는 명령이다.
  • kubelet: 클러스터의 모든 머신에서 실행되는 파드와 컨테이너 시작과 같은 작업을 수행하는 컴포넌트이다.
  • kubectl: 클러스터와 통신하기 위한 커맨드 라인 유틸리티이다.

 

kubectl 예제

kubectl get 명령어로 클러스터를 구성하고 있는 node 정보를 볼 수 있습니다.

## node 정보조회
$ kubectl get nodes

## node 정보 상세조회
$ kubectl get nodes -o wide

컨테이너를 실행하면서 kubectl 명령어 사용하기

아래 명령어는 nginx 최신 버전의 이미지로 webserver 라는 이름의 pod를 생성하고 실행하라는 내용입니다.

$ kubectl run webserver --image=nginx:latest --port 80
pod/webserver created

생성된 pod를 확인합니다. 아래 내용을 보면 현재 상태가 container creating 인 것을 확인할 수 있습니다. pod가 정상적으로 생성완료되면 running으로  상태가 변경됩니다. 현재 진행되는 상태를 보려면 kubectl describe pods 명령어를 수행합니다.

$ kubectl get pods
NAME        READY   STATUS              RESTARTS   AGE
webserver   0/1     ContainerCreating   0          23s

## pods 정보 확인
$ kubectl get pods webserver -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP          NODE     NOMINATED NODE   READINESS GATES
webserver   1/1     Running   0          49m   10.44.0.1   node-1   <none>           <none>

## pods 상태 상세확인
$ kubectl describe pods webserver
## 실행결과
Events:
  Type    Reason     Age   From               Message
  ----    ------     ----  ----               -------
  Normal  Scheduled  57s   default-scheduler  Successfully assigned default/webserver to node-1
  Normal  Pulling    56s   kubelet            Pulling image "nginx:latest"
  Normal  Pulled     48s   kubelet            Successfully pulled image "nginx:latest" in 8.496066344s
  Normal  Created    48s   kubelet            Created container webserver
  Normal  Started    48s   kubelet            Started container webserver

node-1에서 10.44.0.1 IP로 nginx 웹서버가 작동하고 있는 것을 확인할 수 있습니다.

 

오류) 아래와 같은 오류가 발생할 경우에 containerd 를 재설치 후 서버를 reboot하니 오류가 발생하지 않았습니다.

sudo apt-get install containerd

 

  Warning  FailedCreatePodSandBox  18m                 kubelet            Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "...": failed to find network info for sandbox "..."
  Warning  FailedCreatePodSandBox  30s (x83 over 18m)  kubelet            (combined from similar events): Failed to create pod sandbox: rpc error: code = Unknown desc = failed to setup network for sandbox "..": failed to find network info for sandbox "..."

 

 

컨테이너 확인하기

curl 명령어로 위에서 생성한 nginx pod 가 정상 동작하는지 확인해 봅니다.(참고. elinks(이링크스)라는 유닉스 기반 운영 체제를 위한 텍스트 기반 콘솔 웹 브라우저로 웹 페이지를 확인할 수 있습니다.)

curl 10.44.0.1

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
....

 

kubectl create 명령어

파일 또는 표준 입력에서 리소스를 생성합니다. JSON and YAML 형식의 파일을 사용할 수 있습니다.

 

usage:
  kubectl create deployment NAME --image=image -- [COMMAND] [args...] [options]

 

kubectl create deployment mainui --image=httpd:latest --replicas=3

생성된 pod를 확인합니다.

1) kubectl get deployment.apps 명령어로 확인

kubectl get deployments.apps 
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
mainui   3/3     3            3           46s

2) kubectl get pods 명령어로 확인

$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
mainui-7bdb5f79fb-4qvhc   1/1     Running   0          3m29s
mainui-7bdb5f79fb-btblc   1/1     Running   0          3m29s
mainui-7bdb5f79fb-nrdv5   1/1     Running   0          3m29s
webserver                 1/1     Running   0          128m

 

배포한 웹서버의 웹페이지 변경하기

kubectl exec  명령어로 위에서 생성한 webserver pod의 웹페이지를 변경해 봅니다.

kubectl exec  명령어는 동작중인 컨테이너의 셸에 접근할 수 있도록 해주는 명령어입니다.

kubectl exec --stdin --tty webserver -- /bin/bash
또는
kubectl exec -it webserver -- /bin/bash

## 실행결과(컨테이너에 접속됨)
root@webserver:/#

 

nginx 웹페이지는 /usr/share/nginx/html 디렉토리에 있습니다. index.html 파일이 웹서버의 첫 웹페이지입니다.이 웹페이지를 원하는 내용으로 변경하고 curl이나 elinks 로 변경된 내용을 확인합니다.

# cat > index.html
NGINX 웹서버입니다.
ctrl + D 를 클릭하여 저장합니다.
# exit

$ curl 10.44.0.1
NGINX 웹서버입니다.

 

nginx log도 확인해 봅니다. nginx log는 컨테이너의 /var/log/nginx 밑에 access.log, error.log 파일입니다.

$ kubectl logs webserver

...
10.32.0.1 - - [05/May/2022:16:27:14 +0000] "GET / HTTP/1.1" 200 615 "-" "ELinks/0.13.1 (textmode; Linux 5.13.0-1024-gcp x86_64; 153x16-2)" "-"
10.44.0.0 - - [05/May/2022:18:15:45 +0000] "GET / HTTP/1.1" 200 29 "-" "curl/7.68.0" "-"
10.44.0.1 - - [05/May/2022:18:16:20 +0000] "GET / HTTP/1.1" 200 29 "-" "curl/7.74.0" "-"

이제 외부에서 pod에 접속할 수 있도록 port-forward 명령어를 사용합니다.

아래 명령어는 외부에서 8080으로 접속하면 pod의 80 port로 forwarding 하는 예시입니다.

$ kubectl port-forward --address=0.0.0.0 webserver 8080:80

다른 서버에서 curl 명령어를 사용하여 웹서버 페이지를 호출해 봅니다.

$ curl http://10.10.1.35:8080

NGINX 웹서버입니다

위에서 생성한 mainui pod의 개수를 3개에서 kubectl edit 명령어로 변경해 봅니다.

아래 명령어를 수행하면 mainui pod에 대한 설정값을 vi 에디터로 불러옵니다. 여기서 변경하고자 하는 값을 변경하면 됩니다. 본 문서에서는 replicas를 3개에서 5개로 변경해 보겠습니다. 변경 후 :wq 로 저장하고 vi 에디터를 빠져나옵니다.

kubectl edit deployments.app mainui

....
spec:
  progressDeadlineSeconds: 600
  replicas: 5
...

pod 갯수가 변경되었는지 확인합니다. 아래와 같이 mainui pod가 5개로 변경된 것을 볼 수 있습니다.

kubectl get pods

## 실행결과
$ kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
mainui-7bdb5f79fb-4qvhc   1/1     Running   0          76m
mainui-7bdb5f79fb-8t9r9   1/1     Running   0          2m23s
mainui-7bdb5f79fb-btblc   1/1     Running   0          76m
mainui-7bdb5f79fb-nrdv5   1/1     Running   0          76m
mainui-7bdb5f79fb-q6nlg   1/1     Running   0          61s
webserver                 1/1     Running   0          3h20m

 

pod 생성할 내용을 파일로 생성해 봅니다.

--dry-run 플래그를 사용하여 실제로 제출하지 않고 클러스터로 보낼 오브젝트를 미리 볼 수 있습니다.

리다이텍션으로 파일로 저장할 수도 있습니다.

kubectl run webserver --image=nginx --port 80 --dry-run=client -o yaml > webser.yaml

yaml 파일로 pod를 생성합니다. 기존에 생성한 이름과 동일한 pod를 생성하므로 기존 pod를 삭제한 후 실행합니다.

## 기존 webserver pod 삭제
$ kubectl delete pod webserver

## yaml 파일로 pod 생성
$ kubectl create -f webserver.yaml

## 생성된 pod 확인
$ kubectl get pods

 

[참고] kubectl create vs apply 

 

kubectl create
kubectl create는 명령형 관리를 위한 것입니다. 이 접근 방식에서는 생성, 교체 또는 삭제하려는 항목을 Kubernetes API에 알립니다. 간단히 말해서 create는 새 객체를 생성합니다. 리소스가 이미 있는 경우 오류가 발생합니다.

 

kubectl apply

kubectl apply는 다른 변경 사항을 개체에 적용하더라도 라이브 개체에 적용했을 수 있는 변경 사항(즉, 규모를 통해)이 "유지 관리"되는 선언적 관리 접근 방식의 일부입니다.
apply는 우리가 필요로 하는 것을 정의함으로써 기존 객체를 점진적으로 변경합니다. 리소스가 이미 있는 경우 오류가 발생하지 않습니다.

 

pod 삭제

예제) kubectl delete pods <pod> : <pod> 부분에 삭제할 pod 이름을 입력합니다.

kubectl delete pods webserver

 

 

 

Initializing control-plane node

control-plane 노드는 etcd(클러스터 데이터베이스) 및 API 서버(kubectl 명령줄 도구가 통신함)를 포함하여 control-plane 구성 요소가 실행되는 시스템입니다.

 

1. (권장) 이 단일 control-plane kubeadm 클러스터를 고가용성으로 업그레이드할 계획이 있는 경우 --control-plane-endpoint를 지정하여 모든 control-plane 노드에 대한 endpoint 설정해야 합니다. 이러한 endpoint 는 DNS 이름 또는 로드 밸런서의 IP 주소일 수 있습니다.

2. Pod 네트워크 추가 기능을 선택하고 kubeadm init에 전달되는 인수가 필요한지 확인합니다. 선택한 타사 공급자에 따라 --pod-network-cidr을 공급자별 값으로 설정해야 할 수도 있습니다.

3. 

 


# initialize kubernetes with a Flannel compatible pod network CIDR
kubeadm init --pod-network-cidr=10.244.0.0/16;

# setup kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config;

# install Flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml;

# install Dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc2/aio/deploy/recommended.yaml;
cat > dashboard-admin.yaml <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kubernetes-dashboard
  namespace: kubernetes-dashboard
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: kubernetes-dashboard
    namespace: kubernetes-dashboard
EOF
kubectl delete clusterrolebinding/kubernetes-dashboard;
kubectl apply -f dashboard-admin.yaml;

# get the dashboard secret and display it
kubectl get secret -n kubernetes-dashboard \
| grep kubernetes-dashboard-token- \
| awk '{print $1}' \
| xargs kubectl describe secret -n kubernetes-dashboard;

 

 

 

 

'쿠버네티스' 카테고리의 다른 글

쿠버네티스 - namespace  (0) 2022.05.09
쿠버네티스 아키텍처  (0) 2022.05.09
CNI 플러그인 모드  (0) 2022.05.04
쿠버네티스 - 로드 밸런싱  (0) 2022.04.27
쿠버네티스 - katacoda  (0) 2022.04.26

+ Recent posts