Kubernetes

Kubernetes 구축

흥부가귀막혀 2024. 1. 29. 15:25

공통(Master/Worker Node)

Docker 설치

  • Docker Engine Install 을 참고하여 사용하는 OS 에 맞게 설치 진행한다.
  • centos 버전으로 설치 진행
  • root 권한이 필요하기 때문에 root 계정으로 진행한다.

yum-utils 설치 및 docker repository 등록

sudo yum install -y yum-utils
sudo yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

필요한 Docker Package 설치(특정 버전을 설치하고자 한다면, yum list docker-ce --showduplicates | sort -r 로 원하는 버전 확인 후 설치를 진행한다)

sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y

Docker 실행

sudo systemctl start docker

Kubernetes 설치

  • kubeadm 설치 를 참고하여 진행한다.
  • root 권한이 필요하기 때문에 root 계정으로 진행한다.

1. swap 비활성화

sudo /sbin/swapoff -a && sudo sed -i '/swap/s/^/#/' /etc/fstab

2. IPv4 포워딩 및 iptables에서 브리지된 트래픽 확인

  • Container Runtime 가이드에 따라 IPv4 포워딩 및 iptables에서 브리지된 트래픽 확인을 진행한다.
  • root 권한이 필요하기 때문에 root 계정으로 진행한다.
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

# sysctl params required by setup, params persist across reboots
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

# Apply sysctl params without reboot
sudo /sbin/sysctl --system

3. Container Runtime Interface 설치

  • Kubernetes 와 Container Runtime 을 연결해주기 위한 Container Runtime Interface 가 설치되야 하는데 종류가 몇가지 있다.
  • 현재 구축한 kubernetes 는 cri-dockerd 로 설치

1) Containerd

/etc/containerd/config.toml 설정 파일에서 cri disabled 제거

sed -i '/"cri"/ s/^/#/' /etc/containerd/config.toml

/etc/containerd/config.toml 설정 파일에서 runc 설정 추가

vi /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
    SystemdCgroup = true

2) cri-dockerd

  • cri-dockerd README 를 참고하여 설치를 진행한다.
  • # Run these commands as root ###Install GO### wget https://storage.googleapis.com/golang/getgo/installer_linux chmod +x ./installer_linux ./installer_linux source ~/.bash_profile
git clone [https://github.com/Mirantis/cri-dockerd.git](https://github.com/Mirantis/cri-dockerd.git)  
cd cri-dockerd  
mkdir bin  
go build -o bin/cri-dockerd  
sudo mkdir -p /usr/local/bin  
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd  
sudo cp -a packaging/systemd/\* /etc/systemd/system  
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service  
sudo systemctl daemon-reload  
sudo systemctl enable cri-docker.service  
sudo systemctl enable --now cri-docker.socket

4. kubeadm, kubelet, kubectl 설치

kubernetes repository 등록

cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

SELinux mode 변경

# Set SELinux in permissive mode (effectively disabling it)
sudo /sbin/setenforce 0
# 가이드에서는 permissive 모드로 변경하였지만, 효과적으로 하려면 disabled 로 설정해도 된다.(현재 구축된 kubernetes 는 disabled 로 설정)
# sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config     # permissive 로 변경 
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config      # disabled 로 변경 

kubeadm, kubelet, kubectl 설치 및 kubelet 실행

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

Master Node 구축(⚠️ Worker 노드에서는 하면 안됨!)

1. kubeadm init 실행

  • Container Network Interface 를 어떤걸 쓰냐에 따라 init 수행시 --pod-network-cidr 설정을 다르게 가야한다.
  • 현재 구축된 kubernetes 는 flannel 을 설치하였고 이에 맞게 init 설정을 진행함
  • 원래는 calico 를 초기에 셋팅했었으나, ncloud 장비의 bpf 관련 이슈로 정상적으로 동작하지 않아 변경함.
  • CRI 로 Containerd, cri-dockerd 둘다 설치했을 경우 어떤 CRI 를 사용할 것인지 정해줘야 한다. init 실행시 --cri-socket 옵션을 추가하여 사용할 CRI 가 어떤건지 설정한다.

init command 실행

# flannel 의 기본 cidr 설정값인 10.244.0.0/16 을 설정한다.
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --cri-socket=unix:///var/run/cri-dockerd.sock

init 호출 후 stdout 에 출력된 Worker node 추가에 필요한 join command 내용을 잘 기록해둔다. 이거 안하면 Worker Node 추가가 불가능하기 때문에 다시 reset 해야함.

vi token.txt

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

sudo 권한 없이 kubectl 사용을 위한 설정 추가

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

❔ 혹시나 init 과정에서 실패가 발생했거나 master node 설정을 초기화 하고 싶다면? reset command 를 호출한다.

# 어떤 CRI 로 구축했는지 알아야 해서 --cri-socket 옵션을 넣어준다. 
sudo kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock 

2. CNI 설치(flannel)

  • 다음 명령어를 통해 flannel 을 설치한다.
  • kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml
  • 간혹 flannel 설치 이후 /run/flannel 디렉토리 안 subnet.env 파일이 생성되지 않아 오류가 발생할 수 있다. 파일이 생성되었는지 확인하고 혹시 생성이 안되어있다면 다음과 같이 생성해준다.
  • sudo vi /run/flannel/subnet.env
FLANNEL\_NETWORK=10.244.0.0/16  
FLANNEL\_SUBNET=10.244.0.1/24  
FLANNEL\_MTU=1450  
FLANNEL\_IPMASQ=true

3. Master Node 에 필요한 pod 이 정상인지 확인

  • kubectl 을 통해 node 상태 및 control-plane 이 정상적으로 운영중인지 확인한다.
kubectl get nodes
NAME STATUS ROLES AGE VERSION  
dev-k8s-node-002 Ready control-plane 179m v1.26.1
  • 혹여 node 의 STATUS 가 NotReady 일 경우 정확한 확인을 위해 pod 상태를 확인해본다.
  • kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE  
coredns-787d4945fb-2f9f7 1/1 Running 0 179m  
coredns-787d4945fb-ksp7d 1/1 Running 0 179m  
etcd-dev-k8s-node-002 1/1 Running 0 3h  
kube-apiserver-dev-k8s-node-002 1/1 Running 0 3h  
kube-controller-manager-dev-k8s-node-002 1/1 Running 0 3h  
kube-proxy-98thd 1/1 Running 0 174m  
kube-proxy-d5ddx 1/1 Running 0 179m  
kube-scheduler-dev-k8s-node-002 1/1 Running 0 3h
  • STATUS 가 Running 이 아닌 Pod 이 있을 경우 다음 명령어를 통해 log 및 pod event 내용을 확인한다.

log 확인

kubectl logs coredns-787d4945fb-2f9f7 -n kube-system

pod event 확인

kubectl describe pod coredns-787d4945fb-2f9f7 -n kube-system

Name:                 coredns-787d4945fb-2f9f7
Namespace:            kube-system
Priority:             2000000000
Priority Class Name:  system-cluster-critical
Service Account:      coredns
Node:                 dev-k8s-node-002/10.113.137.19
Start Time:           Thu, 02 Feb 2023 12:09:20 +0900
Labels:               k8s-app=kube-dns
                      pod-template-hash=787d4945fb
Annotations:          <none>
Status:               Running
IP:                   10.244.0.3
IPs:
  IP:           10.244.0.3
Controlled By:  ReplicaSet/coredns-787d4945fb
Containers:
  coredns:
    Container ID:  docker://bb053af27773abb6622792d75f56835f1530ca435601337b9afd68910309790c
    Image:         registry.k8s.io/coredns/coredns:v1.9.3
    Image ID:      docker-pullable://registry.k8s.io/coredns/coredns@sha256:8e352a029d304ca7431c6507b56800636c321cb52289686a581ab70aaa8a2e2a
    Ports:         53/UDP, 53/TCP, 9153/TCP
    Host Ports:    0/UDP, 0/TCP, 0/TCP
    Args:
      -conf
      /etc/coredns/Corefile
    State:          Running
      Started:      Thu, 02 Feb 2023 12:09:21 +0900
    Ready:          True
    Restart Count:  0
    Limits:
      memory:  170Mi
    Requests:
      cpu:        100m
      memory:     70Mi
    Liveness:     http-get http://:8080/health delay=60s timeout=5s period=10s #success=1 #failure=5
    Readiness:    http-get http://:8181/ready delay=0s timeout=1s period=10s #success=1 #failure=3
    Environment:  <none>
    Mounts:
      /etc/coredns from config-volume (ro)
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-4xgx5 (ro)
Conditions:
  Type              Status
  Initialized       True 
  Ready             True 
  ContainersReady   True 
  PodScheduled      True 
Volumes:
  config-volume:
    Type:      ConfigMap (a volume populated by a ConfigMap)
    Name:      coredns
    Optional:  false
  kube-api-access-4xgx5:
    Type:                    Projected (a volume that contains injected data from multiple sources)
    TokenExpirationSeconds:  3607
    ConfigMapName:           kube-root-ca.crt
    ConfigMapOptional:       <nil>
    DownwardAPI:             true
QoS Class:                   Burstable
Node-Selectors:              kubernetes.io/os=linux
Tolerations:                 CriticalAddonsOnly op=Exists
                             node-role.kubernetes.io/control-plane:NoSchedule
                             node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                             node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:                      <none>

Worker Node 구축

1. Master Node 구축시 출력된 join 명령어를 수행한다.

# CRI 가 여러개 설치되었을 경우 join 명령어 수행시 --cri-socket 설정을 추가하여 CRI 를 설정한다.
sudo kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash> --cri-socket=unix:///var/run/cri-dockerd.sock 

2. Master Node 에서 Worker Node 가 정상적으로 Join 되었는지 확인한다.

kubectl get nodes

NAME               STATUS   ROLES           AGE    VERSION
dev-k8s-node-002   Ready    control-plane   3h9m   v1.26.1
dev-k8s-node-003   Ready    <none>          3h3m   v1.26.1

Reference