• 요즘은 kubernetes(이하 k8s) 소스 코드를 읽고 있다.
  • 디자인이 단순하기 때문에 비교적 읽기 어렵지 않다.
  • 그래서 이렇게 인기를 얻는 것이겠지.
  • 디자인이 단순해진 것은 etcd의 기능 덕분이라고 생각한다.
    • k8s는 etcd를 task-queue처럼 사용한다.
    • mesos는 zookeeper를 사용하는데, 이 선택이 큰 차이를 만드는게 아닐까.
  • 오래전에 분석할땐 “미니언”이라는 용어를 사용하더니 “노드”로 변경했다.
    • “노드”로 선택한 덕분에 미니언이 뭐하는 것인지 추가 설명이 필요없다.
    • 변경한 시점에 나온 이름 후보들을 보니(Koupi, Rower, Krew)
    • “항해”에 비유하고 싶은 욕망이 강했나 보다.
    • 하지만 비유나 추상화 보단, 구체적인 용어가 좋다.

쿠버네티스를 소스에서 빌드

  • 나는 내가 쓰는 솔루션은 직접 빌드해서 쓰는걸 좋아한다.
    • (물론 내 개발용도에만)
  • 예를 들면, mysql을 많이 쓰니 (코드 수정을 해서) 직접 빌드해서 쓰는 식이다.
  • 그리고 문서를 읽기 보다는
  • 코드를 읽고, 로그를 찍고, 돌려본다.
  • 그러면 아주 많은 장점이 있는데, 아마 해본 사람만 느끼리라.
    • 리눅스 데스크탑을 운영체제로 쓰는 장점,
    • vim을 사용하는 것의 장점이 매우 크다고 생각하는데
    • 막상 이유를 설명해보라고 하면 어렵다.
    • (사실 장점을 얻기 위해선 수많은 문제를 스스로 해결해야 하기도 하고)
  • 나같은 이상한 사람을 아직 본적이 없었다.
  • 회사에서 점심먹고 산책하다가 yan도 비슷한 (악)취미가 있다는 것을 알았다.
    • vim 덕후로 수렴한 사람들은 비슷한 길을 걷는걸까
  • 아무튼 k8s도 궁금한 부분에 대해 로깅을 추가해서 빌드하고
    • 내가 빌드한 버전으로 하나씩 갈아끼우는 일을 하고있다.
  • 우선 나같은 생각을 한 사람이라면 높은 확률로 kubectl수정을 시작할 것이다.

kubectl 빌드

  • 빌드 스크립트를 따라가 보면 cmd/kubectl을 빌드하는 것을 알 수 있다.
  • 빌드를 아무생각 없이 일단 해보면, 1시간 정도 걸린다.
  • 결과는 아래의 바이너리들이 만들어진다.
    -rwxr-xr-x 1 sangwook sangwook 201M  6월 11 22:39 kube-apiserver
    -rwxr-xr-x 1 sangwook sangwook  65M  6월 11 22:40 kubectl
    -rwxr-xr-x 1 sangwook sangwook 141M  6월 11 22:39 kubelet
    ...
    
  • 코드를 고칠때마다 빌드에 1시간을 기다렸다.
    • 나는 쿠알못이기 때문에 모르면 이정도는 참아야 한다.
    • 빌드 스크립트를 파는게 목적이 아니니.
  • 그러다가 도저히 참지 못하고
    • 시간을 내서 빌드 스크립트를 읽었다.
    • 결과적으로 빌드에 9분-10분 정도 걸리도록 시간을 줄였다.
    • 이것도 느려서 못참겠지만, 더 빠르게 하는건 다음에 시간이 남을때 하자.
  • 하지만 또 10분씩 기다리는걸 참지 못하고.
    • 빌드 스크립트를 좀 더 자세히 봤다.
    • 테스트 코드를 돌리지 않도록 하는 옵션이 예전에 있었던것 같은데.
    • 지금은 그 옵션이 동작하지 않는다.
    • 일단 10분 기다리는걸 참는걸로..
  • kubespray에서 kubectl, kubelet의 업데이트는.
  • 내가 빌드한 kubectl을 사용하도록 바이너리 경로를 변경하고.
    • 클러스터의 config를 ~/.kube/sangwook-cluster.conf 로 복사하고.
    • KUBECONFIG 에 config 경로를 지정하고
    • kubectl 명령을 하면서 테스트하면 된다.

apiserver 빌드

  • 별거 없다.
  • apiserver는 다커 이미지만 만들어서, 이미지 주소를 변경만 하면.
    • (apiserver는 static-pod로 정의되어 있기 때문에)
    • manifest가 즉시 적용된다.
  • 다커 이미지를 만드는 것은 수 초 밖에 안 걸린다. (hyperkube 하나만 하면 10초 정도)
  • 자주 수정하고 빌드하고 다커 이미지 만들고 하다보면
    • 내가 방금 빌드한 버전으로 돌아가고 있는지 궁금할때가 있는데. (제대로 배포했나?)
    • 빌드한 서버에서 docker images --digests 를 해서 digest sha256 값을 확인하고.
      REPOSITORY               TAG                    DIGEST                                                                  IMAGE ID     CREATED        SIZE
      sangwook/hyperkube-amd64 v1.9.5-sangwook-custom sha256:71d332a5b8cdb21329b9ca75c5aae454fa3d60c8a87b6088aaeee1720a8850f4 944446664a2b 32 minutes ago 619MB
      
    • apiserver를 배포한 서버에서 나오는 digest sha256이 일치하는지 확인하면 된다. (IMAGE ID가 아니라는게 핵심)
      CONTAINER ID IMAGE                                                                                             COMMAND               CREATED        STATUS
      0b11ac196ea3 sangwook/hyperkube-amd64@sha256:71d332a5b8cdb21329b9ca75c5aae454fa3d60c8a87b6088aaeee1720a8850f4 "/hyperkube apiser..." 13 minutes ago Up 13 minutes
      

etcd에 업데이트

  • etcd와 통신하는 로직이 궁금하여 따라가다 보면.
  • 코드를 따라가다가 스택을 자주 확인해야 하고,
    • 스택에 해당하는 코드로 쉽게 이동해야 한다.
    • 그것 때문에 아래와 같은 vim 플러그인을 만들어서 쓰고 있다.

2018/180619-vim.gif

  • 처음엔 kubectl get pods 같은 get 로직을 따라 갔었는데.
    • 기억에 남을만한 특별한 로직이 없었다.
  • etcd 변경이 필요한. 예를 들면, service의 nodePort를 kubectl로 변경하면.
    • 변경한 spec의 셀렉터와 변경후의 값만 request body로 해서
    • PATCH 메소드의 요청을 한다. (apiserver에)
    • apiserver가 요청을 받아서, etcd에 업데이트 한다.
  • etcd를 덤프해서 전후를 diff 하는 일을 반복적으로 해서.
    • 아래와 같이 반복을 줄이고 있다.
    • etcdctl ls -r 은 단순히 key만 리스팅하기 때문에.
    • 값까지 보기 위해선, etcdctl ls -r -p | sort | grep -v '/$' 을 해서 key를 가져오고.
    • 루프를 돌면서 etcdctl get 을 하도록 만들어야 했다. (하지만 분명히 더 좋은 방법이 있겠지)

2018/180619-etcddump.gif