kubeadm을 사용한 쿠버네티스 설치 분석

Related POST

컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커
읽는 중인데 kubeadm의 설치가 필요없이 Vagrant로 제공하고 있습니다.

어떤식으로 구성하는지 직접 설치한 블로그들을 참조하며 주석을 달며 분석한 내용입니다

k8s 설치

Vagrantfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
N = 3 # 워커 노드 수 , config.sh 실행시 아규먼트로 넘겨준다
Ver = '1.18.4' # Kubernetes 설치 버전

#=============#
# Master Node #
#=============#

config.vm.define "m-k8s" do |cfg|
cfg.vm.box = "sysnet4admin/CentOS-k8s"
cfg.vm.provider "virtualbox" do |vb|
vb.name = "m-k8s(github_SysNet4Admin)"
vb.cpus = 2
vb.memory = 3072
vb.customize ["modifyvm", :id, "--groups", "/k8s-SgMST-1.13.1(github_SysNet4Admin)"]
end
cfg.vm.host_name = "m-k8s"
cfg.vm.network "private_network", ip: "192.168.1.10"
cfg.vm.network "forwarded_port", guest: 22, host: 60010, auto_correct: true, id: "ssh"
cfg.vm.synced_folder "../data", "/vagrant", disabled: true
cfg.vm.provision "shell", path: "config.sh", args: N
cfg.vm.provision "shell", path: "install_pkg.sh", args: [ Ver, "Main" ] #버전, Main판단 파라미터
cfg.vm.provision "shell", path: "master_node.sh"
end

#==============#
# Worker Nodes #
#==============#

(1..N).each do |i|
config.vm.define "w#{i}-k8s" do |cfg|
cfg.vm.box = "sysnet4admin/CentOS-k8s"
cfg.vm.provider "virtualbox" do |vb|
vb.name = "w#{i}-k8s(github_SysNet4Admin)"
vb.cpus = 1
vb.memory = 2560
vb.customize ["modifyvm", :id, "--groups", "/k8s-SgMST-1.13.1(github_SysNet4Admin)"]
end
cfg.vm.host_name = "w#{i}-k8s"
cfg.vm.network "private_network", ip: "192.168.1.10#{i}"
cfg.vm.network "forwarded_port", guest: 22, host: "6010#{i}", auto_correct: true, id: "ssh"
cfg.vm.synced_folder "../data", "/vagrant", disabled: true
cfg.vm.provision "shell", path: "config.sh", args: N
cfg.vm.provision "shell", path: "install_pkg.sh", args: Ver
cfg.vm.provision "shell", path: "work_nodes.sh"
end
end

end

config.sh

  • kubeadm으로 쿠버네티스를 설치하기 위한 사전 조건을 설정하는 스크립트
    config.sh
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    #!/usr/bin/env bash

    # vim configuration : 코드 하이라이팅
    echo 'alias vi=vim' >> /etc/profile

    # swapoff -a to disable swapping
    # → 현재 쿠버네티스는 스왑 메모리 비활성 필요
    swapoff -a
    # sed to comment the swap partition in /etc/fstab
    # → /etc/fstab에 swap이 적혀있는 라인을 #을 붙여서 주석처리
    sed -i.bak -r 's/(.+ swap .+)/#\1/' /etc/fstab

    # kubernetes 리포지터리 설정
    gg_pkg="packages.cloud.google.com/yum/doc" # path줄이기 위한 변수 처리
    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=0
    repo_gpgcheck=0
    gpgkey=https://${gg_pkg}/yum-key.gpg https://${gg_pkg}/rpm-package-key.gpg
    EOF

    # Set SELinux in permissive mode (effectively disabling it)
    ##########
    # SELinux : (Security-Enhanced Linux)
    # 관리자가 시스템 액세스 권한을 효과적으로 제어할 수 있게 하는
    # 리눅스 시스템용 보안 아키텍쳐다.
    # enforce, permissive, disable 세 가지 동작 모드가 있으며 설치하면
    # 기본적으로 enforce 모드로 동작한다.
    #############
    # 변경 이유 : 컨테이너가 호스트 파일 시스템에 접근 용이하게 하기 위해서
    # ex) pod간 네트워크에 사용되는 파일 시스템등
    setenforce 0 #현재 동작모드 변경
    sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config #동작모드 영구변경

    # RHEL/CentOS 7 have reported traffic issues being routed incorrectly due to iptables bypassed
    ############
    # 브릿지 네트워크를 통과하는 IPv4, IPv6 패킷을 iptables가 관리하게 설정
    # pod 간의 통신을 iptables로 제어
    #################
    # iptables : 리눅스 방화벽 설정 도구
    # 커널상에서 netfilter 패킷 필터링 기능을 사용자 공간에서 제어하는 수준으로 사용 가능
    # CentOS같은 배포판의 기본값은 `net.bridge.bridge-nf-call`의 디폴트가 0
    # 이는 브릿지 네트워크를 통해 송수신되는 패킷이 iptables 설정을 우회한다는 뜻
    # 컨테이너 네트워크 패킷이 호스트 머신의 iptables의 설정에 제어되는 것이 바람직함
    # 이를 위해 1로 설정 필요
    # ** iptables 설정을 따라가기 위해서는 밑의 br_netfilter를 enable 해야함 **
    cat <<EOF > /etc/sysctl.d/k8s.conf
    net.bridge.bridge-nf-call-ip6tables = 1
    net.bridge.bridge-nf-call-iptables = 1
    EOF

    # br_netfilter 커널 모듈을 사용해 bridge로 네트워크 구성
    # IP Masquerade를 사용해 내부/ 외부 네트워크 분리
    ##################
    # Ip 마스커레이드(Masquerade)
    # 아주 쉽게 설명하면 커널에서 제공하는 NAT(Network Address Translation)기능이라고 보면 됨
    modprobe br_netfilter

    # local small dns & vagrant cannot parse and delivery shell code.
    # 쿠버네티스간 노드간 통신을 이름으로 할 수 있도록 각 노드의 호스트이름과 IP를 /etc/hosts에 설정

    echo "192.168.1.10 m-k8s" >> /etc/hosts
    for (( i=1; i<=$1; i++ )); do echo "192.168.1.10$i w$i-k8s" >> /etc/hosts; done

    # config DNS
    # 외부와 통신할 수 있도록 DNS 서버 지정
    cat <<EOF > /etc/resolv.conf
    nameserver 1.1.1.1 #cloudflare DNS
    nameserver 8.8.8.8 #Google DNS
    EOF

install_pkg.sh

  • 클러스터를 구성하기 위해서 머신에 설치되어야 하는 의존성 패키지 명시
install_pkg.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/env bash

# install packages
yum install epel-release -y
yum install vim-enhanced -y
yum install git -y # git 설치

# 쿠버네티스 관리하는 컨테이너를 설치하기 위해 도커 설치 및 구동
yum install docker -y && systemctl enable --now docker

# install kubernetes cluster
# $1은 넘겨받은 쿠버네티스 버전
# Kubeadm은 kybelet, kubectl을 설치 하지 않으므로 직접 설치해야함
# kubectl : 클러스터에게 명령을 내리기 위한 CLI 유틸
# kubelet : 각 노드마다 구동되는 에이전트로 k8s 마스터와 통신
yum install kubectl-$1 kubelet-$1 kubeadm-$1 -y # 쿠버 패키지 kubectl, kubelet, kubeadm 설치



systemctl enable --now kubelet # kubelet 시작

# Main을 넘겨받은 마스터 노드의 경우에만 해당 예제를 git clone함
if [ $2 = 'Main' ]; then
git clone {예제}
mv /home/vagrant/_Book_k8sInfra $HOME
find $HOME/{예제}/ -regex ".*\.\(sh\)" -exec chmod 700 {} \; # 예제내의 sh에 실행권한
fi

master_node.sh

  • 1개의 가상머신(m-k8s)를 쿠버네티스 마스터 노드로 구성하는 스크립트
  • 쿠버네티스 클러스터 구성시 꼭 선택해야하는 CNI도 함께 구성
  • k8s는 자체적으로 네트워크 구성이 없으므로 CNI 스펙을 구현한 CNI 플러그인을 함께 설치해야함
  • CNI : Container Network Interface
    • CNCF 프로젝트
    • 컨테이너의 네트워크 안정성과 확장성을 보장하기 위해 개발됨
    • 플러그인들은 각자 구성 방식, 지원 기능, 성능이 다 다름 : 목적에 맞게 사용
      ex)Calico는 L3으로, Flannel은 L2로 컨테이너 네트워크를 구성
    • Calico : https://kubernetes.io/ko/docs/concepts/cluster-administration/networking/#캘리코
      • 네트워킹 및 네트워크 폴리시 제공자
      • 순수 리눅스 eBPF 데이터플레인, 표준 리눅스 네트워킹 데이터플레인, 윈도우 HNS 데이터플레인을 포함한 여러 데이터플레인을 지원
      • 캘리코는 완전한 네트워킹 스택을 제공하지만, 클라우드 제공자 CNI와 함께 사용하여 네트워크 정책 시행을 제공 가능등 유연하게 상황에 맞는 옵션 선택 가능
      • Calico는 동일한 엔진을 사용하여 서비스 메시 계층(service mesh layer)에서 호스트, 파드 및 (이스티오(istio)와 Envoy를 사용하는 경우) 애플리케이션에 대한 네트워크 폴리시를 적용한다.
      • 공식 설치 문서
master_node.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#!/usr/bin/env bash

# init kubernetes
#
# kubeadm으로 k8s의 worker node를 받아들일 준비
# 토큰 ttl을 0으로 설정해서 기본값인 24시간동안 유지
# worker node가 정해진 토큰으로 들어오게 함
#
# k8s가 자동으로 pod에 부여하는 네트워크를
# 172.16.0.0./16(172.16.0.1 ~ 172.16.255.254)로 제공
# - CNI와 충돌이 나지 않도록 다른 대역으로 설정되는 것으로 보임
# - CNI로 Calico 대신 flannel을 사용할 경우 "10.244.0.0/16" 대역을 주어야 한다.
#
# woker노드가 접속하는 API 서버 IP는 192.168.1.10(master private ip)

kubeadm init --token 123456.1234567890123456 --token-ttl 0 \
--pod-network-cidr=172.16.0.0/16 --apiserver-advertise-address=192.168.1.10

# config for master node only
# 현재 사용자가 쿠버네티스를 정상적으로 구동할 수 있도록
mkdir -p $HOME/.kube # 설정 폴더를 만들고
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config # 설정파일을 홈디렉터리에 복사하고
chown $(id -u):$(id -g) $HOME/.kube/config # 쿠버를 ㅣㅇ용할 사용자에게 권한을 준다

# 만약 root를 사용할 경우라면 위 내용 대신
# export KUBECONFIG=/etc/kubernetes/admin.conf 명령어로 환경변수를 등록하면 된다고 한다
# (export는 로그아웃후 초기화됨, profile 수정하면 되는데 귀찮다고 ;)


# config for kubernetes's network
# CNI Calico의 설정을 적용해 k8s 네트워크 구성
kubectl apply -f \
https://raw.githubusercontent.com/sysnet4admin/IaC/master/manifests/172.16_net_calico.yaml

worker_nodes.sh

  • worker node 구성 스크립트
  • master node에 구성된 클러스터에 조인 명령이 들어 있음
    worker_nodes.sh
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #!/usr/bin/env bash

    # config for work_nodes only
    # kubeadm을 이용해 master node에 접속
    # master에서 init시 지정한 token 정보가 들어있음
    # discovery-token-unsafe-skip-ca-verification 옵션으로 인증 무시

    kubeadm join --token 123456.1234567890123456 \
    --discovery-token-unsafe-skip-ca-verification 192.168.1.10:6443

ref

공유하기