Linux single node 에서 kubeadm 으로 kubernetes 설치하기

    728x90

    안녕하세요, devyu입니다.
    현재 데보션 쿠버네티스 스터디를 진행하고 있습니다. 이번 주에는 리눅스를 통해 kubeadm으로 kubernetes를 직접 설치해보았는데요, 그 과정을 자세히 적어보겠습니다.

    1. sudo 사용자 추가, 보안 s/w 내리기, swap off

    {본인이름} 부분은 원하는 닉네임으로 진행해주세요.

    $ sudo adduser {본인이름}
    
    $ cat <<EOF | sudo tee /etc/sudoers.d/sudoers-{본인이름}
    {본인이름}     ALL=(ALL:ALL)   NOPASSWD:ALL
    EOF
    
    $ sudo systemctl stop ufw
    $ sudo systemctl disable ufw
    $ sudo systemctl stop apparmor.service
    $ sudo systemctl disable apparmor.service
    $ sudo swapoff -a

    2. module load

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

    이 코드는 Kubernetes에 필요한 커널 모듈을 로드합니다. overlay와 br_netfilter 모듈을 /etc/modules-load.d/k8s.conf 파일에 추가하고, modprobe 명령어를 사용하여 즉시 로드합니다. 이 모듈들은 컨테이너 네트워킹과 관련된 기능을 제공합니다.

    3. network forwarding 설정

    $ cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes.conf
    net.bridge.bridge-nf-call-iptables  = 1
    net.bridge.bridge-nf-call-ip6tables = 1
    net.ipv4.ip_forward                 = 1
    EOF
    
    
    $ sudo sysctl --system
    $ sudo iptables -P FORWARD ACCEPT

    이 설정은 Kubernetes 네트워킹을 위한 시스템 설정을 변경합니다. 브리지 네트워크를 통과하는 패킷이 iptables 규칙을 따르도록 하고, IPv4 포워딩을 활성화합니다. sysctl --system 명령어로 변경사항을 적용하고, iptables의 FORWARD 체인 기본 정책을 ACCEPT로 설정합니다.

    4. containerd 설치

    $ sudo apt-get update
    $ sudo apt-get install -y apt-transport-https ca-certificates curl gpg
    $ sudo install -m 0755 -d /etc/apt/keyrings
    $ sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    $ sudo chmod a+r /etc/apt/keyrings/docker.asc
    
    $ echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
      $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
      sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    
    $ sudo apt-get update
    $ sudo apt-get install -y containerd.io
    
    $ sudo mkdir -p /etc/containerd
    $ sudo containerd config default | sudo tee /etc/containerd/config.toml
    
    $ sudo sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
    
    $ sudo systemctl restart containerd
    $ sudo systemctl enable containerd
    $ sudo systemctl status containerd

    containerd를 설치하고 구성합니다. Docker의 GPG 키를 추가하고 저장소를 설정한 후, containerd를 설치합니다. 그 다음 containerd의 기본 구성 파일을 생성하고, SystemdCgroup을 true로 설정합니다. 마지막으로 containerd 서비스를 재시작하고 활성화한 후 상태를 확인합니다.

    위 과정 성공시 아래와 같이 표기됩니다. active가 아닌 경우, 커멘드를 잘못 입력하기 않았나 확인해보세요.

    5. crictl 설치

    #----------------------------------------------------------
    # 서버가 arm64 or amd64 인지 확인하여 설치
    #----------------------------------------------------------
    $ VERSION="v1.30.0"
    $ curl -L https://github.com/kubernetes-sigs/cri-tools/releases/download/$VERSION/crictl-${VERSION}-linux-arm64.tar.gz --output crictl-${VERSION}-linux-arm64.tar.gz
    
    $ sudo tar zxvf crictl-$VERSION-linux-arm64.tar.gz -C /usr/local/bin
    $ rm -f crictl-$VERSION-linux-arm64.tar.gz
    
    #----------------------------------------------------------
    # crictl 이 어느 container 를 접속할 것인지 세팅
    #----------------------------------------------------------
    $ cat <<EOF | sudo tee /etc/crictl.yaml
    runtime-endpoint: unix:///run/containerd/containerd.sock
    image-endpoint: unix:///run/containerd/containerd.sock
    timeout: 2
    debug: false
    pull-image-on-create: false
    EOF
    
    $ sudo bash -c "crictl completion > /etc/bash_completion.d/crictl"
    $ source ~/.bashrc
    
    
    #----------------------------------------------------------
    # containerd 설정 확인
    #----------------------------------------------------------
    $ sudo crictl info

    이 코드는 crictl(Container Runtime Interface Command Line Interface)을 설치하고 구성합니다. 먼저 지정된 버전의 crictl을 다운로드하고 압축을 해제합니다. 그 다음 crictl이 containerd와 통신할 수 있도록 구성 파일을 생성합니다. bash completion을 설정하여 명령어 자동 완성 기능을 활성화하고, 마지막으로 containerd 설정을 확인합니다.

    위 과정 완료 후 sudo crictl info 시 일부 오류가 표기되는데, 이는 추후 과정에서 해결되니 아래 스크린샷 과 같은 오류인 경우 무시해주세요.

    위 부분들은 아래 과정까지 모두 끝낸다면 정상적으로 작동하게 됩니다.

    6. kubectl 설치

    #----------------------------------------------------------
    # 서버가 arm64 or amd64 인지 확인하여 설치
    #----------------------------------------------------------
    $ curl -LO "https://dl.k8s.io/release/v1.30.0/bin/linux/arm64/kubectl"
    $ chmod +x ./kubectl
    $ sudo mv ./kubectl /usr/local/bin/kubectl

    이 코드는 kubectl을 다운로드하고 설치합니다. 서버 아키텍처(arm64 또는 amd64)에 맞는 버전을 다운로드하고, 실행 권한을 부여한 후 시스템 경로로 이동시킵니다.
    amd64 인 경우, curl -LO "https://dl.k8s.io/release/v1.30.0/bin/linux/amd64/kubectl" 명령어로 진행해주세요.

    7. Kubernetes 설치

    아래 코드 중 에는 본인의 IP를 넣어주세요.
    프라이빗은 hostname -I | awk '{print $1}' 를 통해 확인할 수 있으며, 퍼블릭은 curl ifconfig.me 로 확인할 수 있습니다. ip a 로도 전체 IP를 확인할 수 있습니다.

    $ mkdir -p ~/kubeadm && cd ~/kubeadm
    
    #-----------------------------------------------
    # kubernetes 다운로드 key 와 url 등록
    #-----------------------------------------------
    $ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
    
    $ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
    $ sudo apt-get update
    
    
    #========================================================================
    # kubelet 설치 (아직 kubelet 이 뜨지는 않음)
    #========================================================================
    $ sudo apt-get install -y kubelet="1.30.3-*" kubeadm="1.30.3-*"
    $ sudo systemctl enable --now kubelet
    $ sudo systemctl start kubelet
    
    #========================================================================
    # 1. kubeadm 설치
    #========================================================================
    $ sudo kubeadm config images pull
    
    #------------------------------------------------------------
    # 자기 노드의 ip: --apiserver-advertise-address
    # multi control-plane 일 경우 L4 ip: --control-plane-endpoint
    # cgroup driver 세팅 (https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/configure-cgroup-driver/)
    #------------------------------------------------------------
    $ vi kubeadm-config.yaml
    
    apiVersion: kubeadm.k8s.io/v1beta3
    kind: InitConfiguration
    nodeRegistration:
      criSocket: "/var/run/containerd/containerd.sock"
    
    ---
    apiVersion: kubeadm.k8s.io/v1beta3
    kind: ClusterConfiguration
    apiServer:
      certSANs:
      - 127.0.0.1
      - localhost
      - <Node private IP>
      - <Node public IP>
    networking:
      serviceSubnet: 10.233.0.0/18
      podSubnet: 10.233.64.0/18
      dnsDomain: "cluster.local"
    
    
    #----------------------------------------------------------------
    # kubeadm init 을 하고 나면 /var/lib/kubelet/config.yaml 이 생성되어
    # kubelet 이 정상적으로 실행됨
    #----------------------------------------------------------------
    $ sudo kubeadm init --config kubeadm-config.yaml --v=5
    
    
    #------------------------------------------------------------
    # kubeconfig
    #------------------------------------------------------------
    $ mkdir -p ~/.kube
    $ sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
    $ sudo chown $(id -u):$(id -g) $HOME/.kube/config


    이제 Kubernetes를 설치하고 초기화합니다. Kubernetes 저장소를 추가하고, kubelet과 kubeadm을 설치합니다. 그 다음 kubeadm을 사용하여 Kubernetes 클러스터를 초기화하고, 홈 디렉토리에 kubeconfig 파일을 설정합니다.

    8. Calico 설치

    $ mkdir -p ~/calico && cd ~/calico
    
    $ curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/tigera-operator.yaml
    
    $ kubectl create -f tigera-operator.yaml
    
    $ curl -LO https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/custom-resources.yaml
    
    #------------------------------------------------------------
    # yaml 을 열어서 pod 네트워크를 확인하고 변경
    #------------------------------------------------------------
    $ vi custom-resources.yaml
    ...
        cidr: 10.233.64.0/18
    ...
    
    $ kubectl create -f custom-resources.yaml
    
    #------------------------------------------------------------
    # calico 설치 확인
    #------------------------------------------------------------
    $ kubectl get pods -n calico-system

    Calico 네트워크 플러그인을 설치합니다. Tigera Operator를 설치하고, Calico 커스텀 리소스를 생성합니다. Pod 네트워크 CIDR을 설정하고, Calico 설치를 확인합니다.

    9. kubectl bash completion

    $ source <(kubectl completion bash)
    $ kubectl completion bash > ~/.kube/completion.bash.inc
    
    $ printf "
    # kubectl shell completion
    source '$HOME/.kube/completion.bash.inc'
    " >> $HOME/.bash_aliases
    
    $ source $HOME/.bash_aliases

    kubectl 명령어의 bash 자동 완성 기능을 설정합니다. 자동 완성 스크립트를 생성하고, 이를 bash 설정 파일에 추가하여 매번 터미널을 열 때마다 자동으로 로드되도록 합니다.

    10. taint 제거

    $ kubectl taint nodes --all node-role.kubernetes.io/control-plane-

    컨트롤 플레인 노드의 taint를 제거합니다. 이를 통해 워크로드 Pod들이 컨트롤 플레인 노드에도 스케줄링될 수 있게 됩니다.

    11. 설치 테스트

    $ mkdir -p ~/sample-yaml && cd ~/sample-yaml
    
    $ cat <<EOF | tee ./nginx-service.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: nginx-deployment
      name: nginx-deployment
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.21.0
            ports:
            - containerPort: 80
    
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service-nodeport
    spec:
      selector:
        app: nginx
      ports:
      - protocol: TCP
        port: 8080
        targetPort: 80
        nodePort: 30180
      type: NodePort
      externalTrafficPolicy: Local
    EOF
    
    
    $ kubectl apply -f nginx-service.yaml
    
    $ kubectl get pods
    
    $ curl <Node ip>:30180

    마지막으로, Kubernetes 설치를 테스트합니다. Nginx 웹 서버를 배포하고 NodePort 서비스로 노출시킵니다. 그리고 Pod의 상태를 확인하고, 노드의 IP와 지정된 포트로 curl 요청을 보내 웹 서버에 접근할 수 있는지 테스트합니다.

    curl <Node ip>:30180에는 Node private IP를 입력하면 됩니다.

    댓글