LabHub
배우기 러닝패스 코스

Kubernetesディストリビューション — 自分で立てる

k0s.yaml を直して再起動までしたのに何も起きなかった

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

이 실습은 진짜 k0s 에서 돕니다

VM 안에 k0s v1.36.4+k0s.0 한 대(컨트롤러 겸 워커)가 정적 구성으로 떠 있습니다. 설정 파일은 /etc/k0s/k0s.yaml, 작업 디렉터리는 /root/k0scfg 입니다. 처음 뜨는 데 3분 안팎이 걸립니다. 실습 중에 k0s 를 세 번 재시작합니다.

목표

k0s 설정이 어디서 오는지를 모드별로 확인합니다. 정적 구성에서는 파일 변경이 재시작해야 반영되고, 동적 구성에서는 파일 대신 ClusterConfig 오브젝트가 반영된다는 것을 워커 프로필 ConfigMap 으로 보여 줍니다. 헬름 확장을 선언하고 지워서 Chart 오브젝트와 릴리스가 어떻게 따라가는지 기록합니다.

왜 중요한가

k0s 는 파일 하나로 설정한다고 알려져 있어, 동적 구성을 켠 클러스터에서도 사람들이 파일을 고칩니다. 그러면 재시작까지 해도 아무것도 바뀌지 않고, 오류도 나지 않습니다. 반대로 정적 구성에서는 파일을 고친 노드가 재시작되는 날 갑자기 설정이 바뀝니다. 두 경우 모두 "명령이 성공했다" 가 아니라 실제로 무엇이 생겼는지를 봐야 알 수 있습니다.

단계

  1. 기본값과 이 VM 의 설정을 비교해 /root/k0scfg/defaults.yaml/root/k0scfg/defaults.json 에 저장하세요.
  2. k0s sysinfo 결과를 /root/k0scfg/sysinfo.json/root/k0scfg/sysinfo-summary.txt 로 남기세요.
  3. 정적 구성에서 파일에 워커 프로필 edge-small 을 넣고, 재시작 없이 반영되지 않는 것을 /root/k0scfg/static-edit.json 에 기록하세요.
  4. k0s 를 재시작해 프로필 ConfigMap 이 생기는 것을 /root/k0scfg/static-restart.json 에 기록하세요.
  5. 동적 구성으로 바꾸고 ClusterConfig 오브젝트를 /root/k0scfg/dynamic.json 에 기록하세요.
  6. 동적 구성에서 파일에 프로필 from-file 을 넣고 재시작한 결과를 /root/k0scfg/file-ignored.json 에 기록하세요.
  7. ClusterConfig 에 프로필 from-api 를 더해 재시작 없이 반영되는 것을 /root/k0scfg/api-patch.json 에 기록하세요.
  8. ClusterConfig 에 podinfo 차트를 선언하고 /root/k0scfg/helm.json 을 쓰세요.
  9. 차트 선언을 지운 결과를 /root/k0scfg/removal.json 에, 정리를 /root/k0scfg/report.md 에 쓰세요.

참고

적지 않은 값은 무엇이 되나

k0s config create 출력을 /root/k0scfg/defaults.yaml 에 저장하고, /root/k0scfg/defaults.jsondefault_pod_cidr, default_service_cidr, default_storage_type, default_telemetry, file_pod_cidr, file_service_cidr, file_telemetry, apiserver_service_cidr, reason(대역을 바꾼 이유, 30자 이상) 키를 적으세요.

기본값은 설치된 바이너리가 알려 줍니다. 파일 값은 /etc/k0s/k0s.yaml 에, 실제 API 서버가 쓰는 서비스 대역은 kube-apiserver 프로세스 인자의 service-cluster-ip-range 에 있습니다. 이 VM 이 어디서 도는지 생각하면 대역을 바꾼 이유가 나옵니다.

설치 전 점검을 읽는다

k0s sysinfo -o json 결과를 /root/k0scfg/sysinfo.json 에 저장하고, /root/k0scfg/sysinfo-summary.txttotal=<항목 수>, 결과 분류마다 <분류>=<수>(예: pass=), cgroups=<Control Groups 항목의 값> 줄과, pass 가 아닌 항목마다 not_pass=<displayName> 줄을 쓰세요.

JSON 은 항목의 배열이고 각 항목에 category·displayName·prop 이 있습니다. 분류별로 세고, pass 가 아닌 것의 이름을 옮기세요. 채점기는 sysinfo 를 다시 돌려 같은 수가 나오는지 봅니다.

파일을 고쳤는데 아무 일도 없다

/etc/k0s/k0s.yaml 의 spec 에 워커 프로필 edge-small(maxPods: 40)을 넣고 k0s config validate 로 확인한 뒤, 재시작하지 않고 30초 이상 기다려 /root/k0scfg/static-edit.jsonprofile, configmap(생겨야 할 ConfigMap 이름), configmap_present, k0s_pid(k0scontroller 서비스의 MainPID) 키를 적으세요.

워커 프로필은 spec.workerProfiles 목록의 name·values 입니다. k0s 가 파일을 감시한다면 기다리는 동안 kube-system 에 ConfigMap 이 생겨야 합니다. PID 는 나중에 '그 뒤에 재시작이 있었는가' 를 대조하는 값이니 systemctl 에서 읽으세요.

재시작하자 생겼다

k0s 를 재시작하고 edge-small ConfigMap 이 생기면 /root/k0scfg/static-restart.jsonconfigmap, configmap_uid, max_pods(ConfigMap 의 kubeletConfiguration 에서 읽은 값), k0s_pid_before, k0s_pid_after 키를 적으세요.

재시작은 k0s stop·start 입니다. API 가 돌아온 뒤 ConfigMap 이 생길 때까지 잠깐 기다리세요. kubeletConfiguration 은 ConfigMap 데이터 안의 JSON 문자열입니다. 재시작 전 PID 는 3단계 기록에 있습니다.

진실의 원천을 API 로 옮긴다

k0scontroller 서비스를 --enable-dynamic-config 를 더해 다시 설치하고 시작한 뒤, /root/k0scfg/dynamic.jsonclusterconfig_uid, object_has_edge_small, object_service_cidr(오브젝트의 spec.network.serviceCIDR), apiserver_service_cidr(실제 API 서버 인자) 키를 적으세요.

이미 설치된 서비스는 k0s install controller 를 그냥 다시 치면 거절됩니다. 원래 인자를 모두 유지해야 워커가 사라지지 않습니다. 동적 구성이 켜지면 kube-system 에 clusterconfig 리소스가 생깁니다. 오브젝트의 서비스 대역과 실제 값을 따로 읽어 비교하세요.

이번에는 재시작해도 무시된다

동적 구성에서 /etc/k0s/k0s.yaml 의 워커 프로필 목록에 from-file(maxPods: 30)을 더하고 k0s 를 재시작한 뒤 20초 이상 기다려, /root/k0scfg/file-ignored.jsonprofile, generation_before, generation_after(ClusterConfig 의 metadata.generation), object_has_profile, configmap_present 키를 적으세요.

정적 구성이었다면 재시작으로 반영됐을 변경입니다. 동적 구성에서 파일이 무엇에 쓰이는지 이론 글의 '클러스터 설정과 노드 설정' 절을 보세요. generation 은 오브젝트의 spec 이 바뀔 때마다 오릅니다.

오브젝트를 고치면 바로 반영된다

재시작하지 않고 ClusterConfig 의 워커 프로필 목록에 from-api(maxPods: 60)를 기존 프로필을 지우지 않고 더한 뒤, ConfigMap 이 생기면 /root/k0scfg/api-patch.jsonprofile, configmap_uid, max_pods, controller_started_at(k0scontroller 서비스가 마지막으로 시작된 시각, 유닉스 초) 키를 적으세요.

merge patch 는 목록 필드를 통째로 바꿉니다. 목록 끝에 하나를 더하는 방법은 JSON patch 에 있습니다. 서비스 시작 시각은 systemctl 의 ActiveEnterTimestamp 를 date 로 바꾸면 됩니다. 채점기는 ConfigMap 이 그 시각보다 뒤에 생겼는지 봅니다.

선언한 차트가 Chart 오브젝트가 된다

ClusterConfig 의 spec.extensions.helm 에 저장소 podinfo(https://stefanprodan.github.io/podinfo)와 차트 podinfo(chartname podinfo/podinfo, version 6.14.1, namespace podinfo)를 선언하고, 배포가 준비되면 /root/k0scfg/helm.jsonchart_object(생긴 Chart 이름), chart_uid, chart_version(Chart status 의 version), namespace_uid(podinfo 네임스페이스 UID) 키를 적으세요.

k0s 는 선언을 kube-system 의 Chart 오브젝트로 바꿉니다. 그 이름 규칙은 kubectl get charts 로 확인하세요. 차트 설치가 끝나면 Chart 의 status 에 판이 채워집니다. 네임스페이스 UID 는 다음 단계에서 '무엇이 남는가' 를 대조하는 값입니다.

선언을 지우면 무엇이 남나

ClusterConfig 에서 podinfo 차트 선언만 지우고, /root/k0scfg/removal.jsonremoved_chart_uid, chart_object_present, release_secrets(podinfo 네임스페이스의 헬름 릴리스 시크릿 수), namespace_kept 키를 적으세요. 그리고 /root/k0scfg/report.mdstatic_restart_needed=, dynamic_file_applied=, dynamic_object_applied=(셋 다 yes/no), object_service_cidr=, apiserver_service_cidr= 다섯 줄과 설명 150자 이상을 쓰세요.

차트 목록만 지우고 저장소 선언은 둬도 됩니다. Chart 오브젝트가 사라지는 데 몇 초 걸립니다. 헬름 릴리스 시크릿은 owner=helm 라벨로 찾을 수 있습니다. 설명에는 어느 모드에서 무엇이 진실의 원천이었는지, 오브젝트의 서비스 대역을 믿어도 되는지를 넣으세요.