Kubespray 변수 우선순위 및 컴포넌트 구조 가이드

진웅·2026년 2월 7일

k8s deploy

목록 보기
15/20
post-thumbnail

Kubespray 변수 우선순위 구조

변수 우선순위 개요

Ansible은 변수 우선순위가 명확하게 정의되어 있다. 숫자가 높을수록 우선순위가 높으며, 나중에 정의된 값이 이전 값을 Override한다.

우선순위 레벨 (낮음 → 높음)

┌─────────────────────────────────────────────┐
│ 1. Role Defaults (가장 낮은 우선순위)          │
│    roles/*/defaults/main.yml                 │
└─────────────────────────────────────────────┘
                    ⬇ override
┌─────────────────────────────────────────────┐
│ 2. Inventory group_vars ★ 99% 여기서 조절    │
│    inventory/mycluster/group_vars/all/*.yml  │
│    inventory/mycluster/group_vars/k8s_cluster/*.yml │
└─────────────────────────────────────────────┘
                    ⬇ override
┌─────────────────────────────────────────────┐
│ 3. Inventory host_vars                       │
│    inventory/mycluster/host_vars/<node>.yml  │
└─────────────────────────────────────────────┘
                    ⬇ override
┌─────────────────────────────────────────────┐
│ 4. Playbook vars                             │
│    playbooks/*.yml (vars:, vars_files:)      │
└─────────────────────────────────────────────┘
                    ⬇ override
┌─────────────────────────────────────────────┐
│ 5. Extra vars (최고 우선순위)                 │
│    --extra-vars (-e)                         │
└─────────────────────────────────────────────┘

1단계: Role Defaults

위치: roles/*/defaults/main.yml

설명: Kubespray Role의 기본값이 정의되어 있다. 가장 낮은 우선순위를 가지며, 다른 모든 설정에 의해 Override될 수 있다.

예시:

# roles/kubespray_defaults/defaults/main/main.yml
bin_dir: /usr/local/bin
kube_version: v1.29.0

특징:

  • Kubespray 개발자가 설정한 기본값
  • 일반적으로 직접 수정하지 않음
  • 참고용으로만 사용

2단계: Inventory group_vars ★

위치:

  • inventory/mycluster/group_vars/all/*.yml
  • inventory/mycluster/group_vars/k8s_cluster/*.yml
  • inventory/mycluster/group_vars/etcd.yml

설명: 전체 노드에 공통으로 적용되는 설정. 실무에서 99%의 설정 변경이 이 레벨에서 이루어진다.

주요 설정 파일:

inventory/mycluster/group_vars/
├── all/
│   └── all.yml                    # 전체 노드 공통
├── k8s_cluster/
│   ├── k8s-cluster.yml            # 클러스터 전반 설정
│   ├── k8s-net-flannel.yml        # Flannel CNI 설정
│   └── addons.yml                 # 애드온 설정
└── etcd.yml                       # etcd 설정

예시:

# inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml
kube_version: v1.32.9
kube_network_plugin: flannel
kube_proxy_mode: iptables
enable_nodelocaldns: false

자주 변경하는 변수들:

  • kube_version: Kubernetes 버전
  • kube_network_plugin: CNI 플러그인 (calico, flannel, cilium 등)
  • kube_proxy_mode: kube-proxy 모드 (iptables, ipvs)
  • enable_nodelocaldns: NodeLocal DNS 활성화 여부
  • metrics_server_enabled: Metrics Server 설치 여부

3단계: Inventory host_vars

위치: inventory/mycluster/host_vars/<node>.yml

설명: 특정 노드에만 적용되는 설정. 노드별로 다른 설정이 필요한 경우에만 사용한다.

사용 예시:

# inventory/mycluster/host_vars/k8s-node1.yml
node_labels:
  node-role.kubernetes.io/control-plane: "true"
  special-node: "true"

node_taints:
  - key: "dedicated"
    value: "control-plane"
    effect: "NoSchedule"

언제 사용하는가:

  • 특정 노드에만 라벨이나 Taint 설정
  • GPU 노드, 스토리지 노드 등 특수 목적 노드 설정
  • 노드별 리소스 제한 설정

4단계: Playbook vars

위치: playbooks/*.ymlvars: 섹션

설명: 특정 플레이북 실행 시에만 적용되는 변수. 플레이북 내부에서 임시로 Override할 때 사용한다.

예시:

# playbooks/scale.yml
- name: Install etcd
  vars:
    etcd_cluster_setup: false         # etcd 신규 클러스터 구성 안 함
    etcd_events_cluster_setup: false  # 이벤트 전용 etcd 구성 안 함
  import_playbook: install_etcd.yml

특징:

  • 해당 플레이북 실행 범위 안에서만 유효
  • inventory/group_vars보다 우선순위가 높음
  • 특수한 상황에서만 사용 (예: scale out, upgrade)

5단계: Extra vars (CLI) ★★

위치: 명령줄 옵션 --extra-vars 또는 -e

설명: 모든 설정을 Override하는 최강 우선순위. 테스트나 긴급 상황에서 사용한다.

예시:

# Kubernetes 버전을 일시적으로 변경
ansible-playbook -i inventory/mycluster/inventory.ini \
  cluster.yml \
  -e kube_version="v1.32.9"

# 여러 변수 동시 Override
ansible-playbook -i inventory/mycluster/inventory.ini \
  cluster.yml \
  -e kube_version="v1.32.9" \
  -e kube_network_plugin="cilium" \
  -e kube_proxy_mode="ipvs"

언제 사용하는가:

  • 테스트 목적으로 일시적인 설정 변경
  • 긴급 패치나 핫픽스
  • CI/CD 파이프라인에서 동적 설정 주입

주의사항:

  • 파일에 기록되지 않으므로 재현성이 떨어짐
  • 프로덕션 환경에서는 가급적 사용 자제
  • 사용했다면 반드시 문서화

변수 검색 방법

특정 변수가 어디에 정의되어 있고, 어떻게 사용되는지 찾으려면 grep 명령어를 사용한다.

기본 검색

# 변수가 정의되고 사용되는 위치 찾기
grep -Rn "변수명" inventory/mycluster/ playbooks/ roles/ -A1 -B1

옵션 설명:

  • -R: 재귀적으로 검색
  • -n: 라인 번호 표시
  • -A1: 매치된 라인 이후 1줄 표시
  • -B1: 매치된 라인 이전 1줄 표시

실전 예시

# allow_unsupported_distribution_setup 변수 검색
grep -Rn "allow_unsupported_distribution_setup" \
  inventory/mycluster/ playbooks/ roles/ -A1 -B1

출력 예시:

inventory/mycluster/group_vars/all/all.yml-141-## If enabled it will allow kubespray to attempt setup...
inventory/mycluster/group_vars/all/all.yml:142:allow_unsupported_distribution_setup: false
--
roles/kubernetes/preinstall/tasks/0040-verify-settings.yml-22-  assert:
roles/kubernetes/preinstall/tasks/0040-verify-settings.yml:23:    that: (allow_unsupported_distribution_setup | default(false))...
roles/kubernetes/preinstall/tasks/0040-verify-settings.yml-24-    msg: "{{ ansible_distribution }} is not a known OS"

YAML 파일만 검색

# .yml 파일만 검색
grep -Rni "dns_autoscaler" \
  inventory/mycluster/ playbooks/ roles/ \
  --include="*.yml" -A2 -B1

출력 예시:

roles/kubespray_defaults/defaults/main/main.yml:130:# Enable dns autoscaler
roles/kubespray_defaults/defaults/main/main.yml:131:enable_dns_autoscaler: true

특정 디렉터리만 검색

# group_vars만 검색
grep -Rn "kube_version" inventory/mycluster/group_vars/ -A1

# roles의 defaults만 검색
grep -Rn "kube_version" roles/*/defaults/ -A1

실전 변수 설정 예시

예시 1: 네트워크 플러그인 변경

# 1. 현재 설정 확인
grep "kube_network_plugin" inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml

# 2. Calico에서 Flannel로 변경
sed -i 's|kube_network_plugin: calico|kube_network_plugin: flannel|g' \
  inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml

# 3. Flannel 인터페이스 지정
echo "flannel_interface: enp0s9" >> \
  inventory/mycluster/group_vars/k8s_cluster/k8s-net-flannel.yml

예시 2: Metrics Server 활성화

# 1. Metrics Server 활성화
sed -i 's|metrics_server_enabled: false|metrics_server_enabled: true|g' \
  inventory/mycluster/group_vars/k8s_cluster/addons.yml

# 2. 리소스 요청량 설정
cat >> inventory/mycluster/group_vars/k8s_cluster/addons.yml << EOF
metrics_server_requests_cpu: 25m
metrics_server_requests_memory: 16Mi
EOF

예시 3: DNS Autoscaler 비활성화

# 1. 변수 위치 확인
grep -Rni "dns_autoscaler" inventory/mycluster/ roles/

# 2. group_vars에 추가 (defaults보다 우선순위 높음)
echo "enable_dns_autoscaler: false" >> \
  inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml

Kubespray 변수 우선순위 구조도 (Variable Precedence)


Kubespray 설치 후 Control Plane 컴포넌트 구조

Control Plane 컴포넌트 개요

Kubespray로 설치된 Kubernetes 클러스터의 Control Plane은 다음 컴포넌트들로 구성된다:

Control Plane Node
├── kube-apiserver (Static Pod)
├── kube-controller-manager (Static Pod)
├── kube-scheduler (Static Pod)
└── etcd (systemd unit)

kube-apiserver 설정

Manifest 파일 위치

/etc/kubernetes/manifests/kube-apiserver.yaml

주요 설정 확인

ssh k8s-node1 cat /etc/kubernetes/manifests/kube-apiserver.yaml

핵심 설정 항목

spec:
  containers:
  - command:
    - kube-apiserver
    - --advertise-address=192.168.10.11      # 자신의 IP 광고
    - --apiserver-count=3                     # API Server 개수 (HA)
    - --authorization-mode=Node,RBAC          # 인증 모드
    - --bind-address=::                       # IPv6/IPv4 모두 지원
    - --etcd-servers=https://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13:2379

kubeadm 직접 설치와의 차이점

Kubespray:

--etcd-servers=https://192.168.10.11:2379,https://192.168.10.12:2379,https://192.168.10.13:2379

kubeadm 직접 설치:

--etcd-servers=https://127.0.0.1:2379  # 로컬 etcd만 참조

의미:

  • Kubespray는 모든 etcd 노드를 직접 참조한다
  • HA 구성에서 더 명시적이고 안정적이다
  • etcd 장애 시 다른 etcd로 자동 전환 가능

kube-controller-manager 설정

Manifest 파일 확인

ssh k8s-node1 cat /etc/kubernetes/manifests/kube-controller-manager.yaml

주요 설정 항목

spec:
  containers:
  - command:
    - kube-controller-manager
    - --allocate-node-cidrs=true              # 노드별 CIDR 자동 할당
    - --cluster-cidr=10.233.64.0/18           # Pod CIDR 대역
    - --node-cidr-mask-size-ipv4=24           # 노드당 /24 할당
    - --service-cluster-ip-range=10.233.0.0/18  # Service CIDR 대역
    - --bind-address=::                       # IPv6/IPv4 지원
    - --leader-elect=true                     # Leader Election 활성화

Leader Election 확인

kubectl get lease -n kube-system

출력 예시:

NAME                      HOLDER
kube-controller-manager   k8s-node2_5d90d703-85ad-4f58-a413-3f484214c4f1
kube-scheduler            k8s-node2_c3bdf688-9708-4313-8827-a727f2bded21

의미:

  • Controller Manager와 Scheduler는 1대만 Active (Leader)
  • 나머지는 Standby 상태로 대기
  • Leader 노드 장애 시 자동으로 다른 노드가 Leader가 됨

kube-scheduler 설정

Manifest 파일 확인

ssh k8s-node1 cat /etc/kubernetes/manifests/kube-scheduler.yaml

주요 설정 항목

spec:
  containers:
  - command:
    - kube-scheduler
    - --bind-address=::                       # IPv6/IPv4 지원
    - --leader-elect=true                     # Leader Election 활성화

etcd 클러스터 구성

systemd Unit으로 관리

Kubespray는 etcd를 파드가 아닌 systemd unit으로 설치한다.

# etcd 서비스 상태 확인
ssh k8s-node1 systemctl status etcd

etcd 클러스터 멤버 확인

ssh k8s-node1 etcdctl.sh member list -w table

출력 예시:

+------------------+---------+-------+----------------------------+----------------------------+------------+
|        ID        | STATUS  | NAME  |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-------+----------------------------+----------------------------+------------+
|  8b0ca30665374b0 | started | etcd3 | https://192.168.10.13:2380 | https://192.168.10.13:2379 |      false |
| 2106626b12a4099f | started | etcd2 | https://192.168.10.12:2380 | https://192.168.10.12:2379 |      false |
| c6702130d82d740f | started | etcd1 | https://192.168.10.11:2380 | https://192.168.10.11:2379 |      false |
+------------------+---------+-------+----------------------------+----------------------------+------------+

포트 역할:

  • 2380: etcd 클러스터 내부 통신 (Peer)
  • 2379: API Server가 연결하는 포트 (Client)

etcd Leader 확인

for i in {1..3}; do 
  echo ">> k8s-node$i <<"
  ssh k8s-node$i etcdctl.sh endpoint status -w table
  echo
done

출력 예시:

>> k8s-node1 <<
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
|    ENDPOINT    |        ID        | VERSION | DB SIZE | IS LEADER | IS LEARNER | RAFT TERM | RAFT INDEX | RAFT APPLIED INDEX | ERRORS |
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+
| 127.0.0.1:2379 | c6702130d82d740f |  3.5.25 |  8.3 MB |      true |      false |         4 |       2834 |               2834 |        |
+----------------+------------------+---------+---------+-----------+------------+-----------+------------+--------------------+--------+

주요 필드:

  • IS LEADER: true인 노드가 현재 Leader
  • RAFT TERM: Raft 합의 알고리즘의 Term 번호
  • DB SIZE: etcd 데이터베이스 크기

DNS 설정 (Kubespray 특징)

CoreDNS Service 정보

kubectl get svc -n kube-system coredns

출력:

NAME      TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
coredns   ClusterIP   10.233.0.3   <none>        53/UDP,53/TCP,9153/TCP   5h34m

kubeadm 직접 설치와의 차이점

항목kubeadmKubespray
서비스명kube-dnscoredns
ClusterIP10.96.0.10 (Service 대역의 10번째 IP)10.233.0.3 (Service 대역의 3번째 IP)
Service CIDR10.96.0.0/1610.233.0.0/18

kubelet DNS 설정 확인

kubectl get cm -n kube-system kubelet-config -o yaml | grep clusterDNS -A2

출력:

clusterDNS:
- 10.233.0.3
clusterDomain: cluster.local

Pod 내부 /etc/resolv.conf

kubectl exec -it -n kube-system <pod-name> -- cat /etc/resolv.conf

출력 예시:

search kube-system.svc.cluster.local svc.cluster.local cluster.local default.svc.cluster.local
nameserver 10.233.0.3
options ndots:5

호스트 노드의 /etc/resolv.conf

Kubespray는 호스트 노드에서도 Service 도메인을 질의할 수 있도록 /etc/resolv.conf를 자동 설정한다.

ssh k8s-node1 cat /etc/resolv.conf

출력:

# Generated by NetworkManager
search default.svc.cluster.local svc.cluster.local
nameserver 10.233.0.3
nameserver 168.126.63.1
nameserver 8.8.8.8
options ndots:2 timeout:2 attempts:2

주요 특징:

  • search 도메인에 클러스터 도메인이 추가됨
  • nameserver의 최상단에 CoreDNS IP가 추가됨
  • 호스트에서도 curl http://service-name.namespace.svc.cluster.local 가능

클러스터에 Join되지 않은 노드:

ssh k8s-node5 cat /etc/resolv.conf
# Generated by NetworkManager
nameserver 168.126.63.1
nameserver 8.8.8.8

클러스터에 Join되지 않은 노드는 기본 DNS 설정만 있다.


인증서 관리

인증서 만료일 확인

for i in {1..3}; do 
  echo ">> k8s-node$i <<"
  ssh k8s-node$i kubeadm certs check-expiration
  echo
done

출력 예시:

>> k8s-node1 <<
CERTIFICATE                  EXPIRES                  RESIDUAL TIME   CERTIFICATE AUTHORITY
admin.conf                   Jan 28, 2027 08:17 UTC   364d            ca
apiserver                    Jan 28, 2027 08:17 UTC   364d            ca
apiserver-kubelet-client     Jan 28, 2027 08:17 UTC   364d            ca
controller-manager.conf      Jan 28, 2027 08:17 UTC   364d            ca
front-proxy-client           Jan 28, 2027 08:17 UTC   364d            front-proxy-ca
scheduler.conf               Jan 28, 2027 08:17 UTC   364d            ca
super-admin.conf             Jan 28, 2027 08:17 UTC   364d            ca

>> k8s-node2 <<
...
!MISSING! super-admin.conf

>> k8s-node3 <<
...
!MISSING! super-admin.conf

super-admin.conf 특징

  • k8s-node1에만 존재한다
  • 최고 권한을 가진 관리자 kubeconfig 파일
  • 긴급 복구 시 사용

인증서 파일 위치 확인

for i in {1..3}; do 
  echo ">> k8s-node$i <<"
  ssh k8s-node$i ls -l /etc/kubernetes/super-admin.conf
  echo
done

kubeadm-config ConfigMap

ConfigMap 확인

kubectl get cm -n kube-system kubeadm-config -o yaml

주요 내용:

apiVersion: kubeadm.k8s.io/v1beta4
clusterName: cluster.local
controlPlaneEndpoint: 192.168.10.11:6443  # Control Plane 1번 노드

etcd:
  external:  # systemd unit으로 구성 (파드가 아님)
    caFile: /etc/ssl/etcd/ssl/ca.pem
    certFile: /etc/ssl/etcd/ssl/node-k8s-node1.pem
    endpoints:
      - https://192.168.10.11:2379
      - https://192.168.10.12:2379
      - https://192.168.10.13:2379
    keyFile: /etc/ssl/etcd/ssl/node-k8s-node1-key.pem

kubernetesVersion: v1.32.9

networking:
  dnsDomain: cluster.local
  podSubnet: 10.233.64.0/18
  serviceSubnet: 10.233.0.0/18

주요 필드 설명

controlPlaneEndpoint:

  • API Server 엔드포인트 주소
  • 여기서는 k8s-node1을 가리킴
  • HA 구성에서는 LoadBalancer IP를 사용하는 것이 일반적

etcd.external:

  • etcd가 파드가 아닌 외부 클러스터로 구성됨
  • systemd unit으로 실행 중
  • 3개 노드의 엔드포인트를 모두 명시

networking:

  • Pod CIDR: 10.233.64.0/18 (노드당 /24씩 할당)
  • Service CIDR: 10.233.0.0/18
  • DNS 도메인: cluster.local

CSR (Certificate Signing Request)

CSR 목록 확인

kubectl get csr

출력 예시:

NAME        AGE   SIGNERNAME                                    REQUESTOR                 REQUESTEDDURATION   CONDITION
csr-4h74m   20m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:74gawm   <none>              Approved,Issued
csr-7t6rz   21m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:cu2j8d   <none>              Approved,Issued
csr-j6dj7   21m   kubernetes.io/kube-apiserver-client-kubelet   system:node:k8s-node1     <none>              Approved,Issued
csr-mxn26   21m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:d3e4e2   <none>              Approved,Issued

CSR 동작 과정

  1. kubelet 최초 Join 시:

    • kubelet이 부트스트랩 토큰을 사용해 CSR 생성
    • SIGNERNAME: kubernetes.io/kube-apiserver-client-kubelet
  2. kube-apiserver 자동 승인:

    • kube-controller-manager가 CSR을 자동 승인
    • CONDITION: Approved,Issued
  3. 인증서 발급:

    • 승인된 CSR에 대해 인증서 발급
    • kubelet이 이 인증서로 API Server와 통신

kubeadm과의 공통점

Kubespray도 kubeadm과 동일하게 CSR 기반 인증서 발급 메커니즘을 사용한다.


Lease 리소스를 통한 Leader Election

Lease 목록 확인

kubectl get lease -n kube-system

출력 예시:

NAME                                   HOLDER                                                                      AGE
apiserver-3jsrenrspxlfjr2cvxzde6qwdi   apiserver-3jsrenrspxlfjr2cvxzde6qwdi_25f81820-25e1-4e92-b27d-116b9429c353   5h12m
apiserver-syplgv2uz3ssgciixtnxs4xeza   apiserver-syplgv2uz3ssgciixtnxs4xeza_62b92e03-f014-4b16-9de2-b4f82de0f861   5h12m
apiserver-z2kpjb5k5ch6lznxmv3gnpujmy   apiserver-z2kpjb5k5ch6lznxmv3gnpujmy_c6523dd7-2550-462f-80c1-ab8d16a38781   5h12m
kube-controller-manager                k8s-node2_5d90d703-85ad-4f58-a413-3f484214c4f1                              5h12m
kube-scheduler                         k8s-node2_c3bdf688-9708-4313-8827-a727f2bded21                              5h12m

Lease의 역할

API Server:

  • 모든 API Server가 각자 Lease를 가짐
  • 모든 API Server가 Active 상태로 동작
  • 로드밸런서를 통해 요청 분산

Controller Manager:

  • 1대만 Leader로 동작
  • Leader가 실제 작업 수행
  • Leader 장애 시 다른 노드가 Leader가 됨

Scheduler:

  • 1대만 Leader로 동작
  • Leader가 Pod 스케줄링 수행
  • Leader 장애 시 다른 노드가 Leader가 됨

kubeadm 직접 설치와 Kubespray의 주요 차이점 정리

구분kubeadm 직접 설치Kubespray
etcd 설치 방식Static Podsystemd unit
etcd-servers 설정https://127.0.0.1:2379전체 노드 IP 나열
CoreDNS 서비스명kube-dnscoredns
CoreDNS ClusterIP10.96.0.1010.233.0.3
Service CIDR10.96.0.0/1610.233.0.0/18
Pod CIDR10.244.0.0/1610.233.64.0/18
호스트 /etc/resolv.conf수동 설정 필요자동 설정
super-admin.conf모든 Control Plane에 존재k8s-node1에만 존재
설치 자동화수동 명령어 실행Ansible 자동화

핵심 포인트 요약

변수 우선순위

  1. group_vars에서 99% 설정 관리

    • inventory/mycluster/group_vars/k8s_cluster/ 디렉터리
    • 클러스터 전체에 적용되는 공통 설정
  2. host_vars는 특수한 경우만 사용

    • 노드별로 다른 설정이 필요한 경우
    • 예: GPU 노드, 스토리지 전용 노드
  3. -e 옵션은 테스트나 긴급 상황에만

    • 파일에 기록되지 않아 재현성 떨어짐
    • 사용 시 반드시 문서화
  4. 변수 검색은 grep으로

    • grep -Rn "변수명" inventory/ playbooks/ roles/
    • 어디서 정의되고 사용되는지 파악

컴포넌트 구조

  1. etcd는 systemd unit으로 관리

    • 파드가 아님
    • 더 안정적이고 독립적
  2. API Server는 모든 etcd를 참조

    • --etcd-servers에 전체 노드 IP
    • etcd 장애 시 자동 전환
  3. CoreDNS는 10.233.0.3 사용

    • kubeadm과 다른 IP 대역
    • 서비스명도 coredns
  4. 호스트에서도 Service 도메인 질의 가능

    • /etc/resolv.conf 자동 설정
    • 편리한 디버깅과 테스트
  5. Leader Election은 Lease로 관리

    • Controller Manager와 Scheduler는 1대만 Active
    • API Server는 모두 Active

Kubespray 설치 후 Control Plane 컴포넌트 구조

참고 자료

profile
bytebliss

0개의 댓글