외부망 환경에서 k8s 설치하는 경우, 별도의 레지스토리나 이미지를 다운받아서 사용할 필요가 없다.
- 설치 버전 정보
Contianerd(1.7.13v)/ CNI-Plugin(1.3.0v)/ runC(1.1.12v)/ k8s(1.30v) 으로 설치- 운영체제 : RHEL 9.4
- Master2 / Worker1을 사용하여 실습
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 msfree -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 0Bswapoff -afree -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
| 서비스 | 포트 번호 |
|---|---|
| api-server | 6443 |
| etcd | 2379-2380 |
| kubelet | 10250 |
| kube-scheduler | 10259 |
| kube-controller-manager | 10257 |
방화벽이 설치되어있는 경우
# 방화벽 비활성화
# 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.
findmnt /sys/fs/cgroup파일시스템: 운영체제가 데이터를 저장하고, 읽고, 관리하는 방식이다. 데이터 저장 및 관리, 파일 디렉터리 구조 제공, 접근제어 및 권한 관리등 역할을 한다.
| 파일 시스템 | 설명 |
|---|---|
| ext4 | 리눅스에서 가장 많이 쓰이는 파일 시스템 (ext2 → ext3 → ext4) |
| XFS | 대용량 파일과 고성능을 지원하는 파일 시스템 |
| Btrfs | 고급 기능(Snapshot, RAID 지원)을 제공하는 차세대 파일 시스템 |
| tmpfs | RAM(메모리)에 데이터를 저장하는 파일 시스템 (재부팅 시 삭제됨) |
| 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이란 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)
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 모듈은 파일 시스템 관련) |
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
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, FORWARD | PREROUTING, POSTROUTING, OUTPUT |
| 사용 목적 | 특정 포트/프로토콜을 제한하여 보안 강화 | 사설 네트워크와 외부 네트워크 간 통신 가능하게 함 |
| 명령어 | 의도 | 이유 |
|---|---|---|
iptables -L | 현재 방화벽 규칙 확인 | 기존 설정 점검 |
iptables -F | 기존 방화벽 규칙(룰) 삭제 | Kubernetes 네트워크 충돌 방지 |
iptables -X | 사용자 정의 체인 삭제 | 커스텀 방화벽 규칙 제거 |
iptables -Z | 패킷 및 바이트 카운터 초기화 | 새로운 트래픽 모니터링 가능하게 함 |
iptables -t nat -F | NAT 테이블 초기화 | 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
k8s나 docker같은 컨테이너 오케스트레이션 도구는 직접 컨테이너를 실행하지 않기 때문에 컨테이너 실행을 담당하는 컨테이너 런타임이 필요하다.
| 구성 요소 | 역할 |
|---|---|
| kubelet | Kubernetes 노드에서 컨테이너를 실행 및 관리 |
| containerd | 컨테이너 런타임으로서 컨테이너 생성 및 이미지 관리 |
| runc (OCI) | 리눅스 네임스페이스와 cgroup을 사용하여 컨테이너 실행 |

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
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
config.toml)을 생성 및 초기화 SystemdCgroup = true 설정은 containerd가 systemd의 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
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

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
[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
[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
# 필요한 이미지 목록 확인
[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
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 # 반영됨
CoreDNS가 Pending 상태인 이유는 네트워크 플러그인(예: 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 사용
기업에서 이미 신뢰하는 CA를 사용해서 보안정책을 통제하는 경우
고가용성 HA 클러스터 구축
각 마스터 노드가 자체적으로 CA를 생성하면 인증이 일관되지 않기 때문에 공통된 CA를 만들어서 마스터에게 동일하게 적용시켜야하기 때문
클러스터 재설치 혹은 마스터 노드 교체를 해야할때
클러스터를 재설치하거나 마스터 노드를 교체할때 인증서가 필요함
사용자 인증
RBAC정책을 적용하는 경우 사용자 또는 서비스 계정에 맞는 인증서를 발급해야함
서비스간 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 등)