
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) │
└─────────────────────────────────────────────┘
위치: roles/*/defaults/main.yml
설명: Kubespray Role의 기본값이 정의되어 있다. 가장 낮은 우선순위를 가지며, 다른 모든 설정에 의해 Override될 수 있다.
예시:
# roles/kubespray_defaults/defaults/main/main.yml
bin_dir: /usr/local/bin
kube_version: v1.29.0
특징:
위치:
inventory/mycluster/group_vars/all/*.ymlinventory/mycluster/group_vars/k8s_cluster/*.ymlinventory/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 설치 여부위치: 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"
언제 사용하는가:
위치: playbooks/*.yml의 vars: 섹션
설명: 특정 플레이북 실행 시에만 적용되는 변수. 플레이북 내부에서 임시로 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보다 우선순위가 높음위치: 명령줄 옵션 --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"
언제 사용하는가:
주의사항:
특정 변수가 어디에 정의되어 있고, 어떻게 사용되는지 찾으려면 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"
# .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. 현재 설정 확인
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
# 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
# 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로 설치된 Kubernetes 클러스터의 Control Plane은 다음 컴포넌트들로 구성된다:
Control Plane Node
├── kube-apiserver (Static Pod)
├── kube-controller-manager (Static Pod)
├── kube-scheduler (Static Pod)
└── etcd (systemd unit)
/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
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만 참조
의미:
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 활성화
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
의미:
ssh k8s-node1 cat /etc/kubernetes/manifests/kube-scheduler.yaml
spec:
containers:
- command:
- kube-scheduler
- --bind-address=:: # IPv6/IPv4 지원
- --leader-elect=true # Leader Election 활성화
Kubespray는 etcd를 파드가 아닌 systemd unit으로 설치한다.
# etcd 서비스 상태 확인
ssh k8s-node1 systemctl status 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 |
+------------------+---------+-------+----------------------------+----------------------------+------------+
포트 역할:
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인 노드가 현재 LeaderRAFT TERM: Raft 합의 알고리즘의 Term 번호DB SIZE: etcd 데이터베이스 크기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 | Kubespray |
|---|---|---|
| 서비스명 | kube-dns | coredns |
| ClusterIP | 10.96.0.10 (Service 대역의 10번째 IP) | 10.233.0.3 (Service 대역의 3번째 IP) |
| Service CIDR | 10.96.0.0/16 | 10.233.0.0/18 |
kubectl get cm -n kube-system kubelet-config -o yaml | grep clusterDNS -A2
출력:
clusterDNS:
- 10.233.0.3
clusterDomain: cluster.local
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
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
for i in {1..3}; do
echo ">> k8s-node$i <<"
ssh k8s-node$i ls -l /etc/kubernetes/super-admin.conf
echo
done
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:
k8s-node1을 가리킴etcd.external:
networking:
10.233.64.0/18 (노드당 /24씩 할당)10.233.0.0/18cluster.localkubectl 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
kubelet 최초 Join 시:
SIGNERNAME: kubernetes.io/kube-apiserver-client-kubeletkube-apiserver 자동 승인:
CONDITION: Approved,Issued인증서 발급:
Kubespray도 kubeadm과 동일하게 CSR 기반 인증서 발급 메커니즘을 사용한다.
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
API Server:
Controller Manager:
Scheduler:
| 구분 | kubeadm 직접 설치 | Kubespray |
|---|---|---|
| etcd 설치 방식 | Static Pod | systemd unit |
| etcd-servers 설정 | https://127.0.0.1:2379 | 전체 노드 IP 나열 |
| CoreDNS 서비스명 | kube-dns | coredns |
| CoreDNS ClusterIP | 10.96.0.10 | 10.233.0.3 |
| Service CIDR | 10.96.0.0/16 | 10.233.0.0/18 |
| Pod CIDR | 10.244.0.0/16 | 10.233.64.0/18 |
| 호스트 /etc/resolv.conf | 수동 설정 필요 | 자동 설정 |
| super-admin.conf | 모든 Control Plane에 존재 | k8s-node1에만 존재 |
| 설치 자동화 | 수동 명령어 실행 | Ansible 자동화 |
group_vars에서 99% 설정 관리
inventory/mycluster/group_vars/k8s_cluster/ 디렉터리host_vars는 특수한 경우만 사용
-e 옵션은 테스트나 긴급 상황에만
변수 검색은 grep으로
grep -Rn "변수명" inventory/ playbooks/ roles/etcd는 systemd unit으로 관리
API Server는 모든 etcd를 참조
--etcd-servers에 전체 노드 IPCoreDNS는 10.233.0.3 사용
coredns호스트에서도 Service 도메인 질의 가능
/etc/resolv.conf 자동 설정Leader Election은 Lease로 관리
