본문 바로가기

DevOps/도커(Docker)

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

쿠버네티스에서 직접 만든 컨테이너 사용하기

지금까지 도커를 이용해 컨테이너를 다루고 새로운 컨테이너 이미지를 빌드해보았다. 컨테이너 이미지 빌드방법을 다양하게 알아본 이유는 직접 만든 컨테이너 이미지를 쿠버네티스에서 사용하는것이다. 쿠버네티스에서 이미지를 사용하려면 쿠버네티스가 이미지를 불러올 수 있는 공간에 이미지를 넣어두어야 한다.

 

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

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

도커를 빌드해서 만든 multistage-img 이미지를 쿠버네티스에서 구동해보자.

 

 

1. 이미지 확인 

$ docker images multistage-img

 

 

 

2. 디플로이먼트 생성

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

 

 

 

3. 파드의 상태 및 변화 확인

$ kubectl get pods -w

kubectl get pods -w로 파드의 상태 및 변화를 확인한다. 상태가 정상이라면 STATUS에 Running으로 표시되어야한다. 하지만 이미지를 내려받는 데 문제가 발생해 ErrImagePull 과 ImagePullBackOff라는 오류 메세지가 번갈아 발생한다. 이는 이미지가 호스트에 존재함에도 기본 설정에 따라 이미지를 외부(도커 허브)에서 받으려고 시도하기 때문이다.

 

 

 

4. YAML파일 출력

# 구문을 야믈 형태로 뽑아내기
$ kubectl create deployment failure2 --dry-run=client -o yaml \\
> --image=multistage-img > failure2.yaml

내부에 존재하는 컨테이너 이미지를 사용하도록 설정해서 디플로이먼트를 생성한다. 사용자가 원하는 형태의 디플로이먼트를 만드는 가장 좋은 방법은 현재 수행되는 구문을 야믈 형태로 뽑아내는 것이다. --dry-run=client 옵션은 해당 내용을 실제로 적용하지 않은 채 명령을 수행하고, -o yaml 은 현재 수행되는 명령을 야믈 형태로 바꾼다. 두 옵션을 조합하면 현재 수행되는 명령을 야믈 형태로 출력해서 사용자가 원하는 형태로 변경할 수 있다. 마지막에 > failure2.yaml을 붙여 실행결과를 파일로 저장한다.

 

 

 

5. yaml 파일 수정

# failure2.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: failure2
  name: failure2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: failure2
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: failure2
    spec:
      containers:
      - image: multistage-img
        imagePullPolicy: Never    # 추가한 부분
        name: multistage-img
        resources: {}
status: {}

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

 

 

 

6. 디플로이먼트에 적용

$ kubectl apply -f failure2.yaml
$ kubectl get pods

수정한 failure2.yaml 파일을 디플로이먼트에 적용하고 상태를 확인한다. 형태는 바뀌었지만 여전히 오류(ErrImageNeverPull)가 발생한다. 내부의 이미지를 사용하도록 옵션을 추가했는데, 왜 이미지를 가져오지 못할까?

 

 

 

7. 디플로이먼트 삭제

$ kubectl delete deployment failure1
$ kubectl delete deployment failure2

 

 

 

8. k-node3 접속

$ vagrant ssh k-node3

 

 

9. Dockerfile 작성

FROM openjdk:8 AS int-build
LABEL description="Java Application builder"
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"
EXPOSE 60434
COPY --from=int-build inbuilder/target/app-in-host.jar /opt/app-in-image.jar
WORKDIR /opt
ENTRYPOINT [ "java", "-jar", "app-in-image.jar" ]

 

 

10. 컨테이너 이미지 빌드

$ sudo docker build -t multistage-img .

docker build로 컨테이너 이미지 multistage-img를 워커노드 3번에 빌드하고 결과가 성공적으로 이루어 졌는지 확인한다.

 

 

 

11. failure2.yaml 파일을 success1.yaml로 복사

$ cp failure2.yaml success1.yaml

마스터 노드로 돌아와 failure2.yaml 파일을 success1.yaml로 복사한다.

 

 

 

12. sed 명령어로 success1.yaml 파일 수정

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

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

 

 

 

13. 배포

워커노드 3번만 배포에 성공한다. 컨터이너 이미지가 워커노드 3번에만 있기 때문인다. 워커노드 1번과 2번에는 multistage-img가 없어서 파드를 생성할 수 없다.

기본으로 사용하는 도커 허브에 이미지를 올려서 다시 내려받거나 쿠버네티스 클러스터가 접근할 수있는곳에 이미지 레지스터리를 만들고 그곳에서 받아오도록 설정하는것이다.

 

 

 

14. deployment 삭제

$ kubectl delete deployment success1

 

 

 

15. 컨테이너 이미지와 댕글링 이미지 삭제

$ sudo docker rmi multistage-img
$ sudo docker rmi $(sudo docker images -f dangling=true -q)

 

 

 

 

 

출처:

"컨테이너 인프라 환경 구축을 위한 쿠버네티스/도커 - 조훈,심근우,문성주 지음/길벗출판사" 책을 기반으로 실습한 내용입니다.