티스토리 뷰

728x90
반응형

Docker를 사용하지 않고 Containerd 기반의 Kubernetes Cluster를 CentOS 8 에 kubeadm으로 설치하기

CentOS 8 버전부터 도커 Docker 는 레드햇의 도구인 podman, buildah 로 대체된 상태로 기본 패키지 저장소에서 제거되었고, API를 사용해서 처리되는 것이기 때문에 특정 툴에 한정될 필요가 없다.

현재 제공되고 있는 컨테이너 런타임Container Runtime 은 다음과 같다.

이 문서는 containerd를 사용해서 클러스터를 구성한다.

  • 1개의 마스터 노드와 3개의 워커 노드 모두 CentOS 8 설치
  • 각 노드는 2G RAM, 2 CPU 를 최소 사양으로 한다.
  • 모든 노드는 저장소에서 쿠버네티스 Kubernetes 및 기타 필수 패키지를 설치할 수 있도록 인터넷에 연결이 가능해야 하고, dnf 패키지 관리자를 사용할 수 있으며 원격으로 패키지를 가져올 수 있는지 검증되어야 한다.

설치환경 요약

쿠버네티스의 최소 요구 사항은 2G RAM, 2 CPU 를 기준으로 한다.

  • Master
    • CentOS 8.2.2004
    • monitor.master
    • centos
  • Worker
    • CentOS 8.2.2004
    • monitor.worker1, 2, 3
    • centos
  • CNI : Calico

CentOS 의 버전을 확인하는 방법은 아래와 같다.

$ cat /etc/redhat-release
CentOS Linux release 8.2.2004 (Core) 

$ cat /etc/*release*
CentOS Linux release 8.2.2004 (Core) 
Derived from Red Hat Enterprise Linux 8.2 (Source)
NAME="CentOS Linux"
VERSION="8 (Core)"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Linux 8 (Core)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://www.centos.org/"
BUG_REPORT_URL="https://bugs.centos.org/"

CENTOS_MANTISBT_PROJECT="CentOS-8"
CENTOS_MANTISBT_PROJECT_VERSION="8"
REDHAT_SUPPORT_PRODUCT="centos"
REDHAT_SUPPORT_PRODUCT_VERSION="8"

CentOS Linux release 8.2.2004 (Core) 
CentOS Linux release 8.2.2004 (Core) 
cpe:/o:centos:centos:8

CentOS 8.2의 경우 일반 계정 생성 후에 sudo 권한을 줄 경우는 아래의 명령을 사용한다.

$ usermode -aG wheel <user>

CentOS 8.2에는 wheel 이라는 특별한 그룹이 존재하는데 sudo 설정에는 이 그룹에 한해 sudo 권한을 부여하고 있기 때문에 이 그룹에 사용자를 포함시키면 된다.

공통 설정

마스터와 워커 노드 모두 Static IP를 가지고 있어야 하며, 일반 계정이 존재해야 하며 sudo 권한을 가져야 한다.

  • 관리자 권한으로 설정
  • sudo -s
  • 패키지 관리자 갱신
  • dnf -y upgrade
  • Hosts 정보 설정
  • # 각 노드에서 각자에 맞도록 호스트 명 설정 hostnamectl set-hostname <host name> # /etc/hosts 에 각 구성 노드들의 IP와 HostName 설정 vi /etc/hosts ... <node ip> <hostname> <node ip> <hostname> ...
  • 방화벽 설정CentOS 8에는 기본적인 방화벽이 설치되어 있기 않기 때문에 설치를 수행한다.정상적인 방화벽 설정
    • 방화벽 규칙 설정
    • # 공통으로 설정할 경우 $ sudo firewall-cmd --permanent --add-port=22/tcp # SSH $ sudo firewall-cmd --permanent --add-port=80/tcp # Web $ sudo firewall-cmd --permanent --add-port=443/tcp # API Requests and End-User, used by Workers $ sudo firewall-cmd --permanent --add-port=2376/tcp # Docker daemon TLS, used by all $ sudo firewall-cmd --permanent --add-port=2379-2380/tcp # ETCD Server client API, used by kueb-apiserver, etcd $ sudo firewall-cmd --permanent --add-port=6443/tcp # Kubernetes API Server, used by all $ sudo firewall-cmd --permanent --add-port=8285/udp # Flannel overlay network (UDP Backend), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=8472/udp # Flannel overlay network (VxLan), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=9099/tcp # Liveness/Readiness kubelet, API, used by Master, Worker $ sudo firewall-cmd --permanent --add-port=10250/tcp # kubelet API, used by self and control plane $ sudo firewall-cmd --permanent --add-port=10251/tcp # kube-scheduler, used by self $ sudo firewall-cmd --permanent --add-port=10252/tcp # kube-controller-manager, used by self $ sudo firewall-cmd --permanent --add-port=10254/tcp # Ingress $ sudo firewall-cmd --permanent --add-port=10255/tcp # Heapster, used by Worker $ sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort services, used by all $ sudo firewall-cmd --permanent --add-port=30000-32767/udp # NodePort services, used by all # 역할별 - ETCD 운영용 노드인 경우 $ sudo firewall-cmd --permanent --add-port=2376/tcp # Docker daemon TLS, used by all $ sudo firewall-cmd --permanent --add-port=2379-2380/tcp # ETCD Server client API, used by kueb-apiserver, etcd $ sudo firewall-cmd --permanent --add-port=8472/udp # Flannel overlay network (VxLan), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=9099/tcp # Liveness/Readiness kubelet, API, used by Master, Worker $ sudo firewall-cmd --permanent --add-port=10250/tcp # kubelet API, used by self and control plane # 역할별 - 마스터 Control Plane 노드인 경우 $ sudo firewall-cmd --permanent --add-port=80/tcp # Web $ sudo firewall-cmd --permanent --add-port=443/tcp # API Requests and End-User, used by Workers $ sudo firewall-cmd --permanent --add-port=2376/tcp # Docker daemon TLS, used by all $ sudo firewall-cmd --permanent --add-port=6443/tcp # Kubernetes API Server, used by all $ sudo firewall-cmd --permanent --add-port=8285/udp # Flannel overlay network (UDP Backend), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=8472/udp # Flannel overlay network (VxLan), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=9099/tcp # Liveness/Readiness kubelet, API, used by Master, Worker $ sudo firewall-cmd --permanent --add-port=10250/tcp # kubelet API, used by self and control plane $ sudo firewall-cmd --permanent --add-port=10254/tcp # Ingress $ sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort services, used by all $ sudo firewall-cmd --permanent --add-port=30000-32767/udp # NodePort services, used by all # 역할별 - 워커 노드인 경우 $ sudo firewall-cmd --permanent --add-port=22/tcp # SSH $ sudo firewall-cmd --permanent --add-port=80/tcp # Web $ sudo firewall-cmd --permanent --add-port=443/tcp # API Requests and End-User, used by Workers $ sudo firewall-cmd --permanent --add-port=2376/tcp # Docker daemon TLS, used by all $ sudo firewall-cmd --permanent --add-port=8472/udp # Flannel overlay network (VxLan), used by Master, Worker (if use Flannel) $ sudo firewall-cmd --permanent --add-port=9099/tcp # Liveness/Readiness kubelet, API, used by Master, Worker $ sudo firewall-cmd --permanent --add-port=10250/tcp # kubelet API, used by self and control plane $ sudo firewall-cmd --permanent --add-port=10254/tcp # Ingress $ sudo firewall-cmd --permanent --add-port=30000-32767/tcp # NodePort services, used by all $ sudo firewall-cmd --permanent --add-port=30000-32767/udp # NodePort services, used by all # Calico Pod Network (마스터, 워커) $ sudo firewall-cmd --permanent --zone=public --add-port=179/tcp # Calico Networking (BGP), used by all (if use calico) $ sudo firewall-cmd --reload
  • # 방화벽 설치 dnf -y install firewalld # 활성화 systemctl enable firewalld systemctl start firewalld # 방화벽에 IP Masquerade 활성화 firewall-cmd --add-masquerade --permanent firewall-cmd --reload # 상태 확인 firewall-cmd --state firewall-cmd --list-all # 방화벽 끄기 systemctl stop firewalld systemctl disable firewalld
  • 방화벽은 쿠버네티스에서 제시하는 포트들을 열어주면 사용이 가능하지만 실제 사용할 때는 쿠버네티스 공식문서에 제시되지 않은 포트들도 존재하고, 이상 동작하는 상황들도 발생하기 때문에 일반적인 테스트를 위한 실행기준으로는 방화벽을 끄고 운영하는 것을 권장한다. (당연히 프로덕션 환경이라면 필요한 포트들을 방화벽에 등록하고 정상적으로 사용해야 한다)
  • Container Runtime 설치
    • 사전 설정
    • cat > /etc/modules-load.d/containerd.conf <<EOF overlay br_netfilter EOF modprobe overlay modprobe br_netfilter # Setup required sysctl params, these persist across reboots. cat > /etc/sysctl.d/99-kubernetes-cri.conf <<EOF net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 net.bridge.bridge-nf-call-ip6tables = 1 EOF sysctl --system
    • containerd 설치
    • # Install required packages dnf install -y yum-utils device-mapper-persistent-data lvm2 iproute-tc # Add docker repository dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo # dnf update and Install containerd dnf update -y && dnf install -y containerd.io # Configure containerd mkdir -p /etc/containerd containerd config default > /etc/containerd/config.toml # Restart containerd systemctl restart containerd # Enable containerd on boot systemctl enable containerd
  • CRI Container Runetime Interface 런타임으로 사용할 containerd 를 설치한다.
  • Kubernetes 설치 (kubeadm, kubelet, kubectl)
    • 사전설정
    • # Kubernetes Repository 추가 cat <<EOF > /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF
    • 설치
    • # Install Kubernetes (kubeadm, kubelet and kubectl) - 특정 버전을 지정할 수 있다. dnf install -y kubeadm kubelet kubectl
    • 서비스 활성화
    • # Enable kubelet service on boot systemctl enable kubelet # Configure kubelet echo 'KUBELET_EXTRA_ARGS="--fail-swap-on=false"' > /etc/sysconfig/kubelet # Start kubelet service systemctl start kubelet
  • CentOS 8에 기본적으로 쿠버네티스 리포지토리가 설치되어 있지 않기 때문에 수동으로 추가해야 한다. kubeadm 은 단일 쿠버네티스 컨트롤 플레인을 생성 및 활성화하고, 업그레이드/다운그레이드 및 부트스트랩 토큰 관리와 같은 다른 클러스터 수명주기 기능도 제공한다.

마스터 노드 설정

쿠버네티스는 통신 및 액세스를 위해 다양한 포트를 사용하기 때문에 방화벽 Firewall 에 제한되지 않고 쿠버네티스에 액세스할 수 있는 상태여야 한다. 아래의 방화벽 규칙을 참고하면 된다.

Protocol Direction Port Range Purpose Used By
TCP inbound 6443 k8s API Server all
TCP inbound 2379 - 2380 ETCD server client API kube-apiserver, etcd
TCP inbound 10250 kubelet API self, control plane
TCP inbound 10251 kube-scheduler self
TCP inbound 10252 kube-controller-manager self
  • kubeadm Images Pull
  • kubeadm config images pull
  • Create Control Plane with kubeadm--apiserver-cert-extra-sans 는 외부에서 접근할 수 있는 IP를 지정해서 내부와 외부에서 모두 API Server로 접근할 수 있도록 지정하고 인증서에 관련된 IP 정보를 포함시킨키는 것이다.
    kubeadm join xxx.xxx.xxx.xxx:6443 --token ur9jpx... \        
            --discovery-token-ca-cert-hash sha256:48e4d3cca... 
  • 정상적으로 실행되면 아래와 같이 워커 노드들을 클러스터에 참여시킬 수 있는 구문이 출력된다. 이 명령을 복사해 놓고 이후 워커 노드 작업에서 사용하면 된다.
  • kubeadm init --pod-network-cidr=10.15.0.0/16 --apiserver-cert-extra-sans=<master node ip>
  • kube-api 통신을 위한 환경 설정
    mkdir -p $HOME/.kube
    sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    sudo chown $(id -u):$(id -g) $HOME/.kube/config
  • 쿠버네티스 마스터 명령은 모두 일반 계정으로 처리된다. 따라서 일반 계정이 kube-api 와 통신을 위해서는 아래와 같이 처리해 준다.
  • Pod Network 구성Calico는 쿠버네티스가 운영되는 환경에 따라 설치 과정에 차이가 있고, 같은 환경이라도 노드의 수에 따라서 설치하는 것도 다를 수 있다. 따라서 매뉴얼을 확인하고 작업할 것을 권장한다.
    kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
    설치된 Calico 는 워커 노드가 클러스터에 참여하면 설치되어 동작하게 된다.
  • 여기서는 On-Premise 환경이고 노드가 50개 미만이므로 아주 간단하게 적용하도록 한다.
  • 쿠버네티스 클러스터를 구성할 때 --pod-network-cidr 옵션으로 지정한 CNI Container Network Interface 로 어떤 것을 사용할지에 따라 달라진다. 여기서는 Calico를 사용하도록 한다. 다른 CNI 들을 Installing a pod network add-on 을 참고하도록 한다.

워커 노드 설정

마스터 노드에 Control Plane이 설치되었으므로 이제 구성된 쿠버네티스 클러스터에 참여할 워커 노드들을 구성하면 된다.

  • Kubernetes Cluster 참여
    kubeadm token create --print-join-command
    위의 쿠버네티스 클러스터를 구성할 때 출력된 명령을 사용하거나 토큰이 만료된 상태라면 바로 위의 신규 토큰 생성 방법을 통해서 아래와 같이 클러스터에 참여하면 된다.
  • kubeadm join 10.0.1.186:6443 --token tofo13.... --discovery-token-ca-cert-hash sha256:e39c05bb474f8e6726ef...
  • 기본적으로 마스터 노드에 쿠버네티스 클러스터를 구성하는 작업을 통해서 발행된 토큰은 24시간 존재하도록 되어 있기 때문에 나중에 워커 노드를 추가할 경우는 토큰이 없는 상태가 발생하므로 새롭게 토큰을 생성해서 참여하면 된다.

Dashboard 설치

기본으로 설치하면 Dashboard에 접근하기 위해서는 kubectl proxy 명령을 사용하고 http://localhost:8001/... 로 접근해야 한다. 그러나 실제로는 외부에서도 대시보드를 접근해서 확인하는 경우가 많기 때문에 NodePort 방식을 활용하도록 한다.

# wget이 없는 경우는 설치
dnf install -y wget

# Dashboard Manifest 파일 다운로드 (현재 버전 v2.2.0)
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.2.0/aio/deploy/recommended.yaml

vi recommended.yaml
...  
  ports:  
  - nodePort: 32444     # 이 부분 추가 (생략하면 Kubernetes에서 임의로 지정하므로 중복되지 않는 값으로 설정)    
    port: 443    
    targetPort: 8443  
  selector:    
    k8s-app: kubernetes-dashboard  
  type: NodePort    # 이 부분 추가
...

# 직접 설치 
kubectl apply -f recommended.yaml

# 설치 검증
kubectl get services --all-namespaces # 또는 kubectl get services -n kubernetes-dashboard

최근 버전에서는 기존의 kube-system 네임스페이스에서 kubernetes-dashboard 네임스페이스로 이전되었으며, dashboard와 scraper 파드가 설치된다.

실제 Dashboard를 사용하기 위해서는 사용자 정보와 클러스터 역할 및 바인딩 정보를 구성해야 한다. (파일로 구성해도 되고 직접 kubectl 명령으로 생성해도 된다)

# 서비스 계정 생성
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:  
  name: admin-user  
  namespace: kubernetes-dashboard
EOF

# 클러스터 역할 바인딩 생성
cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:  
  name: admin-user
roleRef:  
  apiGroup: rbac.authorization.k8s.io  
  kind: ClusterRole  
  name: cluster-admin
subjects:
- kind: ServiceAccount  
  name: admin-user  
  namespace: kubernetes-dashboard
EOF

실제 Dashboard에 접속하기 위해서는 Bearer Token을 확인해야 한다.

kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"

결과로 추출된 Bearer Token을 https://<cluster mastaer or worker node ip>:32444 로 접근해서 Token 입력에 넣고 연결하면 대시보드를 확인할 수 있다.

Helm 3 설치

Helm은 쿠버네티스에서 동작하는 많은 애플리케이션들을 손쉽게 설치하도록 지원하는 프로그램으로 Ubuntu의 apt 나 CentOS 의 dnf 와 같은 패키지 관리자와 유사하다고 이해하면 된다.

기존 Helm 2 에서는 Tiler라는 Helm 서버가 필요했지만 Helm 3 에서는 좀 더 단순한 구조로 변경이 되었기 때문에 쉽게 설치 및 사용할 수 있다.

설치는 kubectl이 지원되는 모든 노드에서 사용 가능하다.

# 설치 스크립트를 다운로드해서 설치
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > get_helm.sh
chmod 700 get_helm.sh
./get_helm.sh

# 설치 확인 (현재 버전 v3.5.4)
helm version

# 설치는 /usr/local/bin 경로에 처리되므로 PATH 환경변수에 해당 경로가 설정되어 있어야 한다.
export PATH=/usr/local/bin:$PATH

기본 저장소를 가지고 있지 않기 때문에 설치를 진행할 수 없으므로 기본 저장소를 추가해 준다.

# Repo 검증
helm search repo

# 기본 Repo 추가 (기존의 https://kubernetes-charts.storage.googleapis.com/ 는 더이상 지원되지 않는다)
helm repo add stable https://charts.helm.sh/stable

# Repo 챠트 리스트 확인
helm search repo stable

# Repo 정보 갱신
helm repo update

설치 및 저장소 설정이 되었으므로 필요한 애플리케이션들을 저장소를 통해서 쿠버네티스 클러스터에 설치가 가능하다.

Metrics Server 설치

쿠버네티스 클러스터는 기본적으로 모니터링 정보를 알 수 있는 기능이 제공되지 않기 때문에 추가로 설치해야 한다. 기존에는 Heapster 기반으로 구성되었지만 더 이상 개발되지 않고 Metrics Server 로 대체되었다.

따라서 모니터링 기능 (실 시간 정보, 수집된 정보를 메모리에서만 관리하는)을 추가 설치해야 쿠버네티스 컴포넌트들에 대한 자원 모니터링도 가능하고 Autoscaling 에도 사용 가능해진다.

# 최신 버전 다운로드 (현재 v0.4.2)
wget https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

메트릭스 서버가 API Server와 통신할 때 TLS 문제가 존재한다. API Server는 자체 TLS를 사용하지만 메트릭스 서버는 Public TLS를 사용하기 때문에 그냥 설치하면 문제가 발생하게 된다.

따라서 아래와 같이 다운로드한 파일에서 TLS와 hostNetwork 사용 관련된 부분을 수정해 줘야 한다. Tab 키가 아닌 Space 키로 여백을 처리해야 한다.

vi components.yaml
...
      - args:
        - --cert-dir=/tmp        
        - --secure-port=4443        
        - --kubelet-insecure-tls=true     # 이 부분 추가 (TLS 관련)        
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
...      
      hostNetwork: true              # 이 부분 추가 (Host Network 사용 관련)      
      nodeSelector:
        kubernetes.io/os: linux
...

변경한 components.yaml 파일을 쿠버네티스 클러스터에 배포한다.

# Deploy
kubectl apply -f components.yaml 

# Pods 확인
kubectl get pods -n kube-system

# Deploy 확인
kubectl get deploy -n kube-system

# Node 리소스 사용량 조회
kubectl top node

# Pod 리소스 샤용량 조회
kubectl top pod --all-namespaces

참고

Metrics Server 가 배포되어 정상적으로 동작하고 있다고 해도 즉시 데이터를 가져오는 것은 아니다. 따라서 설치 직후에는 다음과 같이 오류 메시지가 나올 수 있다.

Error from server (ServiceUnavailable): the server is currently unable to handle the request (get nodes.metrics.k8s.io)
Error from server (ServiceUnavailable): the server is currently unable to handle the request (get pods.metrics.k8s.io)

데이터가 수집되지 않아서 처리할 수 없다는 것을 의미한다. 대략 1 ~ 3분 정보 지나서 데이터가 수집되기 시작하면 정상적으로 출력이 된다.

혹시 위의 TLS 및 hostNetwork 관련 수정과 다른 문제가 존재한다면 설정 부분을 다시 확인해야 한다. 이미 배포된 후에 Deployment 옵션을 변경할 경우는 아래의 명령을 사용한다.

kubectl edit deployments.apps -n kube-system metrics-server

참고 자료

728x90
반응형
댓글
댓글쓰기 폼