일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- MySQL
- DBMS
- JPA
- Spring
- 리눅스
- Dining philosopher problem
- 소켓
- springboot
- 인공지능
- CD
- 밥먹는 철학자
- CI
- sql
- swift
- 스프링부트 웹 소켓
- 오라클
- 다이어리
- 스프링
- IOS
- 데이터베이스
- javascript
- 42seoul
- 네트워크
- 프로그래밍언어론
- jenkins
- Xcode
- 아이패드다이어리
- 스프링부트
- libasm
- AI
- Today
- Total
Hi yoahn 개발블로그
오픈소스 소프트웨어 기말 정리 본문
1. CI 환경 구축
CI 도구
- 지속적인 통합을 위한 소프트웨어 도구
- 매 커밋마다 프로젝트 빌드, 단위 테스트 등의 과정을 개발자 대신 자동화
1) Travis CI
- Github 에서 진행되는 오픈소스 프로젝트를 위한 지속적인 통합 서비스
- Private Repository 는 유료
- 관리가 필요 없는 무료 클라우드 기반 호스팅 제공
- 전용 CI/CD 서버가 필요하지 않음
- 느린 속도와 제한된 옵션 제공
2) Jenkins
- 가장 널리 사용되는 오픈소스 CI 도구
- 사용자 정의 옵션
- 방대한 양의 플러그인 지원
- 다양한 적용사례 및 풍부한 레퍼런스
- 별도의 서버 필요
- 시스템 구성 및 사용자 정의 시간이 오래 걸림
3) 공통점
- github의 webhook 지원이 필요
1.1 CI 환경 구축
1. docker 설치
sudo wget -qO- https://get.docker.com/ | sh
sudo usermod -aG docker ${USER} # docker 실행을 sudo 권한 없이 할 수 있게 해줌
sudo systemctl start docker
sudo systemctl enable docker
logout
2. Jenkins 설치
- Jenkins Docker 이미지 빌드
docker build -t myjenkins 로 이미지 빌드
- Jenkins 컨테이너 실행
docker run -d --name myjenkins -p 8080:8080 --restart=always
-v jenkins-home:/var/jenkins_home
-v /var/run/docker.sock:/var/run/docker.sock
--group-add $(stat -c '%g' /var/run/docker.sock) myjenkins
- -v /var/run/docker.sock:/var/run/docker.sock
- 소켓 연결
- 호스트 소켓과 컨테이너 안의 소켓을 연결 (도커 안에서 도커를 실행)
- 젠킨스 컨테이너에서 호스트의 Docker engine 을 활용하기 위해서
- docker volume: bind-mount 방식
- -v jenkins-home:/var/jenkins_home
- docker volume 방식
3. Docker 이미지로 배포하기
- Jenkinsfile 작성
- stage('여기는 원하는 이름으로 작성') {
여기는 Jenkinsfile 명령 사용
}
- stage('여기는 원하는 이름으로 작성') {
node {
def app
stage('Clone repository') {
git 'https://github.com/AYoungSn/jenkins-test.git'
}
stage('Build image') {
app = docker.build("dudtjs0920/sswu-opensource") // docker ID, docker repo
}
stage('Test image') {
app.inside {
sh 'make test'
}
}
stage('Push image') {
docker.withRegistry('https://registry.hub.docker.com', 'dudtjs0920') {
app.push("${env.BUILD_NUMBER}")
app.push("latest")
}
}
}
- Dockerfile 작성
FROM ubuntu:20.04
RUN apt-get update && apt-get -y install build-essential && mkdir -p /app
COPY . /app/
WORKDIR /app/
CMD make
2. 클라우드 개요
"언젠가 컴퓨팅은 전화 시스템과 같이 공공재로 구성 될 것입니다. 사용자들은 다른 사용자들에게 서비스를 제공하기도 할 것이며 컴퓨터 사업은 새롭고 중요한 산업의 기반이 될 것입니다."
John McCarthy (1971 Turing 상)
2.1 클라우드란?
- 클라우드 컴퓨팅 / 클라우드 서비스를 줄인 말
- 클라우드 컴퓨팅은 정보를 자신의 컴퓨터가 아닌 인터넷에 연결된 다른 컴퓨터로 처리하는 기술
- 인터넷을 구성하는 서버들과 네트워크 장비들을 나타내기 위해 구름모양 심볼을 사용하던 것에서 유래
2.2 클라우드의 장점
- 민첩한 서비스 도입, 탄력적인 확장과 축소, 자동화된 서비스 유지 관리 가능
- 낮은 운영 비용과 비즈니스 요구사항의 변화에 빠르게 적응할 수 있는 환경을 제공
- 재난시 장애 복구 가능
- 허리케인, 홍수, 산불 등의 재난으로 인한 데이터 손실로부터 상대적으로 안전
- 여러 대륙에 걸친 데이터센터에 데이터 복제
- 가용성
- 서비스를 호스팅하는 서버가 있는 데이터 센터에 어떤 문제가 발생하더라도 서비스 중단 없이 제공 가능
- 다른 데이터센터의 다른 서버가 서비스를 제공
- 확장성
- 서비스 사용자, 데이터, 요청이 늘어나더라도 공간/성능적인 제약 없이 세계 곳곳에 있는 클라우드 데이터센터로부터 자원 활용 가능
- 웹 애플리케이션 vs 웹 사이트
- 유저와 상호작용이 가능한 동적인 웹
- 정보 관람 목적의 정적 사이트
- 애플리케이션의 구조
- Client Tier, Web Tier, Presentation Logic Tier, Business Logic Tier, Data Access Tier, Data Tier
- 3계층 아키텍쳐
- Presentation Layer
- HTML, CSS, JS - Application Layer
- Java, Js, Python, C#, .NET, C++ - Data Layer
- MySQL, Oracle, MongoDB
- Presentation Layer
- 확장성
- 실 서버를 전부 구입해서 서비스를 제공하게 되면 서비스 인기가 떨어졌을 때 사용량이 떨어져 자원이 낭비됨
- 클라우드를 사용하게 되면 초기 투자 비용이 낮음
- 별도의 초기 투자 비용 없이 시작 가능
- 클라우드 서비스 업체는 일부 기능은 무료로 제공
- Simplicity
별도의 개발/실행 환경 구축 없이 쉽게 클라우드 서비스를 활용 가능 - Automatic software update
서비스 중인 소프트웨어의 업데이트를 downtime 없이 자동으로 제공 - 업무 장소의 유연성
인터넷에 연결되어 있는 모든 곳에서 업무 수행 가능 - Security
기기를 분실하더라도 데이터는 안전함 - 운영 비용 감소
전력, 냉방 및 관리 등 운영비용 감소
2.3 클라우드 컴퓨팅 기술
- 사용량에 따라 요금을 부과하는 종량제 방식의 유틸리티 컴퓨팅을 근간으로 함
- 유틸리티 컴퓨팅 + 그리드 컴퓨팅
그리드 컴퓨팅 | 가상 네트워크를 이용하여 분산된 컴퓨팅 자원을 공유하도록 하는 기술 방식 (인터넷의 유휴 자원을 활용) |
유틸리티 컴퓨팅 | 다양한 컴퓨팅 자원에 대한 사용량에 따라 요금을 부과하는 종량제 방식의 기술 기반으로, 필요할 때 가져다 쓴다는 온디맨드(On Demand) 컴퓨팅 방식 (기업 중심의 서비스) |
클라우드 컴퓨팅 | 기술적으로는 그리드 컴퓨팅을 따르고, 비용적으로는 유틸리티 컴퓨팅을 혼합한 포괄적인 패러다임 차이점 - 기업과 개인이 모두 사용가능한 서비스 - 클라우드 서비스를 제공하는 사업자의 컴퓨팅 자원 이용 |
1) 클라우드 컴퓨팅의 특징
- 주문형 셀프 서비스
고객이 IT 서비스 제공자의 개입없이 원하는 시점에 서비스를 사용 가능 - 광대역 네트워크 접근
각 클라우드 서비스 업체가 제공하는 광대역 네트워크를 이용하여 다양한 클라이언트 플랫폼이 빠르게 접속 - 신속한 탄력성과 확장성
Auto-scaling 기능을 통해 몇분 안에 신속한 확장과 축소를 조정할 수 있음 - 자원의 공동관리
물리적 및 가상화된 자원을 풀(Pool)로 관리하며, 탄력적으로 사용자 요구에 따라 동적으로 할당 또는 재할당 가능 - 측정 가능한 서비스
자원 사용량이 실시간으로 수집되는 요금 산정 기능을 통해 비용을 측정 가능
2) 클라우드 컴퓨팅 구조
- 자원활용
- 클라우드 서비스
- 물리적 시스템 계층
- 여러 형태의 서버 계열을 활용하여 서버에 탑재된 수평적으로 확장 가능한 스토리지 및 네트워크 등의 물리적 요소
- 인텔 서버, 메인 프레임, 블레이드 서버, 스토리지, 네트워크
- 가상화 계층
- 물리적 시스템 계층을 기반으로 민첩성을 제공
- 서버 가상화, 스토리지 가상화, 네트워크 가상화(가상 서브넷)
- 프로비저닝 계층
- 가상화 계층을 기반으로 클라우드 서버 프로비저닝 또는 프로비저닝 해제를 신속히 수행하여 사용자의 요구를 충족
- 서버 프로비저닝, 네트워크 프로비저닝, 스토리지 프로비저닝, 애플리케이션 프로비저닝
- 가상화 계층을 기반으로 함
- 미리 준비해놓는 것
- 서버/네트워크/스토리지/애플리케이션 을 필요할 때 준비해주는 계층
- 가상 서버들을 할당 받아서 위 계층에 제공해줌
- 트래픽에 따라 서버를 조절 (할당 / 반납) => auto-scaling
- 클라우드 서비스 관리 계층
- 클라우드 서비스 제공자 측면에서 중요한 계층
- 제공되는 자원에 대한 전반적인 라이프사이클 관리와 모니터링 지원
- 안정적인 클라우드 서비스를 위한 성능 및 고가용성, 소프트웨어 라이선스와 패치 관리, 사용량 요금 산정을 통한 과금 관리, 클라우드 보안 관리 요소 결합
- 성능 및 가용성 관리
- 백업 복구 관리
- 성능 관리
- 장애 관리
- 구성 관리
- 라이선스 관리
- 패치 관리
- 자원 관리
- 사용량 및 과금 관리
- 과금 관리
- 사용량 요금 산정
- 보안 관리
- 컴플라이언스 관리
- 데이터 보안
- 네트워크 보안
- 접근 권한 관리
- 인증 관리
- 운영프로세스 자동화
- 클라우드 서비스 계층
- 구성된 클라우드 구성 요소를 서비스로서 제공
- 확장 가능한 컴퓨팅 자원을 사용한 양에 따라 비용을 지불
- 클라우드 환경에 있는 모든 자원에 인터넷을 통해 언제든 접근
- IaaS (Infrastructure as a Service)
- Paas(Platform as a Service)
- SaaS(Software as a Service)
- 사용자는 주어진 역할(사용자, 관리자)에 따라 다양한 웹 API(RESTful API, XML 등) 를 통해 클라우드 서비스를 호출할 수 있음
2.4 클라우드의 종류
1) 온프레미스 - 클라우드 아님
- 클라우드 개념이 도입되기 전의 일반적인 접근 방식
- 기업이 자체 데이터 및 솔루션 등을 저장하기 위해 자사에 데이터 센터를 구축하여 IT 서비스를 수행
- 단점
- 높은 초기 투자 비용 (HW + SW)
최대 사용량, 최대 순간 트래픽을 가정하고 설계 - 탄력적이지 않은 제한된 자원 용량 -> 지속적인 관리 비용 증가
- 높은 초기 투자 비용 (HW + SW)
- 장점
- 품질 및 보안에 대한 높은 신뢰도
2) 퍼블릭 클라우드
- 클라우드 서비스 공급자가 제공하는 서버 및 스토리지 등의 클라우드 자원을 인터넷을 통해 다수의 사용자들이 제공받는 방식
- 공유하는 대신 저렴하고 신속한 운영 가능
- 자체 인프라가 없거나 빈약한 스타트업, 중견기업이 주로 사용
- 클라우드 자원을 공유한다고 해서 다른 사용자의 자원에 접근 가능한 것은 아님
3) 프라이빗 클라우드
- 독점적으로 사용하여 보안을 높일 수 있는 인프라 환경 (기업이 직접 클라우드를 구축하고 내부 활용)
- 제한된 네트워크에서 특정 사용자나 기업만을 대상으로 하는 클라우드 서비스 방식
- 클라우드 역량 확보를 바탕으로 퍼블릭 클라우드 사업 진출을 목표로 함
4) 멀티 클라우드
- 여러 퍼블릭 클라우드를 함께 사용하는 경우
- 고가용성
특정 클라우드가 다운되는 경우에도 다른 클라우드가 동작하므로 서비스가 중단되지 않음 - 종속성 제거 (lock-in 제거)
하나의 클라우드만 쓰게 되는 것을 방지 (언제든지 변경 가능)
5) 하이브리드 클라우드
- 퍼블릭 클라우드와 프라이빗 클라우드를 네트워크를 통해 결합한 클라우드 서비스 방식
- 민감한 데이터 -> 프라이빗 클라우드
- 워크로드 예측 어려움 -> 퍼블릭 클라우드
2.5 클라우드 서비스 모델
- 언제 어디서나 별도의 소프트웨어 등을 설치하지 않고 인터넷 접속을 통해 저장해 놓은 데이터에 접근하여 사용할 수 있는 서비스
- IaaS (Infrastructure-as-a-Service)
- 서버, 스토리지, 네트워크와 같은 인프라 하드웨어 자원을 가상화하여 사용자 요구에 따라 인프라 자원을 사용할 수 있게 제공하는 클라우드 서비스 방식 (GCP Compute Engine, AWS)
- 인프라 관리자가 사용
- 클라우드 인프라 하드웨어(서버, 스토리지, 네트워크)를 구축해서 서비스 개발자들한테 제공
- 기업은 클라우드 제공업체로부터 서버와 저장소 자원을 임대, 자체 애플리케이션 구축
- 물리적 자원에 대한 지식이 반드시 필요
- 사용자가 애플리케이션의 실행환경을 직접 구축해야하는 클라우드 서비스 모델
- ex) 건물을 지을 수 있는 토지를 임대
초록색 부분은 사용자가 구축해야 되는 부분
- PaaS (Platform-as-a-Service)
- 개발 도구, 인프라, 운영체제를 포함한 애플리케이션 구축에 필요한 모든 것을 인터넷을 통해 제공
- 개발자가 사용, 플랫폼 제공
- PaaS 에서 제공된 서비스를 바탕으로 SaaS를 구축
- PaaS 사용 시 인프라 구축하는데 수고를 덜 수 있음 -> 바로 개발 가능
- 문제 발생 시 PaaS 제공자가 대신 해결해 줌
- low code, no code
- ex) 집을 빌리는 대신 집을 짓는데 필요한 모든 도구와 장비를 빌림
(Heroku, RedHat OpenShift, Azure machine learning studio, Google Dialogflow)
- SaaS (Software-as-a-Service)
- 사용자가 장치에 애플리케이션을 설치하는 대신 SaaS 애플리케이션이 클라우드 서버에 호스팅되고 사용자는 인터넷을 통해 애플리케이션에 액세스
- 집을 빌려 쓰는 것, 일반 사용자 대상
- 그냥 사용만 하면 됨
- ex) 이메일, Slack, Dropbox
- 사용자가 장치에 애플리케이션을 설치하는 대신 SaaS 애플리케이션이 클라우드 서버에 호스팅되고 사용자는 인터넷을 통해 애플리케이션에 액세스
- FaaS (Function-as-a-Service)
- micro service
- 클라우드 애플리케이션을 필요할 때만 실행되는 더 작은 구성 요소로 나눔
- 이벤트가 발생 했을 때 Function이 동작
- 식사할 때 식당, 잘 때 침실, TV를 볼 때 거실에 대해 비용을 지불
- 확장성 -> 함수 단위로 제공 (Scale up/down)
- ex) AWS Lambda, GCP Functions 등
클라우드 서비스 제공 업체
- AWS
- GCP (Google Cloud)
- Azure (마이크로소프트)
- 네이버, 카카오 등
3. Jenkins Multibranch pipeline
- git branch 를 기반으로 자동으로 파이프라인 생성
- 각 브랜치에 있는 Jenkinsfile 을 사용
- PR 기반의 브랜치 discovery 지원
- 조건에 따른 분기 가능
- Feature 브랜치에 대해서는 배포를 하고 싶지 않은 경우
- Jenkins 를 활용한 개발 프로세스
- 개발자는 feature 브랜치에 코드를 commit
- 개발자가 feature 브랜치로부터 develop 브랜치에 PR 을 요청
- Jenkins 는 Unit test 및 정적 코드 분석 수행 (webhook 동작)
- 분석이 완료되면 PR 에 Job status 가 업데이트 됨
- 개발자는 PR 을 develop 브랜치에 merge
- 릴리즈 준비가 되면, develop 브랜치로부터 master 브랜치로 PR 을 요청
- Jenkins는 Unit test, 코드 분석, 배포 진행
- 분석 완료 후 PR 에 Job status 업데이트
3.1 Pipeline Syntax
Declarative (선언형 프로그래밍) | Scripted (명령형 프로그래밍) |
원하는게 무엇인지, 명령이 어떻게 동작하는지는 이미 구현되어 있음 사전에 정의된 구조가 이미 존재 오류가 발견되면 명령을 실행하지 않음 사용이 쉽고, 문제가 발생할 여지가 적음 |
어떻게 동작하게 할 것인지, 동작의 흐름을 명령하는 구조 오류 발견 시 오류 이전 명령들은 이미 실행된 상태 자유도가 높음, 제한이 적음 |
"무엇을" 명령 | "어떻게" 할 것인지 명령 |
SQL | C |
유효성 검사를 파이프라인이 실행 가능한지 먼저 체크 후 실행 | 일단 실행하면서 에러가 발생하면 이전 단계의 명령들은 실행된 상태로 중단 |
특정 stage 에서 재시작 가능 | 항상 처음부터 stage를 다시 실행해야 함 |
when | if |
- Declarative syntax 안에서 Scripted syntax 를 사용할 수 있다.
- pipeline
파이프라인 전체를 선언하는 키워드- stages { stage,,, { steps...
- node
스크립트를 실행하는 서버- stage
4. 컨테이너 오케스트레이션과 Kubernetes
4.1 컨테이너의 한계
- 배포의 문제점
- 모든 서버에 직접 접속해서 docker stop, run 실행
- 도커 컨테이너 실행에 필요한 리소스 관리가 필요
- 모니터링 시스템, 유휴자원 관리 등
- 컨테이너를 실행하려고 할 때 어디에 실행시킬 수 있을지 등,,
- 새롭게 배포된 애플리케이션 장애 시 신속하게 대처하기 어려움
(update 후 rollback 어려움)
- 서비스 접근 및 노출의 문제점 (IP 주소)
- 동일한 네트워크에서만 접속가능
- 서비스 장애, 부하 모니터링의 문제점
- 모니터링이 어려움
- 컨테이너 오케스트레이션으로 계속 체크
4.2 컨테이너 오케스트레이션
복잡한 컨테이너 환경을 효과적으로 관리하기 위한 도구
기능
- cluster
- 중앙제어
master 가 전체 클러스터들을 관리 - 네트워킹
- 노드 스케일
- 중앙제어
- state
- 상태 관리
- replicas : 복제본의 개수 설정
- 컨테이너 개수를 지정한 개수가 항상 유지되도록 관리해주는 기능
- 장애 발생 시 컨테이너를 자동으로 하나 더 띄워줌
- scheduling
- 배포 관리
- 어플리케이션을 배포하려고 할 때, 어느 컨테이너에 배포할지
- Rollout / Rollback
- 배포 버전 관리
- Service / Discovery
- 서비스 등록 및 조회
- 서비스가 추가되면 새로운 서비스가 자동으로 등록됨
- Volume
- 볼륨 스토리지
- 영구적인 data 저장
- 노드별로 다른 스토리지 사용 가능
(NFS, AWS, GCP)
4.3 쿠버네티스 (K8s)
- 컨테이너 오케스트레이션의 업계 표준
- 배포 계획에 맞춰 신속한 애플리케이션 배포 가능
- 컨테이너 개수, CPU 사용률, 메모리 사용량 설정 가능
- 저장 공간, 네트워크 접근 제어, 로드밸런싱 기능 설정 가능
- 가동 중인 애플리케이션을 스케일 아웃/인 할 수 있음
(스케일 업은 불가능 (스펙 향상 불가))
- 스케일 아웃: 요청이 많을 때는 컨테이너 수를 증가시켜 처리 능력 높임
- 스케일 인: 요청이 적을 때는 컨테이너 수를 줄여 자원 점유율 및 요금 줄임
- 새로운 버전의 애플리케이션 무정지 업그레이드 기능
- 하드웨어 가동률을 높여 자원 낭비를 줄임
- 배포 계획에 맞춰 신속한 애플리케이션 배포 가능
스케일 아웃: 서버 개수가 증가 (컨테이너 증가)
스케일 업: 서버 스펙이 올라감
4.4 쿠버네티스의 특징
- 다양한 환경에서 쿠버네티스 사용 가능
- 퍼블릭, 프라이빗, 멀티, 하이브리드 클라우드, 온 프레미스 위에 구축 가능
- 쿠버네티스는 일관된 인터페이스를 제공하여 인프라의 복잡성을 감춰줌
- 온프레미스와 클라우드 환경에서 동일한 인터페이스로 조작 및 운영 가능
- 높은 유연성과 확장성
- 마이크로 서비스 애플리케이션에 최적화된 실행환경
- 느슨한 결합에 의한 유연성, 교체 용이성
- 다양한 스펙의 서버가 혼재하는 클러스터 구성 가능
Heterogeneous (<-> Homogeneous) - 서버의 정지, 추가, 제거가 용이
- 저장소나 로드밸런서의 동적 프로비저닝
- 퍼블릭 클라우드 API 와 연동 가능
- 고가용성
- 서버 정지 시 애플리케이션 재배포 자동화
- 애플리케이션의 이상 종료 시 자동 재기동
- 성능관리
- 필요한 인스턴스의 개수를 유지
- 높은 부하에서 자동 스케일 아웃 (실행 중에 가능)
4.5 쿠버네티스의 아키텍쳐
- 두 종류의 서버들로 구성
- 마스터
클러스터의 전체 관리를 담당 - 노드 (워킹노드)
컨테이너화된 애플리케이션을 실행
- 마스터
- 계층 구조
- 마스터의 역할
- 클라이언트의 명령을 받아들이고 실행
- 컨테이너를 파드 단위로 스케줄링 및 삭제
- 파드의 컨트롤러 기능과 외부 리소스 관리
- 마스터의 역할
4.6 쿠버네티스의 오브젝트
- 컨테이너
- 컨테이너만을 독자적으로 실행하는 것은 불가능
- 반드시 파드 내에서 실행해야 함
- 컨테이너 기동 시 설정 가능한 항목
- 이미지의 이름
- 실행 명령어
- 실행 인자
- 환경변수
- 볼륨
- CPU 사용시간, 메모리 크기의 요청값 및 상한값
- 파드
- 컨테이너를 실행하는 최소 단위
- 한 개 혹은 여러개의 컨테이너를 담을 수 있음
- 하나의 파드에 속하는 모든 컨테이너들은 같은 노드에서 동작
(하나의 파드는 하나의 노드 위에서 실행) - 파드의 특징
- 컨테이너 재사용 촉진을 위한 플랫폼
(하나의 파드 안에 여러개의 컨테이너 있을 때의 장점)
- 파드 내부 컨테이너들은 파드의 IP 주소와 포트번호를 공유 (파드의 IP주소, 파드에 할당된 port 번호가 주어짐)
- 파드 내부 컨테이너들은 localhost 로 서로 통신 가능
- 파드 내부 컨테이너들은 System V 프로세스 통신이나 POSIX 공유 메모리를 사용하여 서로 통신 가능
- 파드 내부 컨테이너들은 파드의 볼륨을 마운트하여 파일 시스템 공유 가능
- 파드는 일시적인 존재
- 파드 내의 컨테이너는 이미지로부터 매번 생성
(같은 오브젝트 이름으로 파드를 기동해도 이미지의 초기 상태에서 시작) - 파드의 IP 주소도 고정적이지 않음
(파드 종료 시 IP 회수) - 파드에 요청을 보내고 싶은 경우에는 서비스를 사용해야 함
- 파드 내의 컨테이너는 이미지로부터 매번 생성
- 파드는 컨테이너의 실행 상태를 관리
- 파드가 정지한 경우는 담당 컨트롤러가 재가동
- 파드 내부의 컨테이너가 정지한 경우는 파드가 해당 컨테이너를 재시작
- 활성 프로브와 준비 상태 프로브를 설정하여 내부 애플리케이션의 상태를 감시할 수 있음
- 활성 프로브: 애플리케이션이 멈춰 있는 상태를 감지 -> 강제 종료 & 재시작
- 준비 상태 프로브 : 파드가 요청받을 준비가 될 때까지 서비스 오브젝트가 요청을 전송하지 않음
- 파드는 초기화 전용 컨테이너를 실행
- 파드에 초기화만을 담당하는 컨테이너를 설정할 수 있음
- 초기화 담당 컨테이너가 제일 먼저 실행
- 초기화가 끝나면, 핵심 기능을 수행하는 컨테이너들이 실행됨
- 파드는 서비스, 컨트롤러, 퍼시스턴트 볼륨 등의 다른 오브젝트들과 함게 사용될 때 진가를 발휘
- 파드에 초기화만을 담당하는 컨테이너를 설정할 수 있음
- 컨테이너 재사용 촉진을 위한 플랫폼
- 노드는 컨테이너화된 애플리케이션이 실행되는 서버이다.
- 서비스
- 파드와 클라이언트를 연결하는 역할을 수행
- 대표 IP 주소로의 요청 트래픽을 지정된 파드들에 부하분산하며 전송하는 역할도 수행
(로드밸런서) - 서버 파드는 IP주소가 계속 바뀌기 때문에, 이름으로 접근하기 위해 서비스가 필요
- ClusterIP, NodePort, LoadBalancer, ExternalName
- 컨트롤러
- 파드의 실행을 제어하는 오브젝트
- 여러 종류의 컨트롤러가 있어 각 컨트롤러의 기능을 이해하고 목적에 맞게 적절히 구별해서 사용
- 디플로이먼트, 레플리카셋, 스테이트풀셋, 잡,,,
4.7 쿠버네티스의 아키텍처
- kubectl
- K8s 클러스터를 조작하기 위한 도구로 가장 빈번하게 이용되는 커맨드라인 인터페이스
- kube-apiserver
- kubectl 등의 API 클라이언트로부터 오는 REST 요청을 검증
- API 오브젝트를 구성 및 상태 보고
- kube-scheduler
- 새로 생성된 모든 파드에 대해 실행할 최적의 노드 선택
- 파드가 실행 가능한 노드를 찾은 후, 점수를 계산한 후 가장 점수가 높은 노드를 선택
- kube-controller
- 컨트롤러를 구동하는 마스터 상의 컴포넌트
- etcd
- K8s 클러스터의 모든 관리 데이터를 저장
- Key=Value 저장소
- kubelet
- 파드와 컨테이너의 실행
- 파드와 노드의 상태를 모니터링해서 API 서버에 보고
- 컨테이너의 동작을 확인하는 프로브 실행
- 내장된 cAdvisor 를 통해 메트릭 수집 및 공개
- kube-proxy
- 각 노드에서 동작하며 로드밸런싱 기능을 제공
- 서비스와 파드의 변경을 감지하여 최신 상태로 유지
- iptables 규칙을 관리
- 서비스명과 ClusterIP 를 내부 DNS 에 등록
- 각 노드에서 동작하며 로드밸런싱 기능을 제공
클라우드 과금 줄이기 - 클러스터 크기 조절
gcloud container clusters resize kube --num-nodes=0 --zone asia-northeast3-a --project opensource-344906
5. 쿠버네티스 기초
5.1 파드와 컨트롤러
- 단독 파드 구동
- 비정상으로 종료되어도 다시 기동하지 않음
- 컨테이너 종료 후, 삭제 필요
- 수평 스케일 안됨
- 컨트롤러를 가지고 파드 실행
- (디플로이먼트)서버 타입의 파드 제어
- 요구를 계속 대기하면서 종료하지 않는 타입 -> 웹서버
- 수평 스케일
- 비정상 종료 시 다시 기동시킴
- (잡) 배치 처리 타입 파드 제어
- 처리가 정상 종료 시 완료함
- 처리가 실패하면 재시도
- 병렬 처리 수를 설정해서 시간 단축
- (디플로이먼트)서버 타입의 파드 제어
- 파드 직접 실행
kubectl run hello-world --image=hello-world -it --restart=Never --rm
- kubectl
k8s 클러스터 조작 커맨드 - run : 컨테이너 실행을 명령
- hello-world : 쿠버네티스 오브젝트의 이름 (파드, 컨트롤러)
- --image=hello-world: 컨테이너의 이미지. 쿠버네티스에서는 파드 단위로 컨테이너가 기동되며 리포지터리명이 생략된 경우에는 도커 허브를 사용
- -it
도커에서의 -it 와 마찬가지로, -i 는 키보드를 표준 입력에 연결하고, -t 는 유사 터미널과 연결하여 대화 모드 설정.
옵션 '--restart=Never' 인 경우에만 유효. 그 외에는 백그라운드로 실행 - --restart=Never
이 옵션에 따라 파드의 기동 방법 변경. Never는 직접 파드가 기동되며 Always나 OnFailure는 컨트롤러를 통해 파드가 기동됨 - --rm
파드 종료 후 자동으로 삭제하는 옵션
- hello-world
- 커맨드 실행
- 이미지 다운로드
- 컨테이너 실행 & 메시지
같은 이름으로 파드 재기동 불가능 -> 이미 같은 이름의 파드 존재하기 때문에
- kubectl get po (pod)
- docker container ps -a 와 비슷
- 종료한 파드가 남아있는 상태
- kubectl delete pod hello-world
- hello-world 파드를 삭제
- kubectl logs hello-world
파드 로그 출력 - kubectl run hello-world --image=hello-world --restart=Never
-> -it 빠짐
: 백그라운드로 실행 - 컨트롤러에 의한 파드 실행
- 디플로이먼트 컨트롤러의 제어 하에 실행- kubectl create deployment hello-world --image hello-world
deployment 생성
hello-world pod 생성, replica 1개
- kubectl create deployment hello-world --image hello-world
- hello-world 컨테이너는 출력 후 종료되는 컨테이너
- 디플로이먼트로 관리되는 파드는 웹서버처럼 상시 가동되어야 함
- 웹 서버 Nginx 디플로이먼트 실행
- kubectl create deployment webserver --image nginx --replicas=5
파드 5개가 유지되도록 설정 - kubectl delete po webserver-{해시값}
강제로 일부 파드 삭제
-> 레플리카를 설정했기 때문에 다시 기동시켜 5개를 유지함
- kubectl create deployment webserver --image nginx --replicas=5
- 잡에 의한 파드 실행
- 단발성 형태의 워크로드에 적합한 잡 컨트롤러
- 파드가 비정상 종료될 시 재시작
- 정상 종료할 때까지 지정한 횟수만큼 재실행
- 컨테이너의 프로세스 종료 코드 값으로 성공(0)과 실패(1)를 결정함
- kubectl create job job-1 --image=ubuntu -- /bin/bash -c "exit 0"
-- 로 kubectl 의 argument 와 분리하여 컨테이너 커맨드를 입력한다.
5.2 매니페스트와 파드
매니페스트란?
- 쿠버네티스의 오브젝트를 생성하기 위한 메타 정보를 YAML이나 JSON으로 기술한 파일
- 단독 파드 구동을 위해 매니페스트를 작성하는 경우는 많지 않음
- 실제 운영 환경에서는 컨트롤러를 사용해 파드를 기동하는 것이 일반적임
kubectl run nginx -- image=nginx:latest --restart=Never
ex) nginx-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:latest
파드 설정
apiVersion | (yml 버전 설정) v1 |
kind | 오브젝트 타입 설정 (Pod) |
metadata | 파드의 이름을 지정하는 name 은 필수 항목이며, 네임스페이스 내에서 유일한 이름이어야 함 |
spec | 파드의 사양을 기술 |
containers | 컨테이너의 사양을 배열로 기술 |
initContainers | 초기화 전용 컨테이너의 사양을 배열로 기술 |
nodeSelector | 파드가 배포될 노드의 레이블을 지정 파드가 어떤 노드에서 실행될지 |
volumes | 파드 내 컨테이너 간에 공유할 수 있는 볼륨을 설정 |
컨테이너 설정 (containers)
image | 이미지의 리포지터리명과 태그 |
name | 컨테이너를 여러개 기술할 경우 필수 항목 |
livenessProbe | 컨테이너 애플리케이션이 정상적으로 동작 중인지 검사하는 프로브 활성프로브 |
readinessProbe | 컨테이너 애플리케이션이 사용자의 요청을 받을 준비가 되었는지 검사하는 프로브 준비상태 프로브 |
ports | 외부로부터 요청을 전달받기 위한 포트 목록 |
resources | CPU 와 메모리 요구량과 상한치 |
volumeMounts | 파드에 정의한 볼륨을 컨테이너의 파일 시스템에 마운트하는 설정. 복수개 기술 가능 |
command | 컨테이너 기동 시 실행할 커맨드. args 가 인자로 적용 |
args | command 의 실행 인자 |
env | 컨테이너 내에 환경 변수를 설정 |
관련 kubectl 서브 커맨드
- kubectl create
동일한 이름 오브젝트가 있을 때 에러 반환 - kubectl apply
동일한 이름 오브젝트가 있을 때 매니페스트 내용 적용
-> update 개념, Manifest 설정을 update- kubectl apply -f (manifest 파일명)
- kubectl delete
오브젝트 삭제- kubectl delete -f (yaml 파일명)
파일명 대신 URL도 사용 가능
- kubectl delete -f (yaml 파일명)
- 접근 실패 원인
클러스터 내부 IP 이므로 클러스터 외부에서 접근 불가능 - 매니페스트 적용 및 확인
- 대화형 파드를 기동해서 nginx 파드에 접근
$ kubectl run busybox --image=busybox --restart=Never --rm -it sh
busybox 파드를 통해 nginx 파드 접속
- 대화형 파드를 기동해서 nginx 파드에 접근
5.3 파드의 헬스 체크 기능
- 두 종류의 프로브
- 활성 프로브 (Liveness Probe)
- 준비상태 프로브 (Readiness Probe)
- 사용 방법
- 매니페스트에 명시적 설정 필요
- 애플리케이션도 적절한 응답을 반환하도록 구현 필요
- 프로브 대응 핸들러의 종류
exec | 컨테이너 내 커맨드를 실행. Exit 코드 0으로 종료하면 진단 결과는 성공으로 간주되며, 그 외의 값은 실패로 간주 |
tcpSocket | 지정한 TCP 포트번호로 연결할 수 있다면, 진단 결과는 성공으로 간주 |
httpGet | 지정한 포트와 경로로 HTTP GET 요청이 정기적으로 실행. HTTP 상태 코드가 200 이상 400 미만이면 성공으로 간주되고, 그 외에는 실패로 간주. 지정 포트가 열려 있지 않은 경우도 실패로 간주 |
step07/hc-probe/webapl-pod.yml
헬스 체크 기술 방법
apiVersion: v1
kind: Pod
metadata:
name: webapl
spec:
containers:
- name: webapl
image: dudtjs0920/webapl:0.1 # 핸들러가 구현된 이미지
livenessProbe: # 활성 프로브에 대한 핸들러 설정
httpGet:
path: /healthz
port: 3000
initialDelaySeconds: 3 # 처음으로 검사 수행하기 전의 대기 시간
periodSeconds: 5 # 검사 간격
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 15
periodSeconds: 6
- httpGet
HTTP 핸들러- path, port
핸들러의 경로, 포트번호
- path, port
- initialDelaySeconds
프로브 검사 시작 전 대기 시간
(컨테이너 실행될 시간을 줘야 함) - periodSeconds
검사 간격
컨테이너 이미지 빌드
15_DandK/step07/hc-probe/webapl
health check 애플리케이션
// 모의 애플리케이션
//
const express = require('express')
const app = express()
var start = Date.now()
// Liveness 프로브 핸들러
// 기동 후 40초가 되면, 500 에러를 반환한다.
// 그 전까지는 HTTP 200 OK를 반환한다.
// 즉, 40초가 되면, Liveness프로브가 실패하여 컨테이너가 재기동한다.
//
app.get('/healthz', function(request, response) {
var msec = Date.now() - start
var code = 200
if (msec > 40000 ) {
code = 500
}
console.log('GET /healthz ' + code)
response.status(code).send('OK')
})
// Rediness 프로브 핸들러
// 애플리케이션의 초기화 시간으로
// 기동 후 20초 지나고 나서부터 HTTP 200을 반환한다.
// 그 전까지는 HTTPS 200 OK를 반환한다.
app.get('/ready', function(request, response) {
var msec = Date.now() - start
var code = 500
if (msec > 20000 ) {
code = 200
}
console.log('GET /ready ' + code)
response.status(code).send('OK')
})
// 첫 화면
//
app.get('/', function(request, response) {
console.log('GET /')
response.send('Hello from Node.js')
})
// 서버 포트 번호
//
app.listen(3000);
- docker image build --tag dudtjs0920/webapl:0.1
컨테이너 이미지 빌드 - docker image push dudtjs0920/webapl:0.1
리포지터리에 등록
헬스체크 매니페스트 적용하여 파드 실행
step07/hc-probe/
- kubectl apply -f webapl-pod.yml
- kubectl logs webapl
- LivenessProbe -> /healthz 5초 간격으로 요청
40초 지나면 500 응답
40초 전에는 200 응답 - ReadinessProbe -> /ready 15초 후 6초 간격으로 요청
20초 전에는 500 응답, 20초 지나면 200 응답
- LivenessProbe -> /healthz 5초 간격으로 요청
- 활성 프로브가 호출하는 /healthz 의 응답이 40초가 지나면 3회 연속해서 HTTP 500 에러를 반환한다.
5.2 디플로이먼트
- 파드의 개수를 관리
- 레플리카셋과 함께 동작
- 컨트롤러
- 상시 가동되는 파드 관리
- 디플로이먼트 대상 파드의 특징
- 요청을 계속 받아들이며 종료하지 않음
(웹서버형태) - 수평 스케일 가능
- 비정상 종료 시 재기동됨
- 요청을 계속 받아들이며 종료하지 않음
디플로이먼트 생성과 삭제
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 3
selector:
matchLables:
app: web ## 디플로이먼트와 파드를 묶는 라벨
template: ## 파드 템플릿
metadata:
labels:
app: web ## 디플로이먼트와 파드를 묶는 라벨
spec:
containers:
- name: nginx
image: nginx:latest
디플로이먼트 deployment API
- metadata
name 에 오브젝트의 이름을 설정한다 - kind
Deployment를 설정한다 - spec
여기에 디플로이먼트의 사양을 기술
- replicas
파드 템플릿을 이용해서 기동할 파드의 개수를 지정한다.
디플로이먼트는 이 값을 유지하도록 동작함
노드가 정지되는 경우, 남아있는 노드에 파드를 기동해서 기동되고 있는 파드의 개수가 replicas 값과 일치하도록 만듦 - selector
디플로이먼트 제어 하의 레플리카셋과 파드를 대응시키기위해 matchLabels의 라벨이 사용된다.
이 라벨이 파드 템플릿의 레이블(template->metadata->labels->app: web)과 일치하지 않으면, kubectl create/apply 시 에러 발생 - template
파드 템플릿
- metadata
이 라벨의 내용은, 상기의 셀렉터가 지정하는 라벨과 일치해야 함 - spec: containers
파드 컨테이너의 사양
- metadata
- replicas
/step08/
디플로이먼트 상태 - kubectl get deploy
레플리카셋 상태 - kubectl get rs
파드의 상태 IP 주소와 노드 - kubectl get po -o wide
스케일 기능
- 스케일
레플리카의 값을 변경하여 파드의 개수를 조절하여 처리 능력을 높이거나 낮추는 기능 - 이미 배포된 디플로이먼트의 레플리카 값을 변경하여 처리 능력 향상
- deployment1.yml 의 replicas 값을 3 -> 10 으로 변경
kubectl apply -f deployment2.yml\ - 기존 돌아가고 있던 파드들을 포함해서 총 10개의 파드를 가짐
- deployment1.yml 의 replicas 값을 3 -> 10 으로 변경
- 스케일 업 명령
- kubectl scale --replicas=10 (deployname)
5.3 서비스
- 서비스 타입 종류
ClusterIP | 타입을 지정하지 않으면 기본으로 설정됨 클러스터 내부의 파드에서 서비스의 이름으로 접근할 수 있다. (이 서비스를 사용하지 않으면 클러스터 내부 파드끼리도 이름으로 접근 불가, IP 주소로 접근해야 함) |
NodePort | ClusterIP의 접근 범위뿐만 아니라 K8s 클러스터 외부에서 대표 IP 주소와 포트번호로 접근할 수 있다. |
LoadBalancer | NodePort 의 접근 범위뿐만 아니라 K8s 클러스터 외부에서 대표 IP 주소로 접근할 수 있다. |
ExternalName | K8s 클러스터 내의 파드에서 외부 IP 주소에 서비스의 이름으로 접근할 수 있다. 바깥쪽의 endpoint 에 접근할 때 |
ClusterIP
- 헤드리스 모드도 가능
- 대표 IP 주소 없이 서비스 동작 -> 스테이트풀셋에서 활용
- 로드밸런싱 또는 프록시 동작을 수행하지 않음
- 클러스터 내부에서만 접근 가능
클라이언트는 파드만 가능
NodePort
- 클러스터의 모든 노드에 지정한 port 오픈
- ClusterIP + 노드의 IP 주소의 포트 공개
- 클러스터 외부에서 내부 파드에 요청 보낼 수 있음
- 정식 서비스에 사용하진 않음 -> 접근 가능한 포트들과 IP 주소로 요청을 보내야 하기 때문에 복잡해서
- kube-proxy 와 연동해서 각 노드에 포트를 열고 대상 파드에 요청을 전달한다.
LoadBalancer
- NodePort 기능 + 외부에서 대표 IP 주소로 접근 가능
- 로드밸런스로 요청이 오면 서비스가 어느 파드로 접근할지 처리를 도와줌
- 외부에서 접근 가능
ExternalName
- 반대로, 파드에서 클러스터 외부의 엔드포인트에 접속하기 위한 이름을 해결
- 외부 서비스에 접근할 때 이름으로 접근하면 내부 DNS 에서 외부 DB 서버의 DNS 주소를 응답
서비스와 파드의 연결
- 서비스가 요청 전송 파드 결정하는 방법
- 셀렉터의 라벨과 일치하는 파드를 etcd 로부터 선택
- 라벨이 중복되지 않도록 주의해야 한다.
- etcd: master에 저장, 관리에 필요한 정보들을 저장하는 Key:Value 스토어
selector의 app 라벨과 디플로이먼트 template의 metadata 라벨이 일치하는 파드에 요청을 전달해준다.
서비스의 매니페스트
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
- kind
Service 설정 - metadata
name 에 네임스페이스 내 유일한 이름을 설정. 여기서 설정한 이름은 내부 DNS 에 등록되며, IP 주소 해결에 사용. 또한 이후 기동된 파드의 환경변수에 설정됨 - spec
서비스 사양- type
서비스 공개 방법을 설정
생략 시 ClusterIP 사용 -> 내부에서만 접근 가능
선택: ClusterIP, NodePort, LoadBalancer, ExternalName - ports
서비스에 의해 공개되는 포트번호.- port
필수 항목. 이 서비스에 의해 공개되는 포트번호 - name
port 가 하나인 경우는 생략 가능, 여러개인 경우는 필수 설정
각 포트의 이름은 서비스 스펙 내에서 유일해야 함 - protocol
생략 시 TCP
TCP / UDP - nodePort
생략 시 시스템이 자동으로 할당
type = NodePort, LoadBalancer -> 모든 노드에서 포트 공개
설정한 포트가 이미 사용중인 경우, 오브젝트 생성 실패함 - targetPort
생략 시 port 와 동일한 값이 사용됨
selector 에 의해 대응되는 파드가 공개하는 포트번호 또는 포트 이름 설정
- port
- selector
여기서 설정한 라벨과 일치하는 파드에 요청을 전송
서비스 타입이 ClusterIP, NodePort, LoadBalancer 인 경우에 해당하며 ExternalName인 경우는 무시.
이 항목을 설정하지 않는 경우, 외부에서 관리하는 엔드포인트를 가진 것으로 간주함 - sessionAffinity
설정이 가능한 세션 어피니티는 ClientIP.
생략시 None으로 설정됨 -> 어떤 파드에 고정적으로 요청 전달되게끔 함
Random: 라벨이 일치하는 파드 중 랜덤으로 선택하여 요청을 전달 - clusterIP
이 항목을 생략하면 대표 IP 주소가 자동으로 할당.
None 으로 설정하면 헤드리스로 동작함 (ClusterIP 없이 동작)
- type
로드밸런서 매니페스트
apiVersion: v1
kind: Service
metadata:
name: web-service-lb
spec:
selector:
app: web
ports:
- name: webserver
protocol: TCP
port: 80
type: LoadBalancer ## 로드밸런서 지정
- spec 에 type을 LoadBalancer 로 지정하여 외부에서 접근 가능한 IP 주소가 할당됨
kubectl get svc 로 서비스에 할당된 외부 IP 주소를 확인할 수 있다.
kubectl describe svc web-service-lb 로 서비스의 상세 정보 확인
5.4 스토리지
1) 퍼시스턴트 볼륨 PV
- K8s 에 배포한 애플리케이션이 데이터를 보존하기 위해 이용
- 데이터의 보존
데이터의 분실, 파손, 잘못된 변경을 막는 것 - 퍼시스턴트
컨테이너나 파드가 종료되어도 데이터를 분실하지 않음
- 데이터의 보존
- 추상화된 내부 혹은 외부 스토리지의 볼륨을 컨테이너에 마운트하여 사용
컨테이너 : 데이터 영구 저장 -> volume 사용
bind-mount -> host 에 data를 저장
5.4.1 스토리지 종류와 클러스터 구성
1) 클러스터 내부 볼륨
- emptyDir
- 같은 파드 내에서만 공유 가능
- 다른 파드에서 접근 불가
- 파드 종료 시 삭제됨
- hostPath
- 다른 노드에서 접근 불가 (같은 노드에서만 접근 가능)
- 노드 정지 시 데이터 접근 불가능 (데이터 분실)
- 내부 볼륨은 모든 노드/파드가 공유하지 못하는 문제가 있기 때문에 외부 스토리지 시스템을 사용한다.
2) 클러스터 외부 스토리지 시스템과 연동
- 모든 노드에서 접근 가능
- 반드시 모든 노드에서 볼륨을 동시에 공유할 수 있는 것은 아님
- 외부 스토리지 시스템이 어떤 식으로 볼륨을 제공하냐에 따라 다름
- Block Storage Device
HDD, SSD (DBMS)- OS 가 추상화 되어있음
- 모든 것들이 블락 단위로 관리됨 (저장, 읽기, 쓰기)
- 하나의 블록 스토리지 -> 하나의 서버만 마운트해서 사용 가능
- 동시에 사용 시 data 일관성이 깨질 수 있음 -> 동시에 하나의 노드만 하나의 블럭 스토리지를 마운트해서 사용하도록 강제
- 성능이 좋아서 사용함
(한명만 쓰고 있다고 생각하고 최적화가 가능)
- 노드 정지 시 다른 노드에 파드 재기동하여 애플리케이션 수행 (마스터로 알 수 있음)
- 다른 노드로 넘어가서 실행되더라도 외부 볼륨이랑 연결하여 원래 동작하던대로 동작이 가능하다.
- 활용도가 높음
3) 스토리지 시스템의 방식
쿠버네티스와 연동 가능한 스토리지 시스템 방식
스토리지 종류명 | 분류 | 액세스 범위 | ReadWrite | 개요 |
hostPath | K8s 노드 | 노드 (같은 노드 내) | Once | 파드가 배포된 노드의 파일 시스템상의 디렉터리를 마운트 |
local | K8s 노드 | 노드 (같은 노드 내) | Once | 노드의 디스크를 마운트 |
iSCSI | OSS | 클러스터 | Once | iSCSI의 디스크 마운트 |
NFS | OSS | 클러스터 | Many | NFS의 파일 시스템을 마운트 |
- Once
- 디스크를 그대로 마운트해서 사용
- 블락 스토리지 디바이스 형태로 제공하는 외부 스토리지 시스템
- Many
- 파일 시스템
- 파일 시스템에 저장되는 각각의 파일을 다른 파드에 전달해주면 각자 사용하더라도 문제 X
5.4.2 스토리지의 추상화와 자동화
- 퍼시스턴트 볼륨의 설정
- PV
퍼시스턴트 볼륨- 클러스터의 자원
- 관리자에 의해 미리 provision
- Storage Class 를 사용해 동적 provision
- provision:
해당 자원을 사용할 수 있도록 예약, 준비하는 것
- PVC
퍼시스턴트 볼륨 요구- 프로비저너가 PVC를 참고하여 PV 를 준비한다.
- K8s 가 PVC를 참고해서 적절한 PV를 찾아서 제공 => pod 와 바인드 함
- PVC를 작성하고, 파드의 매니페스트에 PVC 의 이름을 기술하면, 컨테이너가 퍼시스턴트의 볼륨을 마운트
- PV
퍼시스턴트 볼륨 이용
- PVC 사용 방법
- 파드에 설정되어있는 볼륨으로부터 PVC 명을 찾고, PVC 명과 대응
- 컨테이너 안에 /mnt/에 PV를 마운트
- PV의 volumes: persistentVolumeClaim: claimName: 과
PVC의 metadata: name: 이 같아야 연결됨 - PVC를 통해 스토리지 클래스에 요청해서 동적으로 볼륨을 프로비저닝 하게됨
PVC 매니페스트
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data1
spec:
accessModes:
- ReadWriteOnce
storageClassName: standard
resources:
requests:
storage: 2Gi
- kind
PVC 설정
PersistentVolumeClaim - metadata
이름, 레이블, 주석 등 정보 기술- annotations
스토리지 시스템에 넘겨 주는 파라미터나 스토리지 클래스를 기술 - labels
월 단위나 시간 단위의 과금을 클라우드의 스토리지 시스템에 부여하기 위해 사용됨 - name
name은 오브젝트를 특정하기 위한 필수 항목
네임스페이스 내에서 유일한 이름이어야 함
- annotations
- spec
스토리지 요구 사양 기술- accessModes
- 스토리지를 복수 노드에서 마운트할 수 있는지, 단일 노드에서만 마운트할 수 있는지 선택
- ReadWriteOnce
단일 노드에서만 read 액세스와 write 액세스 허용 - ReadOnlyMany
복수 노드의 read 액세스 허용 - ReadWriteMany
복수 노드의 read 액세스와 write 액세스 허용
- storageClassName
생략 시 default 스토리지 클래스가 선택됨
(kubectl get storageclass 로 선택 가능한 스토리지 클래스 목록 확인) - resources
스토리지 용량 설정
여러가지 해당 볼륨에서 요청하는 것들을 적어줌- requests
퍼시스턴트 볼륨의 용량을 지정
사용하는 스토리지 클래스의 사양에 따라 설정 가능한 용량이 정해져 있는 경우 있음
- requests
- accessModes
- 컨테이너 실행 시 PVC를 참조해서 프로비저닝한 볼륨을 마운트한다.
5.4.3 클라우드에서의 동적 프로비저닝
GKE의 블록 스토리지
- iSCSI 사용
- SCSI
한대의 컴퓨터에 여러개의 하드디스크 드라이브를 연결하기 위한 기술- SCSI 케이블로 호스트 어댑터에 하드디스크를 연결
- 블록 스토리지를 위해 만들어진 표준
블록 스토리지 디바이스에 접근하기 위해 사용하는 인터페이스
- iSCSI
물리적인 케이블 대신 IP 프로토콜 사용
- 복수의 노드에서 하나의 블록 스토리지 공유 불가
- ReadWriteOnce O (
ReadWriteManyXX - 네트워크를 통해서 블록 스토리지에 접근할 수 있는 프로토콜
- 원격에 있는 외부 블록 스토리지에 접근해서 사용
- SCSI
step11/iks-block/gke-pvc-block.yml
GKE 블록 스토리지 퍼시스턴트 볼륨 요구
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: bronze-blk ## pvc 이름
spec:
accessModes:
- ReadWriteOnce ## 다중 액세스는 불가능
resources:
requests:
storage: 20Gi ## 프로비저닝 요구 용량
iks-block/deploy-1pod.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: dep1pod-blk ## deployment의 이름
labels:
app: dep1pod-blk
spec:
selector:
matchLabels: ## 디플로이먼트와 파드를 묶는 라벨
app: dep1pod-blk ## 같은 deployment에 속하는 레플리카 그룹
template:
metadata:
labels:
app: dep1pod-blk ## 디플로이먼트와 파드를 묶는 라벨
spec:
containers:
- image: ubuntu
name: ubuntu
volumeMounts: ## 아래의 volumes를 마운트
- name: blk
mountPath: /mnt
command: ["/usr/bin/tail","-f","/dev/null"]
volumes: ## 파드의 볼륨 정의
- name: blk
persistentVolumeClaim:
claimName: bronze-blk ## pvc 이름
퍼시스턴트 볼륨 작동 확인
-> 파드 내부로 접속하여 /mnt/ 위치에 파일을 생성한 뒤 파드를 삭제한 후, 다시 파드를 생성하여 파일이 존재하는지 확인
5.5 스테이트풀셋
- Stateful
- 서버의 클라이언트 이전 상태를 보존 (서버에 데이터 저장)
- 대화를 주고받을 때 컨텍스트를 이해 (상태 유지)
- 사과 얼마? -> 2000원이야
- 2개 줘 -> 4000원이야, 결제는? (사과 줌)
- Stateless
- 서버의 클라이언트 이전 상태 보존 X
- 대화를 주고받을 때 컨텍스트를 이해하지 않음
- 사과 얼마? -> 2000원이야
- 2개 줘 -> 뭐?
- 상태 유지 안됨
Stateful | Stateless | |
장점 | 애플리케이션 구현 편리 성능 (서버가 대부분 처리함) |
확장성 (컨텍스트를 몰라도 되므로 어떤 서버든 처리 가능) 트래픽 몰리면 확장/축소 가능 -> 비용 효율 |
단점 | 서버의 부담 (어떤 클라이언트가 요청했었는지 저장) 클라이언트와 서버의 연결정보 유지/관리 어려움 |
상태를 유지해야하는 경우 필요 (로그인 인증, 쿠키, 세션으로 단점 극복 가능) |
StatefulSet
- 데이터를 관리하는 파드에 적합한 컨트롤러
- 컨테이너나 파드는 태생적으로 데이터를 보관하는 것이 어려움
- 파드와 퍼시스턴트 볼륨의 조합이 필요
- 파드와 퍼시스턴트 볼륨의 대응 관계를 엄격하게 관리
- 퍼시스턴트 볼륨의 데이터 보관을 우선시하여 동작
StatefulSet vs Deployment 와 차이
1. 파드의 이름과 퍼시스턴트 볼륨의 이름
- Replica 수에 해당하는 파드를 생성할 때
- deployment: hash
- statefulset: 순서대로 번호 부여
(파드와 PVC가 하나의 단위)
2. 서비스와의 연결 및 이름 해결
- 스테이트풀셋
대표 IP 를 가지지 않는 ClusterIP의 헤드리스 모드 사용 필요- 스테이트풀셋의 매니페스트에 연동할 서비스 이름을 설정
-> 각 파드의 이름으로 파드의 IP 주소를 얻을 수 있음
- 스테이트풀셋의 매니페스트에 연동할 서비스 이름을 설정
- 레플리카셋은 가용성과 처리 능력 향상을 위해 여러개의 파드를 기동시킴
- 서비스는 대표 IP 주소로 온 요청을 파드에 분배시킴
3. 파드 분실 시 동작
- 파드가 노드 장애로 없어진 경우, 스테이트풀셋은 같은 이름으로 기동됨
- 파드의 이름은 같아도 IP 주소는 변경됨
- 반드시 내부 DNS 사용해서 이름 해결
- 디플로이먼트는 다른 해시값으로 기동됨
- 퍼시스턴트 볼륨은 파드가 삭제되어도 계속 남아 있음
4. 노드 정지 시의 동작
- 스테이트 풀셋은 다음 경우에만 파드를 다른 노드에서 재기동
(문제가 있다는 것을 명확하게 알았을 때만 재기동)
- 장애 노드를 K8s 클러스터의 멤버에서 제외시켰을 때
(제외시킨 노드를 다시 추가하면 아무것도 없는 상태로 다시 시작) - 문제가 있는 파드를 강제 종료를 시켰을 때
(노드 문제 X, 파드에 접근 가능, 노드 정지 안된 경우만 가능) - 장애로 인해 정지한 노드를 재기동했을 때
(노드를 재실행해서 정상 상태 -> K8s 마스터와 통신하여 문제 파악 가능)
- 장애 노드를 K8s 클러스터의 멤버에서 제외시켰을 때
- 디플로이먼트는 노드가 정지한 경우, 응답이 오지 않으면 다른 노드에서 실행
- 스테이트풀셋은 노드 정지로 파드를 다른 노드에서 실행시키지 않음
- 노드를 명시적으로 (삭제)제외시키면, 대체 파드가 가동한다.
- 바로 다른 노드에서 파드를 실행시키는 것은 위험할 수 있음
- 노드에 장애가 있다고 판단했는데, 실제로는 장애가 아닐 수도 있음 (파드와 PV가 연결되어 있음)
- 삭제하지 않고 대체 노드에서 파드를 실행시켜버리면 두개의 노드에서 PV에 접근하게 되어 데이터가 깨질 수 있음
- 노드를 컨트롤 하는게 아니라 파드를 컨트롤 함
- 노드 문제 -> 외부에서 동작 시킴
장애 노드를 제외
5. 파드 순번 제어
- 디플로이먼트
기동 순서는 랜덤하게 적용됨 - 스테이트풀셋
파드 이름에 붙는 번호를 파드의 기동과 정지, 롤링 업데이트의 순서에 활용
(파드랑 PV를 연결할 때 사용)
- 레플리카 숫자에 도달할 때까지 파드와 퍼시스턴트 볼륨이 짝을 지어서 차례대로 기동됨
(낮은 번호부터 기동) - 정지할 때는 번호가 큰 순서부터 정지
- 레플리카 값을 늘리면 파드 이름 뒤에 붙는 숫자가 늘어남 (파드-1, 파드-2..)
값을 줄이면 숫자 큰것부터 삭제 - 롤링 업데이트 할 때도 파드의 이름에 붙는 번호에 따라 갱신됨
(동작 중인 상태에서 컨테이너 버전 업데이트)
- 레플리카 숫자에 도달할 때까지 파드와 퍼시스턴트 볼륨이 짝을 지어서 차례대로 기동됨
매니페스트 특징
- clusterIP: None
헤드리스 서비스 설정 - serviceName: 서비스명
연동할 서비스 이름 지정 - template: /mnt
PVC 템플릿의 이름으로 마운트 포인트 지정 - volumeClaimTemplates:
레플리카 수 만큼 볼륨 요구를 작성한다
## 서비스 부분
apiVersion: v1
kind: Service
metadata:
name: mysql ## 이 이름이 k8s내 DNS에 등록됨.
labels:
app: mysql-sts
spec:
ports:
- port: 3306
name: mysql
clusterIP: None ## 특징① 헤드리스 서비스 설정
selector:
app: mysql-sts ## 후술하는 스테이트풀셋과 연결시키는 라벨
---
## MySQL 스테이트풀셋
#
apiVersion: apps/v1 ## 표1 스테이트풀셋 참고
kind: StatefulSet
metadata:
name: mysql ## 스테이트풀셋 이름
spec: ## 표2 스테이트풀셋 사양
serviceName: mysql ## 특징② 연결할 서비스의 이름 설정
replicas: 1 ## 파드 기동 개수
selector:
matchLabels:
app: mysql-sts
template: ## 표3 파드의 템플릿
metadata:
labels:
app: mysql-sts
spec:
containers:
- name: mysql
image: mysql:5.7 ## Docker Hub MySQL 리포지터리 지정
env: ## 환경변수
- name: MYSQL_ROOT_PASSWORD
value: qwerty
ports:
- containerPort: 3306
name: mysql
volumeMounts: ## 특징③ 컨테이너상의 마운트 경로 설정
- name: pvc
mountPath: /var/lib/mysql ## 이 경로에 볼륨 마운트함
subPath: data ## 초기화 시 빈 디렉터리가 필요 (/var/lib/mysql/data 생성)
livenessProbe: ## MySQL 기동 확인
exec:
command: ["mysqladmin","-p$MYSQL_ROOT_PASSWORD","ping"]
initialDelaySeconds: 60
timeoutSeconds: 10
volumeClaimTemplates: ## 특징④볼륨 요구 템플릿
- metadata:
name: pvc
spec: ## 표4 퍼시스턴트볼륨 요구 스펙
accessModes: [ "ReadWriteOnce" ]
## 환경에 맞게 선택하여, sotrage의 값을 편집
#storageClassName: ibmc-file-bronze # 용량 20Gi IKS
#storageClassName: gluster-heketi # 용량 12Gi GlusterFS
storageClassName: standard # 용량 2Gi Minikube/GKE
resources:
requests:
storage: 2Gi
StatefulSet
- kind: StatefulSet 설정
- spec
스테이트풀셋 사양- serviceName:
헤드리스 서비스의 이름 - replicas:
파드 템플릿을 사용해서 기동하는 파드 수를 지정 - selector: matchLabels:
본 컨트롤러(스테이트풀셋) 제어하의 파드를 관리하기 위해 matchLabels의 라벨을 사용. 이 라벨이 파드 템플릿의 라벨과 일치하지 않으면 kubectl create/apply 시에 에러 발생 - template:
본 컨트롤러가 기동하는 파드 템플릿을 기술- metadata: labels: app:
selector의 matchLabels 라벨과 일치하는 라벨 설정으로 해야 함 - spec: containers:
파드의 컨테이너에 대해 기술
- metadata: labels: app:
- volumeClaimTemplates:
파드가 마운트하는 볼륨의 템플릿을 기술- metadata:name:
pvc 명의 접두어가 됨 - spec:
볼륨의 사양
- metadata:name:
- serviceName:
5.6 인그레스
- K8s 클러스터 외부에서의 요청을 K8s 클러스터 내부의 애플리케이션에 연결
- 기존 웹 애플리케이션을 쿠버네티스화 하는데 유용하다.
- 브라우저가 DNS 서버를 통해 외부 공개용 ip 주소에 접근
- 인그레스는 내부 DNS 를 통해 서비스 이름을 가지고 접근한다.
대표적인 기능
- 공개 URL과 애플리케이션 매핑
- IP 주소는 같아도 도메인 주소에 따라 다른 서비스로 연결 가능
IP addr -> abc.com, xyz.com - 공개 URL 경로에 복수의 애플리케이션 매핑
- 사용자 입장에서는 하나의 URL 이지만, 내부적으로는 애플리케이션이 분리되어 느슨하게 결합
- http://abc.sample.com/reservation
예약 애플리케이션 파드에 전송 - http://abc.sample.com/order
주문 애플리케이션 파드에 전송 - 하나의 서비스를 작은 단위로 쪼갬 -> 마이크로서비스
- http://abc.sample.com/reservation
- 가상 호스트와 서비스를 매핑하는 매니페스트 기술
- metadata & annotation 이 중요한 역할을 수행
- annotation에 키와 값을 기재하여 인그레스 컨트롤러에 명령 전달
- kubernetes.io/ingress.class: 'nginx'
여러 인그레스 컨트롤러가 K8s 클러스터에서 동작 중인 경우 명시적으로 컨트롤러 지정 필요 - nginx.ingress.kubernetes.io/rewrite-target: /
- 서비스 전달할 url
- URL 경로를 바꾸도록 하는 annotation
- /
abc.com/abc 로 들어오면 -> abc.com/abc 로 전달됨
/abc
abc.com/abc -> abc.com/ 으로 전달
- kubernetes.io/ingress.class: 'nginx'
- 사용자 입장에서는 하나의 URL 이지만, 내부적으로는 애플리케이션이 분리되어 느슨하게 결합
- IP 주소는 같아도 도메인 주소에 따라 다른 서비스로 연결 가능
- 복수의 도메인 이름을 가지는 가상 호스트 기능
- 클라이언트의 요청을 여러 파드에 분산 (로드밸런서)
- SSL/TLS 암호화 통신 HTTPS
- 세션 어피니티 (클라이언트-서버 세션 유지)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-ingress
annotations:
kubernetes.io/ingress.class: 'nginx'
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: abc.sample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: helloworld-svc
port:
number: 8080
- path: /apl2
pathType: Prefix
backend:
service:
name: nginx-svc
port:
number: 9080
- host: xyz.sample.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: java-svc
port:
number: 9080
- spec: rules
- hosts
도메인명 목록 - secretName
서버 인증서 시크릿의 이름 - host
FQDN(Fully Qualified Domain Name) 설정 - http
- paths
URL 의 경로와 백엔드 서비스를 대응시키는 목록을 기술 - backend
요청이 전달될 서비스와 포트번호 기재
- paths
- hosts
docker exec -it --user=root myjenkins bash
--> --user=root 로 들어가야 root 계정으로 접속할 수 있다. 그냥 들어가면 jenkins 계정으로 들어감
Dockerfile의 RUN, ADD, COPY 명령어는 적을수록 레이어 수가 줄어든다.
deployment.yaml
- containers:resources:
- limits
자원의 최대 요구량 (넘어갈 수 없음
- memory: "2Gi"
GiBibyte - cpu: "1000m"
millicore (1코어 == 1000m"
- memory: "2Gi"
- requests:
자원의 최소 요구량
요청한 만큼의 자원을 제공하지 못하는 경우 스케줄하지 않음
- memory, cpu
- limits
'sswu' 카테고리의 다른 글
Dockerfile 레이어 수 (0) | 2022.06.13 |
---|---|
디자인 패턴 기말 정리 (0) | 2022.05.30 |
독일어 정리 (0) | 2022.04.15 |
디자인패턴 중간 정리 (0) | 2022.04.03 |
오픈소스 소프트웨어 중간 정리 (0) | 2022.03.20 |