Kubernetes Distributions — Build Them Yourself
A k3s with the certification logo failed a conformance test
한국어 원문으로 표시합니다.
목표
판을 고정한 k3s 에서 쿠버네티스 공식 적합성 시험을 실제로 몇 개 골라 돌리고, JUnit 결과를 읽어 통과·실패·시간 초과를 구분합니다. 적합성 시험이 무엇을 확인하고 무엇을 확인하지 않는지를 결과로 설명할 수 있게 됩니다.
왜 중요한가
배포판을 고를 때 "Certified Kubernetes" 로고는 강한 신호처럼 보입니다. 하지만 그 인증은 GA 이면서 필수인 API 와 동작이 업스트림과 같다는 것을 시험 모음 하나로 확인한 결과이고, 시험에는 노드 두 대 이상 같은 전제가 있습니다. 성능·가용성·보안 설정·선택 기능은 범위 밖입니다. 로고를 올바르게 읽으려면 시험이 무엇으로 이루어져 있고 실패가 어떤 모양으로 기록되는지 직접 봐야 합니다. 또 시험 바이너리와 서버의 판이 어긋나면 결과 자체가 무의미해지므로, 판을 맞추는 일부터 시작합니다. 마지막으로 일부러 DNS 를 망가뜨려 같은 시험이 떨어지고 복구 뒤 다시 통과하는 것을 보면, 적합성 시험을 "복구 확인 도구" 로도 쓸 수 있다는 것을 알게 됩니다.
단계
/root/conformance/versions.json에server(API 서버 gitVersion),server_minor(1.36형식),e2e_test(e2e.test --version출력),ginkgo(ginkgo version의 판 번호만, 예2.0.0),same_minor(서버와 e2e.test 의 마이너 판이 같은지, 불리언)를 적으세요./usr/local/conformance/conformance.yaml(v1.36.4 태그의 목록)을 읽어/root/conformance/catalog.json에total(항목 수),sig_network(codename 이[sig-network]로 시작하는 항목 수),dns_tests(codename 이[sig-network] DNS로 시작하는 codename 을 정렬한 배열),dns_cluster_release([sig-network] DNS should provide DNS for the cluster [Conformance]의 release 값)를 적으세요.e2e.test를--ginkgo.dry-run으로 두 번 실행해/root/conformance/dryrun.json에conformance_will_run(focus\[Conformance\]일 때 실행될 spec 수),total_specs(전체 spec 수),dns_will_run(focus\[sig-network\] DNS.*\[Conformance\]일 때 실행될 수),matches_catalog(conformance_will_run 이 2단계 total 과 같은지, 불리언)를 적으세요.[sig-network] DNS should provide DNS for the cluster [Conformance]하나만 focus 로 실행해 JUnit 결과를/root/conformance/dns-pass/junit_01.xml에(--report-dir), 표준 출력·오류를/root/conformance/dns-pass/e2e.log에 남기세요. 통과해야 합니다.[sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance]를 실행해 결과를/root/conformance/two-nodes/junit_01.xml·/root/conformance/two-nodes/e2e.log에 남기고,/root/conformance/two-nodes.json에status(JUnit 의 그 testcase status),reason(e2e.log 의[FAILED]줄 가운데 소스 위치(in [It] - ...)가 아니라 이유 문장이 적힌 줄의 문장),schedulable_nodes(지금 테인트 없는 Ready 노드 수, 숫자)를 적으세요.- kube-system 의 coredns Deployment 를 0 으로 줄이고 파드가 사라진 것을 확인한 뒤, 4단계와 같은 DNS 시험을
--ginkgo.timeout=45s로 실행해/root/conformance/dns-broken/junit_01.xml·/root/conformance/dns-broken/e2e.log에 남기세요./root/conformance/broken.json에coredns_replicas(실행 직전 spec.replicas),coredns_pods(실행 직전 CoreDNS 파드 수),status(JUnit 의 그 testcase status)를 적습니다. 복구는 다음 단계에서 합니다. - coredns 를 1 로 되돌려 Available 이 되게 한 뒤, 같은 DNS 시험을 다시 실행해
/root/conformance/dns-restored/junit_01.xml·/root/conformance/dns-restored/e2e.log에 남기세요. 통과해야 합니다. /root/conformance/report.json에server(서버 gitVersion),catalog_total(2단계 total),passed(4·7단계에서 통과한 testcase 이름을[It]없이 중복 없이 정렬한 배열),failed_single_node(5단계에서 떨어진 시험 codename),timed_out_when_broken(6단계 결과가 시간 초과였는지, 불리언),submission_files(CNCF 인증 PR 에 넣는 파일 이름 네 개를 정렬한 배열),certified_focus(인증 실행에 요구되는 E2E_FOCUS 값 그대로),skip_allowed(인증 실행에서 E2E_SKIP 을 줄 수 있는지, 불리언)를 적으세요.
참고
- VM 안에 k3s v1.36.4+k3s1 한 대와 같은 판의
e2e.test·ginkgo·conformance.yaml이/usr/local/conformance에 있습니다. 시험 이미지는 미리 받아 두었습니다. - 기본 실행 형태:
e2e.test --kubeconfig $KUBECONFIG --provider skeleton --ginkgo.no-color --report-dir <디렉터리> --ginkgo.focus='<정규식>' - 흔한 실수: focus 의 대괄호를 이스케이프하지 않는 것. 정규식의 문자 집합으로 해석되어 엉뚱한 시험이 수백 개 골라집니다. 먼저
--ginkgo.dry-run으로 개수를 확인하세요. - 흔한 실수: 6단계를 시간 제한 없이 실행하는 것. DNS 결과를 600초 기다립니다.
- 전체 적합성 실행(446개)은 이 실습에서 하지 않습니다. k3s 의 인증 제출은 두 대 구성에서 약 2시간 54분이 걸렸습니다.
- 문서: cncf/k8s-conformance · instructions.md · Conformance Testing in Kubernetes
시험 바이너리와 서버의 판을 맞춘다
/root/conformance/versions.json 에 server(API 서버 gitVersion), server_minor(1.36 형식), e2e_test(e2e.test --version 출력), ginkgo(ginkgo version 의 판 번호만, 예 2.0.0), same_minor(서버와 e2e.test 의 마이너 판이 같은지, 불리언)를 적으세요.
시험 바이너리는 /usr/local/conformance 에 있습니다. k3s 판에는 +k3s1 같은 꼬리표가 붙습니다. 적합성 시험은 판마다 목록이 달라지므로, 클러스터 판과 같은 릴리스 브랜치에서 만든 시험을 써야 결과가 의미를 가집니다.
적합성 시험 목록을 읽는다
/usr/local/conformance/conformance.yaml(v1.36.4 태그의 목록)을 읽어 /root/conformance/catalog.json 에 total(항목 수), sig_network(codename 이 [sig-network] 로 시작하는 항목 수), dns_tests(codename 이 [sig-network] DNS 로 시작하는 codename 을 정렬한 배열), dns_cluster_release([sig-network] DNS should provide DNS for the cluster [Conformance] 의 release 값)를 적으세요.
YAML 이라 codename 이 여러 줄로 접혀 있는 항목이 있습니다. grep 으로 줄을 세면 틀리므로 python3 의 yaml 모듈로 읽으세요. 항목마다 testname·codename·description·release·file 키가 있습니다. release 는 그 시험이 적합성에 들어간 판입니다.
돌리기 전에 범위를 센다
e2e.test 를 --ginkgo.dry-run 으로 두 번 실행해 /root/conformance/dryrun.json 에 conformance_will_run(focus \[Conformance\] 일 때 실행될 spec 수), total_specs(전체 spec 수), dns_will_run(focus \[sig-network\] DNS.*\[Conformance\] 일 때 실행될 수), matches_catalog(conformance_will_run 이 2단계 total 과 같은지, 불리언)를 적으세요.
dry-run 은 클러스터에 아무것도 만들지 않고 어떤 spec 이 골라지는지만 보여 줍니다. 출력의 Will run N of M specs 줄을 읽습니다. --ginkgo.no-color 를 주면 색 코드가 섞이지 않습니다.
적합성 시험 하나를 진짜로 돌린다
[sig-network] DNS should provide DNS for the cluster [Conformance] 하나만 focus 로 실행해 JUnit 결과를 /root/conformance/dns-pass/junit_01.xml 에(--report-dir), 표준 출력·오류를 /root/conformance/dns-pass/e2e.log 에 남기세요. 통과해야 합니다.
focus 는 정규식이라 대괄호를 이스케이프해야 합니다. 이름 일부만 쓰면 비슷한 이름의 시험이 함께 골라질 수 있으니 dry-run 으로 1개인지 먼저 확인하세요. JUnit 에는 건너뛴 spec 도 skipped 로 전부 들어갑니다.
한 대짜리 클러스터가 떨어지는 적합성 시험
[sig-architecture] Conformance Tests should have at least two untainted nodes [Conformance] 를 실행해 결과를 /root/conformance/two-nodes/junit_01.xml·/root/conformance/two-nodes/e2e.log 에 남기고, /root/conformance/two-nodes.json 에 status(JUnit 의 그 testcase status), reason(e2e.log 의 [FAILED] 줄 가운데 소스 위치(in [It] - ...)가 아니라 이유 문장이 적힌 줄의 문장), schedulable_nodes(지금 테인트 없는 Ready 노드 수, 숫자)를 적으세요.
이 시험은 실패하는 것이 정상입니다. 적합성 제출에서 k3s 가 어떤 구성으로 시험을 돌렸는지(cncf/k8s-conformance 의 README)와 비교해 보세요. JUnit 에서 failure 자식 요소와 status 속성을 함께 봅니다.
CoreDNS 를 줄이고 같은 시험을 돌린다
kube-system 의 coredns Deployment 를 0 으로 줄이고 파드가 사라진 것을 확인한 뒤, 4단계와 같은 DNS 시험을 --ginkgo.timeout=45s 로 실행해 /root/conformance/dns-broken/junit_01.xml·/root/conformance/dns-broken/e2e.log 에 남기세요. /root/conformance/broken.json 에 coredns_replicas(실행 직전 spec.replicas), coredns_pods(실행 직전 CoreDNS 파드 수), status(JUnit 의 그 testcase status)를 적습니다. 복구는 다음 단계에서 합니다.
이 시험은 DNS 조회 결과를 600초 동안 기다리므로 시간 제한 없이 돌리면 10분을 멈춰 있습니다. 스위트 제한이 끝나면 ginkgo 는 실패가 아니라 시간 초과로 기록합니다. e2e.log 에서 어떤 이름의 조회가 실패했는지 찾아보세요.
되돌리고 같은 시험으로 증명한다
coredns 를 1 로 되돌려 Available 이 되게 한 뒤, 같은 DNS 시험을 다시 실행해 /root/conformance/dns-restored/junit_01.xml·/root/conformance/dns-restored/e2e.log 에 남기세요. 통과해야 합니다.
복구를 확인하는 가장 확실한 방법은 망가뜨렸을 때 떨어진 바로 그 시험을 다시 통과시키는 것입니다. 앞 실행의 네임스페이스가 Terminating 으로 남아 있어도 시험은 새 네임스페이스를 만듭니다.
결과를 적합성의 말로 해석한다
/root/conformance/report.json 에 server(서버 gitVersion), catalog_total(2단계 total), passed(4·7단계에서 통과한 testcase 이름을 [It] 없이 중복 없이 정렬한 배열), failed_single_node(5단계에서 떨어진 시험 codename), timed_out_when_broken(6단계 결과가 시간 초과였는지, 불리언), submission_files(CNCF 인증 PR 에 넣는 파일 이름 네 개를 정렬한 배열), certified_focus(인증 실행에 요구되는 E2E_FOCUS 값 그대로), skip_allowed(인증 실행에서 E2E_SKIP 을 줄 수 있는지, 불리언)를 적으세요.
앞 단계의 JUnit 파일에서 이름과 상태를 다시 읽으세요. 제출 파일과 focus·skip 규칙은 cncf/k8s-conformance 의 instructions.md 에 있습니다.