쿠버네티스를 이루는 기본 오브젝트가 파드고, 파드는 컨테이너로 이루어져 있고, 컨테이너를 만들고 관리하는 도구가 도커이기 때문에 도커를 배우고 나서 쿠버네티스를 배우는 것이 흐름에 맞다. 트러블 슈팅을 제대로 하려면 컨테이너를 잘 알아야 함.
파드(컨테이너 1개 이상)들은 워커 노드라는 노드 단위로 관리, 워커 노드와 마스터 노드가 모여 쿠버네티스 클러스터가 됨.
파드는 쿠버네티스로부터 IP를 받아 컨테이너가 외부와 통신할 수 있는 경로를 제공하고 컨테이너들이 정상적으로 작동하는지 확인하고 네트워크나 저장 공간을 서로 공유하게 함.
-> 컨테이너를 돌보는 것이 파드, 파드를 돌보는 것이 쿠버네티스 워커 노드, 워커 노드를 돌보는 것이 쿠버네티스 마스터. (쿠버네티스 마스터 역시 파드로 이루어짐)
컨테이너 : 하나의 운영 체제 안에서 커널을 공유하며 개별적인 실행 환경을 제공하는 격리된 공간
각 컨테이너가 독립적으로 작동하기 때문에 여러 컨테이너를 효과적으로 쉽게 다룰 방법이 필요해졌는데 이를 제공하는 도구가 도커임.
도커는 컨테이너를 사용하는 방법을 명령어로 정리한 것이다.
도커를 사용하면 사용자가 따로 신경 쓰지 않아도 컨테이너를 생성할 때 개별적인 실행 환경을 분리하고 자원을 할당
구분 | 컨테이너디 | 크라이오 | 카타 컨테이너 | 도커 |
---|---|---|---|---|
명령어 도구 | 별도 지원 | 타 도구 사용 | 자체 지원 | 자체 지원 |
내부 구조 | 단순 | 매우 단순 | 복잡 | 복잡 |
확장성 | 좋음 | 좋지 못함 | 좋지 못함 | 매우 좋음 |
컨테이너 관리 | 좋음 | 좋음 | 좋음 | 매우 좋음 |
이미지 관리 | 좋음 | 좋음 | 좋음 | 매우 좋음 |
보안성 | 좋음 | 좋음 | 매우 좋음 | 좋음 |
자원 사용량 | 매우 좋음 | 매우 좋음 | 좋지 못함 | 좋음 |
정보량 | 적음 | 거의 없음 | 거의 없음 | 매우 많음 |
-> 도구들의 특징을 비교했을 때 현재 쿠버네티스 인프라를 구성하는 데 가장 적합한 도구로 도커를 선택함
컨테이너 이미지는 베이그런트 이미지와 유사. 베이그런트 이미지는 이미지 자체로는 사용할 수 없고 베이그런트를 실행할 때 추가해야만 사용할 수 있음. 이와 마찬가지로 컨테이너 이미지도 그대로는 사용할 수 없고 도커와 같은 CRI로 불러들여야 컨테이너가 실제로 작동.
이미지 검색하고 내려받기
이미지는 레지스트리라는 저장소에 모여있음. 별도의 레지스트리를 지정하지 않으면 기본으로 도커 허브에서 이미지를 찾음.
이미지 태그
태그 : 이름이 동일한 이미지에 추가하는 식별자. 이름이 동일해도 도커 이미지의 버전이나 플랫폼이 다를 수 있기 때문에 이를 구분하는 데 사용. 컨테이너를 배포할 때는 latest 태그가 아닌 검증된 버전으로 배포해야 문제가 생기지 않음
이미지의 레이어 구조
이미지는 ZIP 같은 압축 파일에 더 가까움
이미지는 같은 내용일 경우 여러 이미지에 동일한 레이어를 공유하므로 전체 용량이 감소함.
내려받은 이미지 조회
stable 이미지가 어떤 과정을 거쳐 생성됐는지 확인
-> SIZE 열의 용량을 모두 더하면 142MB의 이미지가 생성된 것을 알 수 있음. 마지막은 80.5MB
-> 레이어를 두 이미지가 공유하고 있기 때문이다!
curl 127.0.0.1로 전달한 요청을 로컬호스트의 80번 포트로 전달만 될 뿐 컨테이너까지는 도달하지 못함. -> 호스트에 도달한 후 컨테이너로 도달하기 위한 추가 경로 설정이 돼 있지 않은 것. -> 80번으로 들어온 것을 컨테이너에서 받아줄 수 있는 포트로 연결해 주는 설정이 추가로 필요.
[컨테이너 내부에서 외부 파일을 사용하는 방법]
구분 | docker cp | Dockerfile ADD | 바인드 마운트 | 볼륨 |
---|---|---|---|---|
컨테이너 적용 | 구동 중 복사 | 이미지 생성 시 복사 | 구동 시 디렉터리 연결 | 구동 시 도커의 볼륨 연결 |
파일 보관 위치 | 컨테이너 내부 | 컨테이너 내부 | 호스트(디렉터리) | 호스트(도커 볼륨) |
주 활용 용도 | 임시 파일 | 컨테이너 생성 시 필요한 파일 | 보존이 필요한 파일 | 보존이 필요한 파일 |
관리 편의성 | 좋지 못함 | 좋음 | 좋음 | 매우 좋음 |
파일 보존성 | 좋지 못함 | 좋음 | 매우 좋음 | 매우 좋음 |
-> 4가지 방법 중에 nginx 웹 페이지를 사용자가 변경하기에 가장 용이한 바인드 마운트와 볼륨을 실습을 통해 확인
바인드 마운트로 호스트와 컨테이너 연결하기
1. 컨테이너 내부에 연결할 /root/html 디렉터리를 호스트에 생성
nginx-bind-mounts 컨테이너를 조회해 STATUS가 정상인지 확인
컨테이너 내부와 연결된 /root/html/ 디렉터리를 확인
-> 빈 디렉터리가 컨테이너와 연결됐기 때문에 현재 컨테이너의 nginx는 초기 화면으로 보여 줄 파일이 없음
볼륨으로 호스트와 컨테이너 연결하기
볼륨은 도커가 직접 관리하며 컨테이너에 제공하는 호스트의 공간.
볼륨 생성 nginx-volume은 생성할 볼륨의 이름
생성된 볼륨을 조회
-> 볼륨에 적용된 드라이버 종류, 실제 호스트에 연결된 디렉터리, 볼륨 이름 등을 조회 / Mountpoint 행의 디렉터리가 볼륨 디렉터리임.
볼륨으로 생성된 디렉터리를 확인
nginx-volume이라는 컨테이너를 구동하고 컨테이너 내부의 /usr/share/nginx/html 디렉터리와 호스트의 nginx-volume 볼륨을 연결
-v [볼륨 이름]:[컨테이너 디렉터리]
볼륨은 바인드 마운트와 달리 양쪽을 서로 동기화 시키는 구조이기 때문에 비어 있는 볼륨을 연결하는 경우에는 컨테이너 디렉터리에 있는 파일이 보존됨. 하지만 볼륨에 컨테이너 디렉터리와 동일한 파일이 존재한 상태로 연결하는 경우에는 덮어쓰기가 됨
바꿀 파일을 볼륨 디렉터리로 복사해 볼륨에서 변경한 내용이 컨테이너 디렉터리에 동기화되는지 테스트
웹 브라우저에서 다시 연결하여 바뀐 내용 표시
-> 바인드 마운트보다 볼륨이 관리하기가 더 쉬움
컨테이너 정지하기
elastic_colden 컨테이너를 정지
nginx-exposed 컨테이너를 컨테이너 ID로 정지
nginx 이미지를 사용하는 모든 컨테이너 ID 조회
-q : 컨테이너 ID만 출력하게 함
nginx 이미지를 사용하는 모든 컨테이너를 한꺼번에 정지
모든 컨테이너가 정지됐는지 확인
정지된 컨테이너를 포함해 모든 컨테이너 목록을 조회
-a : 정지된 컨테이너를 포함해 조회함
컨테이너와 이미지 삭제하기
1. 현재 정지된 모든 컨테이너를 삭제
컨테이너가 정상적으로 삭제됐는지 확인
용량 확보를 위해 더 이상 필요 없는 이미지를 삭제
자바 개발 도구 설치
자바를 빌드하기 위해 메이븐 실행
생성된 JAR 파일 확인
컨테이너 이미지 빌드
-t : 만들어질 이미지를 의미 / . : 이미지에 원하는 내용을 추가하거나 변경하는 데 필요한 작업 공간을 현재 디렉터리로 지정
생성한 이미지 확인
1.0과 2.0 태그의 이미지도 생성해보기
-> 캐시가 사용돼 매우 빠르게 빌드됨
Dockerfile의 2번째 줄에 있는 Application 부분을 Development로 변경하고 다시 빌드. 태그는 3.0 사용
생성된 이미지 확인
-> 완전히 다른 ID의 이미지가 생성됨. 이름은 같지만 실제로는 다른 컨테이너 이미지다.
생성한 컨테이너 이미지가 컨테이너로 작동하는지 확인하기 위해 컨테이너 실행
컨테이너 상태 출력
curl을 이용해 컨테이너가 정상적으로 외부 요청에 응답하는지 확인
작동 중인 컨테이너를 바로 삭제
빌드한 컨테이너 이미지 모두 삭제
다음 절에서 빌드할 이미지와 용량을 비교하기 위해 컨테이너 이미지 하나를 다시 빌드
빌드한 컨테이너 이미지 보기
컨테이너 용량을 줄여서 빌드하는 과정을 담고 있는 디렉터리로 이동해 어떤 파일이 있는지 살펴보기
추가된 파일 cat으로 살펴보기
Dockerfile 변경된 내용 확인하기
사용되는 기초 이미지가 openjdk에서 distroless로 변경됨. 이것은 자바 실행을 위해 경량화된 이미지임.
메이븐에 실행 권한 부여
build-in-host.sh를 실행해 경량화 이미지 빌드
용량을 줄여 빌드한 컨테이너 이미지와 기본 방법으로 빌드한 이미지를 비교
-> 새로 생성된 optimal-img가 기존 basic-img보다 396MB 작음
생성한 컨테이너 이미지가 컨테이너로 작동하는지 컨테이너 실행
curl로 확인
빌드한 컨테이너 삭제
openjdk 이미지에서 자바 소스를 빌드하는 내용이 있는 디렉터리로 이동해 어떤 파일이 있는지 살펴보기
Dockerfile 살펴보기
이미지 내부에 소스 코드를 내려받으려고 깃을 사용. 내려받은 소스 코드를 이미지 내부에서 실행하기 위해 RUN을 추가. 그리고 이미지 내부에서 파일의 위치만 옮기면 되므로 mv를 사용
이미지 내부에 내려받은 inbuilder 저장소가 어떤 구조인지 확인
컨테이너 이미지 빌드하기
새로 빌드한 컨테이너 이미지를 기존 이미지들과 비교
-> 새로 생성된 nohost-img가 633MB로 이미지 중에서 가장 용량이 큼. 컨테이너 내부에서 빌드를 진행하기 때문에 빌드 중간에 생성한 파일들과 내려받은 라이브러리 캐시들이 최종 이미지인 nohost-img에 그대로 남기 때문에
생성한 컨테이너 이미지가 컨테이너로 잘 작동하는지 컨테이너를 실행
curl로 확인
컨테이너를 삭제
멀티 스테이지 빌드 방법은 최종 이미지의 용량을 줄일 수 있고 호스트에 어떠한 빌드 도구도 설치할 필요가 없음.
현재 사용하는 도커 버전을 확인
호스트 윈도 명령창에서 기존에 사용하던 가상 머신들을 제거
멀티 스테이지를 지원하는 버전의 도커가 포함된 새로운 쿠버네티스 클러스터 환경을 구성
슈퍼푸티로 m-k8s에 접속
도커 버전 확인
멀티 스테이지를 위한 파일이 있는 디렉터리로 이동해 Dockerfile이 있는지 확인
Dockerfile 살펴보기
멀티 스테이지의 핵심은 빌드하는 위치와 최종 이미지를 '분리'하는 것 -> 용량을 줄일 수 있음
멀티 스테이지 방식으로 작성된 Dockerfile로 컨테이너 이미지 빌드
멀티 스테이지로 빌드된 컨테이너 이미지의 용량을 확인
-> optimal-img와 같음. none으로 표시된 이미지가 있는데 이런 이미지를 댕글링 이미지라고 함. 멀티 스테이지 과정에서 자바 소스를 빌드하는 과정에 생성된 이미지임.
댕글링 이미지 삭제
컨테이너 실행
컨테이너가 잘 작동하는지 curl로 확인
컨테이너를 삭제하고 홈 디렉터리로 이동
multistage-img 이미지가 노드에 존재하는지 확인
디플로이먼트 생성
--image 옵션으로 주어 multistage-img 이미지를 사용하게 하고 이름은 failure1로 설정
수정한 failure2.yaml 파일을 디플로이먼트에 적용
상태 확인
-> 형태는 바뀌었지만 여전히 오류가 발생.
오류가 발생하는 디플로이먼트를 모두 삭제
슈퍼푸티로 w3-k8s에 접속
Dockerfile을 받아 와 테스트를 위한 컨테이너 이미지 만들기
컨테이너 이미지 multistage-img를 워커 노드 3번에 빌드하고 확인
마스터 노드로 돌아와 failure2.yaml을 success1.yaml로 복사
sucess1.yaml 파일에 replicas를 1에서 3으로 변경하고 failure2이름도 success1로 변경
success1.yaml를 실행
배포에 성공한 노드가 워커 노드 3번인지 확인
-> 컨테이너 이미지가 워커 노드 3번에만 있기 때문에 3번만 배포에 성공
배포한 Deployment 삭제
워커 노드 3번에 생성한 컨테이너 이미지와 댕글링 이미지도 삭제
호스트에서 생성한 이미지를 쿠버네티스에서 사용하려면 모든 노드에서 공통으로 접근하는 레지스트리(저장소)가 필요. 도커 허브라는 레지스트리에서 이미지를 내려받을 순 있지만 외부에 공개되기를 원하지 않을 때도 있음 -> 제약 없이 사용할 수 있는 레지스트리를 직접 구축하는 방법이 있음.
여기서는 도커에서 제공하는 도커 레지스트리 이미지를 사용해 사설 도커 레지스트리를 만들 예정.
create-registry.sh를 실행해 레지스트리 구성
registry 컨테이너가 정상적으로 구동되는지 확인
사설 도커 레지스트리에 등록할 수 있게 컨테이너 이미지의 이름을 변경
이미지가 정상적으로 생성됐는지 확인
multistage-img를 사설 도커 레지스트리에 등록
이미지가 정상적으로 등록됐는지 확인
호스트에 생성한 이미지 삭제하기 위해 이미지 ID 알아내기
이미지 삭제
이미지가 정상적으로 삭제 됐는지 확인
쿠버네티스에서 파드를 생성할 때 직접 구성한 레지스트리에서 가지고 오는 방법을 확인
워커 노드 3번에만 배포가 성공했던 success1.yaml을 복사해 success2.yaml을 생성
success2.yaml을 열고 21번째 줄을 수정. 22번째 줄 삭제.
워커 노드 3번에 배포한 이미지와 중복되지 않게 success2.yaml에 설정된 이름이 success1을 모두 success2로 바꾸기
새로운 디플로이먼트를 생성
생성된 디플로이먼트가 정상적으로 작동하는지 확인
배포된 파드가 요청에 정상적으로 응답하는지 curl로 확인
배포한 디플로이먼트 삭제