Skip to content

Instantly share code, notes, and snippets.

@kujyp
Created March 29, 2023 08:00
Show Gist options
  • Save kujyp/7639edc9e422130dfa5f3df62454bf7e to your computer and use it in GitHub Desktop.
Save kujyp/7639edc9e422130dfa5f3df62454bf7e to your computer and use it in GitHub Desktop.
유석 학생 질문 답변 2023-03-29

일반적으로 쿠버네티스에서 최소한의 HA를 보장하기 위한 조건이 마스터 노드 3개, 워커 노드 2개라고 하는데, 마스터 노드가 왜 3개 이상이어야 하는지가 궁금합니다 마스터 노드가 etcd 역할을 수행할 때 데이터베이스의 최소한의 무결성을 보장하기 위한 노드의 수가 3개라는데 무결성을 보장하는 방법이 디스크를 RAID5로 묶는 것과 비슷한 방식인가요? 아니면 RAID1처럼 모든 노드에 동일한 데이터를 분배하는 방식인가요? 만약 이 방식이 맞다면 굳이 2개가 아닌 3개 이상이 최소한의 HA 보장 조건인 이유가 무엇인가요? 최소한의 마스터 노드의 개수가 3개인 것은 etcd에 대한 요구사항이고, control plane과는 전혀 관련이 없는건가요? 그리고 etcd가 무결성을 보장하기 위해 RAFT 알고리즘을 통해 투표로 리더를 선출한다고 하는데, 이 과정은 관리자가 직접 지정하지 않아도 프로그램들이 현재 상태를 참고하여 필요할 때마다 실행하는 방식인가요? 투표로 리더를 선출하기 전에는 명확한 리더가 없는 상태인 것 같은데, 이러한 상태는 leader 노드가 터져야만 발생하는 현상인가요? 마지막으로, mariadb galera 클러스터는 전체 노드를 마스터로써 취급한다고 하는데, etcd에서 이 방식을 사용하지 않는 이유는 효율성을 위해서인가요? 아니면 위에서 말한 리더 중심의 무결성 보장 방식이 더 안정적이기 때문인가요?

@uaysk
Copy link

uaysk commented Apr 28, 2023

(재등록)

(답글 못 읽어서 죄송합니다 시험기간이라 확인할 생각을 못했어요...)

안녕하세요 저 저번에 선생님깨서 진행하셨던 AI 캠프에서 선생님께 질문했던 학생인데, kubeadm으로 구성한 쿠버네티스 클러스터에 살짝 이상한 점이 있어서 질문 드립니다
컨테이너 런타임으로 cri-o를 사용한 상태에서 manifest 파일을 적용시킬 때 이미지 이름 앞에 docker.io/ 를 붙이지 않으면 제대로 이미지를 pull 하지 못하는데 cri-o를 사용하면 이게 정상인가요? crictl pull을 사용했을 때도 nginx 이미지를 받는다고 하면 crictl pull nginx가 아니라 crictl pull docker.io/nginx 를 실행해야 제대로 pull이 되더고요

아래는 crictl pull로 이미지 이름 앞에 docker.io/ 를 안 붙였을 때랑, manifest 파일에서 이미지 이름을 수정 안 했을 때 발생하는 에러입니다

FATA[0000] pulling image: rpc error: code = Unknown desc = short-name "nginx" did not resolve to an alias and no containers-registries.conf(5) was found

에러 코드에 나온 설명처럼 /etc/containers/containers-registries.conf 에 아래 내용을 추가해봤는데도 계속 같은 에러가 발생했습니다

[registries.search]
registries = ['docker.io']

혹시 더 정확한 정보가 필요하시면 그냥 서버에 직접 접속하셔서 확인해보셔도 돼요, 제가 선생님께서 정확히 뭘 알려달라고 하시는지 못 알아들을 수도 있을 것 같아서요

teleport.uaysk.com

마스터 노드 이름은 ubuntu-rpi 고 connect 누르신 다음 uaysk 선택하시면 로그인 될거에요

@kujyp
Copy link
Author

kujyp commented Apr 28, 2023

아 로그보니까
22시 33분(9분전)에 리스타트해서 설정바꿨네 ㅋ

Apr 28 22:33:09 ubuntu-rpi systemd[1]: Started Container Runtime Interface for OCI (CRI-O).
Apr 28 22:33:11 ubuntu-rpi crio[3919987]: time="2023-04-28 22:33:11.796884806+09:00" level=info msg="Pulling image: nginx" id=cdeb61f3-03ef-4a07-9450-f77ca0d5fb95 name=/runtime.v1.ImageService/PullImage
Apr 28 22:33:11 ubuntu-rpi crio[3919987]: time="2023-04-28 22:33:11.800606518+09:00" level=info msg="Resolving "nginx" using unqualified-search registries (/etc/containers/registries.conf)"
Apr 28 22:33:11 ubuntu-rpi crio[3919987]: time="2023-04-28 22:33:11.810532812+09:00" level=info msg="Trying to access "docker.io/library/nginx:latest""
Apr 28 22:33:13 ubuntu-rpi crio[3919987]: time="2023-04-28 22:33:13.880

@kujyp
Copy link
Author

kujyp commented Apr 28, 2023

https://gist.github.com/kujyp/7639edc9e422130dfa5f3df62454bf7e?permalink_comment_id=4551876#gistcomment-4551876
이런식으로 답변을 남긴것은
실무에서도 결국은 이런식으로 공식문서 찾아가서 보면서 해결해요.(문서에도 안써있으면 코드 직접 들여다봄.)
디테일은 중간에 cri-o 1.27 버전의 문서까지 찾아가죠? 이런것도 버전별로 문서가 다르니 확인해야함.

결국은 나도 모르는상태로 찾아가는과정을 적은거라서
답을 알아가는 과정을 알면
앞으로 뭘 쓰던간에(containerd 를 쓰던 crio 를 쓰던) 원하는 정보는 찾을수있게됨.

@uaysk
Copy link

uaysk commented Apr 28, 2023

https://gist.github.com/kujyp/7639edc9e422130dfa5f3df62454bf7e?permalink_comment_id=4551876#gistcomment-4551876 이런식으로 답변을 남긴것은 실무에서도 결국은 이런식으로 공식문서 찾아가서 보면서 해결해요.(문서에도 안써있으면 코드 직접 들여다봄.) 디테일은 중간에 cri-o 1.27 버전의 문서까지 찾아가죠? 이런것도 버전별로 문서가 다르니 확인해야함.

결국은 나도 모르는상태로 찾아가는과정을 적은거라서 답을 알아가는 과정을 알면 앞으로 뭘 쓰던간에(containerd 를 쓰던 crio 를 쓰던) 원하는 정보는 찾을수있게됨.

구버전 문서에는 crio.conf 파일을 수정하라고 되있었는데 지금 보니까 crio.conf 파일 자체에도 이 파일을 수정해서 registry 추가하는건 더이상 유효하지 않다고 써져있었네요ㅋㅋㅋㅋ
지금까지 공식 문서 볼 때 버전 다른건 신경을 딱히 안썼는데 버전이 진짜 중요한거였네요

@uaysk
Copy link

uaysk commented May 13, 2023

혹시 galera 클러스터를 각 노드가 다른 네트워크에 있는 상태로 구성해보신 적 있으신가요? 지금 2개의 노드로 구성된 galera 클러스터가 홈 네트워크에서 작동하는 중인데, 여기에 오라클 클라우드에서 작동하고 있는 인스턴스를 추가하고 싶습니다
찾아보니 단순 포트포워딩보다는 vpn 터널링 같은 방법을 권장하던데, 이렇게 하면 서버의 인터넷 지연 시간이나 속도가 전체적으로 느려질 것 같아서 mariadb만 따로 분리해서 터널링을 시키고 싶습니다
근데 이렇게 터널링을 하고 나면 mariadb에 접속을 할 때 mariadb에 바로 접속을 못하고, 터널링된 서버를 통해서 접근을 해야 하는 것 같은데 터널링을 한 상태에서도 mariadb가 설치된 서버에서 직접 mariadb에 접속을 할 수 있는 방법이 있을까요?(localhost:3306 이런 방식으로) 그리고 vpn 터널링이 외부 네트워크에 있는 노드를 galera 클러스터에 추가하는 최적의 방법일까요?

@kujyp
Copy link
Author

kujyp commented May 14, 2023

혹시 galera 클러스터를 각 노드가 다른 네트워크에 있는 상태로 구성해보신 적 있으신가요?

galera 클러스터라는 단어도 첨봐요

@kujyp
Copy link
Author

kujyp commented May 14, 2023

노드가 다른 네트워크에 있는 상태로

이걸 구상하는 이유가 뭐죠.
galera 검색해보니까 필요할 순간이 거의없을거같은데?

단순 포트포워딩보다는 vpn 터널링 같은 방법을 권장하던데 이렇게 하면 서버의 인터넷 지연 시간이나 속도가 전체적으로 느려질 것 같아서 mariadb만 따로 분리해서 터널링을 시키고 싶습니다

성능 벤치마크 결과가 있나요?
없으면 실험 설계해서 속도 실험해보기 추천.
그럴려면 둘다 구성할줄알아야하겟네요.

근데 이렇게 터널링을 하고 나면 mariadb에 접속을 할 때 mariadb에 바로 접속을 못하고

터널링 = A서버의 B 포트 -> C서버의 D포트로 연결
일텐데
접속포트를 접근가능한 C서버 D포트로 터널링하면 되는거 아님?

mariadb가 설치된 서버에서 직접 mariadb에 접속을 할 수 있는 방법이 있을까요?(localhost:3306 이런 방식으로

이거 보니까 maridadb 가 설치된 서버 <- 이게 뭐임? galera cluster 에서 노드1?

mariadb가 설치된 서버에서 직접 mariadb에 접속을 할 수 있는 방법이 있을까요?(localhost:3306 이런 방식으로

mariadb 가 설치된서버의 포트에
galera cluster 접속포트를
터널링해주면되겟죠?

그리고 vpn 터널링이 외부 네트워크에 있는 노드를 galera 클러스터에 추가하는 최적의 방법일까요?

글쎄요 나는 이 구성자체의 필요성도 납득이안가서 잘 모르겠네요.
필요성이 일단 정의가 확실해야 최적의 방법을 고를수있어요.

애초에 이 모든것의 목적이뭔가요.
"galera cluster 체험해보기" 로 잡는다면
질문주신 최적의 방법자체는 존재하지않아요.

체험헤보기의 최적의 방법은
"공부"로 남는게 많은 방법이 최적의 방법.

근데 나라면 안함.

@uaysk
Copy link

uaysk commented May 25, 2023

netdata라는 서버 모니터링 서비스를 이용중이고, 모니터링 에이전트를 helm으로 쿠버네티스에 설치했는데 k8s-state와 k8s-parents에서 오류가 발생해서 확인해보니 persistent volume 관련 에러였습니다, 지금 상태가 persistent volume claim만 설치된 상태이고 persistent volume은 생성이 되지 않은 상태인 것 같은데 kubeadm으로 쿠버네티스를 설치하면 csi 드라이버라는걸 설치해줘야 persistent volume을 사용할 수 있는건가요?
구글에 검색도 해보고 공식 문서도 찾아봤는데 kubernetes.io 의 퍼시스턴트 볼륨 문서에는 csi 드라이버 관련 언급이 거의 없었어요

그리고 galera 클러스터는 말씀하신 것 처럼 애초에 다른 네트워크망에 있는 노드들끼리 묶어놓으라고 만든건 아니었던 것 같네요...

@kujyp
Copy link
Author

kujyp commented May 26, 2023

그리고 galera 클러스터는 말씀하신 것 처럼 애초에 다른 네트워크망에 있는 노드들끼리 묶어놓으라고 만든건 아니었던 것 같네요...

바빠가지고 주말에 시간나면 볼게요~

@uaysk
Copy link

uaysk commented May 26, 2023

그리고 galera 클러스터는 말씀하신 것 처럼 애초에 다른 네트워크망에 있는 노드들끼리 묶어놓으라고 만든건 아니었던 것 같네요...

바빠가지고 주말에 시간나면 볼게요~

네 바쁘시면 굳이 이번 주말 아니어도 괜찮아요 나중에 시간 나시면 그때 봐주세요

그리고 chatgpt로 관련 내용 질문하다가 들은 건데, 파일 시스템이 zfs면 zfs 전용 csi 드라이버를 따로 설치해줘야 하는 건가요?
마스터 노드만 zfs로 구성되어 있고 워커 노드는 ext4 파일 시스템 사용중인 상태고, control-plane=NoSchedule 가 zfs 사용중인 노드(마스터)에 taint로 붙어 있어서 pv가 마스터에 생성될 것 같지는 않은데 정확히 뭘 해야 할 지 헷갈리네요

@kujyp
Copy link
Author

kujyp commented Jun 5, 2023

그리고 galera 클러스터는 말씀하신 것 처럼 애초에 다른 네트워크망에 있는 노드들끼리 묶어놓으라고 만든건 아니었던 것 같네요...

바빠가지고 주말에 시간나면 볼게요~

네 바쁘시면 굳이 이번 주말 아니어도 괜찮아요 나중에 시간 나시면 그때 봐주세요

그리고 chatgpt로 관련 내용 질문하다가 들은 건데, 파일 시스템이 zfs면 zfs 전용 csi 드라이버를 따로 설치해줘야 하는 건가요? 마스터 노드만 zfs로 구성되어 있고 워커 노드는 ext4 파일 시스템 사용중인 상태고, control-plane=NoSchedule 가 zfs 사용중인 노드(마스터)에 taint로 붙어 있어서 pv가 마스터에 생성될 것 같지는 않은데 정확히 뭘 해야 할 지 헷갈리네요

아 맞다 잊고있엇는데
이거 아직 질문 궁금한상탠가요?
답변 ㄱ.ㄱ?

@uaysk
Copy link

uaysk commented Jun 6, 2023

아 맞다 잊고있엇는데 이거 아직 질문 궁금한상탠가요? 답변 ㄱ.ㄱ?

네 아직 해결 못했어요...
일단 pvc 로그를 확인해보니까 지금 스토리지 클래스가 없다고 떠서 hostpath로 생성했는데 helm uninstall로 지우고 다시 설치해봐도 계속 pvc에서는 스토리지 클래스가 없다고 떠요
혹시 저기서 pvc가 말하는 스토리지 클래스가 동적 프로비저닝이 가능한 스토리지 클래스를 말하는건가요? 동적 프로비저닝이 가능한 프로비저너는 전부 gce-pd나 aws-ebs처럼 클라우드에서 사용되는 것 같은데 온프레미스 환경에서 사용 가능한 동적 프로비저너를 못 찾겠어요

@uaysk
Copy link

uaysk commented Jun 6, 2023

아 맞다 잊고있엇는데 이거 아직 질문 궁금한상탠가요? 답변 ㄱ.ㄱ?

방금 해결했어요
솔직히 이게 될 줄은 몰랐는데 netdata pvc랑 같은 이름으로 pv 하나 만들고, pvc 직접 수정해서 pv 할당시키니까 바로 되네요...

근데 온프레미스 환경에서 동적 프로비저닝은 아예 안되는건가요?
그리고 pv는 원래 worker 노드에만 생성되는건가요? 마스터 노드에 no scheduling taint는 제거한 상태인데, 기준이 따로 있는건가요?

@kujyp
Copy link
Author

kujyp commented Jun 16, 2023

방금 해결했어요 솔직히 이게 될 줄은 몰랐는데 netdata pvc랑 같은 이름으로 pv 하나 만들고, pvc 직접 수정해서 pv 할당시키니까 바로 되네요...

와아우 해결했다고해서 끝난줄알앗는데 아래가더잇네요??

마스터 노드에 no scheduling taint는 제거한 상태인데, 기준이 따로 있는건가요?

근데 온프레미스 환경에서 동적 프로비저닝은 아예 안되는건가요?

안찾아봐서 모르겠지만
안되는건없음 ㅋㅋㅋ

온프레미스든 아니든
결국 모든 클라우드도 누군가가 직접 세팅한거임.

그리고 pv는 원래 worker 노드에만 생성되는건가요?
마스터 노드에 no scheduling taint는 제거한 상태인데, 기준이 따로 있는건가요

node 랑 pv 랑 관계없을텐데요?
PV 유형이 node 랑 관련있는 유형을 사용하나본데 일단 그런 세부적인건 다 다름.

kubeadm으로 쿠버네티스를 설치하면 csi 드라이버라는걸 설치해줘야 persistent volume을 사용할 수 있는건가요?

애초에 CSI 는 Container Storage Interface 라서 먼저 고려할사항이아님.

https://kubernetes.io/ko/docs/concepts/storage/persistent-volumes/#%ED%8D%BC%EC%8B%9C%EC%8A%A4%ED%84%B4%ED%8A%B8-%EB%B3%BC%EB%A5%A8%EC%9D%98-%EC%9C%A0%ED%98%95
에서 Persistent Volumes 를 무슨종류로 사용할건지부터 의사결정해야함.
PV 를 뭘로 사용하는지 정해지면 그에 필요한것을 준비하면됨.

@uaysk
Copy link

uaysk commented Aug 8, 2023

혹시 멀티클라우드로 쿠버네티스 클러스터 구성해보신 적 있으신가요? 지금 제 집에 있는 쿠버네티스 클러스터에 오라클 클라우드에서 돌아가고 있는 인스턴스를 워커 노드로 추가하려고 하는데, api server에 공인 ip 추가해주고 쿠버네티스에서 사용되는 포트들 전부 공유기 방화벽이랑 오라클 클라우드 방화벽에서 열어준 다음 kubeadm join으로 노드를 추가하려고 했는데 configmap을 가져올 때 계속 사설 ip를 사용하려고 하더라고요(kubeadm join을 할 때는 공인 ip를 사용했는데)
지금 하고 있는 작업이 멀티클라우드 쿠버네티스 클러스터 구성하는 작업이랑 비슷해 보여서 인터넷에서 멀티클라우드 쿠버네티스 관련 문서도 몇개 찾아봤는데 그냥 공인 ip를 사용하라는 말 외에는 도움될만한 점이 없었어요

아래는 스택오버플로우에 제가 올린 질문 한국어로 번역한건데, 지금까지 시도한 것들, 에러 내용들 정리해놓은 글이에요

안녕하세요 저는 현재 집에서 1개의 마스터 노드와 1개의 작업자 노드로 Kubernetes 클러스터를 실행하고 있습니다. Oracle Cloud에서 실행 중인 인스턴스를 이 Kubernetes 클러스터에 작업자 노드로 추가하려고 했습니다. 집에 있는 라우터에 대한 공식 문서에 나와 있는 모든 포트를 포트 포워딩했고 Oracle Cloud 방화벽에 대해서도 동일한 작업을 수행했습니다.

이후 kubeadm join 명령어를 이용하여 Oracle Cloud의 노드를 클러스터에 추가하려고 했으나(마스터노드 ip의 public ip 입력) X509 인증서 관련 오류가 발생(X509 인증서가 하는 오류) 공용 ip와 일치하지 않음), 그래서 공용 ip를 추가했습니다. ('kubectl get configmap kubeadm-config -n kube-system -o jsonpath='{.data.ClusterConfiguration}' > kubeadm-conf.yaml' 명령을 통해 구성 파일을 추출하고 하위에 certSAN, public 및 private ip를 추가한 후 부분 추가) X509 인증서 오류가 더이상 발생하지 않는데 아래와 같은 오류가 발생함

ubuntu@a1-worker:~$ sudo kubeadm join (public-ip):6443 --token q4a65r.r32wc9cdwtv83jzj --discovery-token-ca-cert-hash sha256:eea8ad19b5d7484ea86f5c06bf993a83b602d44df1aa9c1728ead596e49a7dde --cri-socket=/var/run/crio/crio.sock
W0808 16:19:57.287856 1033278 initconfiguration.go:120] Usage of CRI endpoints without URL scheme is deprecated and can cause kubelet errors in the future. Automatically prepending scheme "unix" to the "criSocket" with value "/var/run/crio/crio.sock". Please update your configuration!
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
error execution phase preflight: unable to fetch the kubeadm-config ConfigMap: failed to get config map: Get "https://172.30.1.4:6443/api/v1/namespaces/kube-system/configmaps/kubeadm-config?timeout=10s": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
To see the stack trace of this error execute with --v=5 or higher

여기서 취해야 할 추가 조치가 무엇인지 말씀해 주시겠습니까?

노드의 설정을 편집하여 노드의 개인 IP를 공용 IP로 교체해 보았습니다. 또한 X509 문제를 해결하기 위해 마스터노드의 public ip를 추가하여 api 서버의 키를 재생성하였습니다.

갑자기 연락드려서 죄송합니다. 바쁘시면 답장 남기지 않으셔도 괜찮습니다. 그리고 동적 프로비저닝은 NFS로 성공했어요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment