블로그

wnsrlf0721

[워밍업 클럽:쿠버네티스] 미션#5. 컨테이너 이미지 사례 실습

해당 실습과정은 큐브옵스 카페의 미션을 실습한 과정입니다. Docker와 Containerd 명령 실습https://cafe.naver.com/f-e/cafes/30725715/articles/137 도커 (Docker)CI/CD 환경이 구축된 서버에서 진행▶ 사전 준비사항# 도커 파일 및 App 소스 다운로드 curl -O https://raw.githubusercontent.com/k8s-1pro/install/main/ground/etc/docker/Dockerfile curl -O https://raw.githubusercontent.com/k8s-1pro/install/main/ground/etc/docker/hello.js curl 명령어로 Dockerfile과 hello.js를 CI/CD 서버에 다운받았다. <실습 시작>​1. 빌드2. 이미지 리스트 조회docker image로 hello가 있는걸 확인 3. 태그 변경태크가 다른 이미지가 하나 더 생겼다. 4-1&2. 로그인 및 이미지 업로드Docker Hub를 확인하면 새로만든 hello image가 hub저장소에 있는 걸 확인 5. 이미지 삭제hello 이미지 1.0과 2.0 이 모두 CI/CD 서버에서 제거 된걸 확인 6. 이미지 다운로드Docker Hub에 저장된 hello 이미지를 서버로 다운로드함새로 1.0 hello가 생긴 걸 확인 7. 이미지 -> 파일로 변환hello 이미지를 file.tar로 변환하여 저장▶ 이미지 삭제8. 파일 -> 이미지로 변환file.tar 파일에 저장된 정보를 바탕으로 image load -> hello image 생성확인▶ 정리컨테이너디 (Containerd)쿠버네티스가 있는 인프라 환경에서 진행 <실습 시작>​1. 네임스페이스 조회2. 특정 네임스페이스 내 이미지 조회3. 다운로드 및 이미지 확인 (이미지는 default라는 네임스페이스에 다운 받아집니다.)default 네임스페이스가 생성되어졌고,default 에 hello image 생성을 확인 4. 태그 변경태그를 변경한 결과,이미지 1.0과 2.0이 존재하는 걸 확인 5. 업로드도커허브 상에 2.0 tag가 올라간걸 확인 6. 이미지 (namespace : default) -> 파일로 변환hello:1.0.0이 file.tar로 변환된걸 확인 7. 파일 -> 이미지로 변환 (namespace : k8s.io)k8s.io 네임스페이스에 file.tar 파일을 이미지로 변환해 저장한다.저장 결과 k8s.io 에 hello 이미지가 생성된걸 확인 8. 삭제 (namespace : k8s.io)같은 이미지를 도커에서 받았을 때와 쿠버네티스에서 받았을 때 사이즈가 다른 이유https://cafe.naver.com/f-e/cafes/30725715/articles/158 ▶ Docker Hub (248.26 MB)Docker Hub의 1pro/api-tester 이미지 중 latest tag를 다운받고 비교할 예정이다. ▶ Docker (490MB)▶ Containerd (248.3 MiB) 가정 1. Container Image를 만들 때 플랫폼(amd64, arm64)을 고려해야 되는데, Docker에서는 amd64를 받았고, Kuberentes에서 arm64를 받아서 이미지 크기가 달라졌을 것이다. ▶ Docker (amd64가 보임)▶ Containerd (amd64, arm64)가 보임containerd는 amd64와 arm64 두 버전을 모두 지원하는 이미지임에도 불구하고,amd64 한 버전만 지원하는 Docker의 이미지보다 크기가 작다.따라서 amd64이건 arm64이건 플랫폼에 따라 크기가 달라지는 건 아닌것 같다. 가정 2. Container 이미지는 각각의 Layer로 구성돼 있는데, Docker에서 다운 받을 때는 전체 Layer를 받았고, Kubernetes에는 기존 이미지에 이미 존재하는 Layer가 있기 때문에 새로 받은 이미지의 Size가 작게 조회 됐을 것이다. 위 가정이 맞는 지 확인을 위해 전 가정에서 설치했던 Docker image -> Containerd 옮겨보고,Containerd image -> Docker 환경으로 옮겨보며 사이즈가 어떻게 바뀌나 확인해보겠습니다.▶ Docker -> ContainerdIMG -> 파일로 변환1pro/api-tester image 를 파일로 변환시킨 후 (docker-image.tar 생성)[root@cicd-server ~]# docker save -o docker-image.tar 1pro/api-tester:latest크기를 확인해보니 490MB -> 472MB 로 조금 줄어들었다.파일 복사 (CI/CD -> k8s 서버로)아래와 같이 파일을 인프라 환경에 복사시키고, k8s-master 서버에서 결과를 확인해보겠습니다.정상적으로 잘 받아온 걸 확인했고, 이제 이미지로 변환해서 자료 크기를 확인해야겠죠?파일 -> IMG 변환기존에 존재했던 이미지를 삭제시킨 후, 복사한 파일을 image로 변환시킵니다.이후 k8s 상 동작하는 image 사이즈를 확인하니, 472MB -> 248.3MiB로 바뀌었습니다.▶ Containerd -> DockerIMG -> 파일로 변환k8s 상 존재하는 이미지는 Docker에서 가져온 파일을 통해 만든 것이므로, Docker Hub에서 pull로 이미지를 다시 다운받음.이 이미지를 이제 파일로 변환하면 되겠죠?IMG (248.3MiB) -> 파일 (249M) 변환 완료파일 복사 (CI/CD -> k8s 서버로)CI/CD 환경 상에 잘 복사가 된걸 확인파일 -> IMG 변환기존 이미지 삭제 후 containerd에서 가져온 파일을 img로 변환사이즈 확인 (490MB) 가정 3. 쿠버네티스에는 다른 Runtime을 사용 했을 수 있고, 같은 이미지더라도 사용하는 Runtime에 따라서 이미지의 크기는 달라질 것이다.일프로 님의 설명에 따르면, Docker는 다른 많은 기능들을 지원해 주기 때문에 (ContainerD 외에도) 실제 이미지가 248.26MB라고 하더라도, 다운 받은 이후 자신의 매타데이터 규격에 맞게 데이터들을 더 추가하고 이미지를 재구성 합니다. 그래서 490MB로 사이즈가 늘어난것!Containerd에서 이미지를 파일로 바꿔 복사를 해도, Docker 상에서 돌아가는 이미지를 구성할 때 데이터들을 추가해주니 사이즈가 늘어난거라 이해하면 될것 같다.즉, 우리는 컨테이너 이미지를 받을 때, 쿠버네티스에서 ContainerD를 사용해 컨테이너를 동작시키는 경우, Docker를 통해 이미지를 만들 경우 불필요한 데이터로 인해 이미지 사이즈가 더 커지게 될 수 있다는 걸 확인했다.

데브옵스 · 인프라k8sci/cd

승현

[인프런 워밍업 클럽 4기] 3주차 발자국

이번주 학습 내용이번주는 Devops의 역할, 배포 방법, 쿠버네티스 패키지 매니저(Helm)에 대해서 학습했다.아무래도 개발자이다 보니, 위 그림을 인상 깊게 보았는데, 내가 경험해온 Devops 엔지니어 분들은 개발 영역은 하지 않으셨고, 개발 부분은 개발자가 맡아서 하는 R&R이 확실하게 분리된 환경에서 업무를 해왔는데, 결국 나의 능력을 높이기 위해서는 개발 + 인프라까지 다룰 수 있어야 하는 건 맞는 것 같다. ( AI가 무섭게 성장하고 있는 흐름에서는 더더욱...! )그리고 추후 PM/PL/아키텍트 역할을 맡게 되었을때도 전체적인 그림을 볼 수 있어야 하기 때문에 전문가처럼 깊게는 아니더라도 전체적인 흐름은 알고 있어야 할 것 같다. 사실 이미지를 보자마자 놀랬다🤣🤣이 많은 내용을 다 알고 있어야 한다고?! 생각했는데 강사님께서 스탭별로 진행하면 된다고 말씀주셔서 다행이었다...나는 인프라는 곧 비용이다. 라고 생각하는데, 인프라 환경에 필요한 장비 또는 클라우드 비용이 매섭기 때문이다.회사의 지갑 사정에 따라서 또는 회사의 투자 상황에 따라서 인프라 환경도 달라질 것인데, 각 재정 상황에 맞는 파이프라인을 구축하면 되는 것 같다. 배포 방식에서는 Recreate / RollingUpdate / Blue&Green / Canary 이렇게 4개의 종류를 배웠는데, 가장 좋은 건 역시 Canary인 것 같다. (서비스는 죽으면 안되니까!)다만 이것도 결국 쿠버네티스를 얼마나 다룰 수 있는지 역량에 따라서 달라질 것 같다. Canary 배포 중 가중치가 안바뀐다거나? / 배포가 실행이 안된다거나?-> 여러 상황에 대해서 수동으로 처리할 수 있게 대응이 필요할 것 같다.)또한 서비스의 특징에 따라서도 어떠한 배포 방식을 선택할지 달라질 것 같다. 무중단이 아닌 운영시간이 정해진 서비스라면?-> 꼭 Canary 배포 방식을 선택하지 않아도 될 것 같다.회고요즘 퇴근 후 저녁에 3km 러닝을 하고 있는데, 러닝을 하면서 느끼는 것이 무엇이든지 단번에 되는 것이 아닌 절대적인 시간이 필요하고, 그 시간을 인내하고 꾸준히 달리는 것이 중요한 것 같다.학습도 마찬가지라는 생각이 든다. 어떠한 지식을 단번에 학습하려고 하지 말고, 천천히 꾸준히 학습하는 것이 중요한 것 같다.저번주 발자국에 일프로님께서 댓글을 달아주셔서 얼마나 놀랬는지 모르겠다ㅎㅎㅎ 이번 스터디는 완주를 목표로 학습하고, 추후에 꼭 복습해야겠다. 항상 디스코드 스레드 보면서 힘을 얻어갑니다! 마지막 4주차까지 파이팅!💪💪

데브옵스 · 인프라Devops일프로워밍업클럽인프런4기데브옵스쿠버네티스k8s

wnsrlf0721

[워밍업클럽: 쿠버네티스] #11. 배포 전에 알아줘야 할 것들

CI/CD 배포 환경을 만들 때, 몇가지 고려할 요소들을 생각한 후에 환경 구성방법을 선정해주는 것이 좋다.배포 환경 안에서 담당부분이 나누어 지는 경우. 운영 정책 상 한 배포 구성에서 개발 과 운영 파트를 분리하는 경우배포한 툴 제품 선정 시 보안 및 유지보수에 따라 선택하는 경우 로 하나씩 요소들을 살펴보겠다.  배포 환경 안에서 담당부분이 나누어 지는 경우CI/CD 환경에서 소스코드를 빌드하고, 컨테이너에 담아 배포하는 과정을 분리해서 담당하는 경우와, 파이프라인을 구축해 과정 전체를 한번에 배포까지 하는 경우로 구분할 수 있다.파이프라인을 구축해 자동화하는 것이 효과적으로 보일 수 있지만, 프로젝트 규모가 커지면서 관리해야하는 담당이 정해져 있는 경우엔 과정 하나하나를 분리해 업무를 분장하는 것이 효율적이다.각 상황에 맞추어서 소스 빌드는 개발자가 담당하고, 컨테이너를 빌드하고 배포하는 역할은 Devops 엔지니어가 담당하는 것과 같이 유동적으로 선정을 할 줄 아는 것이 좋다. 운영 정책 상 한 배포 구성에서 개발 과 운영 파트를 분리하는 경우젠킨스 빌드 환경 안에서 배포를 하는 경우도 가능하지만, ArgoCD를 통해 배포를 구성하는 경우도 가능하다.즉, 빌드 파트와 배포 파트를 분리하는 것이며, 이때 배포 환경과 인프라 환경을 구축할 때 1:N 관계로 한 배포 구성에서 개발과 운영 인프라를 구성하는 방법과1:1 관계로 인프라 환경마다 배포 환경을 구성하는 경우 (개발, 운영 인프라 분리) 로 구분할 수 있다.각 인프라마다 배포 환경을 구성하는 경우(1:1) , 이중 관리가 필요해지지만 서로의 환경에 영향을 주는 것이 없어 한 인프라에 장애가 발생해도 다른 인프라에 영향도가 없다.반면 배포 환경 하나로 여러 인프라를 구성하는 경우(1:N), 관리의 부담은 줄어들지만 개발 인프라에서 장애가 발생하는 경우 운영 인프라에서도 장애를 받아 배포를 못하게 되는 등 영향을 받게된다.이렇게 어떤 구성을 하는 지에 따라 각각의 장단점이 존재하므로, 운영 정책에 따라 관리 편의성을 중시할 지 / 장애 영향도를 중시할 지 적절히 선택을 해야한다. 배포 툴 제품 선정 요소CI/CD 제품은 온라인용으로 GitHub Actions, CI tool로는 TravisCI, circleCI, 오프라인용으로 Jenkins, JenkinsX, Tenton, CD tool로 argoCD, Sprinaker 등이 있다.온라인용을 선택할 시 따로 CI/CD 서버를 별도 구성할 필요가 없다는 장점이 있으며, 오프라인용은 인터넷에 App의 데이터를 올리면 안되는 경우 선택을 한다. 금융권이나 의료기관 등 시스템에서 다루는 데이터가 중요한 경우 인터넷 영역으로 올리지 않으며, 오프라인 툴을 선택을 하는 것이다.  또한 컨테이너 빌드 시 도커를 쓰지 않고 다른 툴들을 사용하기도 한다. 도커는 기능이 많아 제품이 무겁다는 것과(자원 차지 많음), Daemon을 항상 유지해야하는 단점이 있다(리눅스 OS 백그라운드에 항상 실행되어야한다). 반대 개념인 Daemon리스트 앱, kubectl은 별도로 실행유지를 하지 않고 명령어만 사용할 때 실행을 하는 구조이다.그래서 도커로 컨테이너를 여러개 띄운 상태에서 데몬이 죽으면 컨테이너가 모두 다운된다는 단점이 존재한다. 그치만 CI/CD 환경에서 도커는 컨테이너 빌드용으로 사용되고, 인프라 환경에서 쿠버네티스를 통해 컨테이너를 띄우기 때문에 치명적인 단점이 되지는 않는다. 그래도 자원을 잘 활용하려는 상황에선 다른 툴을 사용하는 것이 좋고,대표적인 컨테이너 빌드 툴로 builah가 있다. 도커허브에서 podman으로 jdk 이미지를 받고, 컨테이너 빌드 후 skopeo로 이미지를 허브에 업로드 해주는 과정은 도커와 유사하지만, 자원사용량이 낮다는 장점이 있다. 배포전략배포 전략으로 Recreate, RollingUpdate, Blue/Green, Canary 가 있다.Recreate새로운 파드를 배포를 하게 되면, 기존의 파드들은 운영을 멈추고, 새로운 파드를 생성해 운영하는 방식이다.새로운 파드가 동작하기 전까지 기존 서비스가 운영하지 못하는 Downtime이 존재한다.RollingUpdate새로운 파드를 배포할 때, 기존 파드를 얼마나 줄이고, 새로운 파드를 얼마나 늘릴지 정해서 단계적으로 파드를 교체해나가는 방식이다. 서비스는 중단되지 않고 계속해서 운영된다는 특징이 있다.Recreate와 RollingUpdate 방식은 Deployment를 업데이트하면 자동으로 배포되는 방식이고,배포되는 동안 중지하거나, 기존 버전으로 롤백이 가능하다.또한 각 파드에 대한 트래픽을 조정하는 것은 불가능하며, 파드 개수만큼 트래픽이 1/n 분배되는 방식이다. Blue/Green기존 버전 v1의 Deployment를 업데이트하는 것이 아닌, 새로운 버전으로 v2 Deployment를 생성하면, 관련된 파드들이 추가로 생성이 된다. 이후 Service에서 기존 v1에서 v2로 selector를 변경해 새로운 파드에 트래픽이 들어오도록 변경해주면, 기존의 v1 Deployment를 삭제해주는 방식이 Blue/Green이다.이 방식은 수동으로 배포를 해주는 방식이라 도중에 문제를 발견하면 바로 롤백이 가능하다는 장점과, 배포 과정을 Script로 작성을 하게 되면 자동 배포도 가능해진다는 장점을 가진다.하지만 새로운 버전 v2로 전환한 직후 트래픽이 과도하게 들어올 경우 문제가 발생할 수 있다.앱이 처음 기동을 하면 memory, DB를 최적화하는 과정이 필요해 CPU 사용량이 늘어나게 되고, 해당 과정동안 트래픽이 많아지게 되면 파드가 죽어버리는 경우가 생길 수 있다. -> 사전에 부하 테스트를 통해 배포가 가능한 지 미리 확인하는 과정이 필요하다.또한 운영 DB에서만 테스트가 가능한 유즈케이스의 경우 Blue/Green 배포 방식이 최적의 케이스가 된다.CanaryBlue/Green 방식에서 각 서비스에 Ingress 리소스를 추가해 서비스마다 들어오는 트래픽 양을 조절할 수 있는 방식이다.Nginx 같은 Ingress Controller로 각 서비스의 Ingress마다 트래픽 수치를 조정할 수 있다는 장점을 가진다.Canary 방식은 특정 헤더 값에 한해서 다른 서비스에 트래픽 유입을 조정할 수 있다. SourcePort, User, Language 등 원하는 값을 설정해 특정 트래픽으로 다른 서비스에 유입시키는 방식의 유즈케이스에서 유용하다. 사실 Recreate 방식을 제외하면 모두 무중단배포라는 특징을 가진다. 하지만 무중단배포가 무조건 좋은것은 아니며,상황에 맞게 배포방식을 선택하는 것이 좋다. DB schema를 변경해야하는 경우 서버를 내리고 DB 작업을 마친 후에 다시 서버를 운영하는 것이 맞는 방식이다. 파이프라인 단계별로 구축하는 방법배포 방식으로 여러 방식을 사용하는 걸 앞서 요소 별로 살펴보았는데, 처음부터 파이프라인을 만들고, 배포 툴을 사용해서 CI/CD 환경을 구축하는 것보다, 최대한 간단한 방식으로 먼저 배포 구성을 해보고, 점차 방식을 바꿔가면서 툴을 추가하는 것이 안정적으로 구성하는 방법이다.Jenkins 기본 구성 -> 실습했던 방식처럼 Jenkins 환경 세팅 후, 소스코드 빌드, 컨테이너 빌드, 배포 방식을 구분해서 실행하는 방식이다. Jenkins Pipeline 구성jenkins Pipeline은 배포때 사용한 yaml파일, DockerFile처럼 JenkinsFile이라는 스크립트를 기반으로 파이프라인을 관리할 수 있다. 처음부터 Script를 구성하기 보단, Jenkins Dashboard에서 제공하는 UI로 먼저 만들어보고, 해당 구성에 맞게 샘플 코드를 알려주니 이후 Script 코드를 짜는 방식으로 나아가는 게 좋다.Kustomize, Helm 배포 툴 사용인프라 환경 별로 배포를 하려면 기존에는 각 환경마다 yaml파일을 복사해 값을 수정하는 방식을 사용했다면,배포 툴에선 Package를 통해 각 환경마다 다르게 줘야 할 변수들을 지정해 한 yaml 파일에 동적으로 값을 주는 방식을 사용할 수있다. 덕분에 yaml 여러개를 구성해 관리하지 않고, 하나의 yaml로 관리가 가능해졌다.ArgoCD로 빌드와 배포 분리Jenkins 환경에서 배포를 하는 것이 아닌, 새로운 배포 환경을 구성해 ArgoCD 환경에서 Helm 같은 배포 툴을 사용하는 방식이다. ArgoCD는 기존 yaml 파일 같은 스크립트 파일을 원격 저장소에 저장을 하면, 인프라 환경에 존재하는 파일과 비교를 하며 원격 저장소에서 값이 바뀌면 인프라에도 반영하거나, 인프라에서 수정되면 저장소 상에도 반영을 해주는 동기화를 제공한다. 또한 대시보드를 통해 k8s와 Resource 간의 관계도를 표현해주는 기능도 있어 유용하게 사용할 수 있다.

데브옵스 · 인프라k8sCI/CDDeployment

[워밍업클럽: 쿠버네티스] #9. Devops 한방정리

강의 수강일자: 25.06.10(화)블로그 복습일자: 25.06.12(목) 가볍게 데브옵스에 대해 흐름을 살펴보는 강의였다.앱 개발 -> 빌드 -> 배포 및 실행 을 내 pc환경에서 지금까지 실행했다면, 데브옵스를 적용하면 앱 개발 파트를 내 pc에서 개발 및 테스트 이후 소스코드를 깃허브에 올리고,깃허브에 여러 사람들이 올린 코드를 빌드 툴(jenkens 등) 을 이용해 자동 빌드하고, 빌드 후 만들어진 jar 파일을 도커 허브에 업로드하는 과정을 거친다. 도커 허브에 올리려면 파일을 컨테이너에 올려야 하는데, 도커로 컨테이너를 빌드하고, 해당 컨테이너에 파일을 올린 후, 해당 컨테이너를 내 도커허브에 올린다.이후 젠킨스에서 배포를 진행하면, kubectl을 통해 쿠버네티스 상에 컨테이너 생성 명령을 내리고, 컨테이너에 생성되는 이미지 주소를 확인해 도커허브에서 이미지를 다운받고, 해당 이미지에 대한 컨테이너 생성을 런타임에 요청한다. 이후 쿠버네티스 상에서 컨테이너를 운영을 해준다. 운영간에 사용되는 쿠버네티스의 클러스터, 오브젝트들은 sprint1에서 배웠던 내용이다. 인프라 환경에서 App을 실행한 후, 잘 돌아가는 지. loki나 grafana로 모니터링도 가능하다. 구체적으로 CI/CD 환경을 구축하고, 인프라 환경에 App을 배포하는 과정은 다음 강의에서 다룰 예정이라,이번 강의에서는 전체적인 흐름을 다시 짚고 넘어가는 느낌이 들었다. 정말 가볍게 강의를 듣고, 흐름을 파악하는 정도로 들었다.

데브옵스 · 인프라k8s

[ 인프런 워밍업 클럽 4기 Devops ] 1 주차 발자국(13일의 금요일 -안상민)

강의 수강 내용월 - OT, Q & A화 - Sprint1 컨테이너 한방 정리수 - 무게감 있게 쿠버네티스 설치목 - 실무에서 느껴 본 쿠버네티스 정말 평한 이유금 - Object를 그려보며 쿠버네티스 이해 강의 칭찬하고 싶은 점칭찬하고 싶었던점 헤이해졌었지만 다시 마음 잡아 공부를 시작한거 복습 글을 모두 작성했던 것 칭찬하고 싶습니다.아쉬웠던 점필기로 그려봐서 나의 것으로 확실히 만들려 했는데 글이나 그림 그리는데 시간이 부족해서 다 하지 못했습니다.그리고 시간이 상당히 오래 걸려서 비효율적이였습니다.보안해야 될 점쓸데 없는데 힘 빼지 말고(그림이나 글 직접 그리거나 쓰기) 공부하는 시간 딱 집중해서 수업을 듣고 복습 내용 바로 정리 해서 글 올리기, 발자국을 일주일 다되서 작성하지 말고 복습 그날그날 하면서 회고 때 넣을 내용 생각날 때 적어두기(생각 이 안남) 미션 미션 해결 하는 과정VM & K8S 설치 스크립트 도중에 종료처음에 스크립트가 시간이 꽤나 오래 걸리는지 모르고 렉이 걸려서 안되는지 알았다. ctrl + c 로 중지하게 되었다.그랬더니 남아 있는 베이그란트 프로세스가 컴퓨터 관리자에 남아 있어서 vagrant up 명령이 듣지를 않았다.검색 후에 돌아가고 있는 vagrant 프로세스를 다 종료, VM 에 남아 있는 모든 vagrant 관련 디렉터리를 삭제 후에다시 설치 했더니 문제가 해결이 되었다. 프로메테우스 모니터링 보드 오류프로메테우스 모니터링 보드에 모든 데이터가 No data 로 되어 있어서 Locky 가 k8s 클러스터 상의 컴포넌트들의 메트릭스를 수집 못하고 있나해서 Locky를 삭제 후 다시 깔았다. But 증상은 똑같았고 프로메테우스와 Locky를 모두 삭제 후 다시 설치 했더니 정상적으로 K8s의 파드 디폴로이 먼트 등 컴포넌트들의 모니터링이 가능해졌다.  

k8s회고발자국컨테이너VMk8s클러스터설치

wnsrlf0721

[워밍업 클럽: 쿠버네티스] #6. Configmap, Secret (2주차)

복습한 내용과 미션3를 함께 포함해서 작성하였다. 강의 수강 일자 : 25.06.03 (화)블로그 복습 일자 : 25.06.08 (일) ConfigMapconfigmap에 대한 세팅 정보이다.metadata에는 다른 object와 마찬가지로 소속된 namespace, 이름, labels 등이 존재하고,파드와 연결될 때 아래 코드와 같이 이름을 매칭해서 연결해준다.configmap에서 봐야할 것은 data 부분으로, 아래 데이터들을 Pod에 환경변수로 전달한다. 인프라의 환경: (개발/검증/운영) 환경 중 App이 돌아가는 환경을 뜻한다. "dev" 의 경우 App이 개발환경을 뜻한다. 이 환경변수 값은 App이 기동되는 시점에 전달되어 알려준다.App의 기능을 제어하기 위한 값 : ALL, GET, POST 등등secret stringData로 연결할 파일 경로(filePath)이다.mountPath에 연결될 경로를 설정하고, 해당 경로에서 사용할 파일 이름을 설정한다. Secretsecret은 다음과 같이 세팅을 하게 된다. 우리는 stringData만 잘 살펴보면 된다.postgresql-info.yaml 파일이 만들어 지고,| 이하에 적힌 코드들이 해당 파일에 저장된다는 의미이다.stringData는 쓰기 전용 속성이라 실제 저장될 경우 configmap과 같이 data 형식으로 저장이된다.저장될 경우 위에 적힌 값들이 Base64 기반으로 인코딩된 값으로 변경되어 저장된다.mountPath에 기록된 Path 값에 해당 data가 전달되어 디코딩된 값으로 파일이 저장되고,App이 기동하면 파일을 로딩해 안에 들어있는 정보로 데이터베이스를 세팅한다. 미션#3▶ 응용1 : Configmap의 환경변수들을 Secret을 사용해서 작성하고, App에서는 같은 결과가 나오도록 확인해 보세요.configmap의 이 값을 secret으로 저장을 하고, Deployment 부분에서 연결되는 부분을 secret으로 편집하면 된다.secret은 다음과 같이 생성해준다. 1) dashboard로 생성하기2) 시크릿에 잘 생성되었는지 확인3) Deployment 편집 ▶ 응용2 : 반대로 Secret의 DB정보를 Configmap으로 만들어보고 App을 동작시켜 보세요이번엔 secret에 들어있던 db 세팅정보를 configmap 형태로 전달하도록 바꿔야한다. 1) dashboard로 configmap 생성하기stringData에 들어있는 값을 data에 대입한다. 2) 컨피그 맵 생성 확인하기3) Deployment 값 변경하기 volumes 부분과 MountPath 부분을 업데이트한다.

데브옵스 · 인프라k8smission

David

[인프런 워밍업 클럽 4기 - DevOps] 미션 4

PV, PVC1번 API 파일 생성[root@k8s-master ~] curl http://192.168.56.30:31231/create-file-pod hrgosbpjox.txt [root@k8s-master ~] curl http://192.168.56.30:31231/create-file-pv xprrmxjsna.txt2번 Container 임시 폴더 확인[root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-5krzn -- ls /usr/src/myapp/tmp hrgosbpjox.txt [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-5krzn -- ls /usr/src/myapp/files/dev xprrmxjsna.txt [root@k8s-master ~] ls /root/k8s-local-volume/1231/ xprrmxjsna.txt2번 master node 폴더 확인[root@k8s-master ~] ls /root/k8s-local-volume/1231/ xprrmxjsna.txtpod 삭제[root@k8s-master ~] k delete -n anotherclass-123 pod api-tester-1231-66c489cbb8-5krzn pod "api-tester-1231-66c489cbb8-5krzn" deleted4번 API - 파일 조회[root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-9kpxd -- curl localhost:8080/list-file-pod [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-9kpxd -- curl localhost:8080/list-file-pv xafgvinxxz.txt thschtbuoo.txt pablwvxlec.txt pogdzjqhqs.txt xprrmxjsna.txt 5. hostPath 동작 확인 - Deployment 수정 후 [1~4] 실행apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 volumeMounts: - name: files mountPath: /usr/src/myapp/files/dev - name: secret-datasource mountPath: /usr/src/myapp/datasource volumes: - name: files persistentVolumeClaim: // 삭제 claimName: api-tester-1231-files // 삭제 // 아래 hostPath 추가 hostPath: path: /root/k8s-local-volume/1231 - name: secret-datasource secret: secretName: api-tester-1231-postgresql[1~4 반복]API - 파일 생성 [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-9kpxd -- curl localhost:8080/list-file-pod [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-66c489cbb8-9kpxd -- curl localhost:8080/list-file-pv xafgvinxxz.txt thschtbuoo.txt pablwvxlec.txt pogdzjqhqs.txt xprrmxjsna.txt Container 임시 폴더 확인 root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-7gtwq -- ls /usr/src/myapp/tmp yrwjythrtf.txt Container 영구저장 폴더 확인 [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-7gtwq -- ls /usr/src/myapp/files/dev lbjgryyqvl.txt pogdzjqhqs.txt xafgvinxxz.txt pablwvxlec.txt thschtbuoo.txt xprrmxjsna.txt Master node 폴더 확인 [root@k8s-master ~] ls /root/k8s-local-volume/1231 lbjgryyqvl.txt pablwvxlec.txt pogdzjqhqs.txt thschtbuoo.txt xafgvinxxz.txt xprrmxjsna.txt API - 파일 조회 root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-7gtwq -- curl localhost:8080/list-file-pod yrwjythrtf.txt [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-7gtwq -- curl localhost:8080/list-file-pv lbjgryyqvl.txt xafgvinxxz.txt thschtbuoo.txt pablwvxlec.txt pogdzjqhqs.txt xprrmxjsna.txt RollingUpdate 하기HPA minReplica 2로 바꾸기 [root@k8s-master ~] k patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":2}}' horizontalpodautoscaler.autoscaling/api-tester-1231-default patched 그외 Deployment scale 명령 [root@k8s-master ~] k scale -n anotherclass-123 deployment api-tester-1231 --replicas=2 deployment.apps/api-tester-1231 scaled edit로 모드로 직접 수정 kubectl edit -n anotherclass-123 deployment api-tester-1231 지속적으로 Version호출 하기 while : do curl http://192.168.56.30:31231/version sleep 2 echo '' done 3) 별도의 원격 콘솔창을 열어서 업데이트 실행 kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.0 kubectl set image -n anotherclass-123 deployment/api-tester-1231RollingUpdate (maxUnavailable: 0%, maxSurge: 100%) 하기strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 0% maxSurge: 100% kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v1.0.0 Recreate 하기 strategy: type: Recreate [root@k8s-master ~] kubectl set image -n anotherclass-123 deployment/api-tester-1231 api-tester-1231=1pro/api-tester:v2.0.0 deployment.apps/api-tester-1231 image updated Rollback[root@k8s-master ~] kubectl rollout undo -n anotherclass-123 deployment/api-tester-1231 deployment.apps/api-tester-1231 rolled back ServicePod 내부에서 Service 명으로 API 호출[root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-88cqq -- curl http://api-tester-1231:80/version [App Version] : Api Tester v1.0.0 Deployment에서 Pod의 ports 전체 삭제, Service targetPort를 http -> 8080으로 수정apiVersion: apps/v1 kind: Deployment metadata: namespace: anotherclass-123 name: api-tester-1231 spec: template: spec: nodeSelector: kubernetes.io/hostname: k8s-master containers: - name: api-tester-1231 ports: // 삭제 - name: http // 삭제 containerPort: 8080 // 삭제 --- apiVersion: v1 kind: Service metadata: namespace: anotherclass-123 name: api-tester-1231 spec: ports: - port: 80 targetPort: http -> 8080 // 변경 nodePort: 31231 type: NodePort [root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-88cqq -- curl http://api-tester-1231:80/version [App Version] : Api Tester v1.0.0 HPA[root@k8s-master ~] k top -n anotherclass-123 pods NAME CPU(cores) MEMORY(bytes) api-tester-1231-6cf7495fcd-88cqq 1m 140Mi [root@k8s-master ~] k top -n anotherclass-123 pods NAME CPU(cores) MEMORY(bytes) api-tester-1231-6cf7495fcd-88cqq 104m 161Mi [root@k8s-master ~]# k get hpa -n anotherclass-123 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE api-tester-1231-default Deployment/api-tester-1231 56%/60% 2 4 2 3d8h [behavior] 미사용으로 적용spec: # behavior: # scaleDown: # policies: # - periodSeconds: 15 # type: Percent # value: 100 # selectPolicy: Max # scaleUp: # policies: # - periodSeconds: 15 # type: Pods # value: 4 # - periodSeconds: 15 # type: Percent # value: 100 # selectPolicy: Max # stabilizationWindowSeconds: 120 [root@k8s-master ~] kubectl edit -n anotherclass-123 hpa api-tester-1231-default horizontalpodautoscaler.autoscaling/api-tester-1231-default edited부하 발생 API[root@k8s-master ~] k exec -n anotherclass-123 -it api-tester-1231-6cf7495fcd-88cqq -- curl http://192.168.56.30:31231/cpu-load[root@k8s-master ~] k get hpa -n anotherclass-123 NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE api-tester-1231-default Deployment/api-tester-1231 101%/60% 2 4 4 3d8h [root@k8s-master ~] k top -n anotherclass-123 pods NAME CPU(cores) MEMORY(bytes) api-tester-1231-6cf7495fcd-5b6bw 202m 157Mi api-tester-1231-6cf7495fcd-88cqq 1m 140Mi api-tester-1231-6cf7495fcd-br5d2 1m 127Mi api-tester-1231-6cf7495fcd-wzx9k 1m 127Mi       

데브옵스 · 인프라devopsk8shpapvpvcservicerolling

kndh2914

인프런 워밍업 클럽 4기 - DevOps 2주차 발자국

[2주차 강의 수강]2주차 기간동안 k8s의 applicaition 기능으로 k8s를 이해하는 시간을 가졌다. 또한 실습시간에 k8s의 기능들을 보다 제대로 활용하기 위해 많이 활용하면서 장난감 다루듯이 마구잡이로 다뤘던 시간들을 경험하게 되었다. 미션과제도 해보고 실습을 따라해보면서 완벽하게 해보지는 못했지만 따로 복습시간을 가지면서 더욱 더 k8s를 이해하게 되었고 실무에 나갔을 때도 확실하게 다룰 수 있도록 배우는 자세를 가지게 되었다.[미션] [2번미션]링크: https://du-hyeon.notion.site/5-Application-1-Probe-20722449e85a8014a350c93b419f22ec?source=copy_link [3번미션]링크:https://du-hyeon.notion.site/6-Application-2-Configmap-Secret-20722449e85a80c3a914c3b9ae1e043b?source=copy_link [4번미션]링크: https://du-hyeon.notion.site/7-Application-PV-PVC-Deployment-Service-HPA-20822449e85a8015ad0de48924b42dbe?source=copy_link  회고: 2주차에는 미션이 3개이면서 많은 실습시간을 투자한 기간이였을뿐더러 더욱 더 손에 익히고 눈으로 많이 보게되면서 k8s의 구조와 어떠한 상황에서 기능을 써야 더 좋은 시너지가 일어나는지에 대한 시간을 가지게 되었다. 다음주부터는 3주차이고 벌써 스터디의 절반이 지났다고 한다. 또한 3주차부터는 Sprint2로 넘어가기 때문에 더더욱 설레는 마음으로 공부를 할 계획이다.

데브옵스 · 인프라k8s인프라일프로devops화이팅워밍업클럽4기

David

[인프런 워밍업 클럽 4기 - DevOps] 미션 3. Configmap, Secret

▶ 응용1 : Configmap의 환경변수들을 Secret을 사용해서 작성하고, App에서는 같은 결과가 나오도록 확인해 보세요.☞ Secret을 이렇게 사용하는 경우는 별로 보지 못했습니다. 여러가지 방법으로 Secret을 만들어본다는데 의의를 두시면 됩니다. Secret 생성 (1) - Dashboard확인을 위해 Dashboard에서 Secret 선택CMD 확인Deployment에서 envFrom 수정▶ 응용2 : 반대로 Secret의 DB정보를 Configmap으로 만들어보고 App을 동작시켜 보세요☞ Configmap을 Volume에 연결해서 쓰는 케이스는 매우 많습니다. apiVersion: v1 kind: ConfigMap metadata: namespace: anotherclass-123 name: api-tester-1231-postgresql labels: part-of: k8s-anotherclass component: backend-server name: api-tester instance: api-tester-1231 version: 1.0.0 managed-by: dashboard data: postgresql-info.yaml: | driver-class-name: "org.postgresql.Driver" url: "jdbc:postgresql://postgresql:5431" username: "dev" password: "dev123"  volumes: - name: files persistentVolumeClaim: claimName: api-tester-1231-files - name: configmap-datasource configMap: name: api-tester-1231-postgresql defaultMode: 420 ... volumeMounts: - name: files mountPath: /usr/src/myapp/files/dev - name: configmap-datasource mountPath: /usr/src/myapp/datasource/dev

데브옵스 · 인프라k8s인프런devopssresecretconfigmap쿠버네티스

David

[인프런 워밍업 클럽 4기 - DevOps] 미션 2. Probe 응용과제

응용 과제Application 로그를 통한 probe 동작 분석#사전 작업#kubectl patch -n anotherclass-123 hpa api-tester-1231-default -p '{"spec":{"minReplicas":1}}' Grafana 접속 후 Pod 로그 화면 설정Pod 삭제Application Log 확인마스터 노드에서 실행// 1번 API - 외부 API 실패 curl http://192.168.56.30:31231/hello // 2번 API // 외부 API 실패 curl http://192.168.56.30:31231/hello // 내부 API 성공 kubectl exec -n anotherclass-123 -it api-tester-1231-7459cd7df-2hdhk -- curl localhost:8080/hello kubectl exec -n anotherclass-123 -it <my-pod-name> -- curl localhost:8080/hello // 3번 API - 외부 API 성공 curl http://192.168.56.30:31231/hello // 4번 API // 트래픽 중단 - (App 내부 isAppReady를 False로 바꿈) curl http://192.168.56.30:31231/traffic-off // 외부 API 실패 curl http://192.168.56.30:31231/hello // 트래픽 재개 - (App 내부 isAppReady를 True로 바꿈) kubectl exec -n anotherclass-123 -it api-tester-1231-7459cd7df-2hdhk -- curl localhost:8080/traffic-on // 5번 API - 장애발생 (App 내부 isAppLive를 False로 바꿈) curl http://192.168.56.30:31231/server-error 응용 1. startupProbe가 실패 되도록 설정해서 Pod가 무한 재기동 상태가 되도록 설정해 보세요.[결과]응용 2. 일시적 장애 상황(App 내부 부하 증가)가 시작 된 후, 30초 뒤에 트래픽이 중단되고, 3분 뒤에는 App이 재기동 되도록 설정해 보세요.설정 후 API 요청하면 성공하지만 그 이후에는 차단응용 3. Secret 파일(/usr/src/myapp/datasource/postgresql-info.yaml)이 존재하는지 체크하는 readinessProbe를 만들어 보세요.해당 Pod 내부에 파일이 존재하기 때문에 실패 로그는 확인 불가 

데브옵스 · 인프라DevOpsSRE일프로Probek8smsa

wnsrlf0721

[워밍업 클럽: 쿠버네티스] 1주차 발자국

5.26 ~ 6.1 까지 쿠버네티스 강의를 듣고 난 후 소감을 정리한 발자국입니다. 인프런으로 공부를 시작한 건 자바와 spring 강의를 들어보면서 처음 공부를 시작했는데,어느 날 우연히 인프런 워밍업 클럽을 홍보하는 걸 보게 되었고, 마침 데브옵스에 대해 스터디를 하는 커리큘럼이 있어, 그냥 고민없이 이 강좌를 신청했습니다.노베이스라 학습 시간이 많이 걸릴거라 예상을 했는데, 취업준비로 크게 준비하고 있는 것이 없어 무난하게 학습할 수 있을거라 생각했고, 이제 1주차를 무사히 마쳤습니다 😀 1주차를 마무리하며 내가 적었었던 복습 블로그를 살펴보니 그래도 꽤 많은 내용을 정리한 것 같습니다.첫번째 강의 #1. 컨테이너 한방정리는 쿠버네티스가 어떤 환경에서 동작하는지, 컨테이너가 무엇이고 컨테이너 런타임은 또 무엇인지 강의 흐름대로 따라와보니 쿠버네티스가 돌아가는 환경에 대해 배운 시간이였습니다.두번째 강의 #2. 쿠버네티스 무게감 있게 설치하기는말그대로 저한테는 좀 무게감이 있는 설치하기 였습니다. 스크립트 코드를 그대로 따라치니 일단 동작은 하는데, 왜 이 스크립트를 짰는지 나름대로 혼자 공부하는 시간을 가졌습니다. 그런데 알고보니 미션1을 따라서 그대로 복습을 하면 저절로 알게 되는 내용들이 많았습니다 ㅋㅋ. 복습하고 나니 스크립트 코드들은 다 쿠버네티스 공식문서에 나온 내용대로 코드가 진행된다는 걸 알게 되었고, 정말 OS가 바뀌거나 다른 컨테이너 기능들을 추가한다 하더라도, 쿠버네티스 공식문서를 참고해 흐름을 따라가는 방법을 어느정도 깨우쳤던 강의였습니다. 1주차 중 가장 시간을 많이 투자했고, 배운 것도 많은 강의입니다. 세번째 강의랑 네번째 강의는 강의를 듣기는 들었지만, 제대로 복습을 하진 못했습니다.토요일날 SQLD 자격증 시험이 있어서, 쿠버네티스 공부를 좀 며칠 놓고 DB공부를 하다 왔습니다 😅주말에 조금씩 공부를 하긴 했지만, 사실 완전히 내용을 이해했다? 라고 말하기엔 부끄러운 수준인것 같습니다.내용을 정리하면서 조금 더 복습을 해야겠다 마음을 다잡게 되었고, 2주차에는 또 이 내용들이 연결되어서 더 자세하게 공부할 수 있는 내용이라 앞으로 배울 내용은 더 열심히 해야겠다 다짐하게 됐습니다.어쨌든 1주일을 쿠버네티스 강의 듣기와 블로그 작성에 시간을 투자하고, 마무리 회고를 작성하니 조금 뿌듯한 기분이 듭니다 ㅎㅎ. 앞으로도 열심히 강의 듣고 완주까지 열심히 달려볼게요~

데브옵스 · 인프라k8s1주차회고

kndh2914

인프런 워밍업 클럽 4기 - DevOps 1주차 발자국

[1주차 강의 수강]1주차 기간동안 쿠버네티스의 역사와 이해하고 제대로 활용하기 위해서 관련 키워드부터 용어들을 알게되는 시간을 가졌다. 또한 섹션 하나하나 마다 좋은 강의들이 있어 이해하는데 다소 어렵지 않았을 뿐더러 실습시간이 포함이 되어있어 눈으로 읽는것 보다 컨테이너를 Pod를 포함하여 전체적인 쿠버네티스를 만들어보고 삭제해보는 시간을 가졌기에 머리로 이해하는데 훨씬 수월해졌다. 회고: 1주차 강의를 퇴근하고 들으면서 다소 피곤하면서 들었던 적이 몇번은 있었지만 그럼에도 매 강의마다 좋은 정보와 조언 그리고 수강생분들이 재밌게 접근할 수 있도록 커리큘럼을 만들었기에 피곤함이 많이 사라지곤 했다. 다음주부터는 2주차 강의를 수강을 하게 된다. 2주차부터는 더욱 더 좋은 컨디션으로 강의 수강에 임할것이다.[미션]링크: https://du-hyeon.notion.site/2-4-20122449e85a80f18d5be4b504858dbb?pvs=4회고: 밑바닥부터 설치를 진행하였고 k8s 구축하는 명령어를 입력할 때마다 무슨 의미이고 이게 어떠한 결과가 일어나는지 몰랐지만 반복의 반복 계속해서 복습하였고 이 명령어가 왜 이 상황에서 일어나야 하는지 알게 되었다. 역시 한번 만에 이해하는 것은 신이 아닌 이상 인간으로써는 복습만이 살 길이라는 것을 알게 되는 시간 이였다.

데브옵스 · 인프라일프로k8sDevOps인프런

wnsrlf0721

[워밍업 클럽: 쿠버네티스] 미션 #1. 쿠버네티스 설치 구간별 상태 확인

강의 수강 일자 : 25.05.28 (수)미션 수행 일자 : 25.05.28 (수), 25.05.29 (목) 위 내용은 https://cafe.naver.com/f-e/cafes/30725715/articles/24?menuid=13&referrerAllArticles=false&page=2쿠버네티스 강의를 듣고 미션을 따라가보며 쿠버네티스 환경을 이해하는 과정을 자연스럽게 적어냈다.미션은 1번 부터 시작해서 마지막 9번까지로 되어있고,분류를 했을 때, 1-3번은 개인 PC에 쿠버네티스를 설치한 후 설치가 잘 이루어졌는지, 버전을 확인하는 과정이고,4-9번은 Vagrantfile 에 적힌 내용을 해석하는 과정이다.우리는 Vagrant를 통해 가상환경을 구축하고, 쿠버네티스의 각종 노드들을 설치하는 과정을 배운다. [1-1] 내 PC 네트워크 확인▶ 윈도우 > 실행 > cmd 입력 > 확인c:\사용자>ipconfigIPv4 Address: 192.168.219.100 확인 [1-2] 내 PC 자원 확인▶ 윈도우 하단 상태바 우클릭 > 작업관리자 > 성능 탭일프로님이랑 동일한 CPU를 쓰고 있었네요... ㅎㅎ [1-3] VirtualBox 설치 버전 확인▶ Virtualbox 실행 > 도움말 > Virtualbox 정보VirtualBox version: 7.1.6 [1-4] Vagrant 설치 버전 확인▶ 윈도우 > 실행 > cmd 입력 > 확인c:\사용자>vagrant --version[1-5] 원격접속(MobaXterm) 설치 버전 확인▶ MobaXterm 실행 > Help > About MobaXterm[2-1] VirtualBox VM 확인▶ Virtualbox 실행 > VM Name 확인▶ 네이밍 : <Vagrant 폴더명>_<VM Name>_<ramdom>[2-2] 내 VM에 적용된 NAT 확인▶ Virtualbox 실행 > k8s_master-node 마우스 우클릭 > 설정 > 네트워크 > 어댑터 1NAT에 연결이 되어있다 😀[2-3] 내 VM에 적용된 Host-Only Network 확인▶ Virtualbox 실행 > k8s_master-node 마우스 우클릭 > 설정 > 네트워크 > 어댑터 2어뎁터 1에 NAT, 어뎁터 2에 Host-Only Network 가 연결된걸 확인했다.강의에서 배운대로 잘 연결되어 있는걸 보니 신기하다 😆 [2-4] VirtualBox Host-Only cidr 확인▶파일 > 도구 > Network Manager처음에 들어가서 확인했을 땐 DHCP 서버가 활성화 되어있었다.DHCP 서버 속성에서 서버 활성화를 해제해 DHCP 서버를 비활성화 해주었다.[3-1] Rocky Linux 버전 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# cat /etc/*-release 위 명령어로 현재 OS가 Rocky Linux ver 8.8임을 확인했다. [3-2] Hostname 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# hostname[3-3], [3-4] Network 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# ip addr[3-5] 자원(cpu, memory) 확인▶ k8s-master 원격접속 후 명령어 실행[root@k8s-master ~]# lscpu [root@k8s-master ~]# free -h CPU 4코어, 메모리 6GB 가 할당된거를 확인할 수 있었다.단계 1-3 까지는 내 PC에 대한 환경설정을 확인하는 단계였으면, 단계 4-9는 쿠버네티스 모든 node에 대한 설치 확인, master node 세팅 확인 작업이다.이걸 적으면서도 단계별로 그림이 눈에 안들어오는데, 복습의 필요성을 또 한번 느끼고 간다 😂미래의 내가 조금 더 고생해야지... [4] Rocky Linux 기본 설정▶ 타임존 설정 확인(스크립트로 적용된 명령: timedatectl set-timezone Asia/Seoul) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# timedatectl [5] kubeadm 설치 전 사전작업관련 공식 문서[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%EC%A0%84%EC%97%90kubeam을 설치하기 전에 여러가지 사전 작업들을 고려한 뒤 설치를 해야하고, 2GB이상 램, 2 이상 CPU 등은 가상환경 설정 때 이미 해결한 것들이다.우리가 추가로 실천할 작업들은 다음과 같다.컴퓨터의 특정 포트들 개방 -> 네트워크 방화벽을 해제해서 모든 포트 개방스왑의 비활성화 ▶ 방화벽 해제 확인(스크립트로 적용된 명령: systemctl stop firewalld && systemctl disable firewalld) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# systemctl status firewalld 스크립트로 설정한stop firewalld 명령어로 Active: inactive 된걸 확인disable firewalld 명령어로 firewalld.service; disabled; 된걸 확인 방화벽 서비스 설정에 관한 명령어 참고했습니다 (서비스 종료 및 구동에 관한 명령어가 정리되어있다).(https://m.blog.naver.com/res0324/221988642463) ▶ 스왑(swap) 비활성화 확인(스크립트로 적용된 명령: swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab) - 중복 실행할 필요는 없습니다.[root@k8s-master ~]# free [root@k8s-master ~]# cat /etc/fstab | grep swap free로 메모리 상태를 확인해 swap된 메모리가 있는 지 확인 -> 스왑된 메모리 x/cat/fstab 파일에 swap 을 검색해 관련된 문자열을 확인 -> # 주석처리가 잘 되어있음.[6] 컨테이너 런타임 설치 [6-1] 컨테이너 런타임 설치 전 사전작업관련 공식 문서[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#ipv4%EB%A5%BC-%ED%8F%AC%EC%9B%8C%EB%94%A9%ED%95%98%EC%97%AC-iptables%EA%B0%80-%EB%B8%8C%EB%A6%AC%EC%A7%80%EB%90%9C-%ED%8A%B8%EB%9E%98%ED%94%BD%EC%9D%84-%EB%B3%B4%EA%B2%8C-%ED%95%98%EA%B8%B0 ▶ iptables 세팅# 설정 세팅 확인[root@k8s-master ~]# cat /etc/modules-load.d/k8s.conf [root@k8s-master ~]# cat /etc/sysctl.d/k8s.conf # 모듈 적제 확인[root@k8s-master ~]# lsmod | grep overlay [root@k8s-master ~]# lsmod | grep br_netfilter #설정 세팅 확인 결과#모듈 적제 확인 결과[6-2] 컨테이너 런타임 (containerd 설치)[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#containerd[Containerd Release] : https://github.com/containerd/containerd/blob/main/RELEASES.md#kubernetes-support​[6-2-1] containerd 패키지 설치 (option2)[Containerd Docs] : https://github.com/containerd/containerd/blob/main/docs/getting-started.md#option-2-from-apt-get-or-dnf​[6-2-1-1] docker engine (containerd.io)만 설치관련 공식 문서[Docker Docs] : https://docs.docker.com/engine/install/centos/#install-using-the-repository▶ docker repo 설정 확인(스크립트로 적용된 명령: yum install -y yum-utils, yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo)[root@k8s-master ~]# yum repolist enabled 도커 엔진을 사용하기 위해선 먼저 도커 저장소를 설정 해야한다.관련 스크립트를 적용하면 도커 저장소를 설정할 수 있고, 잘 적용되었는지 확인하는 과정이다.확인한 결과 docker-ce-stable 설정이 enabled로 잘 적용되어있음을 확인했다. ▶containerd 설치 확인(스크립트로 이미 적용된 명령: yum install -y containerd.io-1.6.21-3.1.el8) - 중복실행은 하지마세요![root@k8s-master ~]# systemctl status containerd 우리는 도커 엔진 중에 containerd.io 만을 설치했다.containerd가 잘 설치되어있고, 활성화된 모습을 확인했다. ▶설치 가능한 버전의 containerd.io 리스트 확인[root@k8s-master ~]# yum list containerd.io --showduplicates | sort -r [6-3] 컨테이너 런타임 (CRI활성화)쿠버네티스 문서에 Kubelet의 Cgroup의 Default가 cgroupfs라고 말씀 드렸는데, 레드햇 계열 리눅스(Rocky Linux) 의 경우 systemd를 메인으로 프로세스를 실행시키는 시스템이기 때문에, 쿠버네티스 설치시Default로 systemd가 세팅됩니다. 이 경우 containerd도 systemd로 변경하여 모두 systemd를 쓰는게 Core 사용에 부담이 없습니다. 관련 공식 문서[Kubernetes Docs] : https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/#containerd▶ cri 활성화 설정 확인(스크립트로 이미 적용된 명령: containerd config default > /etc/containerd/config.toml; sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml) - 중복실행은 하지마세요![root@k8s-master ~]# cat /etc/containerd/config.toml 컨테이너 런타임(containerd) 상 systemdCroup = true 확인(systemd)만약 false 일 경우 cgroupfs 이니 systemd로 변경 필요▶ kubelet cgroup 확인 (configmap)[root@k8s-master ~]# kubectl get -n kube-system cm kubelet-config -o yaml ▶ kubelet cgroup 확인 (kubelet)[root@k8s-master ~]# cat /var/lib/kubelet/config.yaml 쿠버네티스(kubelet) 상 cgroup이 systemd인 것을 확인하였다.[7] kubeadm 설치관련 공식 문서[Kubernetes Docs] :https://kubernetes.io/ko/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#kubeadm-kubelet-%EB%B0%8F-kubectl-%EC%84%A4%EC%B9%98 우리가 설정했던 스크립트 중 [echo '======== [7] kubeadm 설치 ========'] 이후부터 글을 확인하면 위에 코드들이 스크립트에 적용된 걸 확인할 수 있다.▶ repo 설정 확인 [root@k8s-master ~]# yum repolist enabled 쿠버네티스가 repo에 설정된걸 확인할 수 있다. ▶ SELinux 설정 확인[root@k8s-master ~]# cat /etc/selinux/config [root@k8s-master ~]# sestatus SELINUX=permissive 확인▶ kubelet, kubeadm, kubectl 패키지 설치(스크립트로 이미 적용된 명령: yum install -y kubelet-1.27.2-150500.1.1.x86_64 kubeadm-1.27.2-150500.1.1.x86_64 kubectl-1.27.2-150500.1.1.x86_64 --disableexcludes=kubernetes) - 중복실행은 하지 마세요!#버전 보기[root@k8s-master ~]# kubeadm version [root@k8s-master ~]# kubectl version #상태 보기[root@k8s-master ~]# systemctl status kubelet #설정 파일 위치[root@k8s-master ~]# cat /var/lib/kubelet/config.yaml #로그 조회journalctl -u kubelet | tail -10 #버전 보기 결과kubeadm GitVersion: "v1.27.2" , kubectl GitVersion: "v1.27.2" #상태 보기 결과kubelet active(running) 확인* stop 상태일 때는 아래 명령으로 올리기[root@k8s-master ~]# systemctl restart kubelet ▶ 설치 가능한 버전의 kubeadm 리스트 확인[root@k8s-master ~]# yum list --showduplicates kubeadm --disableexcludes=kubernetes [8] kubeadm으로 클러스터 생성관련 공식 문서 [Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/​[8-1] 클러스터 초기화 (Pod Network 세팅)▶ 클러스터 상태 확인(스크립트로 이미 적용된 명령: kubeadm init --pod-network-cidr=20.96.0.0/12 --apiserver-advertise-address 192.168.56.30) - 중복실행은 하지 마세요!# master node 상태확인[root@k8s-master ~]# kubectl get node # pod network cidr 설정 확인[root@k8s-master ~]# kubectl cluster-info dump | grep -m 1 cluster-cidr # apiserver advertise address 적용 확인[root@k8s-master ~]# kubectl cluster-info # kubernetes component pod 확인[root@k8s-master ~]# kubectl get pods -n kube-system ▶ 실행 결과 :스크립트 상 설정했던 pod-network-cidr 값과 apiserver-advertise-address 값이 정상 적용된걸 확인할 수 있다. * Cluster가 정상이 아닐 때는 아래 명령으로 reset후 다시 init 해주기.* reset 실행 후 1분 정도 시간이 지난 후에 init을 해주세요.[root@k8s-master ~]# kubeadm reset [root@k8s-master ~]# kubeadm init --pod-network-cidr=20.96.0.0/12 --apiserver-advertise-address 192.168.56.30 [8-2] kubectl 사용 설정관련 공식 문서[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#more-information​▶ 인증서 설정 확인[root@k8s-master ~]# cat ~/.kube/config [8-3] CNI Plugin 설치 (calico)관련 공식 문서[Calico Docs] : https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico▶ calico pod 설치 및 pod network cidr 적용 확인# Calico Pod 상태 확인[root@k8s-master ~]# kubectl get -n calico-system pod [root@k8s-master ~]# kubectl get -n calico-apiserver pod # Calico에 pod network cidr 적용 확인[root@k8s-master ~]# kubectl get installations.operator.tigera.io default -o yaml | grep cidr ▶ 실행 결과 :* Calico 설치가 정상이 아닐 때 (Calico가 CrashLoopBackOff 상태고, coredns가 가 Pending 상태)#Calico 삭제kubectl delete -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml kubectl delete -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml #Calico 재설치[root@k8s-master ~]# kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml [root@k8s-master ~]# kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml​[8-4] Master에 pod를 생성 할 수 있도록 설정관련 공식 문서[Kubernetes Docs] : https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/#control-plane-node-isolation▶ Master Node에 Taint 해제 확인(스크립트로 이미 적용된 명령: kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane- )[root@k8s-master ~]# kubectl describe nodes | grep Taints ▶ 실행 결과 :[9] 쿠버네티스 편의 기능 설치[9-1] kubectl 자동완성 기능▶ kubectl 기능 설정 확인[root@k8s-master ~]# cat ~/.bashrc▶ 실행 결과 :[9-2] Dashboard 설치▶ dashboard 설치 확인[root@k8s-master ~]# kubectl get pod -n kubernetes-dashboard ▶ 실행 결과 :[9-3] Metrics Server 설치▶ metrics server 설치 확인[root@k8s-master ~]# kubectl get pod -n kube-system | grep metrics [root@k8s-master ~]# kubectl top pod -A * 설치 후 kubectl top pod -A 명령시 error: Metrics API not available 메세지가 나올때최초 설치시 / VM 재기동시 매트릭 정보가 수집되는데 시간이 좀 걸릴 수 있습니다.​ 회고사실 강의를 들으면서 모르는게 생기면 계속 반복해서 듣게 되었고, 그렇게 강의 듣는 시간이 길어졌다 😂이렇게 복습하면서 강의 내용을 다시 되짚고, 스크립트 코드와 쿠버네티스 공식 문서들을 번갈아가며 확인해보니왜 강사님이 스크립트를 그렇게 짰고, 우리가 쿠버네티스 설정을 하기 위해 이러한 사전지식들을 알고 있어야 하는구나 깨달았다.아직 위에 4-9까지 그림이 완벽하게 이해되지는 않았다(50%정도 이해한 것 같다 ㅠ).그래도 이렇게 미션으로 실습 내용을 되짚어보고, 나중에 1.5배속으로 강의를 들으면서 했던 실습들을 리마인드 한다면!!이 쿠버네티스 개념들을 바로잡을 수 있을 것 같다는 막연한 자신감이 생겼다 ㅋㅋ쉽지는 않았지만, 이 미션이나 강의가 없었더라면 직접 공식문서를 보고, 관련블로그를 찾아가며 해결했었을 거라는 생각에 오히려 다행이라고 생각했다 😁.

데브옵스 · 인프라k8svagrantVirtualBoxnetwork

David

[SPG-박상준] 1주차 발자국

26일 OT 이후 [미션1] 쿠버네티스 설치 구간별 상태 확인만 진행된 상태이지만 발자국을 남겨본다. 인프런에서 강의 구매 후 절반 정도 진행을 하고 있었고 스터디 팀을 하는 것이 귀찮기도 했지만 전원 완주 팀에 Sprint4 무료 쿠폰이라는 달콤한 보상이 있었기에 신청하게 되었다.우리 SPG(Senior Pod Group) 팀은 대부분 고연차 경력을 가지고 현업에 계신 분들로 구성이 되어 있기 때문에 개인 공부를 위한 실습은 하겠지만 문서화하고 기록에 남기는 일은 정말 쉽지 않은 것을 알고 있다. (나 또한..) 각설하고 [미션1] 과정은 한차례 진행했었기 때문에 신규로 다시 구성을 했었고 쿠버네티스 설치에 필요한 환경설정은 여러 번 재구축 해보기 위해 스크립트로 작성하여 진행했다. 환경설정 또한 이전 단계 설정을 하고 검증 단계를 걸쳐서 완료되지 않으면 넘어가지 않도록 작성해서 설정이 빠지는 것을 방지했다.[환경설정 코드]#!/bin/bash # 색상 정의 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 로그 함수 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } # 검증 실패 시 종료 함수 exit_on_error() { log_error "$1" log_error "스크립트를 종료합니다." exit 1 } # 사용자 확인 함수 confirm_continue() { read -p "다음 단계로 진행하시겠습니까? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "사용자가 중단했습니다." exit 0 fi } echo "========================================" echo "Kubernetes 기본 환경설정 스크립트 시작" echo "========================================" # ============================================ # 1. 시스템 기본 설정 # ============================================ log_info "======== [1단계] 시스템 기본 설정 ========" log_info "타임존을 Asia/Seoul로 설정 중..." timedatectl set-timezone Asia/Seoul timedatectl set-ntp true chronyc makestep log_info "필수 패키지 설치 중..." yum install -y yum-utils iproute-tc yum update openssl openssh-server -y log_info "hosts 파일 설정 중..." if ! grep -q "k8s-master" /etc/hosts; then cat << EOF >> /etc/hosts 192.168.56.30 k8s-master EOF fi log_info "======== [1단계] 검증 시작 ========" # 타임존 검증 current_timezone=$(timedatectl show --property=Timezone --value) if [ "$current_timezone" = "Asia/Seoul" ]; then log_success "타임존 설정 완료: $current_timezone" else exit_on_error "타임존 설정 실패: $current_timezone" fi # NTP 동기화 검증 ntp_status=$(timedatectl show --property=NTPSynchronized --value) if [ "$ntp_status" = "yes" ]; then log_success "NTP 동기화 완료" else log_warning "NTP 동기화 미완료 (시간이 필요할 수 있음)" fi # 필수 패키지 검증 if command -v tc >/dev/null 2>&1; then log_success "tc 패키지 설치 완료" else exit_on_error "tc 패키지 설치 실패" fi # hosts 파일 검증 if grep -q "192.168.56.30 k8s-master" /etc/hosts; then log_success "hosts 파일 설정 완료" else exit_on_error "hosts 파일 설정 실패" fi log_success "======== [1단계] 시스템 기본 설정 완료 ========" confirm_continue # ============================================ # 2. 보안 설정 # ============================================ log_info "======== [2단계] 보안 설정 ========" log_info "방화벽 해제 중..." systemctl stop firewalld systemctl disable firewalld log_info "SELinux 설정 중..." setenforce 0 sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config log_info "======== [2단계] 검증 시작 ========" # 방화벽 상태 검증 firewall_status=$(systemctl is-active firewalld) if [ "$firewall_status" = "inactive" ]; then log_success "방화벽 해제 완료" else exit_on_error "방화벽 해제 실패: $firewall_status" fi # 방화벽 부팅 시 비활성화 검증 firewall_enabled=$(systemctl is-enabled firewalld) if [ "$firewall_enabled" = "disabled" ]; then log_success "방화벽 부팅시 비활성화 완료" else exit_on_error "방화벽 부팅시 비활성화 실패: $firewall_enabled" fi # SELinux 현재 상태 검증 selinux_current=$(getenforce) if [ "$selinux_current" = "Permissive" ]; then log_success "SELinux 현재 상태: $selinux_current" else exit_on_error "SELinux 설정 실패: $selinux_current" fi # SELinux 설정 파일 검증 selinux_config=$(grep "^SELINUX=" /etc/selinux/config | cut -d'=' -f2) if [ "$selinux_config" = "permissive" ]; then log_success "SELinux 영구 설정 완료: $selinux_config" else exit_on_error "SELinux 영구 설정 실패: $selinux_config" fi log_success "======== [2단계] 보안 설정 완료 ========" confirm_continue # ============================================ # 3. 시스템 리소스 설정 # ============================================ log_info "======== [3단계] 시스템 리소스 설정 ========" log_info "Swap 비활성화 중..." swapoff -a sed -i '/ swap / s/^/#/' /etc/fstab log_info "======== [3단계] 검증 시작 ========" # Swap 상태 검증 swap_status=$(swapon --show) if [ -z "$swap_status" ]; then log_success "Swap 비활성화 완료" else exit_on_error "Swap 비활성화 실패: $swap_status" fi # fstab에서 swap 주석 처리 검증 swap_in_fstab=$(grep -v "^#" /etc/fstab | grep swap) if [ -z "$swap_in_fstab" ]; then log_success "fstab에서 swap 영구 비활성화 완료" else exit_on_error "fstab에서 swap 영구 비활성화 실패" fi log_success "======== [3단계] 시스템 리소스 설정 완료 ========" confirm_continue # ============================================ # 4. 네트워크 설정 # ============================================ log_info "======== [4단계] 네트워크 설정 ========" log_info "커널 모듈 설정 중..." cat <<EOF |tee /etc/modules-load.d/k8s.conf overlay br_netfilter EOF modprobe overlay modprobe br_netfilter log_info "네트워크 파라미터 설정 중..." cat <<EOF |tee /etc/sysctl.d/k8s.conf net.bridge.bridge-nf-call-iptables = 1 net.bridge.bridge-nf-call-ip6tables = 1 net.ipv4.ip_forward = 1 EOF sysctl --system log_info "======== [4단계] 검증 시작 ========" # 커널 모듈 검증 if lsmod | grep -q overlay; then log_success "overlay 모듈 로드 완료" else exit_on_error "overlay 모듈 로드 실패" fi if lsmod | grep -q br_netfilter; then log_success "br_netfilter 모듈 로드 완료" else exit_on_error "br_netfilter 모듈 로드 실패" fi # 네트워크 파라미터 검증 iptables_call=$(sysctl net.bridge.bridge-nf-call-iptables | cut -d'=' -f2 | tr -d ' ') if [ "$iptables_call" = "1" ]; then log_success "iptables 설정 완료" else exit_on_error "iptables 설정 실패: $iptables_call" fi ip6tables_call=$(sysctl net.bridge.bridge-nf-call-ip6tables | cut -d'=' -f2 | tr -d ' ') if [ "$ip6tables_call" = "1" ]; then log_success "ip6tables 설정 완료" else exit_on_error "ip6tables 설정 실패: $ip6tables_call" fi ip_forward=$(sysctl net.ipv4.ip_forward | cut -d'=' -f2 | tr -d ' ') if [ "$ip_forward" = "1" ]; then log_success "IP 포워딩 설정 완료" else exit_on_error "IP 포워딩 설정 실패: $ip_forward" fi log_success "======== [4단계] 네트워크 설정 완료 ========" # ============================================ # 최종 검증 및 완료 # ============================================ log_info "======== 최종 기본 환경설정 검증 ========" log_info "기본 환경설정 상태 요약:" echo "----------------------------------------" echo "1. 타임존: $(timedatectl show --property=Timezone --value)" echo "2. 방화벽: $(systemctl is-active firewalld)" echo "3. SELinux: $(getenforce)" echo "4. Swap: $(if [ -z "$(swapon --show)" ]; then echo "비활성화"; else echo "활성화"; fi)" echo "5. IP 포워딩: $(sysctl net.ipv4.ip_forward | cut -d'=' -f2 | tr -d ' ')" echo "6. 커널 모듈 overlay: $(if lsmod | grep -q overlay; then echo "로드됨"; else echo "로드안됨"; fi)" echo "7. 커널 모듈 br_netfilter: $(if lsmod | grep -q br_netfilter; then echo "로드됨"; else echo "로드안됨"; fi)" echo "----------------------------------------" log_success "========================================" log_success "Kubernetes 기본 환경설정이 완료되었습니다!" log_success "이제 컨테이너 런타임과 Kubernetes 패키지를" log_success "설치할 준비가 되었습니다." log_success "========================================" log_info "다음 단계:" log_info "1. 컨테이너 런타임 (containerd) 설치" log_info "2. Kubernetes 패키지 (kubelet, kubeadm, kubectl) 설치" log_info "3. 클러스터 초기화" [설치 코드]#!/bin/bash # 색상 정의 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' PURPLE='\033[0;35m' NC='\033[0m' # No Color # 로그 함수 log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } log_step() { echo -e "${PURPLE}[STEP]${NC} $1" } # 검증 실패 시 종료 함수 exit_on_error() { log_error "$1" log_error "스크립트를 종료합니다." exit 1 } # 사용자 확인 함수 confirm_continue() { read -p "다음 단계로 진행하시겠습니까? (y/n): " -n 1 -r echo if [[ ! $REPLY =~ ^[Yy]$ ]]; then log_info "사용자가 중단했습니다." exit 0 fi } # 대기 시간 함수 wait_for_service() { local service_name=$1 local max_wait=$2 local count=0 log_info "${service_name} 서비스 시작 대기 중..." while [ $count -lt $max_wait ]; do if systemctl is-active --quiet $service_name; then log_success "${service_name} 서비스가 정상적으로 시작되었습니다." return 0 fi sleep 2 count=$((count + 1)) echo -n "." done echo return 1 } echo "================================================" echo "Kubernetes 컨테이너 런타임 및 클러스터 설치 시작" echo "================================================" # ============================================ # 1. 컨테이너 런타임 설치 (containerd) # ============================================ log_step "======== [1단계] 컨테이너 런타임 설치 ========" log_info "Docker 저장소 추가 중..." yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo log_info "containerd 설치 중..." yum install -y containerd.io-1.6.21-3.1.el9.aarch64 log_info "systemd 데몬 재로드 중..." systemctl daemon-reload log_info "containerd 서비스 활성화 및 시작 중..." systemctl enable containerd systemctl start containerd # containerd 서비스 시작 대기 if ! wait_for_service "containerd" 15; then exit_on_error "containerd 서비스 시작 실패" fi log_info "containerd 기본 설정 생성 중..." containerd config default > /etc/containerd/config.toml log_info "SystemdCgroup 활성화 중..." sed -i 's/ SystemdCgroup = false/ SystemdCgroup = true/' /etc/containerd/config.toml log_info "containerd 서비스 재시작 중..." systemctl restart containerd # containerd 재시작 후 대기 if ! wait_for_service "containerd" 15; then exit_on_error "containerd 서비스 재시작 실패" fi log_info "======== [1단계] 검증 시작 ========" # containerd 서비스 상태 검증 containerd_status=$(systemctl is-active containerd) if [ "$containerd_status" = "active" ]; then log_success "containerd 서비스 실행 중" else exit_on_error "containerd 서비스 실행 실패: $containerd_status" fi # containerd 부팅 시 활성화 검증 containerd_enabled=$(systemctl is-enabled containerd) if [ "$containerd_enabled" = "enabled" ]; then log_success "containerd 부팅시 활성화 완료" else exit_on_error "containerd 부팅시 활성화 실패: $containerd_enabled" fi # SystemdCgroup 설정 검증 if grep -q "SystemdCgroup = true" /etc/containerd/config.toml; then log_success "SystemdCgroup 설정 완료" else exit_on_error "SystemdCgroup 설정 실패" fi # containerd 버전 확인 containerd_version=$(containerd --version 2>/dev/null | cut -d' ' -f3) if [ -n "$containerd_version" ]; then log_success "containerd 버전: $containerd_version" else exit_on_error "containerd 버전 확인 실패" fi # containerd 실행 테스트 if ctr version >/dev/null 2>&1; then log_success "containerd 실행 테스트 성공" else exit_on_error "containerd 실행 테스트 실패" fi log_success "======== [1단계] 컨테이너 런타임 설치 완료 ========" confirm_continue # ============================================ # 2. Kubernetes 패키지 설치 # ============================================ log_step "======== [2단계] Kubernetes 패키지 설치 ========" log_info "Kubernetes 저장소 추가 중..." cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo [kubernetes] name=Kubernetes baseurl=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/ enabled=1 gpgcheck=1 gpgkey=https://pkgs.k8s.io/core:/stable:/v1.27/rpm/repodata/repomd.xml.key exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni EOF log_info "Kubernetes 패키지 설치 중..." log_info "- kubelet (노드 에이전트)" log_info "- kubeadm (클러스터 초기화 도구)" log_info "- kubectl (클러스터 관리 도구)" yum install -y \ kubelet-1.27.2-150500.1.1.aarch64 \ kubeadm-1.27.2-150500.1.1.aarch64 \ kubectl-1.27.2-150500.1.1.aarch64 \ --disableexcludes=kubernetes log_info "kubelet 서비스 활성화 중..." systemctl enable kubelet log_info "======== [2단계] 검증 시작 ========" # kubelet 서비스 활성화 검증 kubelet_enabled=$(systemctl is-enabled kubelet) if [ "$kubelet_enabled" = "enabled" ]; then log_success "kubelet 부팅시 활성화 완료" else exit_on_error "kubelet 부팅시 활성화 실패: $kubelet_enabled" fi # Kubernetes 패키지 설치 검증 및 버전 확인 if command -v kubelet >/dev/null 2>&1; then kubelet_version=$(kubelet --version | cut -d' ' -f2) log_success "kubelet 설치 완료 - 버전: $kubelet_version" else exit_on_error "kubelet 설치 실패" fi if command -v kubeadm >/dev/null 2>&1; then kubeadm_version=$(kubeadm version -o short) log_success "kubeadm 설치 완료 - 버전: $kubeadm_version" else exit_on_error "kubeadm 설치 실패" fi if command -v kubectl >/dev/null 2>&1; then kubectl_version=$(kubectl version --client -o yaml 2>/dev/null | grep gitVersion | cut -d'"' -f4) log_success "kubectl 설치 완료 - 버전: $kubectl_version" else exit_on_error "kubectl 설치 실패" fi # 버전 일관성 검증 if [[ "$kubelet_version" == *"1.27.2"* ]] && [[ "$kubeadm_version" == *"1.27.2"* ]] && [[ "$kubectl_version" == *"1.27.2"* ]]; then log_success "모든 Kubernetes 패키지 버전 일관성 확인 (v1.27.2)" else exit_on_error "Kubernetes 패키지 버전 불일치" fi log_success "======== [2단계] Kubernetes 패키지 설치 완료 ========" confirm_continue # ============================================ # 3. 클러스터 초기화 # ============================================ log_step "======== [3단계] 클러스터 초기화 ========" log_info "클러스터 초기화 설정:" log_info "- Pod 네트워크 CIDR: 20.96.0.0/16" log_info "- API 서버 주소: 192.168.56.30" log_info "- Kubernetes 버전: v1.27.2" log_warning "클러스터 초기화는 시간이 소요될 수 있습니다 (약 2-5분)..." log_info "kubeadm으로 클러스터 초기화 중..." kubeadm init \ --pod-network-cidr=20.96.0.0/16 \ --apiserver-advertise-address=192.168.56.30 \ --kubernetes-version=v1.27.2 if [ $? -ne 0 ]; then exit_on_error "클러스터 초기화 실패" fi log_success "클러스터 초기화 완료!" log_info "kubectl 사용을 위한 설정 중..." mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config chown $(id -u):$(id -g) $HOME/.kube/config log_info "======== [3단계] 검증 시작 ========" # kubectl 설정 파일 검증 if [ -f "$HOME/.kube/config" ]; then log_success "kubectl 설정 파일 생성 완료" else exit_on_error "kubectl 설정 파일 생성 실패" fi # 클러스터 연결 테스트 log_info "클러스터 연결 테스트 중..." if kubectl cluster-info >/dev/null 2>&1; then log_success "클러스터 연결 테스트 성공" else exit_on_error "클러스터 연결 테스트 실패" fi # 노드 상태 확인 log_info "노드 상태 확인 중..." node_status=$(kubectl get nodes --no-headers | awk '{print $2}') if [[ "$node_status" == *"Ready"* ]] || [[ "$node_status" == *"NotReady"* ]]; then log_success "마스터 노드 등록 완료 (상태: $node_status)" if [[ "$node_status" == *"NotReady"* ]]; then log_warning "노드가 NotReady 상태입니다. Pod 네트워크 설치가 필요합니다." fi else exit_on_error "노드 상태 확인 실패" fi log_success "======== [3단계] 클러스터 초기화 완료 ========" confirm_continue # ============================================ # 4. Pod 네트워크 설치 (Calico) # ============================================ log_step "======== [4단계] Pod 네트워크 설치 (Calico) ========" log_info "Calico Pod 네트워크 설치 중..." log_info "- Calico는 Pod 간 네트워크 통신을 가능하게 합니다" log_info "- 설치 후 노드가 Ready 상태가 됩니다" kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico.yaml if [ $? -ne 0 ]; then exit_on_error "Calico 기본 설치 실패" fi kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/calico-3.26.4/calico-custom.yaml if [ $? -ne 0 ]; then exit_on_error "Calico 커스텀 설정 실패" fi log_success "Calico Pod 네트워크 설치 완료" log_info "마스터 노드에서 Pod 실행 허용 설정 중..." kubectl taint nodes k8s-master node-role.kubernetes.io/control-plane- if [ $? -ne 0 ]; then log_warning "마스터 노드 taint 제거 실패 (이미 제거되었을 수 있음)" else log_success "마스터 노드에서 Pod 실행 허용 설정 완료" fi log_info "======== [4단계] 검증 시작 ========" log_info "Pod 네트워크 구성 요소 확인 중..." log_info "Calico Pod들이 Running 상태가 될 때까지 대기합니다 (최대 3분)..." # Calico Pod 상태 확인 (최대 3분 대기) for i in {1..18}; do calico_pods=$(kubectl get pods -n kube-system -l k8s-app=calico-node --no-headers 2>/dev/null | grep -c "Running") if [ "$calico_pods" -gt 0 ]; then log_success "Calico Pod 실행 중 ($calico_pods개)" break fi if [ $i -eq 18 ]; then log_warning "Calico Pod 상태 확인 시간 초과" fi echo -n "." sleep 10 done # 노드 상태 재확인 (Pod 네트워크 설치 후) log_info "노드 Ready 상태 확인 중..." for i in {1..12}; do node_status=$(kubectl get nodes --no-headers | awk '{print $2}') if [[ "$node_status" == *"Ready"* ]] && [[ "$node_status" != *"NotReady"* ]]; then log_success "노드가 Ready 상태입니다!" break fi if [ $i -eq 12 ]; then log_warning "노드가 아직 NotReady 상태입니다. 시간이 더 필요할 수 있습니다." fi echo -n "." sleep 10 done log_success "======== [4단계] Pod 네트워크 설치 완료 ========" # ============================================ # 5. 편의 기능 설치 # ============================================ log_step "======== [5단계] 편의 기능 설치 ========" log_info "kubectl 자동완성 기능 설치 중..." yum -y install bash-completion log_info "kubectl 별칭 및 자동완성 설정 중..." echo "source <(kubectl completion bash)" >> ~/.bashrc echo 'alias k=kubectl' >> ~/.bashrc echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc log_info "Kubernetes Dashboard 설치 중..." kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/dashboard-2.7.0/dashboard.yaml log_info "Metrics Server 설치 중..." kubectl create -f https://raw.githubusercontent.com/k8s-1pro/install/main/ground/k8s-1.27/metrics-server-0.6.3/metrics-server.yaml log_success "======== [5단계] 편의 기능 설치 완료 ========" # ============================================ # 최종 검증 및 완료 # ============================================ log_step "======== 최종 클러스터 상태 검증 ========" log_info "전체 클러스터 상태 요약:" echo "================================================" # 클러스터 정보 log_info "클러스터 정보:" kubectl cluster-info --request-timeout=10s 2>/dev/null || log_warning "클러스터 정보 조회 실패" echo "----------------------------------------" # 노드 상태 log_info "노드 상태:" kubectl get nodes -o wide 2>/dev/null || log_warning "노드 상태 조회 실패" echo "----------------------------------------" # 시스템 Pod 상태 log_info "시스템 Pod 상태:" kubectl get pods -n kube-system 2>/dev/null || log_warning "시스템 Pod 상태 조회 실패" echo "----------------------------------------" # 서비스 상태 요약 log_info "핵심 서비스 상태:" echo "- containerd: $(systemctl is-active containerd)" echo "- kubelet: $(systemctl is-active kubelet)" echo "================================================" log_success "========================================" log_success "Kubernetes 클러스터 설치가 완료되었습니다!" log_success "========================================" log_info "다음 명령어로 클러스터 상태를 확인할 수 있습니다:" echo " kubectl get nodes" echo " kubectl get pods -A" echo " kubectl cluster-info" log_info "kubectl 자동완성을 사용하려면 새 터미널을 열거나 다음 명령어를 실행하세요:" echo " source ~/.bashrc" log_info "이제 Kubernetes 클러스터를 사용할 준비가 완료되었습니다!" # join 명령어 추출 및 출력 log_info "======== Worker 노드 추가 정보 ========" log_info "Worker 노드를 추가하려면 다음 명령어를 사용하세요:" if [ -f /tmp/kubeadm-join-command ]; then cat /tmp/kubeadm-join-command else log_info "다음 명령어로 join 토큰을 다시 생성할 수 있습니다:" echo " kubeadm token create --print-join-command" fi이제 2개의 스크립트로 언제든 쿠버네티스를 재구축할 수 있게 되었다.

데브옵스 · 인프라SPG일프로k8sDevOpsSRE

David

[인프런 워밍업 클럽 4기 - DevOPs] 미션 1. 쿠버네티스 설치 구간별 상태 확인

설치 환경칩 : Apple M4 Mac mini메모리 : 16GBmacOS : Sequoia 15.5가상플랫폼 : UTM UTM 설치는https://mac.getutm.app/ 에서 최신 버전을 다운로드 했다.워밍업 스터디가 시작되기 전 강의를 먼저 구매 후 공부중이였기 때문에 이미 한차례 설치를 했지만 추가적으로 복습 겸 설치를 진행 했다. [OS 설치]UTM 실행 -> 새 가상머신 만들기 선택 -> Start(Virtualize 선택) -> Linux 선택 -> 부팅 이미지 (Rocky 9.2)-> 메모리 4096 MB, CPU 4 Cores , 용량은 32GB, 공유 폴더는 선택 안함, -> Summary에서 이름은 ks-master [UTM ›네트워크 설정][Rocky Linux 설정]언어 : 한국어 (대한민국)[시스템]파티션 설정은 자동 구성으로 두고 완료를 선택한다.[KDUMP]Default 값은 활성화 되어 있지만 체크를 해지한다.[네트워크 및 호스트 이름]설정을 누른 후 내용 작성을 진행한다.[사용자 설정 - root 비밀번호]모든 설정이 완료되면 설치 시작(B)를 눌러 설치를 시작한다. (약 4분 소요)...(설치 과정 생략) [iterm을 통한 원격 접속]발생한 메시지는 동일한 IP를 가진 k8s-master 정보가 이미 있기 때문에 호스트 키 불일치를 감지해서 발생했다.이런 경우에는 ssh-keygen -R 명령을 통해 특정 호스트 키만 삭제하고 재접속을 하면 된다.[쿠버네티스 설치 전 환경설정]설치 전 미리 설정이 되어 있는 부분만 별도 스크립트로 작성 및 검증을 하고 쿠버네티스 설치로 넘어간다. 스크립트를 작성한 이유는 재사용성을 위해서 작성했다.[쿠버네티스 설치]

데브옵스 · 인프라KubernetesDevOpsMSAk8s인프런SRE일프로

wnsrlf0721

[워밍업클럽: 쿠버네티스] 미션 #6. ArgoCD - Github 업데이트

큐브옵스 카페의 실습 미션을 기반으로 작성한 내용이다.https://cafe.naver.com/kubeops/553 1. ArgoCD로 App 생성 및 배포1-1. App 생성 하기▶ GENERALApplication Name : api-tester-2232-build-push-git Project Name : default SYNC POLICY : Manual▶ SOURCE※ <Github-Useranme>은 본인의 Username으로 수정Repository URL : https://github.com/wnsrlf0721/kubernetes-anotherclass-sprint2.git Revision : main Path : 2232-build-push-git/deploy/helm/api-tester▶ DESTINATIONCluster URL : https://kubernetes.default.svc Namespace : anotherclass-223▶ HELM 확인 후 Values files 지정VALUES FILES : values-dev.yamlCreate 버튼으로 App 생성을 하면다음과 같은 ArgoCD App이 만들어지게 된다(Healthy 같이 초록창이 뜨지는 않음). 1-2. 자동 배포 설정api-tester-2232-build-push-git > details > SYNC POLICY 순서로 클릭을 해서 아래와 같이 만들자.1-3. 자동 배포 확인잠시 기다리면 Healthy 상태가 되며 파드가 생성될거고, 대시보드를 확인하면 anotherclass-223 ns에 파드가 생성된 걸 볼수 있다. 2. Jenkins에 Github Token 등록카페에 가면 Github에서 토큰을 생성하는 방법이 자세하게 나와있다. 가서 배우자.토큰을 받은 후에 젠킨스 설정에 토큰을 등록하게 되면,Jenkins관리 > Credentials에서 github_token을 확인할 수 있다. Jekninsfile 에서 Credential 사용 확인▶ 2232-build-push-git > JenkinsfileJenkinsfile을 보면, github_token으로 github USERNAME과 PASSWORD로 깃허브에 파일을 업데이트하는 동작을 수행한다. 3. Jeknins에서 Source/Container 빌드 후 Docker로 업로드 하기3-1.새보기 및 item 생성[새보기] 만들기 -> 조회명 : 223, Type : List View [item name] 만들기 -> item name :2232-build-push-git, [Pipeline] 선택  3-2. Configure▶ Configure > General > GitHub project > Project urlProject url : https://github.com/wnsrlf0721/kubernetes-anotherclass-sprint2/▶ Configure > Advanced Project Options > Pipeline > [저장]※ <Github-Useranme>은 본인의 Username으로 수정Definition : Pipeline script from SCM Definition > SCM : Git Definition > SCM > Repositories > Repository URL : https://github.com/<Github_Username>/kubernetes-anotherclass-sprint2.git Definition > SCM > Branches to build > Branch Specifier : */main Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2232-build-push-git Definition > Script Path : 2232-build-push-git/Jenkinsfile3-3.[저장] 후 [지금 빌드] 실행 (이때는 파라미터가 없어서 실행되지 않아요!)3-4.[파라미터와 함께 빌드] 선택 후 본인의 DockerHub와 Github의 Username 입력 후 [빌드] 실행3-5.Stage View결과 확인​3-6. ArgoCD에서 자동 배포 확인​새로운 이미지가 들어온 걸 인식해서 생성한 후,이미지가 교체된 모습을 볼 수 있다.3-7. 다시 빌드 후 재확인깃허브에도 변경내용이 잘 반영된걸 볼 수 있다.

데브옵스 · 인프라k8sCredentialsArgoCDJenkinsHelmGithubCI/CD

wnsrlf0721

[워밍업클럽: 쿠버네티스] #13. Helm과 Kustomize 비교하기 (3주차)

Helm, Kustomize 내용정리 kubectl -> Helm, Kustomize 사용해보기쿠버네티스 배포를 위한 배포툴로 (jenkins, argoCD) 등을 사용한다.지금까지 배포 툴 위에서 kubectl로 쿠버네티스에 배포 명령(create, apply)을 해왔으나, CLI 명령으론 배포를 위한 부가적인 기능을 기대하기는 어렵다.실무에서는 자원 생성 간 대부분 헬름, 커스터마이즈를 이용해 생성하며, App을 빠르게 조회하거나, 급한 수정이 있을 경우에만 kubectl을 활용한다.헬름과 커스터마이즈는 배포툴에서 동작하는 패키지 매니저 이며, kubectl과는 다르게 앱을 구성하는 yaml 파일들을 패키지 단위로 관리를 한다. 이는 kubectl처럼 여러 yaml 파일을 apply 해줄 필요 없이 한꺼번에 패키지로 처리해주는 것이다. Helm vs Kustomize 비교 정리공통 부분사용하는 목적이 동일하다. 배포를 위한 여러 yaml 파일들을 중복 관리하는 걸 최소화한다. App 종류가 많아지면(MSA 방식 채택 시) 다양한 yaml파일들을 관리해야 하는 불편함이 생기고, 이때 패키지 단위로 yaml을 관리하게 되면 중복으로 yaml파일들을 관리할 필요가 없어진다. 다양한 배포 툴(argoCD, github actions 등)에서 헬름과 커스터마이즈를 지원해준다.차이점배포 편의기능 수 Helm : 200개 ↔ Kustomize : 10개패키지 하나 당 사용하는 활용 범위(권고사항) Helm : MSA 이용하는 경우 And 다양한 배포 환경 (두 목적 모두 가능) Kustomize : MSA 이용 경우 OR 다양한 배포 환경 (둘 중 하나만) →커스터마이즈는 활용 범위가 늘어날 수록 패키지 내부 파일량이 많아지는 구조 (파일관리 복잡해질 수 있음)사용 목적 Helm: 프로젝트관리 패키지용 + 기업 제품 패키지용 Kustomize: 프로젝트관리 패키지용유즈케이스 Helm : 대형 프로젝트에 사용 (App 종류 5개 이상) <-> Kustomize: 간단한 프로젝트에 사용 (5개 미만)Helm은 깃허브에서 다운 받아 설치해서, helm이 동작할 폴더를 생성하는 helm command를 사용해 세팅한다(helm create). Artifact HUB라는 Helm 패키지 저장소를 이용한다(Docker Hub느낌). Kustomize는 kubectl에 포함되어있어서 kubectl -k 명령어로 바로 사용할 수 있다(따로 설치 x).사용 방식 Helm : 템플릿 및 변수주입 방식template 폴더 안에 많은 yaml 파일들이 들어있는 구조이다. helm command로 변수를 주입하는 경우, helm install api-tester-32222 ./app -set port=’80’ -set profile=’dev’ -set nodeport=’32222’ 이렇게 파라미터 값을 주게되면, yaml 파일에 해당되는 파라미터 값을 채워준다.command를 쓰지 않고 파일에 변수 값을 주는 경우, values.yaml, Chart.yaml 등의 파일에 해당 값에 맞는 파라미터를 주입하는 방식을 많이 사용한다.Kustomize : 오버레이 방식 base 폴더 안에 파라미터 값이 없는 yaml 파일이 주어지고, kubectl apply -k ./app/overlays/dev 명령어를 주게 되면, 해당 명령어 뒤에 표시한 파일을 베이스 파일에 덮어쓴다. 즉, 기본 base에 있는 값은 그대로 반영을 하되, 같은 내용이 있는 파일을 덮어 쓸 경우 오버레이한 값으로 수정하고, 내용이 없는 경우 base에 추가를 한다(덮어쓰기). Helm 폴더 살펴보기helm create api-tester 명령어로 api-tester폴더 생성하면 아래와 같이 자동으로 패키지들이 만들어짐Helm 공식문서에 나온 helm create 명령어.생성한 폴더 아래에 yaml파일, ignore파일, charts와 templates 폴더가 생성된다..helmignorehelm은 폴더에 있는 내용 전체를 가지고 배포 yaml 파일을 만들게 되는데, 이때 ignore 파일에 배포하고 싶지 않은 파일목록을 추가해 헬름 차트에서 배포할 파일을 제외할 수 있다. 즉, 배포안할 yaml 파일을 여기에 선언하면됨이런식으로 gitignore같이 파일에 적어두면 여기에 적힌 파일은 배포간에 제외된다.Chart.yaml차트 자체의 기본정보를 선언하는 파일이다. 파일 내에 차트 이름, 버전, App 버전(image) 등이 선언된다.values.yaml배포할 yaml 파일에 들어가는 변수들의 기본값 선언하는 파일이다.templates 폴더 및 하위 파일쿠버네티스에서 필요한 각 yaml들이 여기에 담긴다. tests 폴더 : 메인 App이 배포된 후에 통신이 되는지 체크하는 용도(이번 강의에선 삭제)_helpers.tpl : 사용자 전역변수를 선언하는 파일, 이전에 valus.yaml에서 변수들의 기본값을 선언했지만, 추가로 변수 값들을 가공해 임의의 전역 값을 만들 수 있다.NOTES.txt : 배포 후 안내문구이외의 yaml파일 : 배포때 사용되는 yaml파일들 Kustomize 폴더 살펴보기helm과는 다르게 커스터마이즈는 폴더를 직접 만들어야한다. 심지어 하위 폴더 구성까지도..base 폴더 디폴트로 포맷이 될 yaml파일들을 넣는 폴더이다(helm에서 templates와 유사).kustomization 파일: 이 파일을 통해 우리가 배포할 파일들을 선택하고(helm에서 ignore와 유사), yaml파일에서 공통값(파라미터)를 설정한다(helm에서 values와 유사). 즉, helm에서 ignore와 values의 역할을 모두 맡은 파일이다.역할 : resources 배포 파일 선택 해당 영역에서 내가 배포할 파일을 명시한다. (헬름에서는 values.yaml에서 각 배포파일의 파라미터로 false를 설정해 배포하지 못하게 했음) 역할 : commonLabels 공통값 설정해당 파일에서 commonLabels 요소에 넣고싶은 값들을 넣으면, 모든 yaml 파일에 해당 내용이 labels로 들어간다. (헬름에서는 Deployment 템플릿에 변수를 설정하고, 특정 파일들마다 변수를 주입하는 방식이 다양했음)overlays 폴더오버레이를 할 영역에 대한 상위 폴더이고,(dev,qa,prod 등) 해당 폴더마다 각 환경에 맞게 오버레이할 파일을 넣어야한다.개발 환경을 배포하는경우 kubectl apply -k ./app/overlays/dev 이런 식으로 배포 명령을 준다.반면 Helm의 경우,values.yaml 파일을 환경별로 values-dev / values-qa / values-prod .yaml 이렇게 구분하고, 배포 명령을 할 때 -f 옵션을 추가해서helm install api-tester-32222 ./app -f ./app/values-dev.yaml 이렇게 선택한다.배포 파이프라인 구축 후 생기는 고민들 인증서 보안배포에 필요한 쿠버네티스 인증서, config.json(Docker로그인 정보) 가 서버에 노출되고,이 파일들은 암호화되지 않은 파일이다.config.json은 base64로, 디코딩하면 정보를 알 수 있는 파일이며,쿠버네티스 인증서 (kubeconfig)도 파일 자체로 관리자 권한 인증서라 관리자 권한으로 쿠버네티스 클러스터에 API를 호출할 수 있게 된다.그래서 우리는 이 중요 데이터들을 타인이 활용하지 못하도록 암호화하는 과정이 필요하다.Jenkins의 Credential을 이용하면 암호화할 수 있고, 추가로 도커 config.json은 도커에 로그인 할때마다 추가로 config 파일이 새로 만들어지기 떄문에, 배포시마다 도커허브로 업로드할 때 로그인한 이후에 종료시점에는 항상 로그아웃을 해야한다.(로그아웃 시 접속정보 삭제됨) 물론 Docker-credential-helpers 를 이용하게되면 파일을 열어도 비밀번호가 노출이 안되는 기능을 제공한다. 컨테이너 이미지 제거CICD 서버에서 컨테이너 빌드를 계속 하다보면 이미지들이 쌓이게 되고, 디스크 용량이 다 차게 되면 jenkins가 죽게된다.컨테이너 업로드가 완료되면 서버에 만들어진 이미지는 삭제해야한다.Helm으로 앱을 배포할 때 앱 하나마다 네임스페이스를 만들지 않고,네임스페이스를 미리 만들어두고, 여러 앱들을 한 네임스페이스 안에서 그룹으로 생성될 수 있다.네임스페이스는 배포와 별도로 관리하는 것이 좋다.인스톨 할때는 네임스페이스를 자동으로 만들어주는 기능이 있지만, 언인스톨 할 때는 네임스페이스를 자동삭제해주지 않음(여러 앱들이 한 네임스페이스에 있을 경우 다른 앱들도 같이 삭제될수 있어서) Helm 부가기능 (wait)배포 명령 실행 이후 wait 옵션을 주면 파드가 정상기동이 되는 지 확인을 해주고, 정상적으로 파드와 통신이 되면 배포 종료라는 결과를 보내준다.Helm 부가기능 (Annotations)배포를 했지만 파드가 업그레이드 되지 않는 경우가 있다.위 경우는 Deployment파일에서 templates 스크립트 밑으로 내용의 변경이 있어야 업그레이드가 진행된다.이를 위해 metadata.annotations를 제공해 새 배포마다 랜덤값을 생성해 항상 업그레이드 되도록 한다. Tag (image에 붙이는 버전)Tag는 배포 환경마다 tag를 붙이는 성질이 달라진다.개발 환경에서는 잦은 배포로 versioning이 무의미해 지게 되고, 이 때 tag는 항상 latest로(최신버전의 App), pullPolicy: Always로 한다.Always는 이미지가 없을 때 항상 도커허브에서 이미지를 가져오는 방식이다.HUb가 미연동되어있는 경우, Pod 생성에 에러가 생긴다.Test(검증)나 Prop(운영)환경의 경우는 계획된 배포를 하며, versioning이 필수가 된다.이때 tag는 버전의 유의를 하게되고(항상 latest x), pullPolicy: IfNotPresent를 사용한다.IfNotPresent는 노드에 해당 이미지가 있는 경우 그것을 사용하고, 없을 때 도커허브에서 가져오는 방식이다.운영환경에서는 파드가 scale-out, scale-in 되는 경우가 자주 발생할 상황이 많고, 그럴 떄마다 이미지를 허브에서 가져오게 되면 비효율적이고, 허브에 연결되어있지 않은 경우 파드가 만들어지지 못하게 된다.프로젝트 규모가 커지게 되면, 개발 환경의 버전별로 롤백을 해서 다시 개발을 하는 상황도 생겨서, 빌드한 소스코드의 날짜를 기반으로 tag를 만드는 것이 좋고,latest 버전은 항상 새로운 버전마다 latest를 붙이는 것보단, 운영환경에서 안정적으로 쓰였던 가장 최신의 버전을 latest로 tag해 latest를 최신 안정화 버전으로 사용하는 것이 낫다.

데브옵스 · 인프라k8sHelmKustomizepipelineCI/CD

채널톡 아이콘