Profile picture

[k8s] 쿠버네티스에서 도커 이미지 구동하기

JaehyoJJAng2023년 04월 07일

k8s에서 도커 이미지 구동하기

쿠버네티스에서 도커 이미지를 사용하려면 쿠버네티스가 이미지를 불러올 수 있는 공간에 이미지를 넣어두어야 한다


사전 작업

쿠버네티스는 컨테이너를 효과적으로 다루기 위해서 만들어졌고 컨테이너인 파드도 쉽게 부를 수 있다. 따라서 직접 만든 컨테이너 이미지도 kubectl 명령어로 쿠버네티스 클러스터에서 바로 구동할 수 있다
도커 이미지를 빌드해서 만든 hello:1.0 이미지를 쿠버네티스에서 구동해보자


Dockerfile

FROM openjdk:8 AS int-build
LABEL description="Java Application builder"
WORKDIR /app
RUN git clone https://github.com/iac-source/inbuilder.git
WORKDIR inbuilder
RUN chmod 700 mvnw
RUN ./mvnw clean package

FROM gcr.io/distroless/java:8
LABEL description="Echo IP Java Application"
WORKDIR /opt
COPY --from=int-build /app/inbuilder/target/app-in-host.jar ./app.jar
EXPOSE 80
ENTRYPOINT [ "java", "-jar", "app.jar" ]

이미지 확인

도커 이미지 빌드

$ docker build --tag yshrim12/multistage-img .

도커 이미지 확인

$ docker images yshrim12/multistage-img
REPOSITORY                TAG                 IMAGE ID            CREATED             SIZE
yshrim12/multistage-img   latest              14c516d51db3        15 minutes ago      148MB

도커 이미지 구동

아래 작업을 따라해보자.


1. 위에서 생성한 도커 이미지를 기반으로 디플로이먼트를 생성해보도록 하자. 이때 --image를 옵션으로 줘서 yshrim12/multistage-img를 사용하도록 해보자

$ kubectl create deployment failure1 --image=yshrim12/multistage-img

2. kubectl get pods -w로 파드의 상태 및 변화를 실시간으로 확인해보자. 상태가 정상이라면 STATUS에 Running이 떠야한다.

$ kubectl get pods -w
NAME                        READY   STATUS         RESTARTS   AGE
failure1-644b58ccbb-gm6ls   0/1     ErrImagePull   0          14s
failure1-644b58ccbb-gm6ls   0/1     ImagePullBackOff   0          15s

하지만 이미지는 내려받는데 문제가 발생해 ErrImagePullImagePullBackOff라는 오류메시지가 번걸아 표시되고 있다. 이는 이미지가 호스트에도 존재함에도 기본 설정에 따라 이미지를 외부(도커 허브)에서 받아오려고 시도하기 때문이다. 당연히 도커 허브에 저 이미지가 없으니 에러가 발생할 수 밖에 없다.


4. 이번에는 내부에 존재하는 컨테이너 이미지를 사용하도록 설정해 디플로이먼트를 생성해보자. 사용자가 원하는 형태의 디플로이먼트를 만드는 좋은 방법은 현재 수행되는 구문을 YAML 형태로 뽑아내는 것이다. --dry-run 옵션은 해당 내용을 실제로는 적용하지 않은 채 명령을 수행하고, -o yaml은 현재 수행되는 명령을 YAML 형태로 변환해준다. 두 옵션을 조합하면 현재 수행되는 명령을 YAML 형태로 출력해 사용자가 원하는 형태로 변경이 가능하다.

$ kubectl create deployment failure2 --dry-run=client -o yaml --image=yshrim12/multistage-img > failure2.yaml

마지막에 > failure2.yaml 리다이렉션 기호를 사용하여 실행 결과(출력)를 파일(failure2.yaml)로 저장하였다.


5. failure2.yaml을 열어 컨테이너 설정에 imagePullPolicy: Never 옵션을 다음과 같이 추가해주자. 이 옵션은 외부에서 이미지를 가져오지 않고 호스트에 존재하는 이미지를 사용하게 한다.

    spec:
      containers:
      - image: yshrim12/multistage-img
        imagePullPolicy: Never # 추가한 부분
        name: multistage-img
        resources: {}
status: {}

6. 수정한 failure2.yaml 파일을 디플로이먼트에 적용하고 상태를 확인해보자

$ kubectl apply -f failure2.yaml
NAME                        READY   STATUS              RESTARTS   AGE
failure2-759bb94cd4-lv95t   0/1     ErrImageNeverPull   0          2s

STATUS가 바뀌었지만 여전히 오류(ErrImageNeverPull)가 발생한다. 내부의 이미지를 사용하도록 옵션도 추가했는데 왜 이미지를 못 가져오는걸까?


7. 기존에 배포한 Deployment들을 모두 삭제하자

$ kubectl delete -f ./failure2.yaml
$ kubectl delete deployment/failure1

8. 워커 노드인 w2-k8s에 접속한 후 Dockerfile을 깃허브에서 받아오자.

$ curl -O https://raw.githubusercontent.com/sysnet4admin/_Book_k8sInfra/main/ch4/4.3.4/Dockerfile

9. 테스트를 위한 컨테이너 이미지를 만들자. Dockerfile의 내용은 #1-dockerfile과 같다.

$ docker build --tag yshrim12/multistage-img .

10. 다시 마스터 노드(m-k8s)로 돌아와 failure2.yaml을 success.yaml로 복사하자

$ cp -R ~/failure2.yaml ~/success.yaml

11. sed 명령어로 success.yaml 파일에 replicas를 1에서 3으로 변경하고 failure2 이름도 success로 변경하자

$ sed -i 's/replicas: 1/replicas: 3/' ./success.yaml
$ sed -i 's/failure2/success1/g' ./success.yaml

<br.

12. 배포 전 w2-k8s 워커 노드에서 도커 이미지가 성공적으로 빌드되었는지 확인하고 이미지가 빌드 되었다면 kubectl apply로 success.yaml를 실행하고 kubectl get pods -o wide 명령으로 배포에 성공한 노드가 워커 노드 2번(w2-k8s)인지 확인하자

$ kubectl apply -f success.yaml
deployment.apps/success created

$ kubectl get pods -o wide
NAME                      READY   STATUS              RESTARTS   AGE   IP               NODE     NOMINATED NODE   READINESS GATES
success-654565dd5-5rrpp   1/1     Running             0          3s    172.16.103.135   w2-k8s   <none>           <none>
success-654565dd5-pwv5d   1/1     Running             0          3s    172.16.103.136   w2-k8s   <none>           <none>
success-654565dd5-wm4zt   0/1     ErrImageNeverPull   0          3s    172.16.221.131   w1-k8s   <none>           <none>

왜 워커 노드 2번(w2-k8s)만 배포에 성공한걸까?. 이유는 컨테이너 이미지가 워커 노드 2번에만 존재하기 때문이다. 워커노드 1번에는 yshrim12/multistage-img 이미지가 없기 때문에 파드를 생성할 수 없다.

마무리

그러면 이걸 어떻게 해결할까?
방법은 크게 두 가지가 존재한다.
기본으로 사용하는 도커 허브에 yshrim12/multistage-img를 올려서 다시 내려받거나
쿠버네티스 클러스터가 접근할 수 있는 곳에 이미지 레지스트리를 만들고 그곳에서 받아오도록 설정하는 것이다.
image


Loading script...