728x90
반응형

메인 컴포넌트

#nodes #pods #노드 #파드 #쿠버네티스 #kubernetes #k8ss

노드와 파드

  • 노드
    • 노드는 컨테이너가 배포되고 구동되는 Worker Machine이다.
    • 각 노드는 클러스터 내에서 개별 노드를 의미하고, 물리/가상 머신이다.
    • 노드는 실제 workload를 구동시키고 필요 자원을 제공하는 역할이다.
  • 파드
    • 최소 배포 가능한 단위
    • 하나 혹은 강하게 결합된 컨테이너를 의미함
    • 파드 내의 컨테이너들은 같은 네트워크 네임스페이스를 공유한다
      • 이는 localhost 상에서 서로 소통할 수 있게 함
    • 파드는 클러스터에서 하나의 프로세스 인스턴스를 의미함
apiVersion: v1  
kind: Pod  
metadata:  
    name: webapp-with-db       // 파드 이름
    labels:  
        app: my-webapp  
spec:  
    containers:  
    - name: webapp            // 컨테이너 명
      image: nginx:latest     // 컨테이너 이미지 명
      ports:  
        - containerPort: 80   // 컨테이너 포트
    - name: database  
      image: mongo:latest
  • 왜 컨테이너가 아니라 파드를 사용하는가
    • Grouping Containers
      • 컨테이너들을 논리적으로 그룹화 한다.
      • 스케줄링, 스케일링, 관리를 간단화시킨다.
    • Shared Resources
      • 파드 내의 컨테이너들은 동일한 네트워크 네임스페이스를 공유함
      • 파드 내의 컨테이너들은 동일한 볼륨을 공유할 수 있다.
      • 따라서 서로 소통하기 더욱 쉬워진다
    • Amotic Unit
      • 파드는 배포의 원자 단위이다.
      • 어플리케이션 관리 혹은 스케일링 시, 파드 레벨로 수행한다 (컨테이너 개별 적용말고)
    • Scheduling and Affinity
      • 쿠버네티스는 파드를 노드에 스케줄하지, 각각 컨테이너를 스케줄하지 않는다.
      • 따라서 서로 연간되어있는 파드 내의 컨테이너들은 동일한 노드에 위치하게 된다
728x90
반응형
728x90
반응형

아키텍처

마스터 노드

  • 전체 클러스터를 컨트롤하고, 전체 클러스터 상태를 관리함
  • 새로운 파드들의 스케일링, 노드/파드들의 헬스 모니터링, 수요에 따른 어플리케이션 스케일링 등 전체 클러스터에 대한 결정권을 갖는다.
  • 주요 컴포넌트
    • API Server
      • 클러스터와ㅏ 유저/컴포넌트간의 소통을 가능하게 하는 API를 노출시켜준다.
    • etcd
      • 클러스터의 모든설정 데이터를 key-value 값들이 저장된다
      • 모든 클러스터 상태 정보가 여기 저장된다.
    • Controller Manager
      • API Server를 통해 클러스터 상태를 체크하고 원하는 상태가 유지하기 위한 행동을 취한다.
    • Scheduler
      • 새로운 파드들을 리소스 필요량과 가용성에 따라 노드들에 배정한다.
      • 이를 통해 worker 노드들에 workload들을 공평하게 분배한다.

워커 노드

  • 컨테이너(파드)가 스케쥴되고 구동되는 머신을 의미
  • 클러스터의 data plane을 형성하고, 실제 workload를 실행한다.
  • 워커 노드 주요 컴포넌트
    • kubelet
      • 각각의 워커 노드를 구동시키고 Master Node와 통신하는 역할
      • 파드 명세에 적혀있는 대로 컨테이너가 구동되고 그 상태가 건강하게 하는 역할
    • Container Runtime
      • Docker나 containerd와 같은 복수개의 container runtimes를 지원한다
      • 컨테이너 이미지를 가져오고, 컨테이너를 구동하는 역할
    • Kube Proxy
      • 클러스터 내에서 네트워크 소통을 하는 역할
      • 서비스 네트워크 라우팅을 관리하고 Load Balancing을 수행한다.

상호작용 방식

  • Master node와 Worker Node들은 API Server를 통해 서로 통신한다.
  • 유저와 다른 컴포넌트들 역시 API Server를 통해 서로 상호 작용함
  • 예시
    • 새로운 어플리케이션 배포 시, 설정 파일들이 API Server를 통해 전달됨
      • 그 설정들은 etcd에 저장됨
    • Controller Manager는 API Server를 통해 클러스터 상태를 모니터링함
    • 새로운 파드가 스케줄됐을 때, Scheduler가 적정한 Worker Node를 선정한다
      • 이 선정된 내용을 API Server가 선정된 노드에게 전달한다
      • 그리고 그 노드의 kubelet이 컨테이너를 실행시킨다

728x90
반응형
728x90
반응형
  • 대규모 클러스터 환경에서 컨테이너화된 어플리케이션을 자동으로 배포/확장/관리하는데 필요한 요소들을 자동화하는 플랫폼
    • 코드 기반 클러스터 운영
    • 의도한 상태를 유지하며 클러스터를 관리함
  • Kubernetes: 조타수라는 뜻
  • 컨테이너 오케스트레이션 표준이라 여겨짐
  • 구글에서 2014년 오픈 소스로 공개
  • 여러 대의 도커 호스트를 하나의 클러스터로 만들어 줌
  • 다른 오케스트레이션 툴보다 다양한 기능을 제공하기 때문에 더 어려움
  • 배포, 스케일링, 컨테이너 어플리케이션 관리 자동화하는 컨테이너 오케스트레이션 플랫폼
  • 최소 2기가 램 이상을 사용하고, 2CPU 이상을 사용
    • 아니면 kubernetes로 서버 리소스를 다 써버릴 수 있음

특징

  • 코드 기반 클러스터 운영
    • 동일 코드 기반의 의사소통 -> 효율적
      • YAML 형식으로 파드들 및 기타 컴포넌트들을 정의함
      • 이전에는 다같이 검토 가능한 공통 도구가 없었음
  • 의도한 상태 기준 관리
    • 최초 의도한 상태와 현재 실행중인 상태를 쿠버네티스 컨트롤러가 자동으로 확인 (go 의 watch 모듈)
      • 차이점 발견 시, 현재 상태를 자동으로 처음 의도 상태로 변경
      • 즉, 실행중인 컨테이너가 예상치 않게 종료되면 자동으로 새로운 pod 생성

이후에 쿠버네티스 아키텍처와 쿠버네티스 옵션에 대한 글을 써 보고자 한다.

728x90
반응형
728x90
반응형

아래는 Jenkins 도입 과정과, 겪었던 시행 착오들에 대한 과거 기록들이다.

  • 배포 과정은 아래와 같다.
    • Master 브랜치에 커밋이 발생함을 감지 (Merge 커밋)
    • Matser 브랜치의 소스 코드를 가져와 Docker 이미지 빌드
    • 빌드된 이미지를 Private Registry에 푸시
    • 배포할 서버에 .env 파일과 docker-compose.yml 파일 전송
    • 배포할 서버에 빌드된 이미지를 pull 하여 컨테이너 구동
  • 이를 위해선 Github 연동과 Credentials 생성이 우선이다.

Github 설정

Github SSH KEY 연동

  • 배포용으로 사용할 키 새성
ssh-keygen -t rsa -f jenkins
  • .pub 키를 복사해서 계정/조직의 ssh 키를 추가해 복사해 넣는다
  • Jenkins Credentials 추가
    • Kind: SSH Username with private key
    • ID 임의 설정
    • username: 깃허브 계정명
    • Private key: 생성된 jenkins 키 내용 전체 복사 붙여넣기
    • 이렇게 설정하니, Host key verification failed. 라고 하며 git fetch 실패 에러가 뜨더라
  • Jenkins Secure 설정
    • 위 에러를 해결하기 위해 아래처럼 했다
    • Git Host Key Verification Configuration 설정 변경
      • Accep First connection 설정

Github Access Token

  • 깃헙 계정 에서 personal access token 생성
    • settings - developer settings - personal access tokens - tokens(classic)
    • Classic Token 생성하기
      • exiration: No expiration
      • repo
      • admin:org
      • admin:repo_hook
    • 생성되는 값 복사해두기

Github WebHook 설정

  • 레포지토리/조직의 설정으로 이동
  • 탭 중 webhook 선택
  • Add webhook 선택
    • url에 "${jenkins-url}/github-webhook/"입력
    • 생성하면, 성공 시 초록색 체크와 함께 완료된다
    • 실패 시, 이미 실패한 요청을 선택하여 redeliver하면 해결되더라

Jenkins 설정

Credential 설정

  • Jenkins 관리로 이동
  • Credentials - Stores scoped to Jenkins의 System 클릭 - Global credentials 클릭 -> Add Credentials 클릭
  • 깃허브 레포지토리 / 조직 접근 키 설정 - 깃헙 웹훅 사용 용
    • Kind를 Secret Text로 설정
    • Secret에 위에서 복사한 Personal Access Token 값 붙여넣기
    • ID: 마음껏 설정 - 나중에 이 값으로 깃헙 연동해야 하므로 알 수 있게끔 설정
    • Description: 설명
  • 개인 계정 - 아이템에서 깃헙 레포지토리 접근 용
    • Kind를 Username with password
    • username: 깃허브 계정 명
    • password: Personal Access Token 값
    • ID: 마음껏 설정
    • Description
  • 서버 - 접속 SSH 키 세팅
    • Kind를 Username and SSH
    • private key에 SSH private key 입력
  • 환경변수 파일 - 배포시 서버에 파일 전송.
    • Kind: Secret File
    • Id: 서비스 별로 분리할 수 있게끔 설정
    • 환경변수 파일 업로드

Github webhook 설정

  • Jenkins 관리로 이동
  • System 선택
    • 하단의 Github 탭의 Github Server 클릭
    • Name에 아무거나 임의로 입력
    • API URL은 건들지 말고
    • Credentials 에 위에서 secret text로 생성한 Credentials 선택
    • Manage Hooks 체크
    • Test connection 선택하여 연동 여부 체크

Jenkins Item 설정

  • 실질적인 파이프라인 설정 내용
  • 새로운 Item 클릭

Jenkinsfile로 사용할 시

  • 소스코드 내에 Jenkinsfile을 위치시켜 이를 사용해서 빌드하는 방법
  • Jenkinsfile에서 사용할 키는 위의 SSH Credential
  • pipeline 선택
    • Github project 체크
      • project url 선택: git@github.com:{브랜치명}
      • Github hook trigger for GITScm polling 선택
      • pipeline 변경
        • Definiton을 Pipeline script from SCM 선택
        • SCM을 Git 으로 변경
        • Repository URL에 깃헙 레포 주소 입력
        • Credentials: 깃허브 SSH Credential 선택
        • Branch Specifier: 연동할 브랜치
  • 이제 master 브랜치로 커밋이 감지될 때 마다 Jenkins가 레포 안의 Jenkinsfile을 감지해서 입력된 순서대로 동작할거다

Jenkins 파일 사용 안할 시

  • freestyle project 체크
  • 소스코드 관리 - Git 체크
  • Repository Url: 깃헙 레포 주소 입력
  • Credentials
  • 깃허브 SSH Credential 선택
    • master: 연동할 브랜치 설정 * 빌드 유발
    • Github hook trigger for GITScm polling 선택 * 저장`
  • 이제 Build Steps에 과정을 입력한다.

Plugins

  • Docker common: 도커 통합 플러그인
  • Docker Pipeline
  • SSH Pipeline steps
  • SSH Server
  • Publish Over SSH

에러 해결 - 1 docker.sock 퍼미션

  • Jenkins 빌드 과정에서 도커 이미지 빌드 내용이 있었다
  • 여기에서 permission denied while trying to connect to the Docker daemon socket 에러 발생
  • 결국 호스트의 var/run/docker.sock을 마운트하고 있기 때문이므로, 이를 수정해주었다.
  • # 새로운 계정 생성 sudo adduser jenkins

권한 부여

sudo usermod -a -G docker jenkins
  • 그럼에도 해결되지가 않았다
  • 누군가는 chmod 666으로 변경하면 된다지만, 이럴 경우 권한이 너무 열려버려서 위험해질 수 있다고 한다.
  • 아무튼 확인 결과 컨테이너 내부의 docker.sock은 root:999 으로 잡혀있었다.
    • root:docker 혹은 docker:1000이 되어야 할텐데
  • 때문에 컨테이너 내부 접근해서 직접 퍼미션 체크를 해 줬다.
sudo docker exec -it -u root jenkins-host /bin/bash
chown root:docker /var/run/docker.sock
  • 차후에 퍼미션 문제 없이 마운트 시키고 싶다

에러 해결 - 2 bad crum

curl -v -X GET https://{jenkins_url}/crumbIssuer/api/json --user dong:samquinnWkd1

curl -X POST https://{jenkins_url}/job/manage/credentials/store/system/domain/_/createCredentials/build --user dong:samquinnWkd1 -H 'Jenkins-Crumb: 9e107e40a5f7b6597e4020a4680bdda68b6b04c480aba07311166caa3bf98f9f'
728x90
반응형

'데브옵스 devOps > Jenkins' 카테고리의 다른 글

[Jenkins] 젠킨스란?  (2) 2024.10.07
728x90
반응형

레디스 개요 복습

  • REDIS Remote Dictionary Server
    • 디스크가 아닌 주 메모리(RAM)에 데이터를 저장하는 데이터베이스
      • 따라서 데이터가 주메모리보다 크면 안됨
    • 단일 스레드로 설계됨
    • 디스크 검색이 필요한 다른 DBMS보다 자료 접근이 훨신 빠름
    • 때문에 성능 향을 위한 캐시 서버로 자주 사용됨
      • 자주 접근하는 데이터 및 계산에 많은 시간이 소요되는 데이터를 캐싱해 빠른 접근 제공
  • 키 - 값 쌍을 가진 JSON 객체를 저장하는, 스키마 없는 데이터 베이스(NoSQL)

Redis Command

KEY 관련 명령어

  • SET (key, value): 키 - 값 쌍을 설정
  • GET (key): 주어진 키에 대한 값 조회
  • DEL (key): 주어진 키 삭제
  • EXISTS (key): 키 존재 여부 확인
  • FLUSHALL: 모든 데이터 삭제
  • KEYS (pattern): 특정 패턴을 가진 키 전체 조회
  • SETEX (key, seconds, value): 특정 시간 후에 만료되는 키 - 값 쌍 설정
  • TTL (key): 키의 만료까지 남은 시간 리턴

LIST 관련 명령어

  • LPUSH (key, value): 배열 가장 첫번째에 요소(value) 추가
  • RPUSH (key, value): 배열 가장 마지막에 요소(value) 추가
  • LRANGE (key, startIndex, stopIndex): 시작 인덱스(startIndex)와 종료 인덱스(stopIndex) 사이의 요소 목록 리턴
  • LPOP (key): 배열의 가장 첫번째 요소 제거
  • RPOP (key): 배열의 가장 마지막 요소 제거

HASH 관련 명령어

  • 단일 키 내에 {키 - 값} 쌍 저장이 가능
    • HSET (key, field, value): 키(field) - 값(value) 쌍을 해시 안에 세팅
    • HGET (key, field): 해시 안의 키(field)의 값을 가져옴
    • HGETALL (key): 해시의 모든 키-값 쌍 조회
    • HDEL (key, field): 해시에서 주어진 키(field) 삭제
    • HEXISTS (key, field): 해시 내의 키(field) 존재 여부 확인
728x90
반응형

'데브옵스 devOps > Redis' 카테고리의 다른 글

[REDIS] Redis 란?  (0) 2024.10.25
728x90
반응형

REDIS Remote Dictionary Server

  • 디스크가 아닌 주 메모리(RAM)에 데이터를 저장하는 데이터베이스
    • 따라서 데이터가 주메모리보다 크면 안됨
  • 단일 스레드로 설계됨
  • 디스크 검색이 필요한 다른 DBMS보다 자료 접근이 훨신 빠름
    • 때문에 성능 향을 위한 캐시 서버로 자주 사용됨
      • 자주 접근하는 데이터 및 계산에 많은 시간이 소요되는 데이터를 캐싱해 빠른 접근 제공
  • 키 - 값 쌍을 가진 JSON 객체를 저장하는, 스키마 없는 데이터 베이스(NoSQL)
  • 장점
    • 인메모리 키 - 값 저장소: 순수한 메모리 읽기는 빠른 읽기/쓰기 속도 및 빠른 응답 제공
    • IO 다중화(멀티플렉싱): 단일 스레드가 여러 개의 열린 소켓 연결에서 동시에 대기
    • 저수준 데이터 구조: 효율적인 저수준 데이터 구조 사용
  • 단점
    • 휘발성: 시스템이 갑자기 중단되면 Redis 내의 데이터 손실 가능

Redis Cache 동작 방식

  • 클라이언트의 데이터 요청
  • Redis Cache에서 해당 키 탐색
  • 키 발견 시 - Cache Hit
    • 캐시된 데이터 응답
  • 키 발견 실패 시 - Cache Miss

728x90
반응형

'데브옵스 devOps > Redis' 카테고리의 다른 글

[REDIS] 레디스 명령어  (0) 2024.10.28
728x90
반응형

도커 EXPOSE

  • Expose는 컨테이너에 오픈할 포트를 의미한다.
  • 즉 컨테이너에서만 열려있는 포트로, 동일한 도커 네트워크에 속해있지 않은 호스트나 외부에서 접근할 수 없다.

도커 PORT

  • Port는 EXPOSE 된 컨테이너의 포트를 호스트에 열어주는 것을 의미한다.
  • 앞의 포트는 호스트의 포트, 뒤의 포트는 컨테이너의 노출된 포트를 의미한다.
  • 즉 동일한 도커 네트워크에 속해있지 않더라도, hostIP와 해당 포트를 알고 있다면 컨테이너에 접근이 가능해 진다.
  • 컨테이너의 포트를 호스트와 연결시켜주는 것이므로, 컨테이너 포트와 동일할 필요가 없다
    • 이 말은 다시 말하면, 특정 포트(3306 / 5504 / 6379등) 만을 사용해야하는 어플리케이션에 대해 다양한 포트 번호를 호스트가 사용할 수 있게 되는 것이다.
    • 왜냐하면 특정 포트를 반드시 사용해야 한다는 제약은 컨테이너의 포트에만 적용될 수 있기 때문이다.
      • 3306만을 사용해야하는 mysql을 구동할 때, PORTS를 5587:3306으로 설정한다면 외부에서는 5587로 접근하지만 어플리케이션은 3306 포트를 사용하는 효과를 거둘 수 있는 것이다.
728x90
반응형
728x90
반응형

도커 네트워크

  • 도커 네트워크는 일종의 내부망 이다.
    • 각 컨테이너들은 독립적인 네트워크 망을 가진다.
    • 정확히는 분리된 네트워크를 가진다 -> IP를 나눈다는 의미
    • 때문에 각 컨테이너별로 호스트와는 다른 가상의 IP 주소를 가진다.
  • 도커 네트워크는 컨테이너가 끼리의 통신을 할 수 있는 범위라 말할 수 있을 것 같다.
  • 기본적으로 컨테이너가 구동되게 되면 해당 컨테이너에 대한 default_network가 생성된다.
    • 이렇게 되면 다른 네트워크의 컨테이너와 소통할 수 없기 때문에 도커 외부로 우회하여 소통해야한다.
    • 컨테이너끼리 소통하기 위해 외부로 나갔다 들어와야 하기 때문에 성능적으로 저하가 발생하고, 보안적으로도 문제가 생길 수 있다.
  • 그러나 동일한 네트워크에 속한 컨테이너들 끼리는, 컨테이너의 이름과 포트만으로 서로 통신이 가능하다.

컨테이너 구동 시 도커 네트워크 구성에 대해

  • 컨테이너 구동 시, 순차적으로 도커 내부 IP 부여
    • 일반적으로 172.~~ 으로 시작하더라
    • 순차적으로 IP를 부여하기 때문에, 컨테이너를 내렸다 다시 올리면 컨테이너 IP가 변동 될 수 있음
  • 도커 네트워크는 내부망이기에, 외부와 연결시켜야 함
    • 컨테이너 구동 시, 자동적으로 컨테이너 마다 호스트에 veth(Virtual Ethernet)라는 가상 네트워크 인터페이스를 생성함
    • 네트워크 관련 설정을 하지 않는다면 default0 브릿지를 사용함

Docker Bridge

  • 도커 브릿지는 호스트와 컨테이너를 잇는 라우팅 경로
    • 즉 쉽게 말하면, 각 컨테이너에 가상의 IP를 부여하는 공유기 역할

도커 네트워크 전체 조회

  • 현재 사용중인 도커 네트워크 리스트 조회
docker network ls
  • 도커 네트워크 세부사항 조회
docker network inspect 

도커 네트워크 설정

  • 도커 네트워크 설정
  • docker network create <네트워크 이름>

컨테이너 네트워크 설정

  • 같은 도커 네트워크에 해당하는 모든 컨테이너들은 서로 내부 통신이 가능함
    • 이미 db_mariadb 라는 컨테이너가 proxy라는 도커 네트워크 안에 구동되어 있다면
    • 지금 올리는 어플리케이션 컨테이너를 proxy라는 네트워크에 포함시킴으로 인해서, db_mariadb:3306 을 url로 잡으면 통신이 가능해짐
    • 같은 네트워크가 아니라면, 'HostIP:컨테이너 포트' 를 통해 접근할 수 있음
      • 문제는 컨테이너가 호스트에 포트를 열어둔게 아닌, 컨테이너 포트만 노출 시킨 상태라면 접근할 수 있는 방법이 없어짐
  • 컨테이너 네트워크 설정 - docker compose
    • external: 컨테이너 구동 시 새로운 네트워크를 사용할지에 대한 여부를 설정하는 것
      • true: 기존 도커 네트워크를 할당함
      • false: 새로운 도커 네트워크를 생성함
    services:
        app:
            // 컨테이너 설정
            networks:
                - proxy
    
    networks:
        proxy:
          # proxy라는 새로운 네트워크를 생성하는게 아닌, 기존의 proxy라는 네트워크를 사용한다는 의미
            external: true
  • 컨테이너 네트워크 설정 - Dockerfile
    docker run app_name --net proxy
728x90
반응형
728x90
반응형

프로메테우스란?

  • 프로메테우스는 사운드 클라우드에서 처음 제작한 모니터링 & 알람에 초점이 맞춰진 모니터링 오픈소스 툴이다.
  • 요청 발생 수, DB 연결 수 등의 숫자로 치환될 수 있는 시계열 데이터를 메트릭스(Metrics) 라 하는데, 이를 시계열 데이터로 저장 및 수집하는 툴이다.

특징

  • 다차원 시계열 데이터를 메트릭스 명과 key-value 쌍으로 관리한다.
  • PromQL 이라는 쿼리 언어로 차원들을 관리한다.
  • 다른 저장소에 종속되지 않는다.

데이터 수집 방법

  • 엔드포인트에 HTTP 요청을 통해 데이터를 스크레이핑 한다.
  • exporter를 배포해 해당 exporter의 엔드포인트를 통해 데이터를 스크레이핑한다.

시스템 메트릭 수집

  • 프로메테우스가 서버의 시스템 메트릭스(Load Average, CPU Usage 등)을 수집하는 방법은 node-exporter를 사용하는 것이다.
    • node-exporter는 시스템 정보를 수집하는 툴이라고 생각하면 편하다.

Node Exporter 실행

  • 컨테이너로 이를 시행시킬 수 있다.
  • 아래처럼 설정한다. 이렇게 했을 때, exporter의 엔드포인트로 접근해 데이터를 수집할 수 있다.
services:
    exporter:
        image: prom/node-exporter:v1.8.2
        container_name: exporter
        expose: 9100
        command:
          - '--path.procfs=/host/proc'
          - '--path.rootfs=/rootfs'
          - '--path.sysfs=/host/sys'
          - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
        volumes:
            - /proc:/host/proc:ro
            - /sys:/host/sys:ro
            - /:/rootfs:ro
        networks:
            - proxy
  • path.roofts 설정
    • 호스트 전체 모니터링을 위한 설정
    • 루트 디렉토리에 대해 바인딩 시켜, Exporter가 호스트 FileSystem에 접근하게 해 주는 옵션
    • 이후 루트 디렉토리를 볼륨으로 넣음
    • 일반 디렉토리면 그냥 넣어주면 된다.

프로메테우스 실행

설정

  • 프로메테우스 설정
    • prometheus.yml 파일로 해야 인식한다. 물론 볼륨으로 넣을 때, 명칭을 바꿔주는 것도 가능하다.
    • 수집할 대상의 엔드포인트를 정의한다.
    • 이는 scrape_configs 에 그 타겟 대상과 라벨링이 가능하다.
global:
    scrape_interval: 15s
    evaluation_interval: 15s

# Set the scrape interval to every 15 seconds. Default is every 1 minute.

rule_files:
    - alert.rules.yml
      alerting:
        alertmanagers:
            - static_configs:
            - targets: ["host.docker.internal:9093"]

scrape_configs:
    - job_name: 'System Server'
      static_configs:
        - targets: ['node:9100']

    - job_name: 'cAdvisor'
      static_configs:
        - targets: ['cadvisor:8080']
  • 설정 옵션 관련 내용
    • global: 전체적인 데이터 수집에 대한 전역 설정
    • scrape_configs: 수집 작업에 대한 정의
    • remote_write: 수집된 메트릭을 원격 엔드포인트로 전달하기 위한 설정

컨테이너 설정

  • prometheus.yml 파일 이외에도 alert.rules (장애 알람 규칙) 등 다른 설정들도 먹일 수 있다.
  • 해당 설정들은 /etc/prometheus 경로에 넣어주면 된다.
services:
    prometheus:
        image: prometheus:v2.54.1
        volumes:
            - ./prom-config/prometheus.yml:/etc/prometheus/prometheus.yml
            - ./prom-config/alert.rules.yml:/etc/prometheus/alert.rules.ym
            - prometheus_data:/prometheus
        command:
            - '--config.file=/etc/prometheus/prometheus.yml'
            - '--storage.tsdb.path=/prometheus'
            - '--web.console.libraries=/etc/prometheus/console_libraries'
            - '--web.console.templates=/etc/prometheus/consoles'
            - '--web.enable-lifecycle'
        networks:
            - proxy
        restart: unless-stopped
        ports:
            - 9090:9090

GUI

  • 이제 http://localhost:9090으로 접근해 보면 아래와 같이 확인할 수 있다.
  • 아래 랜딩페이지 화면에서 PromQL을 통해 데이터를 쿼리해 볼 수 있다.

'

  • 또한 현재 데이터를 수집하고 있는 대상을 확인하는 방법은 Status - Target으로 확인할 수 있다.
    • 여기서 현재 정상적으로 데이터가 수집되고 있는지도 확인할 수 있다.

728x90
반응형

'데브옵스 devOps > Monitoring' 카테고리의 다른 글

[CNCF] OpenTelemetry(OTel)란?  (0) 2024.11.22
728x90
반응형

CI / CD

  • CI (Continuous Integration): 지속적 통합
    • 코드에 대한 통합
    • 다수의 개발자들의 코드 베이스를 계속해서 통합한다는 의미
    • 즉 여러 개발자들의 코드를 빠르게 배포함을 의미
  • CD (Continuous Deployment): 지속적 배포
    • 코드 베이스를 사용자가 사용하는 환경에 코드 베이스 배포를 자동화하는 것
  • 즉 CI/CD는 여러명의 개발자들이 개발 환경을 통합하여 사용자가 사용하는 환경에 전달하는 모든 일련의 과정들을 자동화하는 것
    • 여기에는 코드 빌드, 테스트, 배포가 포함됨

젠킨스?

  • Java Runtime Environment에서 동작
    • 플러그인 사용하여 자동화 작업 파이프라인을 설계
    • 파이프라인 마저도 플러그인의 일부
  • Credentials 플러그인을 사용해서 민감정보를 보관

젠킨스 파이프라인

  • Section - 가장 큰 개념
    • Agent Section
      • 오케스트레이션 처럼 slave node에 일 처리 지정
    • Post Section
      • 스테이지가 끝난 이후의 결과에 따른 후속 조치
      • 즉 작업 결과에 따른 행동 조치
    • Stage Section - 카테고리
      • 어떠한 일을 처리할 것인지 stage를 정의
      • Dockerfile의 스테이지를 정의하는 것과 같음
    • Step Section - 카테고리 내부의 동작들
      • 한 스테이지 안에서의 단계
      • 여러 작업들 실행 가능

Declaratives

  • Environment, Stage, Options, Parameters, Triggers, When
  • 각 Stage 안에서 어떠한 일을 할 것인지 정의
  • Environment
    • 환경변수들 정의
  • Parameter
    • 파이프라인 실행시 파라미터를 받음
  • Triggers
    • 파이프라인이 실행되는 트리거 정의
    • 예시: 특정 브랜치에 머지가 감지되었을 때
  • When
    • 수행되는 조건문
    • 예시: 환경변수 BUILD_BRANCH가 dev일 때

예시

  • 깃허브 특정 레포 dev(개발)/main(운영) 브랜치에 머지 인식
    • 미리 Credentials에 등록해 둔 각각 환경에 따라 다른 환경 변수 로드
    • 각각 환경에 따른 이미지 명으로 도커 이미지 빌드
    • 개인 도커 레지스트리에 이미지 푸시
    • 각각 개발/운영 서버에 배포할 서비스 경로 생성
      • docker-compose.yml 파일 복사
      • 빌드하여 푸시한 이미지 가져와서 컨테이너 구동
// 브랜치별 배포 위치

def getDeployTargets(envName) {

targets = [:]



// dev 브랜치

targets['prod'] = [[

    COMPOSE_ENV: 'dev',

    SSH_MODE: 'KEYONLY',

    SSH_IP: '<Server IP>',

    SSH_KEY_ID: 'Key Id From Jenkins Credentials',

    COPY_DIR: '도커 컴포즈 파일 배포할 서버 상의 경로'

]]

    return targets[envName]
}



// 브랜치별 환경 정보

def getBuildBranch(branchName) {
    branches = [
        'origin/main': 'prod',
    ]

    return branches[branchName]
}



pipeline {
    agent any

    //환경변수
    environment {

        //브랜치 선택

        BUILD_BRANCH = getBuildBranch(env.GIT_BRANCH)

        // 도커 설정
        DOCKER_IMAGE = ''
        DOCKER_IMAGE_NAME = '빌드 할 도커 이미지 명'

        // Git, Docker private 레지스트리 로그인 정보 설정    
        GIT_KEY_ID = '깃허브 인증 SSH 키 ID - Credentials에서 관리;'
        REGISTRY_LOGIN_INFO_ID = 'donghquinn_registry'
    }



                        stages {

                            stage('체크아웃') {
                                steps {
                                    echo "작업 브랜치: ${env.GIT_BRANCH}"

                                    git branch: BUILD_BRANCH, credentialsId: GIT_KEY_ID, url: 'git@github.com:donghquinn/<레포 명>.git'

                            }

                        }



                        stage('도커 이미지 빌드') {
                            steps {
                                script {

                                    // 브랜치에 따라 이미지 이름 변경
                                    DOCKER_IMAGE = docker.build(DOCKER_IMAGE_NAME + '-' + BUILD_BRANCH)

                                }

                                echo "Built: ${DOCKER_IMAGE_NAME}-${BUILD_BRANCH}"

                            }
                        }



                        stage('도커 이미지 Push') {
                            steps {
                                script {
                                    // 개발서버 내부 Docker private 레지스트리에 업로드
                                    docker.withRegistry('https://registry.donghyuns.com', REGISTRY_LOGIN_INFO_ID) {

                                    DOCKER_IMAGE.push(env.BUILD_NUMBER)
                                    DOCKER_IMAGE.push('latest')
                                }

                            }
                            echo "Pushed: ${DOCKER_IMAGE_NAME}-${BUILD_BRANCH}:${env.BUILD_NUMBER}"

                            }

                        }



                        stage('도커 컨테이너 배포') {

                        steps {

                            script {

                                def deployTargets = getDeployTargets(BUILD_BRANCH)

                                def deployments = [:]



                                // 배포 타깃별로 병렬 배포

                                for (item in deployTargets) {

                                def target = item



                                deployments["TARGET-${BUILD_BRANCH}"] = {

                                def remote = [:]
                                remote.name = target.SSH_IP
                                remote.host = target.SSH_IP
                                remote.allowAnyHosts = true

                                if (target.SSH_MODE == 'KEYONLY') {

                                    withCredentials([

                                    // DOTENV 파일과 SSH KEY를 가져옴
                                    sshUserPrivateKey(credentialsId: target.SSH_KEY_ID, keyFileVariable: 'SSH_PRIVATE_KEY', usernameVariable: 'USERNAME')
                                    ]) {

                                    // 가져온 키로 ssh 정보 설정
                                    remote.user = USERNAME

                                    remote.identityFile = SSH_PRIVATE_KEY

                                    sshCommand remote: remote, command: """
                                        mkdir -p ${target.COPY_DIR}-${BUILD_BRANCH}/
                                    """

                                    // docker compose 파일 전송
                                    sshPut remote: remote, from: "docker-compose.${BUILD_BRANCH}.yml", into: "${target.COPY_DIR}-${BUILD_BRANCH}/docker-compose.yml", failOnError: 'true'

                                    // 각 상황에 맞는 .env.* 파일 전송

                                   // 각 상황에 맞는 .env.* 파일 전송
                                  sshPut remote: remote, from: DOTENV, into: "${target.COPY_DIR}/.env", failOnError: 'true'

                                    // 도커 이미지 Pull 및 재시작
                                    sshCommand remote: remote, command: """
                                        cd ${target.COPY_DIR}-${BUILD_BRANCH}/
                                        BUILD_BRANCH=${BUILD_BRANCH} docker compose pull
                                        BUILD_BRANCH=${BUILD_BRANCH} docker compose up -d
                                    """
                                }
                            }
                        }

                        parallel deployments

                    }

                }

            }

        }

    }

}
728x90
반응형

'데브옵스 devOps > Jenkins' 카테고리의 다른 글

[Jenkins] 실제 CI/CD 배포 세팅  (2) 2024.10.29

+ Recent posts