Public 환경에서 k8s 구성하기

Nam_JU·2025년 3월 3일

k8s

목록 보기
5/14

Public 환경에서 k8s 구성하기

외부망 환경에서 k8s 설치하는 경우, 별도의 레지스토리나 이미지를 다운받아서 사용할 필요가 없다.

  • 설치 버전 정보
    Contianerd(1.7.13v)/ CNI-Plugin(1.3.0v)/ runC(1.1.12v)/ k8s(1.30v) 으로 설치
  • 운영체제 : RHEL 9.4
  • Master2 / Worker1을 사용하여 실습

1. 운영체제 준비

  • k8s는 리눅스 기반 컨테이너 환경을 지원하기 때문에 RHEL, RockyLinux, Ubuntu 등을 사용한다.
    나의 경우는 RHEL 9.4v을 사용

2. 패키지 및 시스템 설정

외부접속 확인

  • 서버가 외부접속이 가능한지 확인 vi /etc/resolv.conf /etc/resolv.conf 파일은 어떤 DNS 서버를 사용할지 적혀있는 설정파일이다. nameserver는 DNS 서버의 주소를 정해주는 설정이다. 수정후 인터넷 외부접속이 가능한지 ping으로 확인한다.
    [root@k8s-master-2 ~]# cat /etc/resolv.conf
    # Generated by NetworkManager
    search openstacklocal
    nameserver 8.8.8.8 # 추가 
    nameserver 10.0.16.3
    nameserver 10.0.16.4
    nameserver 10.0.16.2
    
    [root@k8s-master-2 ~]# ping 8.8.8.8
    PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
    64 bytes from 8.8.8.8: icmp_seq=1 ttl=117 time=39.7 ms
    64 bytes from 8.8.8.8: icmp_seq=2 ttl=117 time=35.8 ms
    64 bytes from 8.8.8.8: icmp_seq=3 ttl=117 time=35.4 ms

메모리 확인

  • 메모리 공간 확인 : free -h 시스템의 메모리(RAM)사용량을 확인한다.
    [root@k8s-master-2 ~]# free -h
                   total        used        free      shared  buff/cache   available
    Mem:           7.5Gi       2.4Gi       4.0Gi        11Mi       1.3Gi       5.1Gi
    Swap:             0B          0B          0B

스왑 메모리 비활성화

  • 스왑 메모리 비활성화: swapoff -a
  • 스왑 메모리가 0인지 확인: free -m SwapMemory: RAM이 부족할때 디스크의 일부를 가상 메모리로 사용하는 기능이다. 스왑 메모리가 있으면 실제 메모리 사용량을 정확하게 파악하지 못하기 때문에 k8s의 리소스 관리와 스케줄링에 혼란을 줄 수 있다.
    • 비활성화가 되어있지 않은경우: sudo sed -i '/swap/s/^/#/' /etc/fstab

      /etc/fstab 파일에서 스왑 관련 항목을 찾아 그앞에 # 주석처리를 하여 비활성화 하는 명령어 
      [root@k8s-master-2 ~]# swapoff -a
      [root@k8s-master-2 ~]# free -m
                     total        used        free      shared  buff/cache   available
      Mem:            7683        2500        4071          11        1363        5182
      Swap:              0           0           0

방화벽 비활성화

  • 방화벽 비활성화 설정 k8s를 구성하기 위해서는 방화벽을 비활성화 해야한다. k8s는 서로 통신하기 위해 여러 포트를 개방해야한다. 방화벽이 활성화된 상태에서는 포트들을 차단할 가능성이 높기때문에 네트워크 문제가 발생할 수 있다.
    서비스포트 번호
    api-server6443
    etcd2379-2380
    kubelet10250
    kube-scheduler10259
    kube-controller-manager10257
    • 방화벽이 설치되어있는 경우

      # 방화벽 비활성화
      # systemctl disable firewalld && systemctl stop firewalld
      
      # SELinux 일시적으로 비활성화
      # setenforce 0
      
      # SELinux 영구적으로 비활성화
      # sed -i 's@SELINUX=.*@SELINUX=disabled@g' /etc/selinux/config

      나의 경우 방화벽 자체를 설치하지 않았음

      [root@k8s-master-2 ~]# systemctl status firewalld
      Unit firewalld.service could not be found.

Cgroup 설정

  • 파일 시스템 확인: findmnt /sys/fs/cgroup
    • 파일시스템: 운영체제가 데이터를 저장하고, 읽고, 관리하는 방식이다. 데이터 저장 및 관리, 파일 디렉터리 구조 제공, 접근제어 및 권한 관리등 역할을 한다.

      파일 시스템설명
      ext4리눅스에서 가장 많이 쓰이는 파일 시스템 (ext2 → ext3 → ext4)
      XFS대용량 파일과 고성능을 지원하는 파일 시스템
      Btrfs고급 기능(Snapshot, RAID 지원)을 제공하는 차세대 파일 시스템
      tmpfsRAM(메모리)에 데이터를 저장하는 파일 시스템 (재부팅 시 삭제됨)
      cgroup2컨테이너 리소스 제한을 위한 파일 시스템
    • 여기서 cgroup2는 컨테이너 리소스 cpu, 메모리등을 관리하는 역할을 함

    • findmnt는 Linux에서 마운트된 파일 시스템을 확인하는 명령어

      [root@k8s-master-2 ~]# findmnt /sys/fs/cgroup
      TARGET         SOURCE  FSTYPE  OPTIONS
      /sys/fs/cgroup cgroup2 cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot
  • Cgroup 확인
    • Cgroup이란 control group 리눅스 커널에서 제공하는 리소스 관리 기능으로 프로세스 그룹에 대해 cpu, 메모리, 네트워크 등 리소스를 제한 및 할당이 가능 하다.

    • k8s는 왜 cgroup을 사용하는가: k8s는 kubelet과 컨테이너 런타임(containerd, cri-o)은 Cgroup을 사용하여 리소스를 제안하고 관리한다. k8s는 기본적으로 cgroup v1 또는 cgroupv2를 사용함.
      k8s 1.24버전 이상부터는 cgroup v2를 권장한다.

      # /sys/fs/cgroup 디렉토리의 파일 시스템 타입을 확인하는 명령어
      [root@k8s-master-2 ~]# stat -fc %T /sys/fs/cgroup
      cgroup2fs
      
      # mount -l | grep cgroup
      [root@k8s-master-2 ~]# mount -l | grep cgroup
      cgroup2 on /sys/fs/cgroup type cgroup2 (rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot)
  • cgroup v2가 설정되어 있지 않은 경우 GRUB: GRand Unified Bootloader 리눅스 시스템을 부팅할때 실행되는 부트로더이다.
    • systemd.unified_cgroup_hierarchy=1 → cgroup v2 활성화 하겠다.

      # cgroup v2가 설정되어 있지 않을때 
      
      ## GRUB 설정 변경
      k8s_all.hcpkube ~]$ sudo vi /etc/default/grub
      -------------CHANGE-------------
      # GRUB_CMDLINE_LINUX 항목에 "systemd.unified_cgroup_hierarchy=1" 추가
      GRUB_CMDLINE_LINUX="crashkernel=1G-4G:192M,4G-64G:256M,64G-:512M resume=/dev/mapper/rhel-swap rd.lvm.lv=rhel/root rd.lvm.lv=rhel/swap systemd.unified_cgroup_hierarchy=1"
      -------------CHANGE-------------END
      
      ## GRUB 설정을 업데이트 하여 부팅시 새로운 옵션을 적용 
      k8s_all.hcpkube ~]$ sudo grub2-mkconfig -o /boot/grub2/grub.cfg
      Generating grub configuration file ...
      Adding boot menu entry for UEFI Firmware Settings ...
      done
      
      ## 커널 버전을 확인 
      k8s_all.hcpkube ~]$ sudo uname -r
      5.14.0-427.13.1.el9_4.x86_64
      
      ## 현재 실행 중인 커널이 GRUB에서 cgroupv2 를 사용하도록 설정 
      k8s_all.hcpkube ~]$ sudo grubby --update-kernel=/boot/vmlinuz-5.14.0-427.13.1.el9_4.x86_64 --args="systemd.unified_cgroup_hierarchy=1"
      k8s_all.hcpkube ~]$ sudo reboot

커널 모듈 설정

  • 커널: 운영체제의 핵심 부분으로 하드웨어와 소프트웨어에서 다리 역할을 하는 프로그램
  • overlay 모듈: 컨테이너가 이미지 계층을 공유할 수 있도록 지원(Containerd, Docker 등)
  • br_netfilter ****모듈: iptables가 브릿지 네트워크의 트래픽을 필터링할 수 있도록 설정하여, Kubernetes 네트워크 정책 및 Pod 간 통신을 관리할 수 있도록 함.
k8s_all.hcpkube ~]$ sudo vi /etc/modules-load.d/k8s.conf
-------------ADD-------------
overlay
br_netfilter
-------------ADD-------------END
k8s_all.hcpkube ~]$ sudo vi /etc/sysctl.conf
-------------ADD-------------
fs.file-max=66536
-------------ADD-------------END

# 커널 모듈 적용
sysctl --system
개념설명위 설정 중 해당하는 부분
커널 모듈리눅스 커널의 기능을 확장하는 플러그인 같은 것/etc/modules-load.d/k8s.conf (→ overlay, br_netfilter 모듈 로드)
커널 파라미터리눅스 커널이 동작하는 방식을 조정하는 값/etc/sysctl.conf, /etc/sysctl.d/k8s.conf (→ 네트워크 설정, IP 포워딩 등)
파일 시스템데이터를 저장하는 구조 및 방식(해당 없음, 하지만 overlay 모듈은 파일 시스템 관련)

iptables 추가 (네트워크 패킷 설정) & NAT 테이블 초기화

vi /etc/sysctl.d/k8s.conf

net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward=1
  • iptables: 리눅스 방화벽 및 패킷 필터링 도구. 네트워크에서 들어오고 나가는 패킷을 필터링하고 제어하는 역할을 한다.
  • net.bridge.bridge-nf-call-iptables = 1 브리지 네트워크를 통해 전달되는 IPv4 패킷이 iptables를 통해 필터링 되도록한다. 기본적으로 리눅스 시스템에서는 0으로 설정되어 iptables규칙 적용을 받지 않는다. 1로 설정하면서 k8s의 네트워크 구성요소들이 iptables를 통해 트래픽을 제어하고 관리할 수 있게 한다.
  • net.bridge.bridge-nf-call-ip6tables = 1 IPv6 패킷이 ip6tables를 통해 필터링 되도록한다
  • net.ipv4.ip_forward = 1 시스템이 패킷 포워딩을 허용하도록 한다.
# 방화벽 규칙확인 - ACCEPT : 현재 특별한 방화벽 규칙이 적용되지 않음
[root@k8s-master-2 ~]# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

## 모든 방화벽 규칙 삭제 F / 사용자 정의 체인 삭제 X / 패킷 및 바이트 카운터 초기화 Z
[root@k8s-master-2 ~]# sudo iptables -F && sudo iptables -X && sudo iptables -Z
[root@k8s-master-2 ~]# iptables --table nat --flush
--------------------------------------------------------------------- 아래는 추가
k8s_all.hcpkube ~]$ sudo iptables -L
k8s_all.hcpkube ~]$ sudo iptables -F && sudo iptables -X && sudo iptables -Z  (또는 iptables --flush; iptables --delete-chain; iptables --zero )
k8s_all.hcpkube ~]$ sudo iptables --table nat --flush   (또는 iptables -t nat -F)
k8s_all.hcpkube ~]$ sudo systemctl disable firewalld --now && sudo systemctl stop firewalld
k8s_all.hcpkube ~]$ sudo sed -i 's@SELINUX=.*@SELINUX=disabled@g' /etc/selinux/config && cat /etc/selinux/config | grep SELINUX
k8s_all.hcpkube ~]$ sudo setenforce 0 && getenforce
구분iptables (기본 방화벽 기능)NAT 테이블 (IP 주소 변환 기능)
역할패킷을 허용, 차단, 로깅하는 방화벽 역할IP 주소를 변환하여 내부/외부 네트워크 간 통신을 중계
주요 체인INPUT, OUTPUT, FORWARDPREROUTING, POSTROUTING, OUTPUT
사용 목적특정 포트/프로토콜을 제한하여 보안 강화사설 네트워크와 외부 네트워크 간 통신 가능하게 함

명령어의도이유
iptables -L현재 방화벽 규칙 확인기존 설정 점검
iptables -F기존 방화벽 규칙(룰) 삭제Kubernetes 네트워크 충돌 방지
iptables -X사용자 정의 체인 삭제커스텀 방화벽 규칙 제거
iptables -Z패킷 및 바이트 카운터 초기화새로운 트래픽 모니터링 가능하게 함
iptables -t nat -FNAT 테이블 초기화Kubernetes의 CNI 플러그인과 충돌 방지

파일 디스크립터 제한 늘리기

기본적으로 리눅스 시스템은 사용자가 열수 있는 파일 수에 제한을 두고 있다. k8s와 같은 대규모 오케스트레이션 플랫폼에서는 다수의 컨테이너와 프로세스가 동시에 시작되기 때문에 소프트 및 하드 제한을 늘려준다.

cat << EOF | sudo tee -a /etc/security/limits.conf
*               soft    nofile          65536
*               hard    nofile          65536
root            soft    nofile          65536
root            hard    nofile          65536
EOF


3. Containerd, CNI-Plugin, RunC 설치

k8s나 docker같은 컨테이너 오케스트레이션 도구는 직접 컨테이너를 실행하지 않기 때문에 컨테이너 실행을 담당하는 컨테이너 런타임이 필요하다.

  • containerd는 k8s가 컨테이너를 실행하고 관리하는데 필요한 엔진이다 kubelet(파드실행해줘 요청) → container runtime(containerd 요청을 runc에게 전달) → OCI runtime(runc 실제로 실행) → 컨테이너 실행
  • Docker는 불필요한 기능들이 많음, dockershim거쳐서 사용해야한다는 불편함
  • containerd를 설치할 때 CNI 플러그인을 함께 설치하는 이유는 기본적인 네트워크 설정을 하기 위해서
    • Flannel: 가벼운 오버레이 네트워크 제공 (기본 선택)
    • Calico: 네트워크 정책 지원 (보안 강화)
    • Weave: 자동 피어링 지원
    • Bridge (기본 CNI): 단순한 브리지 네트워크 (테스트용)
  • 기본 플러그인 말고 Cilium 을 추가적으로 하는 이유는? CNI 플러그인으로도 Pod 간 통신이 가능하지만, 보안, 성능, 정책 관리가 부족하기 때문에 Cilium을 추가로 설치
  • k8s에서 containerd, runc가 필요한 이유
    구성 요소역할
    kubeletKubernetes 노드에서 컨테이너를 실행 및 관리
    containerd컨테이너 런타임으로서 컨테이너 생성 및 이미지 관리
    runc (OCI)리눅스 네임스페이스와 cgroup을 사용하여 컨테이너 실행


Containerd 설치

dnf install wget
wget https://github.com/containerd/containerd/releases/download/v1.7.13/containerd-1.7.13-linux-amd64.tar.gz
tar Cxzvf /usr/local containerd-1.7.13-linux-amd64.tar.gz

[root@k8s-master-2 ~]# cd /usr/local/bin
[root@k8s-master-2 bin]# ls
...
buildkit-qemu-aarch64    containerd               nerdctl
buildkit-qemu-arm        containerd-shim          rootlessctl
buildkit-qemu-i386       containerd-shim-runc-v1  rootlesskit
buildkit-qemu-mips64     containerd-shim-runc-v2  rootlesskit-docker-proxy
buildkit-qemu-mips64el   containerd-stress
buildkit-qemu-ppc64le    crictl
  • containerd 파일 시스템 등록 Kubernetes에서 컨테이너 런타임을 설정하고, 시스템 부팅 시 자동으로 실행되도록 하여 클러스터 관리컨테이너 실행의 기반을 설정한다.
sudo mkdir -p /usr/local/lib/systemd/system
curl -o /usr/local/lib/systemd/system/containerd.service https://raw.githubusercontent.com/containerd/containerd/main/containerd.service

# 서비스 파일 인식
sudo systemctl daemon-reload
# 서비스 시작 및 자동 실행 설정 
sudo systemctl enable --now containerd
systemctl status containerd
  • containerd의 기본 설정 파일(config.toml)을 생성 및 초기화 SystemdCgroup = true 설정은 containerdsystemd의 cgroup 관리 방식을 사용하도록 하여, Kubernetes와 containerd의 리소스 관리가 일관성 있게 통합되도록 한다.
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

[root@k8s-master-2 bin]# vi /etc/containerd/config.toml
135             Root = ""
136             ShimCgroup = ""
137             SystemdCgroup = true ## 변경 
138

------------------------------------------------------------------
[root@k8s-master-2 bin]# cat /etc/containerd/config.toml | grep -E "root =|sandbox_image|config_path|SystemdCgroup"
root = "/var/lib/containerd"
    sandbox_image = "registry.k8s.io/pause:3.8"
        runtime_root = ""
          runtime_root = ""
            SystemdCgroup = true ## 확인하기 
        runtime_root = ""
      config_path = ""
    plugin_config_path = "/etc/nri/conf.d"
    runtime_root = ""
    config_path = ""
    
systemctl restart containerd
systemctl status containerd    

CNI - plugin 설치

wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
sudo mkdir -p /opt/cni/bin
sudo tar Cxzvf /opt/cni/bin cni-plugins-linux-amd64-v1.3.0.tgz

systemctl daemon-reload
systemctl restart containerd

runC 설치

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

모든 설치 확인

[root@k8s-master-2 k8s_lv1]# containerd --version
containerd github.com/containerd/containerd v1.7.13 7c3aca7a610df76212171d200ca3811ff6096eb8
[root@k8s-master-2 k8s_lv1]# which containerd
/usr/local/bin/containerd
[root@k8s-master-2 k8s_lv1]# runc --version
runc version 1.1.12
commit: v1.1.12-0-g51d5e946
spec: 1.0.2-dev
go: go1.20.13
libseccomp: 2.5.4
[root@k8s-master-2 k8s_lv1]# which runc
/usr/local/sbin/runc

## 만약 이 가이드 기준 runc version이 뜨지 않는다면
echo "export PATH=$PATH:/usr/local/sbin" >> ~/.bashrc
source ~/.bashrc

4. k8s 설치

[root@k8s-master-2 k8s_lv1]# cd /etc/yum.repos.d/
[root@k8s-master-2 yum.repos.d]# ls
local.repo  nexus.repo
[root@k8s-master-2 yum.repos.d]# cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
EOF
[kubernetes]
name=Kubernetes
baseurl=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://pkgs.k8s.io/core:/stable:/v1.30/rpm/repodata/repomd.xml.key
[root@k8s-master-2 yum.repos.d]# ls
kubernetes.repo  local.repo  nexus.repo

sudo dnf install -y kubelet kubeadm kubectl
sudo systemctl enable --now kubelet

[root@k8s-master-2 default]# rpm -qa | grep kube
kubernetes-cni-1.4.0-150500.1.1.x86_64
kubelet-1.30.10-150500.1.1.x86_64
kubeadm-1.30.10-150500.1.1.x86_64
kubectl-1.30.10-150500.1.1.x86_64

## 버전확인
[root@k8s-master-2 yum.repos.d]# kubectl version --client
Client Version: v1.30.10
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
[root@k8s-master-2 yum.repos.d]# kubeadm version
kubeadm version: &version.Info{Major:"1", Minor:"30", GitVersion:"v1.30.10", GitCommit:"ccc69071da5040a2bafc1ba9c4775782e0f4e55c", GitTreeState:"clean", BuildDate:"2025-02-12T21:32:03Z", GoVersion:"go1.22.12", Compiler:"gc", Platform:"linux/amd64"}
[root@k8s-master-2 yum.repos.d]# kubelet --version
Kubernetes v1.30.10
  • cgroup 설정 (Kubelet에 systemd 사용)
[root@k8s-master-2 yum.repos.d]# sudo mkdir -p /etc/default
[root@k8s-master-2 yum.repos.d]# echo 'KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"' | sudo tee /etc/default/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

[root@k8s-master-2 yum.repos.d]# cd /etc/default
[root@k8s-master-2 default]# ls
grub  kubelet  useradd

[root@k8s-master-2 default]# pwd
/etc/default
[root@k8s-master-2 default]# cat /etc/default/kubelet
KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"

[root@k8s-master-2 default]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
     Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/system/kubelet.service.d
             └─10-kubeadm.conf
     Active: activating (auto-restart) (Result: exit-code) since Wed 2025-02-26 00:28:31 EST; 7s ago
       Docs: https://kubernetes.io/docs/
    Process: 139741 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_E>
   Main PID: 139741 (code=exited, status=1/FAILURE)
        CPU: 137ms
  • init전 필요한 이미지 당겨오기
# 필요한 이미지 목록 확인
[root@k8s-master-2 manifests]# kubeadm config images list
I0303 05:09:45.913718    7380 version.go:256] remote version is much newer: v1.32.2; falling back to: stable-1.30
registry.k8s.io/kube-apiserver:v1.30.10
registry.k8s.io/kube-controller-manager:v1.30.10
registry.k8s.io/kube-scheduler:v1.30.10
registry.k8s.io/kube-proxy:v1.30.10
registry.k8s.io/coredns/coredns:v1.11.3
registry.k8s.io/pause:3.9
registry.k8s.io/etcd:3.5.15-0

# 필요한 이미지 pull
[root@k8s-master-2 kubeadm_v]# kubeadm config images pull
I0226 00:35:34.543630  140145 version.go:256] remote version is much newer: v1.32.2; falling back to: stable-1.30
[config/images] Pulled registry.k8s.io/kube-apiserver:v1.30.10
[config/images] Pulled registry.k8s.io/kube-controller-manager:v1.30.10
[config/images] Pulled registry.k8s.io/kube-scheduler:v1.30.10
[config/images] Pulled registry.k8s.io/kube-proxy:v1.30.10
[config/images] Pulled registry.k8s.io/coredns/coredns:v1.11.3
[config/images] Pulled registry.k8s.io/pause:3.9
[config/images] Pulled registry.k8s.io/etcd:3.5.15-0
  • 마스터 노드에서 init 명령어 수행
sudo kubeadm init --apiserver-advertise-address=10.0.16.71 **--v=5**
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.0.16.71:6443 --token zbgtjh.d14vq735od97url0 \
	--discovery-token-ca-cert-hash sha256:28f7a78b3b913ceec0f039f9f8a38ff0770f473d34698c4b2f055df822f0d9fe
  • 마스터 노드 조인시
    ## certificate-key 생성
    kubeadm token create --certificate-key 
    
    ## join할 마스터 노드에 certificate-key 추가
    kubeadm join 10.0.16.71:6443 --token **zbgtjh.d14vq735od97url0 \
    	--discovery-token-ca-cert-hash sha256:28f7a78b3b913ceec0f039f9f8a38ff0770f473d34698c4b2f055df822f0d9fe** --control-plane --certificate-key <certificate-key>
  • 워커 노드 조인시
    kubeadm join 10.0.16.71:6443 --token zbgtjh.d14vq735od97url0 \
    	--discovery-token-ca-cert-hash sha256:28f7a78b3b913ceec0f039f9f8a38ff0770f473d34698c4b2f055df822f0d9fe
[root@k8s-master-2 ~]# k get no
NAME           STATUS     ROLES           AGE     VERSION
k8s-master-2   NotReady   control-plane   8m35s   v1.30.10

[root@k8s-master-2 ~]# k get po -A
NAMESPACE     NAME                                   READY   STATUS    RESTARTS   AGE
kube-system   coredns-55cb58b774-87sng               0/1     Pending   0          8m29s
kube-system   coredns-55cb58b774-n8zcw               0/1     Pending   0          8m29s
kube-system   etcd-k8s-master-2                      1/1     Running   3          8m37s
kube-system   kube-apiserver-k8s-master-2            1/1     Running   3          8m35s
kube-system   kube-controller-manager-k8s-master-2   1/1     Running   3          8m36s
kube-system   kube-proxy-qhls9                       1/1     Running   0          8m29s
kube-system   kube-scheduler-k8s-master-2            1/1     Running   3          8m39s

[root@k8s-master-2 ~]# k get no
NAME           STATUS     ROLES           AGE     VERSION
k8s-master-2   NotReady   control-plane   9m18s   v1.30.10
k8s-worker-1   NotReady   <none>          6s      v1.30.10
  • 레이블 추가
[root@k8s-master-2 ~]# k label node k8s-worker-1 node-role.kubernetes.io/worker-1=worker-1
node/k8s-worker-1 labeled
[root@k8s-master-2 ~]# k get no
NAME           STATUS     ROLES           AGE     VERSION
k8s-master-2   NotReady   control-plane   13m     v1.30.10
k8s-worker-1   NotReady   worker-1        3m56s   v1.30.10 # 반영됨
  • CoreDNSPending 상태인 이유는 네트워크 플러그인(예: Calico 또는 Flannel 등)이 제대로 설치되지 않았기 때문


디렉토리 & 파일 정리

  • /etc/resolv.conf : 시스템에서 DNS(Domain Name System) 설정을 관리하는 파일
  • /sys/fs/cgroup : cgroup(control group) 관련 파일들이 위치한 디렉토리로, 리소스 제한, 계층 구조 등을 설정하는 파일 시스템을 제공하는 디렉토리
  • /etc/default/grub : 리눅스 시스템에서 부트 로더 역할을 하며, 시스템 부팅 시 운영 체제를 로드하는 프로그램 (파일)
  • /etc/modules-load.d/k8s.conf: 리눅스 커널 모듈을 자동으로 로드하는 설정 파일
    → Kubernetes가 정상적으로 동작하기 위해 필요한 커널 모듈을 자동으로 로드하는 파일
  • /etc/sysctl.d/k8s.conf : Kubernetes 클러스터를 운영할 때 네트워크와 관련된 커널 설정을 최적화하는 역할의 파일
    → Kubernetes가 정상적으로 동작하도록 커널 매개변수(sysctl 설정)를 적용하는 파일
  • /etc/security/limits.conf : 리눅스에서 사용자별 또는 그룹별로 시스템 리소스 제한을 설정하는 파일
  • /usr/local/lib/systemd/system : 디렉토리는 systemd의 사용자 정의 서비스 파일을 저장하는 위치
  • /etc/containerd/config.toml : containerd의 주요 설정 파일로, containerd의 동작 방식을 제어하는 여러 가지 설정을 포함

번외 : CA인증서 추가 설치

k8s가 CA인증서를 사용하는 이유

  • k8s는 내부적으로 TLS인증을 사용해서 클러스터 내에서 통신을 보호한다. kubeadm init을 하면 /etc/kubernetes/pki/ 경로에 자동으로 CA인증서가 생성된다.
  • API Server, Kubelet, Controller Manager, Scheduler등의 구성요소간 TLS인증을 제공한다.

따로 CA인증서를 적용해야 하는 이유

  • 보통 Kubeadm이 자동으로 CA를 생성하지만 기업 환경이나 보안 요구사항이 높은 경우에는 직접 CA를 생성해야하는 경우가 있다.
    1. 외부 CA 사용

      기업에서 이미 신뢰하는 CA를 사용해서 보안정책을 통제하는 경우

    2. 고가용성 HA 클러스터 구축

      각 마스터 노드가 자체적으로 CA를 생성하면 인증이 일관되지 않기 때문에 공통된 CA를 만들어서 마스터에게 동일하게 적용시켜야하기 때문

    3. 클러스터 재설치 혹은 마스터 노드 교체를 해야할때

      클러스터를 재설치하거나 마스터 노드를 교체할때 인증서가 필요함

    4. 사용자 인증

      RBAC정책을 적용하는 경우 사용자 또는 서비스 계정에 맞는 인증서를 발급해야함

    5. 서비스간 TLS 보안 통신

      Pod간의 보안 통신을 암호화하기 위해 TLS를 적용할때 별도의 CA를 사용할 수 있다.

/etc/kubernetes/pki/
├── ca.crt  # 클러스터의 루트 CA 인증서
├── ca.key  # 클러스터의 루트 CA 개인 키
├── apiserver.crt  # Kube API 서버 인증서
├── apiserver.key  # Kube API 서버 개인 키
├── apiserver-kubelet-client.crt  # Kubelet이 API 서버와 통신할 때 사용하는 인증서
├── apiserver-kubelet-client.key
├── front-proxy-ca.crt  # 프록시 CA 인증서
├── front-proxy-ca.key
├── front-proxy-client.crt  # 프록시 클라이언트 인증서
├── front-proxy-client.key
├── etcd/
│   ├── ca.crt  # etcd CA 인증서
│   ├── ca.key
│   ├── server.crt  # etcd 서버 인증서
│   ├── server.key
│   ├── peer.crt  # etcd 노드 간 통신 인증서
│   ├── peer.key
  • 인증서 생성방법
[root@k8s-master-2 yum.repos.d]# mkdir -p /etc/kubernetes/pki
[root@k8s-master-2 yum.repos.d]# cd /etc/kubernetes/pki
[root@k8s-master-2 pki]# openssl genrsa -out ca.key 2048
[root@k8s-master-2 pki]# openssl req -x509 -new -nodes -key ca.key -subj "/CN=kubernetes-ca" -days 10000 -out ca.crt

[root@k8s-master-2 pki]# cd /etc/kubernetes/pki
[root@k8s-master-2 pki]# ls
ca.crt  ca.key

/etc/kubernetes/pki/ca.crt  # CA 인증서
/etc/kubernetes/pki/ca.key  # CA 개인 키

수동으로 ca.key와 ca.crt를 생성한 후 kubeadm init을 실행하면 k8s의 기본 동작 방식이 달라진다. 원래는 init시에 CA인증서가 자동생성되지만 init을 실행하면 기존 CA파일을 그대로 사용한다.

CA는 클러스터내 모든 컴포넌트가 서로 신뢰하도록 하기위해 사용됨!
(kube-apiserver, kubelet, controller-manager, scheduler 등)

profile
개발기록

0개의 댓글