ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • kubeadm 으로 local kubernetes 환경 구축
    kubernetes 2021. 9. 8. 14:44
    반응형

    kubernetes 를 제공해 주는 서비스가 많지만 때로는 직접 구축해야 할 필요가 있다. 그런데 막상 설치해보려니 신경 쓸 것도 많고, 선택을 해야 하는 것이 많아서 쉽지가 않았다. 과정을 기록해 보려고 한다.

    • 선택1 - 컨테이너 런타임: docker

    kubernetes 는 요구하는 스펙이 맞으면 굳이 특정 컨테이너 런타임을 사용할 필요는 없다. 다만 docker 가 가장 익숙하기 때문에 이를 사용하도록 하였다.

    참고: 컨테이너 런타임

    • 선택2 - 설치 도구: kubeadm

    kubernetes 환경 설치를 위해 사용할 수 있는 도구들이 있다: kubeadm, kOps, kubespray 등. 이 중 공식 사이트에 가장 설명이 잘 되어 있는 것은 kubeadm 인 것 같아서 이를 선택했다.

    • 선택3 - 네트워크 애드온: calico

    kubernetes 의 네트워크를 사용하기 위해서는 kubernetes 네트워크 모델을 구현한 애드온을 실행할 필요가 있다. 많으 종류가 있는데, 그 중 calico 가 간단하고, 많이 사용하고 있어서 선택하였다.

    참고: 네트워크 애드온 kubernetes network model

    • 환경

     

    서버1: 컨트롤 플레인 (10.10.1.101)

    - CentOS 7.9

    - Docker 20.10.8

    - kubernetes: 1.22.1

    서버2: 워커 (10.10.1.102)

    - CentOS 7.9

    - Docker20.10.8

    - kubernetes: 1.22.1

    kubernetes 네트워크:

    - 서버 네트워크 대역: 10.10.1.0/24

    - kubernetes 네트워크 서비스 대역: 172.22.0.0/16

    - kubernetes 네트워크 파드 대역(calico): 192.168.0.0/16

     

    이하 내용에서 별도로 명시하지 않은 과정은 컨트롤플레인 서버와 워커 서버에 모두 적용해야 하는 과정이다.

    1. Docker 준비

    사실 kubernetes 에서는 컨테이너 런타임이 필요한거지 반드시 Docker 를 사용해야 할 필요는 없다. 그러나 Docker 가 가장 익숙하기 때문에 그대로 사용하도록 했다.

    1-1. enabled 설정

    docker 서비스가 enabled 상태가 아니면 kubeadm 실행시 warning 이 뜬다. 어차피 docker 는 늘 사용할 것이기 때문에, enabled 로 등록하여 부팅시 docker 가 실행되도록 하자.

    $ sudo systemctl enable docker.service

    확인

    $ systemctl list-unit-files | grep "docker.service"

    1-2. Docker cgroup 드라이버 설정

    kubernetes 에서는 도커의 cgroup 관리에 systemd 를 사용하는 것을 권장하고 있다. systemd 가 아니면 kubeadm 구동시 warning 이 뜬다. 무시해도 동작은 하는 것 같지만 맞춰주자.

    도커를 중지시키고 디렉토리를 만든다. (디렉토리가 이미 존재할 수 있는데 이 경우 생략)

    $ sudo mkdir /etc/docker

    여기에 daemon.json 을 작성하자.

    $ 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

    도커를 다시 실행하고 확인

    $ docker info | grep Cgroup

    2. iptables 설정

    br_netfilter 모듈이 활성화 되어야 한다고 한다. CentOS 7.9 기준으로 이미 활성화 되어 있는데, 명시적으로 추가해 주자.

    $ cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
    br_netfilter
    EOF

    또한, iptables 관련 sysctl 설정을 수정해야 한다. 역시 CentOS 7.9 기준으로 활성화 되어 있긴 한데, 영구적용을 위해 sysctl.d 에 설정을 추가하자.

    $ 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

    3. swap 끄기

    kubelet 사용을 위해서는 swap 을 비활성화 하는 것을 권장한다고 한다. 켜 있어도 kubernetes 실행은 가능하지만, 실제 swap 하는 시점에 예상과 다른 동작이 발생할 수 있다고 한다.

    $ sudo swapoff -a

    결과 확인

    $ free -h

    재부팅시에도 반영하려면 /etc/fstab 도 수정하자.

    4. SELinux 비활성화

    현재 kublet 스펙에서는 꺼야 한다고 한다.

    먼저 비활성화

    $ sudo setenforce 0

    확인

    $ sestatus | grep "Current mode"

    Current mode 가 enforcing 에서 permissive 로 변경되었다.

    이후 재부팅 등의 상황에도 적용되도록 /etc/selinux/config 를 고친다.

    $ sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

    SELINUX=enforcing 로 되어 있던 라인이 SELINUX=permissive 로 변경되었다.

    5. firewalld 설정 (포트 열기)

    kubernetes 에서 필요한 포트가 있고 calico 에서 필요한 포트가 있다.

    참고

     

    (주의) 컨트롤 플레인 노드와 워커 노드에서 필요로 하는 포트가 다르다. 이하 각각 설명한다.

    6-1. 컨트롤 플레인 (싱글 컨트롤 패널)

    컨트롤플레인 서버에서 열지 않으면 문제가 생기는 포트가 있다. firewall-cmd 를 통해 열어준다.

    $ sudo firewall-cmd --permanent --add-port=179/tcp
    $ sudo firewall-cmd --permanent --add-port=6443/tcp
    $ sudo firewall-cmd --permanent --add-port=10250/tcp
    • 179 포트가 안열리면 calico-node 관련 pod 가 ready 상태가 되지 않는다. ready 상태가 아니면, calico 가상 network (예를 들어 192.168.62.129) 에 접근하려고 하면 접근되지 않는다. kubernetes 내부로 가야할 것이 외부 게이트웨이로 빠져버린다.
    • 6443 은 kubelete api 를 위한 포트이다.
    • 10250 을 안열어주면 해당 노드에 돌고 있는 pod 에 대한 kubectl exec 가 동작하지 않는다. 컨트롤 플레인 에서도 필요한지는 모르겠는데, waring 에 나와서 그냥 열어줬다.

    공식 페이지에는 10251, 10252 포트도 필요하다고 하는데, 최소한 현재 구성중인 환경 기준으로는 열지 않아도 실행할 때는 문제가 없었다.

    firewalld 를 재시작 하여 반영한다. (주의: permanent 로 설정하지 않은 설정값들이 있다면 사라진다.)

    $ sudo systemctl restart firewalld

    6-2. 워커

    워커에서 열어야 하는 포트들이 있다.

    $ sudo firewall-cmd --permanent --add-port=179/tcp
    $ sudo firewall-cmd --permanent --add-port=10250/tcp
    $ sudo firewall-cmd --permanent --add-port=30000-32767/tcp
    $ sudo firewall-cmd --permanent --add-masquerade
    • 179 포트가 안열리면 calico-node 관련 pod 가 ready 상태가 되지 않는다. ready 상태가 아니면, calico 가상 network (예를 들어 192.168.62.129) 에 접근하려고 하면 접근되지 않는다. kubernetes 내부로 가야할 것이 외부 게이트웨이로 빠져버린다.
    • 10250 을 안열어주면 해당 노드에 돌고 있는 pod 에 대한 kubectl exec 가 동작하지 않는다.
    • 30000-32767 는 NodePort 서비스 실행시 사용된다.
    • masquerade 를 안하면 calico 네트워크 대역(192.168) ip 주소로 들어오는 요청을 처리하지 못한다. (물리 네트워크 대역 10.10 이 아닌 192.168 로 들어온다.)

    firewalld 를 재시작 하여 반영한다. (주의: permanent 로 설정하지 않은 설정값들이 있다면 사라진다.)

    $ sudo systemctl restart firewalld

    7. 설치

    먼저 레포지토리를 추가한다.

    $ 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
    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
    exclude=kubelet kubeadm kubectl
    EOF

    yum 을 통해 설치한다.

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

    먼저 kubelet 을 띄워놓자. 우선 systemctl 에 등록한다.

    $ sudo systemctl enable --now kubelet

    버전에 따라서 enable 명령시 --now 옵션이 안먹을 때가 있다. 그럴 때는 그냥 아래처럼 리로드 해준다.

    $ sudo systemctl daemon-reload

    실행

    $ sudo systemctl restart kubelet

    systemctl 로 확인해 보면 서비스 실행이 실패했다고 뜨는데, 나중에 kubeadm 이 다 구성되면 자동으로 해결된다.

    8. 초기화 및 조인

    (주의) 이하 진행은 컨트롤 패널 서버와 노드가 다르다.

    먼저 컨트롤 플레인에서 kubernetes 를 초기화하고 워커를 추가하는 개념이다.

    8-1. 컨트롤 플레인 노드 (싱글 컨트롤 플레인 초기화)

    https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/

    여기 보면 옵션이 많은데 하나를 제외하고는 모두 디폴트 값을 사용한다. --service-cidr 값만 수정해 주자. 이것은 서비스에 대하여 kubernetes 에서 할당할 ip 범위이다. 기본적으로 10.96.0.0/16 을 사용하고 있다. 그런데 현재 사설망이 10. 으로 시작해서 헷갈릴 것 같아서 172.22.0.0/16 으로 수정한다. (주의: 비슷한 옵션 --pod-network-cidr 이 있는데, 이건 다른 옵션이다.)

    $ sudo kubeadm init --service-cidr=172.22.0.0/16

    실행하면 아래와 같은 로그가 나오는데, 워커 노드에서 사용해야 하니 기억해 두자

        (...)
    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 10.10.1.101:6443 --token cmhczt.dqkpcn0fnytprotj \
        --discovery-token-ca-cert-hash sha256:733ec3943111f0bb91e5f37c9afeb878e638af6767e1c9b70e0689e10fec9d10

    먼저 현재 사용자 기준으로 위 안내에 나온 걸 실행해 준다.

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

    이러면 root 가 아니더라도 kubectl 명령어를 사용할 수 있다. (원래도 단순 호출을 할 수는 있었는데, 실행을 하려면 막혔다.)

     

    이렇게 kubeadm 을 통한 컨트롤플레인 초기화가 완료되었다. 다만 컨트롤플레인에는 calico 설치도 필요하다.

     

    calico 의 경우 노드 서버 수 50개 기준으로 다른 가이드를 주고 있다.

    https://docs.projectcalico.org/getting-started/kubernetes/self-managed-onprem/onpremises

    이 경우는 50 개 미만의 가이드를 따른다.

     

    먼저 설정 파일을 받는다.

    $ curl https://docs.projectcalico.org/manifests/calico.yaml -O

    그리고 적용한다.

    $ kubectl apply -f calico.yaml

    적용 후 시간이 지나면 pending 상태였던 coredns 도 Running 을 바뀌고 calico 관련 서비스가 돌고 있는 것을 확인할 수 있다.

    8-2. 워커 노드 (조인하기)

    위에서 컨트롤플레인 초기화시 나온 로그를 참고하여 적용한다.

    $ sudo kubeadm join 10.10.1.101:6443 --token cmhczt.dqkpcn0fnytprotj \
        --discovery-token-ca-cert-hash sha256:733ec3943111f0bb91e5f37c9afeb878e638af6767e1c9b70e0689e10fec9d10

    아래와 같은 로그가 나오며 완료된다.

    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.

    9. 확인

    컨트롤 플레인 서버에서 확인해 보자.

    $ kubectl get node -o wide
    NAME      STATUS   ROLES                  AGE   VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION           CONTAINER-RUNTIME
    server1   Ready    control-plane,master   12h   v1.22.1   10.10.1.101     <none>        CentOS Linux 7 (Core)   3.10.0-1160.el7.x86_64   docker://20.10.8
    server2   Ready    <none>                 12h   v1.22.1   10.10.1.102     <none>        CentOS Linux 7 (Core)   3.10.0-1160.el7.x86_64   docker://20.10.8

     

    잘 적용되었다.

     

    참고:

    • 현 구조상, 컨트롤 플레인에는 pod 가 뜨지 않는다. pod 를 뜨게 설정할 수 있지만 생략한다.
    반응형

    댓글

Designed by Tistory.