https://www.notion.so/K8s-Apiversion-a7c2c8da3e184d659175d191820db1e0

 

K8s Apiversion

왜 api버전이 바뀌어 있을까 ?

www.notion.so

 

왜 api버전이 바뀌어 있을까 ?

머선129

  • hpa autoscaling v2beta2버전으로 배포한 어느날 수정을 위해 k edit hpa -n ns hpa-name 명령어로 조회한 순간 apiversion이 autoscaling/v1으로 변경된것을 확인했다.
  • 어찌된 일일까 ?

출처

https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api_changes.md#operational-overview

 

```java
To demonstrate the general process, here is a (hypothetical) example:

1. A user POSTs a Pod object to /api/v7beta1/...
2. The JSON is unmarshalled into a v7beta1.Pod structure
3. Default values are applied to the v7beta1.Pod
4. The v7beta1.Pod is converted to an api.Pod structure
5. The api.Pod is validated, and any errors are returned to the user
6. The api.Pod is converted to a v6.Pod (because v6 is the latest stable version)
7. The v6.Pod is marshalled into JSON and written to etcd
```
  • 공식문서에 보면 beta버전으로 등록할 경우 베타버전으로 등록되지않고 최신안정화버전으로 변경되어 등록된 후 etcd에 저장된다.
Now that we have the Pod object stored, a user can GET that object in any supported api version. For example:

1. A user GETs the Pod from /api/v5/...
2. The JSON is read from etcd and unmarshalled into a v6.Pod structure
3. Default values are applied to the v6.Pod
4. The v6.Pod is converted to an api.Pod structure
5. The api.Pod is converted to a v5.Pod structure
6. The v5.Pod is marshalled into JSON and sent to the user
  • 호출할 경우 지원되는 모든버전으로 호출할수 있습니다.

이런 이유로 v2beta2로 등록한 autoscaling이 버전없이 조회할경우 etcd에 저장된 v1버전으로 조회가 된것.

'개발 > Kubernetes' 카테고리의 다른 글

컨테이너 런타임  (0) 2021.03.07
Mutating Webhook 를 이용한 pod injection  (0) 2021.02.16
쿠버네티스의 클러스터 구성  (0) 2021.01.28
k8s 에서 spring boot jib image command 수정  (0) 2020.12.24
클러스터 구성  (0) 2020.09.13
  • 컨테이너 생성

  • 이미지 안에 레이어로 이뤄져 있는 계층구조로 파일이 이뤄져 있음

  • 이 위에 READ WRITE 레이어를 하나 더 올림

  • 이 RW레이어를 통해 이미지의 파일을 읽고 쓰고 할수 있음.

  • 이 상태가 컨테이너

  • 이 RW 레이어를 통해 파일을 읽고 쓰도록 해주는 드라이버가

  • AUFS나 OVERLAY2

  • 도커 컨테이너의 성능은 그래서 이 스토리지 드라이버에 따라 차이가 남.

  • 컨테이너 내부에 프로그램을 구동시켜야되는데

  • 도커파일에 엔트리포인트에 정의된 실행파일 같은걸 실행시킴.

  • 이 과정에서 namespace 격리 cgroup의 자원할당이 일어남.

  • 일어나면서 외부와 격리됨.

  • 위의 과정에서 cgroup와 namespace는 저수준 컨테이너 런타임이 실행과정에서 처리해줌.

  • 저수준 컨테이너 런타임 = ( runc )

  • /var/lib/docker/overlay2/에 이미지가 저장됨

Docker와 containerd

  • 위의 runc로 cgroup namespace 일일히 다 oci 스펙에 맞게 config 작성하는것은 쉽지 않은 일.

  • 이걸 쉽게 해주는게 containerd

  • 도커는 continerd위에 올라가 있는 cli나 데몬 ( dockerd ) 임.

  • 도커는 컨테이너를 다루기 위한 모든 동작이 포함되어있음.

  • 그래서 자체 api나 자체 cli툴이 매우 강력함.

CRI-O

  • 이름부터 container runtime interface - open container initative 이다.

  • CRI 및 이미지가 OCI와 호환되는것에 중점을 둔 CR

  • 오로지 컨테이너의 실행을 목적으로 경량화 했기 떄문에 도커가 제공하는 컨테이너 생성 및 이미지 빌드와 같은 과정이 없었음.

  • 그래서 도커가 필요했음.

  • CRI-O 팀은 도커를 대체하는 툴들을 개발함.

  • Buildah, Podman, Skopeo

 

참고

https://www.samsungsds.com/kr/insights/docker.html

https://ssup2.github.io/theory_analysis/Docker_Component/

lugi 님

 

쿠버네티스는 기본적으로 API 요청이 오면 위와 같은 순서로 작업을 처리합니다.

그 중간에 Mutating admission 부분에 Webhook을

이용한 pod injection 예제로 pod injection 하는 부분을 알아보고

예제가 오래된 관계로 v1beta1인 예제를 v1으로 업데이트하는 부분까지 할 예정입니다.

Webhook의 작동 방식

  • 출처 mutating webhook tutorial 깃헙

MutatingWebhook은 요청이 etcd에 등록되기 전에 MutatingWebhookConfiguration 의 rule과

일치하는 request를 intercept 합니다.

MutatingWebhook은 webhook 서버에 승인을 요청하여

mutation ( injection이라던지 수정같은 작업) 을 수행합니다.

( webhook 서버는 API를 준수하는 일반 http 서버)

예제

https://github.com/morvencao/kube-mutating-webhook-tutorial

이 튜토리얼은 nginx 사이드카 컨테이너를 파드에 injection 하는 MutatingAdmissionWebhook을 빌드하고 배포하는 방법을 보여줍니다.

조건

  • git
  • go version v1.12+
  • docker version 17.03+
  • kubectl version v1.11.3+
  • kubernetes v1.11.3+ cluster with admissionregistration.k8s.io/v1beta1 API enabled
    • 처음은 v1beta1로 작업하고 추후에 v1으로 수정할 예정.

admissionregistration.k8s.io/v1beta1 API enabled 확인 방법

kubectl api-versions | grep admissionregistration.k8s.io

결과는 아래와 같이 나와야합니다.

admissionregistration.k8s.io/v1 admissionregistration.k8s.io/v1beta1

빌드

  1. Build binary

# make build

  1. Build docker image

# make build-image

  1. push docker image

# make push-image

deploy

  1. sidecar injector webhook이 배포될 sidecar-injector  namespace를 생성

# kubectl create ns sidecar-injector

  1. sidecar injector deployment에 사용될 secret 생성

    (이 시크릿은 cert와 key 정보를 가지고 있다):

# ./deployment/webhook-create-signed-cert.sh \\ --service sidecar-injector-webhook-svc \\ --secret sidecar-injector-webhook-certs \\ --namespace sidecar-injector

  1. 위에서 생성한 caBundle 값을 mutatingwebhook.yaml 에 패치를 한 결과를 mutatingwebhook-ca-bundle.yaml로 생성한다.:

# cat deployment/mutatingwebhook.yaml | \\ deployment/webhook-patch-ca-bundle.sh > \\ deployment/mutatingwebhook-ca-bundle.yaml

  1. 리소스들을 배포한다.:

# kubectl create -f deployment/nginxconfigmap.yaml # kubectl create -f deployment/configmap.yaml # kubectl create -f deployment/deployment.yaml # kubectl create -f deployment/service.yaml # kubectl create -f deployment/mutatingwebhook-ca-bundle.yaml

확인

  1. sidecar injector webhook이 잘 배포됬나 확인한다.

# kubectl -n sidecar-injector get pod NAME READY STATUS RESTARTS AGE sidecar-injector-webhook-deployment-7c8bc5f4c9-28c84 1/1 Running 0 30s # kubectl -n sidecar-injector get deploy NAME READY UP-TO-DATE AVAILABLE AGE sidecar-injector-webhook-deployment 1/1 1 1 67s

  1. injection namespace 생성 그리고  sidecar-injector=enabled로 라벨링 한다.

# kubectl create ns injection # kubectl label namespace injection sidecar-injection=enabled # kubectl get namespace -L sidecar-injection NAME STATUS AGE SIDECAR-INJECTION default Active 26m injection Active 13s enabled kube-public Active 26m kube-system Active 26m sidecar-injector Active 17m

  1. alpine app을 예제로 쿠버네티스 클러스터에 배포한다.

# kubectl run alpine --image=alpine --restart=Never -n injection --overrides='{"apiVersion":"v1","metadata":{"annotations":{"sidecar-injector-webhook.morven.me/inject":"yes"}}}' --command -- sleep infinity

  1. sidecar container가 injected 됬는지 확인한다.

# kubectl get pod NAME READY STATUS RESTARTS AGE alpine 2/2 Running 0 1m # kubectl -n injection get pod alpine -o jsonpath="{.spec.containers[*].name}" alpine sidecar-nginx

admissionregistration.k8s.io/v1beta1 를 v1으로 업그레이드 하기

webhook의 작동방식부분에서 mutatingadmissionwebhook 부분과 webhook 서버를 보면

admissionReview를 요청하고 응답받는것을 보실수 있습니다.

v1beta1버전에서는 요청에 대한 응답시 kind와 apiversion 을 넣지 않아도 응답을 정상으로 판단 했습니다.

하지만 v1버전에서는 요청에 대한 응답시 kind와 apiversion 버전을 추가시켜줘야 합니다.

https://github.com/morvencao/kube-mutating-webhook-tutorial/blob/e72f4d5e501d61f22023efb26e16cda35a335941/cmd/webhook.go#L296

위 빈 라인에 아래와 같이 요청으로 들어온 api version 과 kind , uid를 그대로 review 응답에 넣어줍니다.

admissionReview.Response.UID = ar.Request.UID admissionReview.APIVersion = ar.APIVersion admissionReview.Kind = ar.Kind

위와 같이 할 경우 v1beta1로 요청이 들어왔을 경우 그대로 v1beta1로 응답하며

v1로 요청이 왔을 경우 그대로 v1로 응답이 갑니다.

그 후 deployment/mutatingwebhook.yaml 을 수정합니다.

apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: name: sidecar-injector-webhook-cfg labels: app: sidecar-injector webhooks: - name: sidecar-injector.morven.me clientConfig: service: name: sidecar-injector-webhook-svc namespace: sidecar-injector path: "/mutate" caBundle: ${CA_BUNDLE} rules: - operations: ["CREATE", "UPDATE"] apiGroups: [""] apiVersions: ["v1"] resources: ["pods"] namespaceSelector: matchLabels: sidecar-injection: enabled admissionReviewVersions: ["v1"] sideEffects: None

위와 같이 수정하면 v1로 업데이트 완료입니다.

Injection 수정하기

webhook 서버에서 injection 처리 부분은 webhook.go 파일 입니다.

https://github.com/morvencao/kube-mutating-webhook-tutorial/blob/e72f4d5e501d61f22023efb26e16cda35a335941/cmd/webhook.go#L234

webhook.go 안에 createPatch 부분이 injection 할 내용을 생성하는 부분입니다.

이 부분으로 생성 후 apiserver로 다시 요청을 응답하는 작업이 이루어집니다.

이때 이 부분도 같이 response에 담겨서 응답하게 됩니다.

createPatch 부분을 참고하셔서 수정하시면 자신만의 injection 을 만드실수 있습니다.

createPath의 추가적인 참고는 하단의 tumblr github을 참고해주세요.

https://github.com/tumblr/k8s-sidecar-injector/blob/2478960ca6686798d26319956354b48e37108c29/pkg/server/webhook.go#L448

정리

mutating webhook은 추가적인 변경이나, 검증을 쉽게 제공해줘서 go를 처음접하는 저로써도

손쉽게 수정하여 저만의 injection 을 만들수 있었습니다.

다만 v1beta1에서 v1 patch부분이나 인증서 관련 부분은 삽질이 좀 필요해서 글로 남기게 됬습니다.

인증서 부분과 webhook 소스내부 설명은 다음글에 남겨보도록 하겠습니다.

'개발 > Kubernetes' 카테고리의 다른 글

왜 apiversion이 변경되어 있을까  (0) 2021.06.11
컨테이너 런타임  (0) 2021.03.07
쿠버네티스의 클러스터 구성  (0) 2021.01.28
k8s 에서 spring boot jib image command 수정  (0) 2020.12.24
클러스터 구성  (0) 2020.09.13

블랙커피 블로그 스터디 3기를 시작하는 김에 뭐를 올릴까 고민을 했었습니다.

그렇게 고민하다가

"쿠버네티스를 점점 까먹고 있으니 복습을 해보자"

라고 마음먹고 쿠버네티스 관련 글을 적어보자고 결심했습니다.

저는 처음 쿠버네티스를 공부할때 클러스터의 기본구성을 먼저 공부하고

기본구성을 바탕으로 세세하게 공부했을때 효과가 꽤 괜찮았던 경험이 있어서

복습도 처음학습과 동일하게 가져갈 생각으로 클러스터의 구성을 먼저 복습하게 되었습니다.

쿠버네티스의 클러스터 구성

 

크게 쿠버네티스의 클러스터는 마스터노드 ( Control Plane ) 과 워커 노드 들로 이루어져 있습니다.

컨트롤 플레인

일명 마스터노드 라고 불리는 컨트롤 플레인입니다.

API Server와 Etcd , Scheduler , Controller manager 로 이루어져 있습니다.

보통 3대, 5대 구성을 많이합니다.

API Server

API Server가 제공하는 api를 이용하여 컨트롤 플레인과 워커 노드들은

이 api를 사용하여 서로가 통신할수 있게 됩니다.

ETCD

모든 클러스터 내의 정보를 담고 있는 저장소 입니다.

클러스터의 상태나 설정 정보를 저장하며 키 밸류 형태로 이루어져 있습니다.

스케줄러

리소스 생성시 노드에 알맞게 할당을 해주는 역할을 합니다.

컨트롤러 매니저

컨트롤러를 생성하고 이를 각 노드에 배포하며 관리하는 역할을 합니다.

컨트롤러

클러스터의 상태를 읽고 어떠한 작업을 실행하는 역할입니다.

노드

kublet과 kube-proxy , container-runtime 으로 이루어져 있습니다.

kubulet

클러스터의 각 노드에서 실행되는 에이전트로 API 서버와 통신을 하면서

노드의 상태를 전달하거나 마스터 노드로부터 명령을 받아 작업을 수행하는 역할입니다.

kube-proxy

클러스터의 각 노드에서 실행되는 네트워크 프록시로서 역할을 수행합니다.

userspace, iptables, ipvs, kernelspace 모드가 존재하며 현재는 iptables를 사용합니다.

Container Runtime

컨테이너를 실행을 담당하는 소프트웨어입니다.

대표적으로 Docker, containerd, CRI-O가 있으며 Docker는 1.23버전부터 제거될 예정입니다.

'개발 > Kubernetes' 카테고리의 다른 글

왜 apiversion이 변경되어 있을까  (0) 2021.06.11
컨테이너 런타임  (0) 2021.03.07
Mutating Webhook 를 이용한 pod injection  (0) 2021.02.16
k8s 에서 spring boot jib image command 수정  (0) 2020.12.24
클러스터 구성  (0) 2020.09.13

jib buildTar 옵션으로 빌드 후 tar로 떨궈지면

tar파일 안에 config.json 파일이 있다.

 

이 파일에 entrypoint가 있는데 이 entrypoint의 classpath경로가

우리가 빌드한 springboot의 spring boot classpath다.

 

jib는 jar로 패키징하는 단계를 skip 하고 바로 이미지로 빌드시킨다.

이유는 더 빠르기때문이다. ( jar패키징 단계를 skip해서 )

더 자세한이유는 참조링크확인.

 

따로 jar로 패키징하는 옵션도 줄수있다.

 

대충 entrypoint를 보면 java -cp [classpath] 일것이다.

k8s에서

docker의 entrypoint 는 command이고

docker의 cmd는 args다.

 

jib에 entrypoint밖에 없었으므로 command에 똑같이 넣어주자.

만약 -D옵션이나 jvm옵션을 k8s에서 직접 주고싶다면.

java jvm옵션 -D옵션을 주고 -cp [classpath] 이런식으로 작성하자.

 

이 옵션들은 모두 pom.xml의 jib plugin 옵션에서 설정할수 있다.

 

ps. jib의 default image는 distroless/java 다.

이 이미지에는 쉘이없다..

exec로 쉘 접근하고 싶다면 base image를 변경시켜줘야한다.

 

ps2. base image를 로컬에 있는걸 쓰고 싶다면 이미지이름 앞에 docket://를 붙여주면된다.

 

 

참조

https://github.com/GoogleContainerTools/jib/blob/master/docs/faq.md

https://kubernetes.io/ko/docs/tasks/inject-data-application/define-command-argument-container/#참고사항

'개발 > Kubernetes' 카테고리의 다른 글

왜 apiversion이 변경되어 있을까  (0) 2021.06.11
컨테이너 런타임  (0) 2021.03.07
Mutating Webhook 를 이용한 pod injection  (0) 2021.02.16
쿠버네티스의 클러스터 구성  (0) 2021.01.28
클러스터 구성  (0) 2020.09.13

기본구성

  • 마스터 - 노드1 - 노드2
  • VirtualBox를 이용해 CentOs7로 마스터 노드1 노드2 서버를 설치함.
  • 네트워크는 어댑터에 브릿지로 설정하여 마스터 노드 노드2의 아이피를 각각 다르게설정
  • 마스터는 192.168.35.30 노드는 31 노드2는 32
  • 마스터에 calico plugin 와 dashboard plugin 설치

트러블 슈팅

  • 처음에 강의처럼 192.168.0.x로 했다가 timed out이 발생
  • 그 이유는 내 호스트OS의 내부ip가 192.168.35.x 인걸 확인 후 수정
  • 마스터에서 kubernetes를 reset하는 상황이 발생
    • master 에서 자기자신을 node로 등록하려는 실수이후 node에서 master로 join이 안됨
    • 그래서 master에서 kubernetes를 reset함
    • reset 후 init로 초기실행하고 node들을 master에 join 시킴.
    • 하지만 master 에서 권한 문제가 생김
    • KUBECONFIG=/etc/kubernetes/admin.conf 이런식으로 쿠베컨피그에 설정하니 권한잘됨

참조

1. 설치 관련

https://www.cubrid.com/blog/3820603

https://kubetm.github.io/practice/appendix/installation_case2/

2. 2번 문제

https://github.com/kubernetes/kubeadm/issues/1721

https://stackoverflow.com/questions/61072700/issues-after-running-kubeadm-reset

https://github.com/kubernetes/kubeadm/issues/1721

+ Recent posts