개발/Kubernetes

Hyper-V 에서 Kubernetes 설치하기

bitofsky 2022. 5. 27. 00:43

Ubuntu 18.04 / 20.04 를 Hyper-V에 띄운 후 K8s를 Step By Step으로 설치합니다.
이 포스트는 일반적인 minikube / kubespray 등 설치 패키지를 사용하지 않고 kubernetes 구성을 이해하기 위해 마스터, 워커 노드 구성 요소를 하나하나 바이너리 레벨로 설치하는 것을 목표로 합니다.

Linux 기본 지식이 필요합니다.


먼저 마스터노드와 워커노드에 공통으로 필수적인 Kubelet, containerd, cni plugins, runC를 설치합니다.

sudo su
cd ~

# dsn resolve
sh -c 'echo "DNS=8.8.8.8 8.8.4.4" >> /etc/systemd/resolved.conf'
systemctl restart systemd-resolved

# SWAP OFF
swapoff -a

# install binaries
apt-get update
apt-get install socat conntrack

# iptables
cat <<EOF | tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

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

RELEASE="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
DOWNLOAD_DIR=/usr/local/bin
mkdir -p $DOWNLOAD_DIR
ARCH="amd64"
curl -L "https://github.com/kubernetes-sigs/cri-tools/releases/download/${RELEASE}/crictl-${RELEASE}-linux-${ARCH}.tar.gz" | tar -C $DOWNLOAD_DIR -xz
cd $DOWNLOAD_DIR
curl -L --remote-name-all https://storage.googleapis.com/kubernetes-release/release/${RELEASE}/bin/linux/${ARCH}/{kubeadm,kubelet,kubectl}
chmod +x {kubeadm,kubelet,kubectl}

RELEASE_VERSION="v0.4.0"
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubelet/lib/systemd/system/kubelet.service" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | tee /etc/systemd/system/kubelet.service
mkdir -p /etc/systemd/system/kubelet.service.d
curl -sSL "https://raw.githubusercontent.com/kubernetes/release/${RELEASE_VERSION}/cmd/kubepkg/templates/latest/deb/kubeadm/10-kubeadm.conf" | sed "s:/usr/bin:${DOWNLOAD_DIR}:g" | tee /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

# install containerd
cd ~
wget https://github.com/containerd/containerd/releases/download/v1.6.4/containerd-1.6.4-linux-amd64.tar.gz
tar Cxzvf /usr/local containerd-1.6.4-linux-amd64.tar.gz
curl https://raw.githubusercontent.com/containerd/containerd/main/containerd.service -o /etc/systemd/system/containerd.service
systemctl daemon-reload
systemctl enable --now containerd

# install runc
wget https://github.com/opencontainers/runc/releases/download/v1.1.2/runc.amd64
install -m 755 runc.amd64 /usr/local/sbin/runc

# install cni plugins
CNI_VERSION="v1.1.1"
mkdir -p /opt/cni/bin
curl -L "https://github.com/containernetworking/plugins/releases/download/${CNI_VERSION}/cni-plugins-linux-${ARCH}-${CNI_VERSION}.tgz" | tar -C /opt/cni/bin -xz

# start kubelet service
systemctl enable --now kubelet

fstab을 편집해 swap을 완전히 off시킵니다. (/swap.img 라인 주석처리)

vi /etc/fstab

설치가 완료되었다면 kubelet 프로세스가 정상동작 하고있어야 합니다.


마스터노드에서 K8s Cluster를 생성합니다. kubeconfig도 복사해서 kubectl을 쓸 수 있게합니다.

# cluster init - pod using flannel's cidr
kubeadm init --pod-network-cidr=10.244.0.0/16

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

# node status
kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
k8s-master1   Ready    control-plane   5m    v1.24.1

만약 kubectl get nodes에서 노드 STATUS가 NotReady면서 CoreDNS Pod가 뜨지않는 중이라면 CNI 플러그인 설치가 필요한 상태일 수 있습니다. 여기서는 Flannel을 클러스터에 설치합니다.

# install flannel & rbac
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml

systemctl restart kubelet
kubectl get nodes

다른 가상/물리 컴퓨터에서 새로 만든 이 클러스터에 워커노드를 붙여주어야 pod들을 띄울 수 있습니다. 워커노드의 경우 위의 1단계 Kubelet 등 필수 구성요소 설치를 동일하게 해줍니다.

워커노드에 kubelet 설치와 동작 상태가 확인되었다면 마스터노드에서 join 토큰을 만들고 워커노드에서 join 시켜주면 클러스터에 워커가 인식되어 들어옵니다.

# kubeadm token create inside master
kubeadm token create --print-join-command

# kubeadm join inside worker
kubeadm join master-node-ip:6443 --token TOKEN --discovery-token-ca-cert-hash sha256:HASH

# worker node enabled
kubectl get nodes
NAME          STATUS   ROLES           AGE   VERSION
k8s-master1   Ready    control-plane   16m   v1.24.1
k8s-worker1   Ready    <none>           9m   v1.24.1

만약 HA로 마스터노드 컨트롤플레인을 복수 구성하려면 방법은 크게 2가지가 있는데, ETCD와 컨트롤플레인이 함께 도는 Stacked와 ETCD를 외부로 분리시키는 External ETCD가 있습니다. 대형이라면 External ETCD로 하겠지만 여기서는 Stacked로 구성하는걸 간단히 설명해 봅니다.

이미 싱글로 돌고있는 클러스터를 HA로 변경하는방법은 모르겠고... (아시는분은 문서 링크좀... 공식문서에서 못찾겠네요), 다음 명령어를 통해 마스터, 워커에서 각각 설정을 초기화 합니다.

# kube cluster config 초기화
kubeadm reset

# kubelet restart & network cni 초기화
systemctl stop kubelet
ip link set cni0 down
brctl delbr cni0
iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X
systemctl restart kubelet

이제 HA 구성을 위해 먼저 모든 마스터를 묶어줄 로드밸런서가 필요한데 HAProxy를 설치, 구성해 k8s-master1 서버의 56443 포트에 각 마스터들의 6433 포트를 묶겠습니다.

ssh k8s-master
sudo su

# install HAProxy
apt-get install haproxy

# create control-plane loadbalancer config file
cat <<EOF >> /etc/haproxy/haproxy.cfg
frontend k8s-masters-lb
bind 0.0.0.0:56443
option tcplog
mode tcp
default_backend k8s-masters

backend k8s-masters
mode tcp
balance roundrobin
option tcp-check
option tcplog
server k8s-master1 k8s-master1:6443 check
server k8s-master2 k8s-master2:6443 check
EOF

# start HAProxy
systemctl restart haproxy && systemctl enable haproxy
systemctl status haproxy

위 설정 파일 중 k8s-master1, k8s-master2는 Hyper-V안에서 컴퓨터 이름으로 Private IP로 DNS 매핑을 제공하니 IP를 적지 않아도 되며 마스터 구성에 따라 마스터 접속 정보를 넣어줍니다.

k8s-master1, k8s-master2에 각각 kubelet 동작까지 시켜두고 k8s-master에서 클러스터를 생성합니다. 이때는 단일과 달리 HA구성임을 kubeadm에 알려주어야 합니다. --upload-certs 인자를 추가해야 k8s-master1의 인증서가 k8s 클러스터에 업로드되어 다른 마스터를 컨트롤플레인으로 join 시킬 때 cert들을 수동으로 복사하지 않아도 됩니다.

kubeadm init --pod-network-cidr=10.244.0.0/16 --control-plane-endpoint "k8s-master1:56443" --upload-certs

# kubeconfig
mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config
  
# install flannel & rbac
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml
systemctl restart kubelet
kubectl get nodes

정상 init 이 되었다면 단일 구성때와 달리 다른 마스터의 control-plane을 join 시킬 수 있는 커맨드를 알려줍니다. CoreDNS에 문제가 있다면 위에서와 마찬가지로 Flannel을 설치합니다.

You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join k8s-master1:56443 --token TOKEN \
        --discovery-token-ca-cert-hash sha256:HASH \
        --control-plane --certificate-key KEY

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

--control-plane과 --certificate-key가 추가된 명령어를 주는데 이걸 다른 마스터 노드에서 실행해주면 컨트롤 플레인으로 조인이 됩니다. 워커노드 역시 단일 구성때처럼 동일하게 Join 해주면 됩니다.

kubectl get nodes
NAME          STATUS   ROLES           AGE     VERSION
k8s-master1   Ready    control-plane   22m     v1.24.1
k8s-master2   Ready    control-plane   8m26s   v1.24.1
k8s-worker1   Ready    <none>          7m56s   v1.24.1

HA로 설치 이후 Flannel Daemonsets로 생성된 pod들이 마스터1 노드에서만 활성화되고 다른 노드에 뜬 pod는 계속 restart 되는 문제가 발견되었습니다. flannel-ds pod의 log를 보면 다음과 같은 오류가 발생하는데 kube-api server에 제대로 쿼리하지 못하고 있는 것 같습니다.

E0302 09:09:51.398785       1 main.go:127] Failed to create SubnetManager: error retrieving pod spec for 'default/kube-flannel-ds-9cx5f': Get https://10.96.0.1:443/api/v1/namespaces/default/pods/kube-flannel-ds-9cx5f: dial tcp 10.96.0.1:443: i/o timeout

해결법은 다음 커맨드를 k8s-master1이나 HAProxy가 설치된 노드에서 실행해주면 됩니다. Daemonset의 Env에 Kubernetes API Endpoint를 명시적으로 설정해주는 것입니다.

IP=$(/sbin/ip -o -4 addr list eth0 | awk '{print $4}' | cut -d/ -f1)
kubectl set env daemonset/kube-flannel-ds KUBERNETES_SERVICE_HOST=${IP} KUBERNETES_SERVICE_PORT=56443 -c kube-flannel -n kube-system

 

'개발 > Kubernetes' 카테고리의 다른 글

Kubernetes OpenLens 6.1.12 Download  (0) 2022.08.01
kubectl tip  (0) 2022.05.25
오픈소스 무료 윈도우 도커 컨테이너 실행하기  (0) 2022.03.30