결론부터 말하면, “계속 root 계정을 자유롭게 쓰겠다”로 주장하면 보안팀/인프라팀 설득이 어렵습니다. 대신 아래처럼 잡는 게 좋습니다.
Kubernetes 노드는 일반 애플리케이션 서버가 아니라 클러스터 제어면/데이터면의 일부이므로, Kubespray 기반 설치·업그레이드·노드 증설·장애복구·CNI/런타임/커널 튜닝에는 root-equivalent 권한이 필수다.
단, 개인이 공유 root를 상시 사용하는 방식은 줄이고, 운영 자동화 계정 또는 break-glass root 접근을 통제된 방식으로 유지하자.
즉, 논리는 root 계정 자체를 고집하는 것보다 root와 동등한 무중단·무대화형 권한을 유지해야 한다로 세우는 게 맞습니다.
Kubespray 공식 README도 non-root 계정으로 실행할 경우 대상 서버에 올바른 privilege escalation이 구성되어 있어야 하며 ansible_become 또는 --become/-b를 지정해야 한다고 설명합니다. 즉, root로 접속하지 않더라도 결국 root로 승격 가능한 권한이 필요하다는 뜻입니다. (GitHub)
여기서 중요한 포인트는 다음입니다.
sudo를 주겠다는 말만으로는 부족합니다.
Kubespray/Ansible은 단순히 /bin/systemctl, /bin/cp 같은 몇 개 명령만 실행하는 구조가 아니라, 대상 서버에 임시 모듈 파일을 올리고 그 모듈을 실행합니다. Ansible 공식 문서도 privilege escalation은 일반적이어야 하며 특정 명령 경로만 허용하는 방식으로 제한하면 Ansible 모듈 실행이 실패할 수 있다고 설명합니다. (Ansible 문서)
따라서 인프라팀이 말하는 sudo가 아래와 같다면 수용 가능합니다.
ansible_user=k8sops
ansible_become=true
ansible_become_user=root
그리고 대상 노드에서 다음이 모두 가능해야 합니다.
sudo -n true
sudo -n id
sudo -n systemctl status kubelet
sudo -n cat /etc/kubernetes/kubelet.conf
반대로 아래 조건이면 운영 리스크가 큽니다.
- sudo 시 비밀번호 입력 필요
- TTY 필요
- 특정 명령만 sudo 허용
- systemctl/containerd/crictl/iptables/sysctl/modprobe/mount 관련 명령 제한
- /etc/kubernetes, /var/lib/kubelet, /var/lib/containerd, /etc/cni, /opt/cni 접근 제한
- 장애 시 root 전환을 별도 승인 받아야 함
이 경우는 “sudo를 준다”가 아니라 운영 자동화가 불가능한 제한 권한에 가깝습니다.
Kubernetes 운영은 kubectl만으로 끝나지 않습니다. 특히 Kubespray 기반 클러스터에서는 설치 이후에도 다음 작업이 반복됩니다.
- Kubernetes 버전 업그레이드
- kubelet / kubeadm / kubectl / container runtime 변경
- containerd 설정 변경
- CNI 설정 변경
- kubelet systemd unit 변경
- /etc/kubernetes 인증서/manifest/config 확인 및 갱신
- /var/lib/kubelet, /var/lib/containerd, /var/lib/cni 점검
- sysctl, kernel module, iptables/nftables, routing rule 확인
- 노드 증설, 교체, 제거, reset, rejoin
- etcd/control-plane 장애 대응
Kubernetes 공식 문서도 각 노드에 container runtime 설치가 필요하고, 네트워크 구현에 따라 IPv4 forwarding, sysctl, kernel module 설정 등이 필요할 수 있다고 설명합니다. 또한 kubelet과 container runtime은 cgroup을 통해 리소스 제어를 수행하므로 kubelet/runtime의 cgroup 설정 일치도 중요합니다. (Kubernetes)
Kubespray 운영 문서도 노드 추가/교체 시 scale.yml, cluster.yml, remove-node.yml 등을 사용하고, control plane/etcd 변경 시 /etc/kubernetes/manifests/kube-apiserver.yaml 같은 파일 수정이 필요할 수 있음을 설명합니다. (GitHub) Kubernetes 업그레이드도 Kubespray의 upgrade-cluster.yml playbook으로 수행하며, 이 역시 -b 즉 become 권한을 전제로 합니다. (GitHub)
따라서 논리는 이렇게 잡으면 됩니다.
“Kubernetes 운영팀이 필요한 것은 일반 서버 로그인 권한이 아니라, 클러스터 생명주기 관리 권한입니다. Kubespray는 OS 패키지, systemd, kubelet, container runtime, CNI, 인증서, 커널 네트워크 설정을 변경하므로 root-equivalent 권한 없이는 설치 이후의 업그레이드/노드교체/장애복구를 책임질 수 없습니다.”
사용자 환경은 Cilium을 쓰는 구조라서, 이 부분도 중요한 근거가 됩니다.
Cilium 공식 문서는 Cilium이 Linux kernel에 eBPF 프로그램을 설치하며, system-wide eBPF 프로그램 설치에는 CAP_SYS_ADMIN 권한이 필요하고, 가장 빠른 방법은 cilium-agent를 root 또는 privileged container로 실행하는 것이라고 설명합니다. 또한 Cilium pod는 host networking namespace 접근도 필요합니다. (Cilium Documentation)
즉, Cilium 기반 Kubernetes는 단순한 사용자 프로세스가 아니라 호스트 커널 네트워크 경로를 직접 다루는 시스템입니다. 운영 중 문제가 생겼을 때 다음을 확인해야 합니다.
bpftool
tc
ip rule
ip route
iptables / nft
sysctl
journalctl -u kubelet
crictl ps/logs/inspect
ls /sys/fs/bpf
mount | grep bpf
이런 작업은 대부분 root 또는 root-equivalent 권한 없이는 제대로 수행하기 어렵습니다.
Kubernetes 문서에는 kubelet, CRI, OCI, CNI 같은 노드 컴포넌트를 non-root로 실행하는 rootless mode 설명이 있기는 합니다. 하지만 해당 문서는 feature state가 Kubernetes v1.22 [alpha]로 표시되어 있고, user namespace, cgroup v2, systemd user session, subuid/subgid, 별도 sysctl 구성 등이 필요합니다. 또한 해당 문서의 수동 배포 섹션은 일반 운영자가 아니라 Kubernetes distribution 개발자를 위한 내용이라고 명시되어 있습니다. (Kubernetes)
따라서 인프라팀이 “보안상 rootless로 가야 하는 것 아니냐”고 한다면 이렇게 답하면 됩니다.
“rootless Kubernetes는 현재 우리 같은 대규모 Kubespray 기반 운영 클러스터의 표준 운영 방식이 아니라 별도 아키텍처 전환 과제입니다. 현재 클러스터는 root 기반 kubelet/containerd/CNI 운영을 전제로 설치되어 있으므로, 운영 중간에 root 권한만 회수하면 보안 강화가 아니라 장애 대응 능력 저하가 됩니다.”
가장 현실적인 안은 이겁니다.
1. 개인의 상시 root 직접 로그인은 제한한다.
2. 일반 작업은 개인 계정 + sudo 로그 기반으로 수행한다.
3. Kubespray/Ansible 자동화 전용 계정은 passwordless sudo ALL을 허용한다.
4. root 계정은 break-glass 용도로 유지하되, 공유 비밀번호 방식은 금지한다.
5. root 또는 automation key는 bastion/Ansible controller에서만 접근 가능하게 제한한다.
6. 모든 접근은 change ticket, 작업계획서, 세션 로그, sudo 로그로 추적한다.
7. 장애 시 별도 승인 대기 없이 즉시 사용 가능한 긴급 접근 경로를 유지한다.
예시 sudoers는 이런 식입니다.
# Kubernetes lifecycle automation account
k8sops ALL=(root) NOPASSWD: ALL
# 또는 운영 그룹 기반
%k8s-platform ALL=(root) NOPASSWD: ALL
# Ansible/Kubespray 자동화에서 TTY 요구로 실패하지 않도록
Defaults:k8sops !requiretty
Defaults:%k8s-platform !requiretty
# 필요한 경우 air-gap proxy, registry, kubeconfig 등 환경변수 보존
Defaults:k8sops env_keep += "PATH HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy KUBECONFIG"
단, 여기서 핵심은 명령어 whitelist 방식으로 제한하지 말 것입니다. Ansible은 임시 모듈을 생성해 실행하기 때문에 “systemctl만 허용”, “cp만 허용”, “yum만 허용” 같은 방식은 Kubespray 실패 가능성이 큽니다. 이 점은 Ansible 공식 문서의 설명과도 맞습니다. (Ansible 문서)
아래 문구를 그대로 사용해도 됩니다.
현재 Kubernetes 클러스터는 Kubespray 기반으로 설치되어 있으며, 설치 이후에도 업그레이드, 노드 증설/교체/제거, kubelet/containerd/CNI 설정 변경, 인증서/manifest 갱신, 장애복구 작업에서 OS root-equivalent 권한이 필요합니다. Kubespray 공식 문서도 non-root 계정 사용 시 대상 서버에 privilege escalation이 구성되어야 하며
ansible_become또는--become사용을 전제로 합니다.따라서 보안상 개인의 상시 root 직접 로그인은 제한하는 방향에 동의하지만, Kubernetes 운영 책임을 유지하려면 Kubespray/Ansible 자동화 계정 또는 break-glass 계정에는 passwordless sudo ALL 수준의 root-equivalent 권한이 필요합니다. 제한된 sudo, 비밀번호 입력 sudo, 승인 대기형 sudo, 명령어 whitelist sudo는 자동화 실패 및 장애 대응 지연을 유발할 수 있어 운영 SLA 관점에서 수용하기 어렵습니다.
대안으로 root 공유 비밀번호 사용은 금지하고, bastion/Ansible controller 기반 접근 제한, 개인별 계정 추적, sudo 로그, 세션 기록, 작업계획서/변경관리 티켓 기반 사용, 정기 권한 리뷰를 적용하겠습니다. 단, 클러스터 생명주기 운영 및 긴급 장애 대응을 위한 root-equivalent 접근 경로는 유지되어야 합니다.
가장 좋은 협상 포인트는 이것입니다.
수용 가능:
- 개인 일반계정 사용
- root 직접 로그인 제한
- root password lock
- bastion 경유
- 세션 로깅
- 작업계획서/변경관리 기반 사용
- 자동화 계정 분리
수용 불가:
- root-equivalent 권한 완전 회수
- password 필요한 sudo
- 명령어 제한 sudo
- 승인 받아야만 sudo 가능한 구조
- 장애 시 root 접근 불가
- Kubespray 실행 계정의 NOPASSWD ALL 미보장
즉, 주장 방향은 “root를 계속 쓰겠다”가 아니라,
“Kubernetes 플랫폼 운영 책임을 지려면 root-equivalent 권한은 유지되어야 한다. 다만 보안 요구에 맞게 접근 방식은 통제하겠다.”
로 가져가는 게 가장 설득력 있습니다.