Hi yoahn 개발블로그

오픈소스 소프트웨어 기말 정리 본문

sswu

오픈소스 소프트웨어 기말 정리

hi._.0seon 2022. 5. 20. 01:48
반응형

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 이미지 빌드

jenkins docker file

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 명령 사용
      }
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

애플리케이션의 구조 - 확장성

  • 확장성
    • 실 서버를 전부 구입해서 서비스를 제공하게 되면 서비스 인기가 떨어졌을 때 사용량이 떨어져 자원이 낭비됨
    • 클라우드를 사용하게 되면 초기 투자 비용이 낮음
      • 별도의 초기 투자 비용 없이 시작 가능
      • 클라우드 서비스 업체는 일부 기능은 무료로 제공
  • 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)
      최대 사용량, 최대 순간 트래픽을 가정하고 설계
    • 탄력적이지 않은 제한된 자원 용량 -> 지속적인 관리 비용 증가
  • 장점
    • 품질 및 보안에 대한 높은 신뢰도

2) 퍼블릭 클라우드

  • 클라우드 서비스 공급자가 제공하는 서버 및 스토리지 등의 클라우드 자원을 인터넷을 통해 다수의 사용자들이 제공받는 방식
  • 공유하는 대신 저렴하고 신속한 운영 가능
  • 자체 인프라가 없거나 빈약한 스타트업, 중견기업이 주로 사용
  • 클라우드 자원을 공유한다고 해서 다른 사용자의 자원에 접근 가능한 것은 아님

3) 프라이빗 클라우드

  • 독점적으로 사용하여 보안을 높일 수 있는 인프라 환경 (기업이 직접 클라우드를 구축하고 내부 활용)
  • 제한된 네트워크에서 특정 사용자나 기업만을 대상으로 하는 클라우드 서비스 방식
  • 클라우드 역량 확보를 바탕으로 퍼블릭 클라우드 사업 진출을 목표로 함

4) 멀티 클라우드

  • 여러 퍼블릭 클라우드를 함께 사용하는 경우
  • 고가용성
    특정 클라우드가 다운되는 경우에도 다른 클라우드가 동작하므로 서비스가 중단되지 않음
  • 종속성 제거 (lock-in 제거)
    하나의 클라우드만 쓰게 되는 것을 방지 (언제든지 변경 가능)

5) 하이브리드 클라우드

  • 퍼블릭 클라우드와 프라이빗 클라우드를 네트워크를 통해 결합한 클라우드 서비스 방식
    • 민감한 데이터 -> 프라이빗 클라우드
    • 워크로드 예측 어려움 -> 퍼블릭 클라우드

2.5 클라우드 서비스 모델

  • 언제 어디서나 별도의 소프트웨어 등을 설치하지 않고 인터넷 접속을 통해 저장해 놓은 데이터에 접근하여 사용할 수 있는 서비스

  • IaaS (Infrastructure-as-a-Service)
    • 서버, 스토리지, 네트워크와 같은 인프라 하드웨어 자원을 가상화하여 사용자 요구에 따라 인프라 자원을 사용할 수 있게 제공하는 클라우드 서비스 방식 (GCP Compute Engine, AWS)
    • 인프라 관리자가 사용
    • 클라우드 인프라 하드웨어(서버, 스토리지, 네트워크)를 구축해서 서비스 개발자들한테 제공
    • 기업은 클라우드 제공업체로부터 서버와 저장소 자원을 임대, 자체 애플리케이션 구축
    • 물리적 자원에 대한 지식이 반드시 필요
    • 사용자가 애플리케이션의 실행환경을 직접 구축해야하는 클라우드 서비스 모델
    • ex) 건물을 지을 수 있는 토지를 임대

IaaS

초록색 부분은 사용자가 구축해야 되는 부분

  • PaaS (Platform-as-a-Service)
    • 개발 도구, 인프라, 운영체제를 포함한 애플리케이션 구축에 필요한 모든 것을 인터넷을 통해 제공
    • 개발자가 사용, 플랫폼 제공
    • PaaS 에서 제공된 서비스를 바탕으로 SaaS를 구축
    • PaaS 사용 시 인프라 구축하는데 수고를 덜 수 있음 -> 바로 개발 가능
    • 문제 발생 시 PaaS 제공자가 대신 해결해 줌
    • low code, no code
    • ex) 집을 빌리는 대신 집을 짓는데 필요한 모든 도구와 장비를 빌림
      (Heroku, RedHat OpenShift, Azure machine learning studio, Google Dialogflow)

PaaS

  • 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 등

FaaS

클라우드 서비스 제공 업체

  • AWS
  • GCP (Google Cloud)
  • Azure (마이크로소프트)
  • 네이버, 카카오 등

3. Jenkins Multibranch pipeline

jenkins multibranch pipeline

 

  • git branch 를 기반으로 자동으로 파이프라인 생성
    • 각 브랜치에 있는 Jenkinsfile 을 사용
    • PR 기반의 브랜치 discovery 지원
  • 조건에 따른 분기 가능
    • Feature 브랜치에 대해서는 배포를 하고 싶지 않은 경우

branch 가 production 에 있을 때만 파이프라인이 동작

  • Jenkins 를 활용한 개발 프로세스
    1. 개발자는 feature 브랜치에 코드를 commit
    2. 개발자가 feature 브랜치로부터 develop 브랜치에 PR 을 요청 
      • Jenkins 는 Unit test 및 정적 코드 분석 수행 (webhook 동작)
      • 분석이 완료되면 PR 에 Job status 가 업데이트 됨
    3. 개발자는 PR 을 develop 브랜치에 merge
    4. 릴리즈 준비가 되면, 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 컨테이너의 한계

  • 배포의 문제점
    1. 모든 서버에 직접 접속해서 docker stop, run 실행
    2. 도커 컨테이너 실행에 필요한 리소스 관리가 필요
      • 모니터링 시스템, 유휴자원 관리 등
      • 컨테이너를 실행하려고 할 때 어디에 실행시킬 수 있을지 등,,
    3. 새롭게 배포된 애플리케이션 장애 시 신속하게 대처하기 어려움
      (update 후 rollback 어려움)
  • 서비스 접근 및 노출의 문제점 (IP 주소)
    • 동일한 네트워크에서만 접속가능
  • 서비스 장애, 부하 모니터링의 문제점
    • 모니터링이 어려움
    • 컨테이너 오케스트레이션으로 계속 체크

4.2 컨테이너 오케스트레이션

복잡한 컨테이너 환경을 효과적으로 관리하기 위한 도구

기능

  1. cluster
    • 중앙제어
      master 가 전체 클러스터들을 관리
    • 네트워킹
    • 노드 스케일
  2. state
    • 상태 관리
    • replicas : 복제본의 개수 설정
    • 컨테이너 개수를 지정한 개수가 항상 유지되도록 관리해주는 기능
    • 장애 발생 시 컨테이너를 자동으로 하나 더 띄워줌
  3. scheduling
    • 배포 관리
    • 어플리케이션을 배포하려고 할 때, 어느 컨테이너에 배포할지
  4. Rollout / Rollback
    • 배포 버전 관리
  5. Service / Discovery
    • 서비스 등록 및 조회
    • 서비스가 추가되면 새로운 서비스가 자동으로 등록됨
  6. Volume
    • 볼륨 스토리지
    • 영구적인 data 저장
    • 노드별로 다른 스토리지 사용 가능
      (NFS, AWS, GCP)

4.3 쿠버네티스 (K8s)

  • 컨테이너 오케스트레이션의 업계 표준
    • 배포 계획에 맞춰 신속한 애플리케이션 배포 가능
      • 컨테이너 개수, CPU 사용률, 메모리 사용량 설정 가능
      • 저장 공간, 네트워크 접근 제어, 로드밸런싱 기능 설정 가능
    • 가동 중인 애플리케이션을 스케일 아웃/인 할 수 있음
      (스케일 업은 불가능 (스펙 향상 불가))
      • 스케일 아웃: 요청이 많을 때는 컨테이너 수를 증가시켜 처리 능력 높임
      • 스케일 인: 요청이 적을 때는 컨테이너 수를 줄여 자원 점유율 및 요금 줄임
    • 새로운 버전의 애플리케이션 무정지 업그레이드 기능
    • 하드웨어 가동률을 높여 자원 낭비를 줄임

스케일 아웃: 서버 개수가 증가 (컨테이너 증가)

스케일 업: 서버 스펙이 올라감

4.4 쿠버네티스의 특징

  • 다양한 환경에서 쿠버네티스 사용 가능
    • 퍼블릭, 프라이빗, 멀티, 하이브리드 클라우드, 온 프레미스 위에 구축 가능
    • 쿠버네티스는 일관된 인터페이스를 제공하여 인프라의 복잡성을 감춰줌
    • 온프레미스와 클라우드 환경에서 동일한 인터페이스로 조작 및 운영 가능
  • 높은 유연성과 확장성
    • 마이크로 서비스 애플리케이션에 최적화된 실행환경
    • 느슨한 결합에 의한 유연성, 교체 용이성
    • 다양한 스펙의 서버가 혼재하는 클러스터 구성 가능
      Heterogeneous (<-> Homogeneous)
    • 서버의 정지, 추가, 제거가 용이
    • 저장소나 로드밸런서의 동적 프로비저닝
    • 퍼블릭 클라우드 API 와 연동 가능
  • 고가용성
    • 서버 정지 시 애플리케이션 재배포 자동화
    • 애플리케이션의 이상 종료 시 자동 재기동
  • 성능관리
    • 필요한 인스턴스의 개수를 유지
    • 높은 부하에서 자동 스케일 아웃 (실행 중에 가능)

4.5 쿠버네티스의 아키텍쳐

  • 두 종류의 서버들로 구성
    • 마스터
      클러스터의 전체 관리를 담당
    • 노드 (워킹노드)
      컨테이너화된 애플리케이션을 실행
  • 계층 구조
    • 마스터의 역할
      • 클라이언트의 명령을 받아들이고 실행
      • 컨테이너를 파드 단위로 스케줄링 및 삭제
      • 파드의 컨트롤러 기능과 외부 리소스 관리

k8s 클러스터의 구성 개념도

4.6 쿠버네티스의 오브젝트

  1. 컨테이너
    • 컨테이너만을 독자적으로 실행하는 것은 불가능
    • 반드시 파드 내에서 실행해야 함
    • 컨테이너 기동 시 설정 가능한 항목
      • 이미지의 이름
      • 실행 명령어
      • 실행 인자
      • 환경변수
      • 볼륨
      • CPU 사용시간, 메모리 크기의 요청값 및 상한값
  2. 파드
    • 컨테이너를 실행하는 최소 단위
    • 한 개 혹은 여러개의 컨테이너를 담을 수 있음
    • 하나의 파드에 속하는 모든 컨테이너들은 같은 노드에서 동작
      (하나의 파드는 하나의 노드 위에서 실행)
    • 파드의 특징
      • 컨테이너 재사용 촉진을 위한 플랫폼
        (하나의 파드 안에 여러개의 컨테이너 있을 때의 장점)
        • 파드 내부 컨테이너들은 파드의 IP 주소와 포트번호를 공유 (파드의 IP주소, 파드에 할당된 port 번호가 주어짐)
        • 파드 내부 컨테이너들은 localhost 로 서로 통신 가능
        • 파드 내부 컨테이너들은 System V 프로세스 통신이나 POSIX 공유 메모리를 사용하여 서로 통신 가능
        • 파드 내부 컨테이너들은 파드의 볼륨을 마운트하여 파일 시스템 공유 가능
      • 파드는 일시적인 존재
        • 파드 내의 컨테이너는 이미지로부터 매번 생성
          (같은 오브젝트 이름으로 파드를 기동해도 이미지의 초기 상태에서 시작)
        • 파드의 IP 주소도 고정적이지 않음
          (파드 종료 시 IP 회수)
        • 파드에 요청을 보내고 싶은 경우에는 서비스를 사용해야 함
      • 파드는 컨테이너의 실행 상태를 관리
        • 파드가 정지한 경우는 담당 컨트롤러가 재가동
        • 파드 내부의 컨테이너가 정지한 경우는 파드가 해당 컨테이너를 재시작
        • 활성 프로브준비 상태 프로브를 설정하여 내부 애플리케이션의 상태를 감시할 수 있음
          • 활성 프로브: 애플리케이션이 멈춰 있는 상태를 감지 -> 강제 종료 & 재시작
          • 준비 상태 프로브 : 파드가 요청받을 준비가 될 때까지 서비스 오브젝트가 요청을 전송하지 않음
      • 파드는 초기화 전용 컨테이너를 실행
        • 파드에 초기화만을 담당하는 컨테이너를 설정할 수 있음
          • 초기화 담당 컨테이너가 제일 먼저 실행
          • 초기화가 끝나면, 핵심 기능을 수행하는 컨테이너들이 실행됨
        • 파드는 서비스, 컨트롤러, 퍼시스턴트 볼륨 등의 다른 오브젝트들과 함게 사용될 때 진가를 발휘
    • 노드는 컨테이너화된 애플리케이션이 실행되는 서버이다.
  3. 서비스
    • 파드와 클라이언트를 연결하는 역할을 수행
    • 대표 IP 주소로의 요청 트래픽을 지정된 파드들에 부하분산하며 전송하는 역할도 수행
      (로드밸런서)
    • 서버 파드는 IP주소가 계속 바뀌기 때문에, 이름으로 접근하기 위해 서비스가 필요
    • ClusterIP, NodePort, LoadBalancer, ExternalName

서비스의 역할

  • 컨트롤러
    • 파드의 실행을 제어하는 오브젝트
    • 여러 종류의 컨트롤러가 있어 각 컨트롤러의 기능을 이해하고 목적에 맞게 적절히 구별해서 사용
    • 디플로이먼트, 레플리카셋, 스테이트풀셋, 잡,,,

컨트롤러의 종류와 선택

4.7 쿠버네티스의 아키텍처

마스터와 노드의 내부 구조

  • kubectl
    • K8s 클러스터를 조작하기 위한 도구로 가장 빈번하게 이용되는 커맨드라인 인터페이스
  • kube-apiserver
    • kubectl 등의 API 클라이언트로부터 오는 REST 요청을 검증
    • API 오브젝트를 구성 및 상태 보고
  • kube-scheduler
    • 새로 생성된 모든 파드에 대해 실행할 최적의 노드 선택
    • 파드가 실행 가능한 노드를 찾은 후, 점수를 계산한 후 가장 점수가 높은 노드를 선택
  • kube-controller
    • 컨트롤러를 구동하는 마스터 상의 컴포넌트
  • etcd
    • K8s 클러스터의 모든 관리 데이터를 저장
    • Key=Value 저장소

etcd

  • kubelet
    • 파드와 컨테이너의 실행
    • 파드와 노드의 상태를 모니터링해서 API 서버에 보고
    • 컨테이너의 동작을 확인하는 프로브 실행
    • 내장된 cAdvisor 를 통해 메트릭 수집 및 공개

kubelet, kube-proxy

  • 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
  1. kubectl
    k8s 클러스터 조작 커맨드
  2. run : 컨테이너 실행을 명령
  3. hello-world : 쿠버네티스 오브젝트의 이름 (파드, 컨트롤러)
  4. --image=hello-world: 컨테이너의 이미지. 쿠버네티스에서는 파드 단위로 컨테이너가 기동되며 리포지터리명이 생략된 경우에는 도커 허브를 사용
  5. -it
    도커에서의 -it 와 마찬가지로, -i 는 키보드를 표준 입력에 연결하고, -t 는 유사 터미널과 연결하여 대화 모드 설정.
    옵션 '--restart=Never' 인 경우에만 유효. 그 외에는 백그라운드로 실행
  6. --restart=Never
    이 옵션에 따라 파드의 기동 방법 변경. Never는 직접 파드가 기동되며 Always나 OnFailure는 컨트롤러를 통해 파드가 기동됨
  7. --rm
    파드 종료 후 자동으로 삭제하는 옵션

  • hello-world
    1. 커맨드 실행
    2. 이미지 다운로드
    3. 컨테이너 실행 & 메시지

 

같은 이름으로 파드 재기동 불가능 -> 이미 같은 이름의 파드 존재하기 때문에

  • 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개

  • hello-world 컨테이너는 출력 후 종료되는 컨테이너
  • 디플로이먼트로 관리되는 파드는 웹서버처럼 상시 가동되어야 함
  • 웹 서버 Nginx 디플로이먼트 실행
    • kubectl create deployment webserver --image nginx --replicas=5
      파드 5개가 유지되도록 설정
    • kubectl delete po webserver-{해시값} 
      강제로 일부 파드 삭제
      -> 레플리카를 설정했기 때문에 다시 기동시켜 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도 사용 가능

매니페스트 적용 및 확인

  • 접근 실패 원인
    클러스터 내부 IP 이므로 클러스터 외부에서 접근 불가능
  • 매니페스트 적용 및 확인
    • 대화형 파드를 기동해서 nginx 파드에 접근
      $ kubectl run busybox --image=busybox --restart=Never --rm -it sh
      busybox 파드를 통해 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
      핸들러의 경로, 포트번호
  • 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 응답
  • 활성 프로브가 호출하는 /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
        파드 컨테이너의 사양

디플로이먼트와 파드의 YAML 비교

/step08/

디플로이먼트 생성 kubectl

디플로이먼트 상태 - kubectl get deploy

레플리카셋 상태 - kubectl get rs

파드의 상태 IP 주소와 노드 - kubectl get po -o wide

스케일 기능

  • 스케일
    레플리카의 값을 변경하여 파드의 개수를 조절하여 처리 능력을 높이거나 낮추는 기능
  • 이미 배포된 디플로이먼트의 레플리카 값을 변경하여 처리 능력 향상
    • deployment1.yml 의 replicas 값을 3 -> 10 으로 변경
      kubectl apply -f deployment2.yml\
    • 기존 돌아가고 있던 파드들을 포함해서 총 10개의 파드를 가짐
  • 스케일 업 명령
    • kubectl scale --replicas=10 (deployname)

파드 개수 늘리기 (스케일 업)

5.3 서비스

  • 서비스 타입 종류
ClusterIP 타입을 지정하지 않으면 기본으로 설정됨
클러스터 내부의 파드에서 서비스의 이름으로 접근할 수 있다.
(이 서비스를 사용하지 않으면 클러스터 내부 파드끼리도 이름으로 접근 불가, IP 주소로 접근해야 함)
NodePort ClusterIP의 접근 범위뿐만 아니라 K8s 클러스터 외부에서 대표 IP 주소와 포트번호로 접근할 수 있다.
LoadBalancer NodePort 의 접근 범위뿐만 아니라 K8s 클러스터 외부에서 대표 IP 주소로 접근할 수 있다.
ExternalName K8s 클러스터 내의 파드에서 외부 IP 주소에 서비스의 이름으로 접근할 수 있다.
바깥쪽의 endpoint 에 접근할 때

ClusterIP

  • 헤드리스 모드도 가능
    • 대표 IP 주소 없이 서비스 동작 -> 스테이트풀셋에서 활용
    • 로드밸런싱 또는 프록시 동작을 수행하지 않음
  • 클러스터 내부에서만 접근 가능
    클라이언트는 파드만 가능

서비스 타입 ClusterIP 개념

NodePort

  • 클러스터의 모든 노드에 지정한 port 오픈
  • ClusterIP + 노드의 IP 주소의 포트 공개
  • 클러스터 외부에서 내부 파드에 요청 보낼 수 있음
  • 정식 서비스에 사용하진 않음 -> 접근 가능한 포트들과 IP 주소로 요청을 보내야 하기 때문에 복잡해서
  • kube-proxy 와 연동해서 각 노드에 포트를 열고 대상 파드에 요청을 전달한다.

서비스 타입 NodePort 의 개념

LoadBalancer

  • NodePort 기능 + 외부에서 대표 IP 주소로 접근 가능
  • 로드밸런스로 요청이 오면 서비스가 어느 파드로 접근할지 처리를 도와줌
  • 외부에서 접근 가능

서비스 타입 LoadBalancer 개념

ExternalName

  • 반대로, 파드에서 클러스터 외부의 엔드포인트에 접속하기 위한 이름을 해결
  • 외부 서비스에 접근할 때 이름으로 접근하면 내부 DNS 에서 외부 DB 서버의 DNS 주소를 응답

서비스 타입 ExternalName의 개념

서비스와 파드의 연결

  • 서비스가 요청 전송 파드 결정하는 방법
    • 셀렉터의 라벨과 일치하는 파드를 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 에 의해 대응되는 파드가 공개하는 포트번호 또는 포트 이름 설정
    • selector
      여기서 설정한 라벨과 일치하는 파드에 요청을 전송
      서비스 타입이 ClusterIP, NodePort, LoadBalancer 인 경우에 해당하며 ExternalName인 경우는 무시.
      이 항목을 설정하지 않는 경우, 외부에서 관리하는 엔드포인트를 가진 것으로 간주함
    • sessionAffinity
      설정이 가능한 세션 어피니티는 ClientIP.
      생략시 None으로 설정됨 -> 어떤 파드에 고정적으로 요청 전달되게끔 함
      Random: 라벨이 일치하는 파드 중 랜덤으로 선택하여 요청을 전달
    • clusterIP
      이 항목을 생략하면 대표 IP 주소가 자동으로 할당.
      None 으로 설정하면 헤드리스로 동작함 (ClusterIP 없이 동작)

로드밸런서 매니페스트

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 의 이름을 기술하면, 컨테이너가 퍼시스턴트의 볼륨을 마운트

동적 프로비저닝을 하는 경우

퍼시스턴트 볼륨 이용

  • PVC 사용 방법
    • 파드에 설정되어있는 볼륨으로부터 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은 오브젝트를 특정하기 위한 필수 항목
      네임스페이스 내에서 유일한 이름이어야 함
  • spec
    스토리지 요구 사양 기술
    • accessModes
      • 스토리지를 복수 노드에서 마운트할 수 있는지, 단일 노드에서만 마운트할 수 있는지 선택
      • ReadWriteOnce
        단일 노드에서만 read 액세스와 write 액세스 허용
      • ReadOnlyMany
        복수 노드의 read 액세스 허용
      • ReadWriteMany
        복수 노드의 read 액세스와 write 액세스 허용
    • storageClassName
      생략 시 default 스토리지 클래스가 선택됨
      (kubectl get storageclass 로 선택 가능한 스토리지 클래스 목록 확인)
    • resources
      스토리지 용량 설정
      여러가지 해당 볼륨에서 요청하는 것들을 적어줌
      • requests
        퍼시스턴트 볼륨의 용량을 지정
        사용하는 스토리지 클래스의 사양에 따라 설정 가능한 용량이 정해져 있는 경우 있음

PVC를 마운트한 파드를 가동 pod.yml

  • 컨테이너 실행 시 PVC를 참조해서 프로비저닝한 볼륨을 마운트한다.

5.4.3 클라우드에서의 동적 프로비저닝

GKE의 블록 스토리지

  • iSCSI 사용
    • SCSI
      한대의 컴퓨터에 여러개의 하드디스크 드라이브를 연결하기 위한 기술
      • SCSI 케이블로 호스트 어댑터에 하드디스크를 연결
      • 블록 스토리지를 위해 만들어진 표준
        블록 스토리지 디바이스에 접근하기 위해 사용하는 인터페이스
    • iSCSI
      물리적인 케이블 대신 IP 프로토콜 사용
      • 복수의 노드에서 하나의 블록 스토리지 공유 불가
      • ReadWriteOnce O (ReadWriteMany XX
      • 네트워크를 통해서 블록 스토리지에 접근할 수 있는 프로토콜
      • 원격에 있는 외부 블록 스토리지에 접근해서 사용

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 주소로 온 요청을 파드에 분배시킴

서비스 타입 ClusterIP 개념

3. 파드 분실 시 동작

  • 파드가 노드 장애로 없어진 경우, 스테이트풀셋은 같은 이름으로 기동됨
    • 파드의 이름은 같아도 IP 주소는 변경됨
    • 반드시 내부 DNS 사용해서 이름 해결
  • 디플로이먼트는 다른 해시값으로 기동됨
  • 퍼시스턴트 볼륨은 파드가 삭제되어도 계속 남아 있음

디플로이먼트와 스테이트 풀셋의 차이

4. 노드 정지 시의 동작

  • 스테이트 풀셋은 다음 경우에만 파드를 다른 노드에서 재기동
    (문제가 있다는 것을 명확하게 알았을 때만 재기동)
    1. 장애 노드를 K8s 클러스터의 멤버에서 제외시켰을 때
      (제외시킨 노드를 다시 추가하면 아무것도 없는 상태로 다시 시작)
    2. 문제가 있는 파드를 강제 종료를 시켰을 때
      (노드 문제 X, 파드에 접근 가능, 노드 정지 안된 경우만 가능)
    3. 장애로 인해 정지한 노드를 재기동했을 때
      (노드를 재실행해서 정상 상태 -> 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:
        파드의 컨테이너에 대해 기술
    • volumeClaimTemplates:
      파드가 마운트하는 볼륨의 템플릿을 기술
      • metadata:name:
        pvc 명의 접두어가 됨
      • spec:
        볼륨의 사양

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
          주문 애플리케이션 파드에 전송
        • 하나의 서비스를 작은 단위로 쪼갬 -> 마이크로서비스
      • 가상 호스트와 서비스를 매핑하는 매니페스트 기술
        • 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/ 으로 전달

인그레스에 의한 가상 호스트 작성 예시

  • 복수의 도메인 이름을 가지는 가상 호스트 기능
  • 클라이언트의 요청을 여러 파드에 분산 (로드밸런서)
  • 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
        요청이 전달될 서비스와 포트번호 기재

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"
    • requests:
      자원의 최소 요구량
      요청한 만큼의 자원을 제공하지 못하는 경우 스케줄하지 않음
      • memory, cpu

 

 

 

 

반응형

'sswu' 카테고리의 다른 글

Dockerfile 레이어 수  (0) 2022.06.13
디자인 패턴 기말 정리  (0) 2022.05.30
독일어 정리  (0) 2022.04.15
디자인패턴 중간 정리  (0) 2022.04.03
오픈소스 소프트웨어 중간 정리  (0) 2022.03.20
Comments