Kubernetes 1.23 이상 또는 OCP 4.10 이상을 사용하는 Cluster에서 Pod를 구동하다보면,
Pod Status가 SMTAlignmentError 에러 상태가 되면서 구동하지 못하는 경우를 만난다.
CPU Pinning을 위해 아래처럼 Pod Spec을 설정한 경우에 볼 수 있는 에러이다.
아래 YAML 예시에서 cpu 개수를 5개 설정한 것이 문제를 발생시킨다. (홀수로 설명하는 것이 문제)
kind: Pod
metadata:
name: myapp
spec:
... 중간 생략 ...
containers:
resources:
limits:
cpu: 5 ## 이렇게 홀수인 정수를 설정한 것이 에러를 발생시킴.
... 중간 생략 ...
관련 자료를 찾아보니, 아래 문서가 가장 설명을 잘 해주고 있다.
위 문서의 요지는 이렇다.
X86_64 CPU는 아래 그림처럼 1개의 물리 Core가 2개의 논리 CPU(Thread)로 구성되어 있고, 이 2개의 논리 CPU(Thread)가 1개의 L2 Cache를 공유하기 때문에 만약 홀수 개로 CPU를 Pinning(즉, Isolation)하면, L2 Cache의 Hit Ratio가 확 떨어지기 때문에 Core의 처리 속도가 겁나게 떨어진다는 것이다.
즉, L2 Cache 1개를 두고 LCore-0과 LCore-1이 치고 박고 시끄럽게 싸우는 꼴~~~ X86_64 CPU 구조에는 늘상 발생하는 현상으로써, "noisy neighbors"라고 표현한다.
쉽게 이해하기 위해 일상 생활과 비유해본다면,
2명의 사람이 한 집에 살면서 요리를 하는데
주방이 1개라서 홍길동은 된장찌개(Job-A)를 만들어 먹고 싶고, 이순신은 김밥(Job-B)을 만들어 먹고 싶다면
홍길동이 된장찌개 요리를 마무리하고 주방(L2 Cache)를 비워줘야, 이순신이 그 주방(L2 Cache)에서 김밥을 만들 수 있는 것과 같다.
여기서 핵심은 "주방(L2 Cache)를 비워줘야" 한다에 있다.
Local Thread가 서로 다른 일을 할 경우, L2 Cache에 담을 내용이 서로 다르기 때문에 L2 Cache 메모리에 있는 데이터를 재사용할 수 없고(즉, Hit Ratio가 떨어지고) 실제 L2 Cache는 Cache 로써의 역할을 못하게 된다.
L2 Cache의 내용 싹~~~ 갈아 엎어버리고 다른 CPU Core가 해야 할 일과 관련된 데이터를 복사해야 하니까~~~
이렇기 때문에 비슷한 Job(프로그램, 또는 Process)에 대해서 L2 Cache를 같이 사용하도록 2개씩 쌍으로 할당하는 것이 최고의 성능을 낼 수 있다.
그럴 일은 없겠지만, 만약 논리 쓰레드 3개가 1개의 L2 Cache를 공유하는 CPU 제품이 있다면 3개씩 쌍으로 할당해야 최고의 성능을 낼 수 있다. (이것은 그냥 가정이다)
내 생각에는 처음부터 Intel x86 CPU가 Hyper Threading 구조가 아니였다면, 즉 Logical Core가 L2 Cache Memory를 공유하지 않는 구조였다면 CPU Pinning 설정할 때 짝수로 설정해야 하는 제약도 없었을 것 같다.
##
## Cluter Network 설정 정보 보기
##
$ kubectl get network.config/cluster -o jsonpath='{.status}{"\n"}'
{"clusterNetwork":[{"cidr":"10.128.0.0/14","hostPrefix":23}],"clusterNetworkMTU":1450,"networkType":"OpenShiftSDN","serviceNetwork":["172.30.0.0/16"]}
##
## CNI Network Type 설정 정보 보기
##
$ oc get network.config/cluster -o jsonpath='{.status.networkType}{"\n"}'
OpenShiftSDN
$
아래 Script는 Kuberentes Node의 IP Address를 얻어와서, 이 IP Address로 Node에 SSH 접속하여 'shutdown' 명령을 수행하는 예제이다.
#!/bin/bash
for ip in $(oc get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}')
do
echo "reboot node $ip"
ssh -o StrictHostKeyChecking=no core@$ip sudo shutdown -r -t 3
done
연동할 Registry 주소가 Server 인증서의 SAN(Subject Alt Name) 리스트에 포함되지 않은 경우
연동하려는 Registry 주소가 인증서 발급 시 설정한 SAN(Subject Alternative Name) 리스트에 포함되어 있지 않으면 발생하는 인증 에러이다.
따라서 SAN(Subject Alternative Name) 리스트에 있는 주소 값으로 접속 시도해야 한다.
##
## Certificate(인증서) 만들 때, SAN(Subject Alt Name)에 없는 주소 값을 이용하여
## Container Image Registry에 접근하려고 하면, 아래와 같이 오류가 발생한다.
## 즉, Docker Registry(v2) 또는 Harbor를 구동할 때 사용한 Server Certificate이 있을 텐데,
## 그 Certificate을 만들 때 "Subject Alternative Name" 리스트에 서버의 domain name 주소나 IP Address를
## 입력했었을 것이다.
## 그 입력했던 "Subject Alt Name" 리스트 중에 아래와 같이 Registry에 접속할 때 사용한 Server의 주소 값이 없으면
## "Authenticting creds error"가 발생한다.
##
$ podman login 10.10.12.10:5000
Username: myid
Password: ~~~~~
Error: error authenticating creds for "10.10.12.10:5000": error pinging docker registry 10.10.12.10:5000: Get "https://10.10.12.10:5000/v2/": x509: cannot validate certificate for 10.10.12.10 because it doesn't contain any IP SANs
##
## 인증서의 Subject Alt Name과 동일한 값으로 Registry에 접근하면 문제 없이 접속된다.
## 즉, 아래 예제로 본다면, "my-registry.my-domain"이
## 인증서의 Subject Alt Name인 것이다.
##
$ podman login my-registry.my-domain:5000
Username: myid
Password: ~~~~~
Login Succeeded!
Case (B)
Client OS에 Server Certificate이 등록되지 않은 경우
정확히 표현하면, Podman 명령, Docker 명령을 실행하려는 장비에 Harbor 또는 Docker Registry의 Server Certificate(인증서)가 등록되어 있지 않은 경우에 이런 Unknown Authority 에러가 발생한다.
보통 Self-signed Certificate을 사용한 경우라면, 이 인증 에러가 발생할 것이다.
심각한 에러는 아니고, Podman명령을 수행할 장비(예: Macbook, Ubuntu, Windows 10, Windows 11)에서 아래와 같이 OS에 Self-signed Certificate을 신뢰(Trust)하겠다는 명령만 수행하면 된다.
##
## podman 명령이나 docker 명령을 수행하는 Client OS 쪽에 CA로부터 Sign받은 Server Certificate 이 없는 경우,
## 아래와 같이 인증 에러가 발생한다.
##
$ podman login my-registry.my-domain:5000
Username: myid
Password: ~~~~~
Error: authenticating creds for "my-registry.my-domain:5000":
error pinging docker registry registry.base.twcm.cloud:5000:
Get "https://registry.base.twcm.cloud:5000/v2/": x509:
certificate signed by unknown authority
$
##
## 이럴 때는 CA에게 Sign받은 Certificate을 아래와 같이 Client OS에 복사해주고 등록(Update)하면 된다.
##
## 참고 사항: my-server-domain.crt 파일은 Image Registry를 구동할 때 사용했던 파일이다.
## (즉, my-server-domain.crt는 harbor 구동시 사용한 server certificate이라는 뜻이다)
##
$ cp my-server-domain.crt /etc/pki/ca-trust/source/anchors/my-server-domain.crt
$ update-ca-trust
$ podman login my-registry.my-domain:5000
Username: myid
Password: ~~~~~
Login Succeeded!
$
참고: 위 설명은 CentOS, RHEL을 사용할 때를 예로 든 것이고, Ubuntu OS에서 Server Certificate 등록하는 방법은 아래와 같다.
##
## Ubuntu OS를 사용하는 경우는 아래처럼 update-ca-certificates 명령을 사용해야 한다.
## Ubuntu에서 Certificate을 등록하는 방법은 CentOS, RHEL 8와 다르다.
##
$ cp my-domain.crt /usr/local/share/ca-certificates/domain.crt
$ update-ca-certificates
Updating certificates in /etc/ssl/certs...
rehash: warning: skipping ca-certificates.crt,it does not contain exactly one certificate or CRL
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
done.
$ podman login my-registry.my-domain:5000
Username: myid
Password:
Login Succeeded!
$
##
## Container Image 목록 조회하기
##
$ curl -X GET http://192.168.2.2:5000/v2/_catalog
##
## 특정 Image의 tag list 조회하기
##
$ curl -X GET http://192.168.2.2:5000/v2/almighty/tags/list