Search
Duplicate

Development Note

Common

나중에 볼거

Dev

Network

Database

Virtual

Memo

kafka

실시간 데이터 스트림을 처리하기 위해 설계된 오픈 소스 분산 스트리밍 플랫폼
다양한 소스에서 발생하는 대량의 데이터를 실시간으로 수집, 저장, 처리, 전달할 수 있도록 도와주는 강력한 도구
여러 소스에서 데이터 스트림을 처리하고 여러 사용자에게 전달되도록 설계
A → B 뿐만아니라 A → Z까지의 모든 경로를 동시에 이동 가능
분산 시스템, 페이지, 캐시, 배치 전송 처리, 압축 전송, 고가용성 보장

redis

고성능 Key-Value 구조의 저장소
비정형 데이터를 저장, 관리하기 위한 오픈 소스 기반의 NoSQL
DB, Cache, Message Queue, Shared Memory 용도로 사용
mongoDB
문서 지향적인 NoSQL로, 대량의 비정형 데이터를 저장하고 처리하는데 사용
비정형 데이터 : 미리 정의된 데이터 모델이나 구조를 따르지 않는 데이터를 의미 (텍스트, 이미지, 음성, 동영상)
소스코드

postgreSQL

객체 관계형 데이터베이스(ORDBMS) 중 하나로 무료로 제공되고 있는 데이터베이스
사용이유
JSON을 사용함에 있어 윈도우 함수, 재귀 쿼리, CTE등 고급 SQL 기능 지원
수평 및 수직 확장을 모두 지원하여 대용량 데이터 처리 및 고성능 시스템 구축에 적합
MVCC를 통해 동시성 제어를 효율적으로 처리하여 읽기 성능이 우수, MariaDB는 쓰기 작업이 많은 환경에 적합

슬로우 기술 블로그 정리

Flutter 상태 관리 패키지

애플리케이션의 데이터나 UI 상태를 관리
앱의 데이터 흐름을 관리하고 UI를 업데이트하는 데 필요
선언형 프로그래밍 방식에서 중요하며, 현재 안드로이드의 경우 선언형 프로그래밍(Compose)으로 넘어가는 추세
# 명령형 프로그래밍 대표적으로 C, Java, Python과 같이 프로그램이 어떻게 실행되어야 하는지 명시하는 방식 코드는 명령어의 연속으로 구성되며, 명령어는 컴퓨터가 실행할 단계별 작업을 정의 명령형 프로그래밍은 코드가 실행되는 순서가 중요하며, 개발자는 프로그램의 상태를 명령어로 변경하고 관리 # 선언형 프로그래밍 대표적으로 Android Compose, Flutter, IOS Swift, SQL과 같은 DB 퀴리 언어 등 존재 프로그램이 어떻게 실행 되어야 하는지를 명시하는 것이 아닌, 원하는 결과를 명시하는 방식으로 프로그래밍 명령형 프로그래밍의 반대 개념으로 코드가 어떻게 동작하는지가 아니라 무엇을 원하는지가 중점
Bash
복사
상태 관리 패키지를 사용해야하는 이유
복잡한 애플리케이션 상태관리 : 사용자 입력, 네트워크 요청, 로컬 데이터 변경 등 다양한 요인에 의해 상태가 변경 됨
UI 업데이트 관리 : UI는 애플리케이션 상태에 따라 동적으로 변경됨. 상태 관리 패키지를 사용할 시 UI 업데이트 방법을 추상화하고 단순화함
비동기 처리 : 네트워크 요청, 데이터베이스 액세스, 파일 I/O 등의 작업을 쉽게 처리하고 상태를 업데이트
모듈성 및 유지보수성 : 라이브러리를 사용하면 상태 및 관련 로직을 분리하므로 추상화화 모듈성을 촉진하여 재사용성을 높이고 유지보수성을 향상

Docker란?

도커(docker)는 Go언어로 작성된 linux 컨테이너를 기반의 오픈소스 가상화 플랫폼
현재 Docker 0.9버전 부터는 직접 개발한 libcontainer 컨데이너를 사용
향상된 컴퓨터의 성능을 더욱 효율적으로 사용하기 위해 가상화를 사용
컨테이너는 소프트웨어를 패키지화하여 실행하는데 사용되며, 도커는 이러한 컨테이너를 관리하고 배포하는 도구
도커는 컨테이너 관리 기능 외에도 명령어 입력도구인 CLI와 명령어를 받아들이는 도커 데몬과 이미지를 저장하는 레지스트리로 구성
도커와 쿠버네티스를 함께 설치할 경우 쿠버네티스는 컨테이너 오케스트레이션을 위해 도커에 포함된 컨데이너디를 활용
containerd는 Docker에서 만든 컨테이너 런타임

컨테이너란?

컨테이너(Container)는 개별 애플리케이션의 실행에 필요한 실행환경을 독립적으로 운용하며,
다른 실행환경과의 간섭을 막고 실행의 독립성을 확보해주는 운영체제 수준의 격리 기술
즉, 기존 OS를 가상화 시키던 것과 달리 컨테이너는 OS레벨의 가상화로 프로세스를 격리시켜 동작하는 방식
대표적으로 LXC(Linux Container)이 존재
LXC : OS의 수준의 가상화를 제공. 각 컨테이너는 독립된 운영 체제처럼 동작하며, 사용자가 직접 운영 체제 설정 및 관리
Docker : Docker 이미지는 애플리케이션 실행에 필요한 모든 파일과 설정을 포함하며, 레이어 구조를 통해 효율적인 저장 및 공유 가능
컨테이너는 독립된 애플리케이션의 실행환경으로 VM보다 메모리를 덜 소모하고, 셋업이 빠르다. 또한, VM과 비교해 크기가 작기 때문에 마이그레이션, 백업, 전송이 쉽고 하드웨어와의 커뮤니케이션이 빨라 전달 시간이 감소할 수 있기 때문에 성능이 효과적이다. 애플리케이션의 배치와 유지보수를 향상시킨다는 장점을 가지고 있다.

호스트 OS형 가상화

베이스가 되는 호스트OS 위에 게스트OS가 구동되는 방식.
VM workstation, VMware Server, VMware Player, MS Virtual Server, Virtual PC, Parallers Workstation
장점 : 가상의 하드웨어를 에뮬레이팅하기 때문에 호스트 운영체제의 크게 제약사항이 없음
에뮬레이팅(Emulating)은 다른 시스템이나 환경을 모방하여 특정 소프트웨어나 하드웨어를 실행하는 것
단점 : OS위에 OS가 얹히는 방식이기 때문에 오버헤드가 클 수 있음

하이퍼바이저 가상화 기술

호스트OS를 설치하는 게 아니라, 하이퍼바이저라는 소프트웨어를 물리 하드웨어 위에 직접 작동시켜 게스트OS가 구동되는 방식
독립적인 호스트 시스템처럼 작동하며 복수의 가상머신이 서로 간섭하지 않아 처리 오버헤드가 존재하지 않음
장점 : 별도의 호스트OS가 없기 때문에 오버헤드가 적고, 하드웨어를 직접 제어하기 때문에 효율적으로 리소스를 사용
단점 : 자체적으로 머신에 대한 관리 기능이 없기 때문에 관리를 위한 컴퓨터나 콘솔 필요

전가상화(Full-Virtualization)

하드웨어를 완전히 가상화하며, 여러개의 독립된 VM을 생성. Hardware Virtual Machine이라고도 불림
하이퍼바이저를 구동하면 DOM0이라고 하는 관리용 가상 머신이 실행. 모든 명령에 DOM0이 개입
VM(가상 머신)에서 할당된 게스트 OS의 명령을 번역, 자원 할당
장점 : 하드웨어를 완전히 가상화하기 때문에 게스트OS 운영체제의 별다른 수정이 필요 없음
단점 : 하이퍼바이저가 모든 명령을 중재하기 때문에 비교적 느림

반가상화(Para-Virtualization)

그림의 왼쪽은 반가상화 방식, 오른쪽은 전가상화 방식
게스트가 하드웨어에 직접 접근할 수 있는지에 차이가 있음
전가상화의 가장 큰 단점인 성능저하의 문제를 해결하기 위해 하이퍼콜이라는 인터페이스를 통해 하이퍼바이저에게 직접 요청
각 게스트 OS는 하이퍼콜을 통해 하이퍼바이저에게 자신에게 필요한 특정 작업을 요청할 수 있음
장점 : 모든 명령을 DOM0을 통해 하이퍼바이저에게 요청하는 전가상화에 비해 성능이 빠름
단점 : 하이퍼바이저에게 하이퍼콜 요청 할 수 있도록 각 OS의 커널을 수정해야하며 오픈소스 OS가 아니면 반가상화를 이용하기가 쉽지 않음

컨테이너형 가상화

하드웨어나 운영체제를 가상화하는 대신, 애플리케이션 실행에 필요한 최소한의 환경만을 캡슐화하여 격리된 공간에서 실행하는 방식
즉,  OS를 가상화하지 않고 소프트웨어를 바로 가상화
장점 : 컨테이너 가상화는 오버헤드가 적어 가볍고 빠름
단점 : OS가상화보다 더 낮은 격리 레벨을 지원
그럼에도 쓰는 이유
높은 성능
뛰어난 이식성
쉽게 Scale Out을 할 수 있는 유연성

Docker 주요 구성요소

Docker엔진은 서버-클라이언트 형태의 기술
컨테이너를 생성 실행 및 관리하는 중앙 집중식 서비스 제공
Docker 엔진의 구성
Daemon (dockerd) :
docker 데몬은 백그라운드에서 실행되며 컨테이너 관리를 담당하는 주요 서비스.
이미지, 컨테이너, 네트워크, 볼룸의 생성과 관리
데몬 : 멀티태스킹 운영체제에서 사용자가 직접적으로 제어하지 않고, 백그라운드에서 여러 작업을 하는 프로그램
특징 : 부모 프로세스 없음 (PPID = 1), Init 프로세스의 바로 하위에 위치
REST API :
docker 데몬과 통신하는 인터페이스
다양한 dcoker 클라이언트와 프로그램들이 docker 데몬과 통신
Client (docker) :
사용자가 명령어를 입력하여 docker 데몬과 상호 작용할 수 있는 커맨드라인 인터페이스(CLI)
docker 클라이언트는 사용자의 명령을 API 요청으로 변환하여 docker 데몬에 전달
docker 이미지는 읽기 전용의 템플릿으로 컨테이너를 생성하는 데 사용
이미지는 애플리케이션과 그 모든 종속성을 포함하며, Dockerfile이라는 스크립트를 통해 구축
docker 이미지는 Docker Hub와 같은 레지스트리에서 공유되고 관리될 수 있음
레지스트리 :
시스템 및 응용 프로그램의 설정 정보와 데이터를 저장하는 계층적인 데이터베이스
마치 나무의 가지처럼 뻗어나가는 구조를 가지고 있으며, 각각의 가지는 '키(key)'라고 불리며, 그 안에는 '값(value)'이라는 데이터가 저장
컨테이너는 이미지를 기반으로 실행되는 격리된 환경에서 애플리케이션을 실행
즉, 이미지로 컨테이너를 실행하며 자체 파일 시스템, 네트워킹 환경, 독립적인 프로세스 공간 등을 가짐
사용자는 컨테이너를 시작, 정지, 이동, 삭제 가능
Dockerfile
FROM komljen/nodejs MAINTAINER Alen Komljen <alen.komljen@live.com> ENV GHOST_VERSION 0.5.7 ENV APP_ROOT /data/app RUN \ curl -sLO http://ghost.org/archives/ghost-${GHOST_VERSION}.zip && \ mkdir -p ${APP_ROOT} && \ unzip -uo ghost-${GHOST_VERSION}.zip -d ${APP_ROOT} && \ rm ghost-${GHOST_VERSION}.zip RUN \ cd ${APP_ROOT} && \ npm install --production COPY start.sh start.sh VOLUME ["$APP_ROOT"] RUN rm /usr/sbin/policy-rc.d CMD ["/start.sh"] EXPOSE 2368
Docker
복사
Dockerfile 분석: Node.js 기반 Ghost 블로그 설치 및 실행 이 Dockerfile은 Ghost 블로그 플랫폼을 Node.js 환경에서 실행하기 위한 Docker 이미지를 빌드하는 데 사용됩니다. 각 명령어의 의미를 자세히 살펴보겠습니다. 1. 기본 이미지 설정 FROM komljen/nodejs: komljen/nodejs 이미지를 기본 이미지로 사용합니다. 이 이미지는 Node.js 실행 환경을 이미 갖추고 있어, Ghost 블로그를 실행하기 위한 기반을 제공합니다. 2. 메인테이너 정보 MAINTAINER Alen Komljen <alen.komljen@live.com>: 이 Dockerfile을 관리하는 사람의 정보를 명시합니다. 3. 환경 변수 설정 ENV GHOST_VERSION 0.5.7: Ghost 블로그 버전을 0.5.7로 설정합니다. ENV APP_ROOT /data/app: 애플리케이션이 설치될 경로를 /data/app으로 설정합니다. 4. Ghost 블로그 설치 RUN \ ...: 여러 개의 명령어를 순차적으로 실행합니다. curl -sLO http://ghost.org/archives/ghost-${GHOST_VERSION}.zip: Ghost 블로그 압축 파일을 다운로드합니다. mkdir -p ${APP_ROOT}: 애플리케이션 설치 경로를 생성합니다. unzip -uo ghost-${GHOST_VERSION}.zip -d ${APP_ROOT}: 압축 파일을 해제하고, 파일들을 애플리케이션 설치 경로에 덮어씁니다. rm ghost-${GHOST_VERSION}.zip: 압축 파일을 삭제합니다. 5. Node.js 종속성 설치 RUN \ ...: 여러 개의 명령어를 순차적으로 실행합니다. cd ${APP_ROOT}: 애플리케이션 설치 경로로 이동합니다. npm install --production: package.json에 명시된 production 환경의 Node.js 종속성들을 설치합니다. 6. 시작 스크립트 복사 COPY start.sh start.sh: 현재 디렉토리의 start.sh 파일을 이미지의 start.sh로 복사합니다. 이 스크립트는 Ghost 블로그를 실행하는 데 사용될 것입니다. 7. 볼륨 설정 VOLUME ["$APP_ROOT"]: 애플리케이션 설치 경로를 볼륨으로 설정합니다. 이를 통해 컨테이너 내부의 데이터를 외부 호스트 시스템에 영구적으로 저장하거나, 다른 컨테이너와 공유할 수 있습니다. 8. 불필요한 서비스 제거 RUN rm /usr/sbin/policy-rc.d: Ubuntu 시스템에서 사용되는 policy-rc.d 서비스를 제거합니다. 이 서비스는 Ghost 블로그 실행에 필요하지 않으며, 컨테이너 이미지 크기를 줄이기 위해 제거합니다. 9. 실행 명령어 설정 CMD ["/start.sh"]: 컨테이너가 시작될 때 실행될 명령어를 설정합니다. 즉, 컨테이너가 시작되면 /start.sh 스크립트를 실행하여 Ghost 블로그를 실행합니다. 10. 포트 노출 EXPOSE 2368: Ghost 블로그가 사용하는 2368 포트를 외부에 노출합니다. 이를 통해 외부에서 컨테이너 내부의 Ghost 블로그에 접속할 수 있습니다. 요약: 이 Dockerfile은 Node.js 환경에서 Ghost 블로그를 실행하기 위한 Docker 이미지를 빌드합니다. Ghost 블로그를 설치하고, 필요한 종속성을 설치하며, 시작 스크립트를 복사하고, 볼륨 및 포트 설정을 구성합니다.
YAML
복사
docker compose는 여러 컨테이너를 정의하고 실행하기 위한 도구
YAML 파일을 사용하여 서비스, 네트워크, 볼륨 등을 구성
YAML 파일을 이용하여 여러 컨테이너로 구성된 애플리케이션을 관리
version: '3' services: planka: image: ghcr.io/plankanban/planka:latest restart: on-failure volumes: - user-avatars:/app/public/user-avatars - project-background-images:/app/public/project-background-images - attachments:/app/private/attachments ports: - 3000:1337 environment: - BASE_URL=http://plank.example.com:3000 - DATABASE_URL=postgresql://postgres@postgres/planka - SECRET_KEY=secret - DEFAULT_ADMIN_EMAIL=admin@example.com # Do not remove if you want to prevent this user from being edited/deleted - DEFAULT_ADMIN_PASSWORD=Password - DEFAULT_ADMIN_NAME=Admin - DEFAULT_ADMIN_USERNAME=admin depends_on: postgres: condition: service_healthy postgres: image: postgres:14-alpine restart: on-failure volumes: - db-data:/var/lib/postgresql/data environment: - POSTGRES_DB=planka - POSTGRES_HOST_AUTH_METHOD=trust healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d planka"] interval: 10s timeout: 5s retries: 5 volumes: user-avatars: project-background-images: attachments: db-data:
YAML
복사
Docker Compose 파일 분석: Planka 애플리케이션 실행 환경 구성 이 Docker Compose 파일은 Planka라는 애플리케이션을 실행하기 위한 두 가지 서비스, planka와 postgres를 정의하고 있습니다. 각 서비스는 Docker 컨테이너로 실행되며, 서로 연결되어 애플리케이션을 구성합니다. 1. planka 서비스 image: ghcr.io/plankanban/planka:latest: Planka 애플리케이션의 최신 이미지를 사용하여 컨테이너를 생성합니다. restart: on-failure: 컨테이너가 실패하면 자동으로 재시작합니다. volumes: 컨테이너 내부 디렉토리와 호스트 시스템 디렉토리를 연결합니다. user-avatars, project-background-images, attachments: 사용자 아바타, 프로젝트 배경 이미지, 첨부 파일을 저장하는 디렉토리를 각각 연결합니다. ports: 컨테이너의 1337 포트를 호스트 시스템의 3000 포트에 연결합니다. 즉, http://localhost:3000 으로 접속하면 Planka 애플리케이션에 접근할 수 있습니다. environment: 애플리케이션 실행에 필요한 환경 변수를 설정합니다. BASE_URL: 애플리케이션의 기본 URL을 설정합니다. DATABASE_URL: PostgreSQL 데이터베이스 연결 정보를 설정합니다. SECRET_KEY: 애플리케이션 보안을 위한 암호화 키를 설정합니다. DEFAULT_ADMIN_EMAIL, DEFAULT_ADMIN_PASSWORD, DEFAULT_ADMIN_NAME, DEFAULT_ADMIN_USERNAME: 기본 관리자 계정 정보를 설정합니다. depends_on: postgres 서비스가 "healthy" 상태가 될 때까지 planka 서비스 시작을 기다립니다. 2. postgres 서비스 image: postgres:14-alpine: PostgreSQL 14 버전의 Alpine Linux 기반 이미지를 사용하여 컨테이너를 생성합니다. restart: on-failure: 컨테이너가 실패하면 자동으로 재시작합니다. volumes: 데이터베이스 데이터를 저장하는 디렉토리를 호스트 시스템에 연결합니다. environment: 데이터베이스 이름(POSTGRES_DB)을 설정하고, 호스트 기반 인증 방식(POSTGRES_HOST_AUTH_METHOD)을 사용합니다. healthcheck: 컨테이너의 상태를 주기적으로 확인하여 정상적으로 실행 중인지 확인합니다. pg_isready 명령어를 사용하여 PostgreSQL 서버가 준비되었는지 확인합니다. 3. volumes user-avatars, project-background-images, attachments: 이름만 정의된 볼륨입니다. Docker Compose는 이 볼륨들을 자동으로 생성하고 관리합니다. db-data: PostgreSQL 데이터베이스 데이터를 저장하는 볼륨입니다. 요약: 이 Docker Compose 파일은 Planka 애플리케이션과 PostgreSQL 데이터베이스를 Docker 컨테이너로 실행하고, 필요한 설정 및 연결을 구성하여 애플리케이션 실행 환경을 구축합니다.
YAML
복사
5.
Docker Hub/Registry
docker hub는 docker 이미지를 공유하고 배포할 수 있는 클라우드 기반 서비스이다
사용자는 docker Hub을 통해 이미지를 저장하거나 docker 공식 이미지 뿐만 아니라 다른 사용자가 만든 이미지도 찾아 사용 가능
개발에서부터 배포까지 전 과정에서 컨테이너를 효율적으로 관리할 수 있는 강력한 도구 제공

Kubernetes란

컨테이너화된 워크로드와 서비스를 관리하기 위한 이식 가능하고 확장 가능한 오픈 소스 플랫폼
워크로드 :
시스템, 네트워크 또는 컴퓨팅 자원에서 처리되는 작업의 양과 유형을 의미
컴퓨터가 치리해야하는 일의 종류와 규모
빠르게 성장하는 대규모 에코시스템(복잡한 시스템)
조타수 또는 조장사를 의미
약자로서 K8s
Planet Scale(확장성) :
애플리케이션을 구성하는 컨테이너를 논리적 단위로 그룹화하여 쉽게 관리하고 검색 가능
Never Outgrow(안정성) :
Google이 일주일에 수십억 개의 컨테이너를 실행할 수 있는 것과 동일한 원리로 설계된 k8s는 운영팀을 늘리지 않고도 확장 가능
Run K8s Anywhere
쿠버네티스는 온프레미스, 하이브리드 또는 퍼블릭 클라우드 인프라를 자유롭게 활용할 수 있는 오픈 소스로써 워크로드를 중요한 위치로 이동 가능

쿠버네티스 특징

오픈소스
엄청난 인기
무한한 확장성
사실상 표준

배포 환경의 변화

전통적인 배포
초기에는 애프리케이션을 물리 서버 상에서 운영
단일 물리 서버 상에서 여러 애플리케이션의 리소스 한계를 명확히 설정할 수 없어서 리소스 할당 관련 문제가 발생
예를들어 하나의 서버에서 여러 애플리케이션을 실행할 경우, 어떤 애플리케이션 인스턴스가 모든 리소스를 점유하여 성능 저하 가능성 보유
이 문제의 해결 방안으로 각 애플리케이션을 서로 다른 물리서버에서 실행할 수 있으나,
이 경우 리소스가 충분히 활용되지 못하고 많은 물리 서버를 유지하기 위한 높은 비용 발생
가상화된 배포
이러한 문제를 해결하기 위해 가상화 기술 도입
가상화는 단일 물리 서버의 CPU에서 여러 가상 시스템(VM)을 실생할 수 있게 함으로써,
VM 간에 애플리케이션을 격리시키고, 서로 다른 애플리케이션 간의 정보 접근을 제한하여 일정 수준의 보안을 제공
가상화를 통해 물리 서버의 리소스를 보다 효율적으로 활용하고,
애플리케이션을 손쉽게 추가하거나 업데이트 할 수 있으며, 하드웨어 비용을 절감하여 더욱 향상된 확장성을 제공
가상화를 이용해 일련의 물리 리소스를 가상 머신으로 구성된 클러스터로 전환 가능
각 VM은 가상화된 하드웨어 상에서 자체 운영체제를 포함한 모든 구성 요소를 실행하는 하나의 완전한 머신으로 작동
컨테이너 배포
컨테이너는 VM과 유사하나, 애플리케이션 간에 운영체제를 공유하면서 격리 속성을 완화
자체 파일 시스템, CPU 점유율, 메모리, 프로세스 공간이 존재하며, 기본 인프라와 종속성이 없기 때문에 다양한 클라우드나 OS 배포판에 이식 가능
컨테이너 기능
VM 이미지 사용에 비해 컨테이너 이미지 생성이 보다 쉽고 효율적
안정적이고 주기적으로 컨테이너 이미지를 빌드 및 배포할 수 있으며, 이미지의 불변성 덕분에 빠르고 효율적으로 롤백 가능
배포 시점이 아니라 빌드/릴리즈 시점에 애플리케이션 컨테이너 이미지를 생성함으로써, 인프라 구조에서 애플리케이션 분리
OS 수준에 국한 되지 않고, 애플리케이션의 헬스와 기타 신호들을 확인
어떤 OS환경에서도 동일하게 구동
Ubuntu, RHEL, 온프레미스, 주요 퍼블릭 클라우드 등 다양한 환경에서 구동
애플리케이션은 단일 목적의 머신에서 모놀리식 스택으로 구동되지 않고 독립적인 단위로 나뉘며 동적으로 배포되고 관리
리소스 격리 : 애플리케이션 성능 예측 가능
리소스 사용량 : 고효율 및 고집적 사용 가능

쿠버네티스 사용 이유

컨테이너 환경에서의 애플리케이션 관리 및 가동 중지의 자동화
쿠버네티스 사용시 분산 시스템을 유연하게 운영 가능하며, 애플리케이션의 확장, 장애 대응, 다양한 배포 전략 지원

쿠버네티스 기능

컨테이너를 외부에 노출하여 외부 사용자나 다른 서비스가 해당 컨테이너에 접근할 수 있는 기능 제공
DNS 이름이나 자체 IP 주소를 통해 컨테이너를 외부에 노출
이를 통해 컨테이너로의 트래픽이 증가할 경우, 트래픽 분산 및 로드 밸런싱을 자동으로 수행하여 시스템을 안정적으로 운영
사용자는 쿠버네티스를 통해 로컬 저장소부터 퍼블릭 클라우드 공급자에 이르기까지 다양한 저장소 시스템을 자동으로 마운트 가능
원하는 상태의 컨테이너 배포를 서술적으로 정의할 수 있으며, 시스템은 현재 상태를 사용자가 정의한 원하는 상태로 점진적 변경
새로운 컨테이너의 배포, 기존 컨테이너의 제거 및 업데이트등을 포함
컨테이너화 된 작업을 위한 클러스터 노드의 자동할당을 지원
사용자는 각 컨테이너에 필요한 CPU와 메모리(RAM) 요구사항을 명시, 리소스 사용률을 극대화
클러스터 : 여러 개의 컴퓨터 또는 서버를 네트워크로 연결하여 하나의 시스템처럼 동작하도록 구성한 집합체를 의미
자동화된 복구 기능을 지원. 실행의 실패한 컨테이너를 자동으로 재시작하고 정상 작동하지 않는 컨테이너를 종료
암호, OAuth 토큰, SSH 키와 같은 중요 정보를 안전하게 저장하고 관리
컨테이너 인미지를 재구성하지 않고도 애플리케이션 구성을 안전하게 배포 및 업데이트

쿠버네티스 구성 및 설계

여러 개의 Component와 Node로 구성된 분산 시스템
컴포넌트 : 재사용 가능한 독립적인 소프트웨어 모듈
컨테이너화된 애플리케이션의 배포, 확장 및 관리를 자동화

컨트롤 플레인 (Control Plane)

클러스터의 전반적인 관리 및 조정을 담당
클러스터의 상태 관리, 스케줄링, 구성 변경 등 포함
컴포넌트 구성 요소
API 서버 : 클러스터 주요 관리 인터페이스
스케줄러 : 새로 생성된 파드를 워커 노드에 할당
컨트롤러 매니저 : 다양한 컨트롤러를 실행하여 클러스터 상태를 원하는 상태로 유지.
노드가 실패하면 자동으로 대체 리소스를 스케줄링
클라우드 컨트롤러 매니저 : 클라우드 제공 업체의 API와 통신
etcd : 모든 클러스터 데이터를 저장하는 경량의 분산 키-값 스토어

워커 노드 (Worker Nodes)

실제로 애플리케이션 컨테이너를 실행하는 서버
컴포넌트 구성 요소
kubelet : 각 노드에서 실행되는 에이전트로, API 서버와 통신하며 파드의 실행을 관리
컨테이너 런타임 (docker, containerd 등) : 컨테이너를 실행하기 위한 환경을 제공
kube-proxy : 네트워크 프록시 및 로드 밸런서 역할을 하며 컨테이너의 네트워크 규칙을 관리

클러스터 네트워킹

쿠버네티스는 클러스터 내의 모든 컴포넌트 간 통신을 가능하게 하는 강력한 네트워킹 모델을 제공
모든 파드는 고유한 IP 주소를 가지며, 서로 통신할 수 있어야 함
네트워크 플러그인을 사용하여 복잡한 네트워킹 요구 상항을 충족 시킴

스토리지

쿠버네티스는 퍼시스턴트 볼륨(PV)과 퍼시스턴스 볼륨 클레임(PVC)을 통해 스토리지 관리
이를 통해 스토리지 리소스를 동적으로 프로비저닝(미리 준비)하고 파드에서 사용하게 함
결론
쿠버네티스는 PV와 PVC를 통해 애플리케이션과 스토리지를 분리하여 유연하고 효율적인 스토리지 관리를 가능하게 합니다.
사용자는 PVC를 통해 필요한 스토리지 자원을 요청하고, 쿠버네티스는 자동으로 적절한 PV를 찾아 바인딩하여 애플리케이션이 데이터를 안전하게 저장하고 사용할 수 있도록 지원합니다.

클러스터 보안

쿠버네티스는 RBAC(Role-Based Access Control, 역할 기반 접근 제어), 네트워크 폴리시, 시크릿 관리 등을 통해 클러스터 보안을 강화
RBAC : 사용자, 서비스 계정에 특정 역할을 부여하고, 해당 역할에 정의된 권한에 따라 쿠버네티스 리소스에 대한 접근을 제어하는 방식
네트워크 폴리시 : 파드 간의 네트워크 통신을 제어하는 규칙을 정의하는 방식. 특정 파드, 네임스페이스 간의 통신을 허용하거나 차단하여 무분별한 네트워크 접근 방지, 보안 강화
시크릿 관리 : 데이터베이스 비밀번호, API 키, 인증서 등 민감한 정보를 안전하게 저장하고 관리하는 방식. 암호화된 형태로 저장, 필요한 파드에만 제한적으로 접근 권한을 부여하여 정보 유출 방지
이를 통해 민감한 데이터를 보호, 클러스터 리소스에 대한 접근을 제어
쿠버네티스 클러스터 아키텍처는 컴포넌트 개념을 기반으로 복잡한 컨테이너화된 애플리케이션의 배포와 운영을 단순화

쿠버네티스 오브젝트

Pod
가장 작은 배포 단위
전체 클러스터에서 고유한 IP를 할당
여러개의 컨테이너가 하나의 Pod에 속할 수 있음
Pod 추가 설명
파드는 컨테이너로 이루어져 있으며, 컨테이너를 만들고 관리하는 도구가 도커
파드들은 워커노드 단위로 관리하며, 워커 노드와 마스터 노드가 모여 쿠버네티스 클러스터가 된다
파드들은 1개 이상의 컨테이너로 이루어져 있다.
파드들은 쿠버네티스로부터 IP를 받아 외부와 통신할 수 있는 경로를 제공 → NAT와 같음
컨테이너들은 커널, 네트워크나 저장 공간을 서로 공유함
컨테이너는 개별적인 실행 황경을 갖는데, CPU, 네트워크, 메모리와 같은 시스템 자원을 독자적으로 사용하도록 할당된 환경
ReplicaSet : 쿠버네티스의 안정적인 파드 복제 및 관리 도구
여러개의 Pod를 관리
Deployment : 배포 버전을 관리
내부적으로는 ReplicaSet을 사용
Workloads : 다양한 워크로드가 있음
Service-ClusterIP : 클러스터 내부에서 사용하는 프록시
Pod는 재생성 될 때 새로운 IP가 할당되지만 Service는 고유 IP를 가짐
클러스터 내부에서 서비스 연결은 DNS를 이용
Service-NordPort : 노드(host)에 노출되어 외부에서 접근 가능한 서비스
모든 노드에 동일한 포드로 생성
Service-LoadBalancer : 특정 노드가 죽거나 하는 경우에 서비스가 안되는 경우를 방지
하나의 IP주소를 외부에 노출
Ingress : 도메인 또는 경로별 라우팅; 쿠버네티스 클러스터 외부 트래픽을 내부 서비스로 연결
기타 기본 오브젝트
Volume -Storage (EBS, NFS, …)
Namespace
ConfigMap/Secret - 설정
ServcieAccount - 권한 계정
Role/ClusterRole - 권한 설정

KaKao Cloud Kubernetes

사용 목적 및 사례

사용자가 직접 쿠버네티스 클러스터를 배포할 경우 VM의 인스턴스를 준비하고, 마스터 노드와 워커 노드를 구성하고 지속적으로 마스터 노드를 관리해야 함
카카오 클라우드의 쿠버네티스 엔진은 이러한 번거로운 과정을 클릭 몇 번만으로 대신해 줌
사용자는 별도로 쿠버네티스 클러스터를 배포할 필요가 없으며, 수시로 변화하는 서비스 요구사항에 맞게 클러스터를 확장하고 삭제할 수 있음
마스터 노드는 별도의 영역에서 관리되어 사용자가 관리할 필요가 없고, 사용자는 자신의 VPC에 배포한 워커 노드와 애플리케이션에만 집중할 수 있음

간편한 클러스터 관리

쿠버네티스 클러스터를 효율적으로 관리하기 위한 최적화된 메뉴 구성, 기능과 노드 풀을 이용한 노드 그룹 관리 기능을 제공
VM 서비스와의 긴밀한 연계로 다양한 VM 플레이버(템플릿)을 지원하고 손쉬운 인스턴스 관리가 가능

Multi-AZ로 고가용성 지원

쿠버네티스 엔진의 클러스터와 노드를 Multi-AZ에서 실행하여 높은 수준의 가용성을 제공
Multi-AZ : 여러 가용영역에 복제본 배포
클러스터와 노드가 여러 AZ(가용 영역)에서 실행되며, 특정 AZ에 문제가 발생해도 다른 AZ에서 정상적으로 실해되어 서비스 중단 없는 고가용성을 제공

다양한 서비스팩 연동

카카오클라우드의 다른 Container Pack 서비스인 Container Resgistry와 함께 연동하여 사용
카카오클라우드 Container Registry 서비스는 클라우드 환경에서 도커의 컨테이너 이미지를 클라우드에 안전하게 보관하고 관리할 수 있는 비공개 이미지 저장소
내 클러스터에 Helm Chart와 컨테이너 이미지를 간단하게 배포
Helm Chart : 쿠버네티스 애플리케이션 패키지 관리 도구
애플리케이션 패키징, 의존성 관리, 템플릿 기능, 공유 및 재사용 기능 지원

안전한 서비스 환경

사용자의 VPC 환경에 노드를 배포하는 방식으로 논리적으로 분리된 사용자 네트워크에서 안전하게 클러스터 운영

문제 발생시 Grafana Alert 보내는 방법

1. 기술 블로그 내용 1회 정독 2. Container 기술 및 Docker container 사용법 익히기 (기술블로그 Docker vs. Kubernetes 참조) 3. Grafana+Prometheus에 대한 개념 익히기 4. Grafana에서 Alert 추가하기 (grafana.slowplat.com) (id: slowadmin, p/w: slowgrafana@4411) - 각 서버 서비스 포트 모니터링 및 서비스 포트에 이상이 있을때 Alert 보내기 (mailto: tony.cho@slowplat.com, leo.heo@slowplat.com)
YAML
복사
grafana alert 소개
alert 동작 방식
알림 패널을 하나 만들고 알림을 보내고 싶은 쿼리를 작성
패널 타입은 꼭 타임 시리즈로 설정 (그라파나에서 타임 시리즈와 그래프 타입의 패널에서만 알림을 지원하기 때문)
alert의 룰과 컨디션을 작성하는데, 룰을 알아야 알림이 동작하는 방식을 이해 가능
OK 상태
PENDING 상태
ALERTING 상태
Rule
Evaluate Every : ‘몇 분에 한번씩 평가한다’ 기본 5분
Evaluate For : ‘몇 분 동안 지켜본다’ 기본 1분
Conditions
알림 평가 조건 (임계치) : 쿼리에서 설정한 매트릭의 어떨 때 알림을 보내라를 설정
No data and error handling : 예외 상황에 대한 처리방식

개발 방법론

소프트웨어 개발의 생명주기

프로토타입 단계
소프트웨어 개발 과정에서 초기 아이디어를 구체화
사용자와의 상호작용을 통해 피드백을 수집하는 단계
개발 과정에서의 방향성을 설정하고 잠재적인 문제 사전 파악
개발 단계
기술 스택의 선택, 아키텍처 설계, 개발 팀의 구성과 협업 방식이 중요
코드의 품질 관리, 지속적인 통합(CI) 및 지속적인 배포(CD) 적용을 통해,
개발과정의 효율정을 톺이고, 버그를 조기에 발견하여 대응
프로덕션 단계
개발이 완료되고 제품이 사용자에게 공개되는 프로덕션 단계는 개발의 마지막 단계
제품의 배포, 모니터링, 유지보수가 중요한 활동으로 이루어짐
제품의 성공적인 배포를 위해서는 배포 전략의 스립, 롤백 계획의 준비, 사용자 피드백 수집 및 대응 계획이 필요
실시간 모니터링 도구를 활용하여 시스템의 상태를 지속적으로 관찰하고, 성능 저하나 오류를 조기에 발견하여 대응하는 것이 중요
사용자 피드백과 시장에 변화에 민첩하게 대응하기 위해 제품의 지속적인 개선과 업데이트가 필요
제품 초기 출시뿐만 아니라 장기적인 관점에서의 제품 관리와 개선이 중요

CI/CD란

CI
CD
Continuous Delivery (지속적인 서비스 제공)
공유 레포지토리로 자동으로 Release 하는 것
Release : 배포 가능한 소프트웨어 패키지를 작성
Continuous Deployment (지속적인 배포)
프로덕션 레벨까지 자동으로 Deploy 하는 것을 의미
즉, 개발자의 변경사항이 레포지토리를 넘어 고객의 프로덕션 환경까지 고려
Deploy : 프로비저닝을 실행하고 서비스를 사용자에게 노출 → 실질적인 배포
지속적인 서비스 제공(Continuous Delivery) 및 지속적인 배포(Continuous Deployment)를 의미하며 이 두 용어는 상호 교환적으로 사용된다.
이 부분은 Release - Deploy - Operate 단계에서 꾀할 수 있다.
Release : 배포 가능한 소프트웨어 패키지를 작성.
Deploy : 프로비저닝을 실행하고 서비스를 사용자에게 노출 => 실질적인 배포
Operate : 서비스 현황을 파악하고 생길 수 있는 문제를 감지
지속적 배포의 경우, 코드 변경 사항의 병합부터 프로덕션에 적합한 빌드 제공에 이르는 모든 단계로, 테스트 자동화와 코드 배포 자동화가 포함된다
이 프로세스를 완료하면 프로덕션 준비가 완료된 빌드를 코드 리포지토리에 자동으로 배포할 수 있기 때문에 운영팀이 보다 빠르고 손쉽게 애플리케이션을 프로덕션으로 배포할 수 있게 된다.
최근에는 클라우드 기술 발전과 맞물려 지속적 통합과 지속적 배포가 빠른 속도로 진행되면서 CI/CD를 하나로 묶어서 다루는 경우가 점차 증가하고 있다. 예를 들어, 이전에는 배포 자체가 상당히 오래 걸리고 서버를 전부 재시작해야 한다거나, 일부 기능을 제공하지 못하는 경우도 많았기 때문에 배포 이전 단계에서 많은 고민을 하곤 했다. 요즘은 고객의 피드백을 빨리 받기 위해서라도, 서비스를 중단하지 않기 위해서라도 릴리즈만 잘 기록해두고 바로바로 배포하는 사례가 증가하고 있다.

LDAP 계정 인증, 추가 해야 될 것들

아지트 : CPO실에서 필요한 피드 초대 받기
레드마인 : 접근 권한 설정
타이가 : 로그인 안됨
슬로우 위키 : 접근 권한 설정 (slowtalk project만 들어가짐)
깃랩 : 로그인은 되나, 아무것도 없음
젠킨스 : 이상 없음
비트워든 : 접근 권한 설정
포테이너 : 로그인은 되나, 아무것도 없음
npm : 로그인 안됨
피그마 : 구글로그인 초대 받기

CPO 온보딩 요청

온보딩 ppt 자료

Git : 브랜치 생성 후 해당 브랜치로 이동, 리모트 기능

git switch -c jenkins_pipline_test --track origin/develop git switch -c jenkins_pipeline --track origin/develop git switch -c deploy-test --track origin/develop # 로컬에서 브랜치 삭제하기 명령어 git branch -d localBranchName(로컬의 브랜치 이름) # 원격에서 브랜치 삭제하기 명령어 git push origin --delete remoteBranchName(원격 브랜치 이름)
Bash
복사

암복호화

git submodule init git submodule update cd env && ./file_crypto.sh dec && cd - && cd android/app/signing && ./file_crypto.sh dec && cd -
Bash
복사

빌드

flutter build apk --release --target-platform=android-arm64
Bash
복사

Flutter 설치

# GitLab 토큰 : tok glpat-c_5G2BVyz2wKS5ZcBvHE
Bash
복사
# 빌드 명령어 flutter build appbundle --obfuscate --split-debug-info=./build/debug_info
Bash
복사

해야할 일

1. docker 명령어 숙지. 2. 서버 인스턴스에 접근하여 컨테이너 내부에 있는 파일을 외부로 복사하거나 반대로 외부의 내용을 내부로 복사할 수 있어야 함. 3. do
Bash
복사
새로운 과제 하나 드립니다.
## API, CHAT, PUSH 서버를 하나의 VM으로 통합
체크리스트
Jenkins pipeline 수정
서버 config 및 배포 스크립트 수정
DNS 설정 검토 및 수정
Reverse Proxy 수정
관련 수정사항 정리 및 업무관계자에게 알림
일단 전체적인 과제 내용을 파악 후 플랜을 세워서 1차 보고 해주세요.
1차 보고 검토 후 진행을 하고 최종 보고
베포관련 설정 - configs/config 3개 파일
config-Dev : 개발
config-Real : 운용
config : 로컬
배포용 스크립트 - scripts/deploy-DEV
deploy-DEV만 확인
# docker port # api CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 149105e3901d slowtalk.kr-central-2.kcr.dev/slowtalk/api-dev:latest "supervisord -c /etc…" 4 hours ago Up 4 hours 9000/tcp, 0.0.0.0:39000->8000/tcp, :::39000->8000/tcp api-dev-container 27ac0c4ba7c3 gcr.io/cadvisor/cadvisor:latest "/usr/bin/cadvisor -…" 7 weeks ago Up 10 days (healthy) 0.0.0.0:8090->8080/tcp, :::8090->8080/tcp cadvisor 840af957a918 prom/node-exporter:latest "/bin/node_exporter …" 7 weeks ago Up 10 days 0.0.0.0:9100->9100/tcp, :::9100->9100/tcp node-exporter # chat CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b27853befb24 gcr.io/cadvisor/cadvisor:latest "/usr/bin/cadvisor -…" 7 weeks ago Up 10 days (healthy) 0.0.0.0:8090->8080/tcp, :::8090->8080/tcp cadvisor 46a5c4f485c6 prom/node-exporter:latest "/bin/node_exporter …" 7 weeks ago Up 10 days 0.0.0.0:9100->9100/tcp, :::9100->9100/tcp node-exporter # push CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 91221486fc1d slowtalk.kr-central-2.kcr.dev/slowtalk/push-dev:latest "supervisord -c /etc…" 5 hours ago Up 5 hours 9000/tcp, 0.0.0.0:9000->8020/tcp, :::9000->8020/tcp push-dev-container d9760242f0db gcr.io/cadvisor/cadvisor:latest "/usr/bin/cadvisor -…" 7 weeks ago Up 10 days (healthy) 0.0.0.0:8090->8080/tcp, :::8090->8080/tcp cadvisor a5a86a41ee4e prom/node-exporter:latest "/bin/node_exporter …" 7 weeks ago Up 10 days 0.0.0.0:9100->9100/tcp, :::9100->9100/tcp node-exporter
Bash
복사
API 서버 (api-dev-container) 9000/tcp: 컨테이너 내부에서 애플리케이션이 실제로 수신 대기하는 포트입니다. 외부에서 직접 접근할 수 없습니다. 0.0.0.0:39000->8000/tcp: 호스트 시스템의 39000번 포트로 들어오는 요청을 컨테이너 내부의 8000번 포트로 연결합니다. 즉, 외부에서 http://호스트_IP:39000으로 접속하면 API 서버에 접근할 수 있습니다. :::39000->8000/tcp: IPv6 주소를 사용하는 경우에도 위와 동일하게 호스트 시스템의 39000번 포트로 들어오는 요청을 컨테이너 내부의 8000번 포트로 연결합니다. CHAT 서버 CHAT 서버 컨테이너는 현재 docker ps 명령 결과에 나타나지 않습니다. 따라서 포트 정보를 확인할 수 없습니다. CHAT 서버가 실행 중인지, 그리고 포트 매핑이 제대로 설정되었는지 확인해야 합니다. PUSH 서버 (push-dev-container) 9000/tcp: 컨테이너 내부에서 애플리케이션이 실제로 수신 대기하는 포트입니다. 외부에서 직접 접근할 수 없습니다. 0.0.0.0:9000->8020/tcp: 호스트 시스템의 9000번 포트로 들어오는 요청을 컨테이너 내부의 8020번 포트로 연결합니다. 즉, 외부에서 http://호스트_IP:9000으로 접속하면 PUSH 서버에 접근할 수 있습니다. :::9000->8020/tcp: IPv6 주소를 사용하는 경우에도 위와 동일하게 호스트 시스템의 9000번 포트로 들어오는 요청을 컨테이너 내부의 8020번 포트로 연결합니다. 모니터링 도구 (cadvisor, node-exporter) cadvisor: 0.0.0.0:8090->8080/tcp: 호스트 시스템의 8090번 포트로 들어오는 요청을 컨테이너 내부의 8080번 포트로 연결합니다. cAdvisor 웹 인터페이스에 접근할 수 있습니다. :::8090->8080/tcp: IPv6 주소를 사용하는 경우에도 위와 동일하게 호스트 시스템의 8090번 포트로 들어오는 요청을 컨테이너 내부의 8080번 포트로 연결합니다. node-exporter: 0.0.0.0:9100->9100/tcp: 호스트 시스템의 9100번 포트로 들어오는 요청을 컨테이너 내부의 9100번 포트로 연결합니다. Prometheus가 node-exporter에서 시스템 메트릭을 수집할 수 있도록 합니다. :::9100->9100/tcp: IPv6 주소를 사용하는 경우에도 위와 동일하게 호스트 시스템의 9100번 포트로 들어오는 요청을 컨테이너 내부의 9100번 포트로 연결합니다. 주의 사항: 호스트 시스템의 방화벽 설정에 따라 외부에서 컨테이너 포트에 접근하지 못할 수 있습니다. 방화벽 설정을 확인하고 필요한 포트를 열어주어야 합니다. PUSH 서버와 API 서버 모두 호스트 시스템의 9000번 포트를 사용하고 있습니다. 이는 포트 충돌을 일으킬 수 있으므로, PUSH 서버의 포트 매핑을 변경하거나 Reverse Proxy를 사용하여 트래픽을 적절히 라우팅해야 합니다. 다음 단계: CHAT 서버 컨테이너의 포트 정보를 확인하고 필요 시 포트 매핑을 설정합니다. PUSH 서버의 포트 충돌 문제를 해결합니다. Reverse Proxy 설정 시 각 서버에 대한 적절한 포트 번호를 지정합니다. . api, chat, push 매핑 되어 있는 ip 정보 - api "MONGODB_LOGGER": { "HOST": "10.0.2.254", "PORT": 27017, DATABASE_SLOWTALK": { "HOST": "10.0.3.79", "PORT": 5000, "READ_PORT": 5000, "PUSH_KAFKA": { "bootstrap_servers": ["10.0.35.25:9092", "10.0.33.244:9092", "10.0.33.243:9092"] "SMS_KAFKA": { "bootstrap_servers": ["10.0.35.25:9092", "10.0.33.244:9092", "10.0.33.243:9092"] , "topic" : "SMSServer" - api 로컬 "MONGODB_LOGGER": { "HOST": "210.109.55.105", "PORT": 27017, "DATABASE_SLOWTALK": { "HOST": "210.109.55.245", "PORT": 5000, "READ_PORT": 5000, PUSH_KAFKA": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] "SMS_KAFKA": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] - chat "MONGODB_CHATBOT": { "HOST": "10.0.2.254", "PORT": 27017, "DATABASE": "ChatBot", "MONGODB_CHATTING": { "HOST": "10.0.2.254", "PORT": 27017, "DATABASE": "ChatServer", "COLLECTION": "Chatting", "DATABASE_SLOWTALK": { "HOST": "10.0.3.79", "PORT": 5000, CHATTING_PUBSUB": { "bootstrap_servers": ["10.0.35.25:9092", "10.0.33.244:9092", "10.0.33.243:9092"] "CHATTING_PUSH_PUBSUB": { "bootstrap_servers": ["10.0.35.25:9092", "10.0.33.244:9092", "10.0.33.243:9092"] - chat 로컬 "MONGODB_CHATBOT": { "HOST": "210.109.55.105", "PORT": 27017, "DATABASE": "ChatBot", "MONGODB_CHATTING": { "HOST": "210.109.55.105", "PORT": 27017, "DATABASE": "ChatServer", "DATABASE_SLOWTALK": { "HOST": "210.109.55.245", "PORT": 5000, "CHATTING_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] "CHATTING_PUSH_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] - push "MONGODB_PUSH": { "HOST": "210.109.55.105", "PORT": 27017, "DATABASE_SLOWTALK": { "HOST": "210.109.55.245", "PORT": 5000, PUSH_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] , "topic" : "PushServer" "CHATTING_PUSH_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] "SMS_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] - push 로컬 "MONGODB_PUSH": { "HOST": "210.109.55.105", "PORT": 27017, "DATABASE_SLOWTALK": { "HOST": "210.109.55.245", "PORT": 5000, "PUSH_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] "CHATTING_PUSH_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] , "topic" : "ChattingPushServer" "SMS_PUBSUB": { "bootstrap_servers": ["210.109.55.175:9094", "210.109.54.17:9094", "210.109.55.220:9094"] # 궁금한 거 1. chat 서버와 kafka 서버는 모니터링 도구만 docker로 사용하는데 서비스를 docker에 올리지 않는 것인가요? 서버가 죽어있었슴 2. 그렇다면 chat 서버와 kafka는 어디서 구동되고 있는 것인가요? 네이티브 컨트롤러(클러스터, 통신), 브로커(서버) - 카프카 공부 진행 3. 통합 서버를 운용할 경우 컨테이너로 나누게 될텐데 config 설정 파일은 어떻게 구분시키나요? 빌드 크리거, 소스코드 클론, 개발, prod config 파일 - 도커이미지 - 컨테이너레지스트리 - 4. Reverse Proxy 설정하기 위해서 nginx 경로로 들어가서 설정 파일을 여는 걸로 알고 있는데, nignx 디렉터리가 존재하지 않습니다. 설정 파일 경로는 어디인가요? npm 기존거 확인 5. 인스턴스에 접속한 후, 루트 계정의 암호는 어떻게 설정이 되어있나요?
Bash
복사
# api, chat, push 서버 통합 상세 계획 1. 카카오 클라우드 인스턴스 생성 - 인스턴스 스팩 - 이름 : dev-api-chat-push - 유형 : t1i.medium - 운영체제 : rocky linux 9 - vCPU : 2 - 메모리 : 4GB - 스토리지 : 30GB - 키페어 : slowtalk.pub (pem으로 pub 생성 : ssh-keygen -f my_key.pem -y) - 네트워크 : 퍼블릭 IP 할당, 보안 그룹 설정(com-bastion-target-sg, com-monitoring-target-sg), 추가적인 서비스 포트 보안 그룹 설정, 포트 번호 변경이 있으니 보안 그룹도 설정 - api 포트 : 19000 - chat 포트 : 29000 2. 도커 컨테이너 생성 및 네트워크 설정 - 컨테이너 생성 - vm 인스턴스 생성 - vm 초기화 스크립트(위키) 첨부파일 확인, vm 스크립트를 사용하여 도커 컨테이너 생성 (포함 되어 있음) - Dockerfile 작성된거 이용 (api, chat, push 컨테이너) - 컨테이너 생성 및 빌드 - 젠킨스 - 컨테이너 포트 설정 (api-39000,8090,9100 / chat-9000,8090,9100 / push-9000,8090,9100) 매핑 어디서 설정하는지 찾기, 외부 호스트 포트 곂치지 않아야함. - 카카오 클라우드 보안 그룹 설정 변경 - docker port 인바운드 규칙 추가 - 디테일하게 확인 각각에 어떤 식으로 커넥션이 이루어지는지 파악 api chat - 클라이언트 인바운드를 어떤식으로 열어야 하는가 클라이언트는 api - push는 다름 # 수정된 포트 API 서버: 컨테이너 내부 포트: 8000 호스트 시스템 포트: 39000 CHAT 서버: 컨테이너 내부 포트: 8010 호스트 시스템 포트: 39001 PUSH 서버: 컨테이너 내부 포트: 8020 호스트 시스템 포트: 9000 정상적인 동작이 되는지 확인 후 젠킨스 파이프라인 진행 - vm 인스턴스에서 push 한 코드를 git clone 후 docker 빌드 한 후 이미지 생성 - deploy 해보면서 확인 - 컨테이너 레지스트리 - 단계를 나눠서 작업하기 - 기존 설정되어 있는 config를 열어서 확인 (ip주소만 다를 거임) - docker build - 도커 이미지를 생성하는 과정 - 컨테이너와 이미지에 대한 차이 검색 - 컨테이너 : 동적 ex) 애플리케이션 - 이미지 : 정적, ex)애플리케이션 실행 파일 # NCP Container Registry의 레지스트리 이미지 이름 / 로컬에 있는 이미지 이름으로 변경 후 실행해야함!! DOCKER_IMAGE_NAME="slowtalk.kr-central-2.kcr.dev/slowtalk/${APP_NAME}:latest" # 로컬 도커 이미지 경로 /var/lib/docker/image/overlay2/imagedb/content/sha256/ 컨테이너 충돌있는지 확인 후 npm 1. config 수정 업로드 2. 서버에서 도커 재빌드 - git clone -b deploy-test ssh... - dockerfile이 존재한는 디렉터리에서 - docker build -t [이미지] . - bash deploy-DEV.sh 3. 젠킨스 파일 수정 - parmeters - deployserverIPs 수정 # 젠킨스 돌리면 자동 카피 됨 // sh '''cp configs/config-Dev.json configs/config.json''' - 파이프라인 스크립트에서 환경 변수 설정 - 파이프라인에서 변수 (파라미터, 글로벌 env, 로컬 env) - 인헤도 될거같음 # 커밋 덮어씌우기 git commit --amend -m "새로운 커밋 메시지" git push origin HEAD -- force git commit -m "chore: Jenkins Global Env 설정" # api 스웨거 로그인 slowplat test API 서버: - apitest.slowplat.com - 스웨거 화면이 뜨는지 확인 - config.json 수정 - config-Dev와 config.json 일치 - Jenkinsfile 수정 - parmeters - deployserverIPs 서버ip 수정 CHAT 서버: - wstest.slowplat.com - config.json 수정 (config-Dev와 config.json 일치) - /templates/chatbot.html - refresh_token 수정 (3분마다 제한됨) - aes_encrypt.py - python /Users/tony.cho/Development/AES_ENC/aes_encrypt.py "slowplat | test" | tr -d '₩n' | pbcopy - soket url 수정 - 'wss://wstest.slowplat.com/chatbot' - Jenkinsfile 수정 - parmeters - deployserverIPs 서버ip 수정 PUSH 서버: - config.json 수정 (config-Dev와 config.json 일치) - 서버 스타트에 대해서 로그 확인 - kafbat 확인 - deploy-DEV 변경 - Jenkinsfile 수정 - parmeters - deployserverIPs 서버ip 수정 - 로드벨런서 9001 포트에 연결 로그 확인, 서버 스타트에 대해서 - push 문제 없이진행 되면 젠킨스 파일 수정!! + DeployDev_Jenkinsfile을 DeployProd_Jenkinsfile 처리 방식으로 수정 - Dev는 Jenkins 파일의 parameter로 처리 -> Prod는 PROD_CHAT_SRV_IPS와 같이 Jenkins Global Env로 설정되도록 수정. - Dev는 Jenkins 파일의 parameter로 처리하고 있고 Prod는 PROD_CHAT_SRV_IPS와 같이 Jenkins Global Env로 설정이 되도록 되어 있습니다. - 관리측면에서 더 좋은 방식이니 수정 필요 + 추가로 젠킨스 알면 좋은 거 - 음 jenkinsfile이니까 서버에는 로그가 기록되지 않고, jenkins에 등록이 되는구나 맞아? 그리고 jenkins agent 인스턴스에 접속하면 해당 로그를 볼 수 있나? 답안 표시 네, 맞습니다. Jenkinsfile에서 실행되는 sh 명령어의 출력 결과는 Jenkins 에이전트 인스턴스에 기록되지 않고, Jenkins 서버의 빌드 로그에 저장됩니다. 따라서, 헬스 체크 결과를 포함한 모든 로그들은 Jenkins 웹 인터페이스의 빌드 콘솔 출력에서 확인할 수 있습니다. Jenkins 에이전트 인스턴스에 직접 접속하여 로그를 확인하는 것은 일반적으로 권장되지 않습니다. Jenkins 에이전트는 빌드 작업을 실행하는 환경을 제공하는 역할을 하며, 로그 저장 및 관리 기능은 Jenkins 서버에서 담당합니다. 따라서, 헬스 체크 로그를 확인하려면 Jenkins 웹 인터페이스에서 해당 빌드의 콘솔 출력을 확인하는 것이 가장 안전하고 효율적인 방법입니다. 플랜보다 시간이 많이 걸린 이유 파악 - 다음에 할때는 이것보다 몇배는 빨라져야된다. - 환경에 익숙, 없는거 만들라는게 아니잖아. 근데 다음에는 없는 기능을 만들어야해, 고로 기본기를 잘 알아야 한다. - 새로운 기술을 잘 모르는 건 당연하지만, 단기간에 습득하는 사람이 있듯이, 기본기가 반역이 되어서 업무가 진행되니, 관련 기술이나 테크닉에 대해서는 학습이 필요하다. - 스터디를 하면서 꼼꼼히 메모하는 것이 중요 - 실패했을 땐 어디가 실패했는지, 성공했을 땐 어떻게 했는지 매뉴얼 작성이 필요 3. Reverse Proxy 설정 - nginx 설치 , npm 서버에서 설정 - nginx 설정 파일에서 ip 주소 및 컨테이너 포트정보를 수정하여 트래픽 라우팅 규칙 설정 - 정상적으로 작동하는지 테스트 4. jenkins pipeline 수정 - 도커 이미지 빌드 경로 수정 (ex. dev-api -> dev-api-chat-push) 할 필요 x - Jenkinsfile 확인 - 파이프라인 스크립트에서 환경 변수 설정 - 파이프라인에서 변수 (파라미터, 글로벌 env, 로컬 env) - 수정된 파이프라인을 이용하여 빌드 및 테스트 진행 - scripts/deploy-DEV.sh 수정 (api, chat, push 함께 배포) - 뭘 수정해야 되는 지 파악, config 수정이 되어야되는지 파악 - configs/config-DEV.json 수정 (mongoDB, postgresql, redis, kafka 연결 정보 / 포트 번호) 5. 매뉴얼 작성 - 중요한 정보만 - 인스턴스 생성 정보 - 컨테이너 생성 및 실행 방법 - Jenkins Pipeline 수정 내용 - DNS 설정 변경 내용 - Reverse Proxy 설정 내용 - 기타 관련 정보 및 주의 사항
Bash
복사
config - 로컬이긴한데 서버에 올렸을 때 dev, real 코드중 하나와 동일해야함
# 터널링으로 인스턴스 접속하기 # bastion host에 접속 ssh -i ~/.ssh/slowtalk.pem rocky@210.109.54.69 # dockerfile 디렉토리에서 도커 빌드 docker build -t api-dev . docker build -t chat-dev . docker build -t push-dev . # 도커 이미지 확인 # 파일 권한 부여 sudo chown rocky:rocky docker # 스크립트 수정 # 로컬 이미지 경로 : /var/lib/docker/image/overlay2/imagedb/content/sha256/[컨테이너ID] # 로컬 테스트용 스크립트 경로 추가 LOCAL_IMAGE_ID="sha256:c1291292d9a785f34adbf7d38dfb541710443082ff96d2ece891f03492ed2a21" # docker test 실행 docker run --restart always -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Seoul -p ${DOCKER_PORT}:${LOCAL_PORT} --name ${APP_NAME}-container -d ${LOCAL_IMAGE_ID} # 컨테이너 실행 docker run -d -p 8080:80 my-image # 접속 포트 설정 ssh -i ~/.ssh/slowtalk.pem -L <로컬 포트>:<대상 서버 IP>:<대상 서버 포트> rocky@<Bastion Host IP> ssh -i ~/.ssh/slowtalk.pem -L 6379:10.0.0.238:6379 rocky@<Bastion Host IP> ssh -i ~/.ssh/slowtalk.pem -L 6379:10.0.0.238:6379 210.109.54.69 -p 10063 ssh -i ~/.ssh/slowtalk.pem 210.109.54.69 -p 10063 ssh -i ~/.ssh/slowtalk.pem -L 22:10.0.0.122:22 210.109.54.69 -p 10061 ssh -i ~/.ssh/slowtalk.pem rocky@210.109.54.69 -p 10098
Bash
복사
# real-api 배포용 스크립트 APP_NAME="push-dev" # NCP Container Registry의 레지스트리 이미지 이름 # DOCKER_IMAGE_NAME="slowtalk.kr-central-2.kcr.dev/slowtalk/${APP_NAME}:latest" # 로컬 테스트용 LOCAL_IMAGE_ID="sha256:f046496c4f96e98afa679d67cb312be2276065a5a1d92f23a9a372005d0912a9" # 배포서버 /etc/nginx/conf.br/kbo-fast-api.conf 참고 LOCAL_PORT=8020 DOCKER_PORT=9000 echo "${APP_NAME} Docker start" # 기존에 실행중인 도커 중지, 삭제 if [ $( docker ps -a | grep ${APP_NAME}-container | wc -l ) -gt 0 ]; then sudo docker ps -a -q --filter "name=${APP_NAME}-container" | grep -q . && docker stop ${APP_NAME}-container && docker rm ${APP_NAME}-container | true echo "${APP_NAME} down" fi # 이미지 pull docker pull ${DOCKER_IMAGE_NAME} echo "${APP_NAME} Docker run" # docker 실행 # docker run --restart always -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Seoul -p ${DOCKER_PORT}:${LOCAL_PORT} --name ${APP_NAME}-container -d ${DOCKER_IMAGE_NAME} # docker test 실행 docker run --restart always -v /etc/localtime:/etc/localtime:ro -e TZ=Asia/Seoul -p ${DOCKER_PORT}:${LOCAL_PORT} --name ${APP_NAME}-container -d ${LOCAL_IMAGE_ID} # 안쓰는 더미 도커 이미지 삭제 docker images | grep "<none>" | awk '{print $3}' | xargs -r docker rmi
Bash
복사
monitoring 인스턴스에 접속하여 ssh -i ~/.ssh/slowtalk.pem -L 22:10.0.0.122:22 210.109.54.69 -p 10061 → 잘못된 명령어
명령어를 통해 터널링 포트설정을 진행하려는데 Connection refused가 나옵니다 어떻게 설정할 수 있을까요?
터널링 설명
두가지
npm
Streams에 터널링
10000~10100까지 설정
스트림 추가
ip 포트 10098 22 할당
Streams
명령어를 통해 터널링
81 : npm
10000 - 10100 터널링 포워딩을 위한 포트
3가지 포트
npm, https, 포트포워딩 포트
보안그룹 설정
인바인드 룰만 건들이면 됨
pet 로컬 config pet edit
리눅스에서 화살표 방향키를 사용하지 않고 history를 검색하는 방법은 다음과 같습니다: 1. Ctrl+R: Ctrl+R을 누르면 'reverse-i-search' 모드가 시작됩니다. 찾고 싶은 명령어의 일부를 입력하면, 입력한 문자열과 일치하는 가장 최근 명령어가 표시됩니다. 계속해서 Ctrl+R을 누르면, 이전에 실행했던 명령어 중 일치하는 명령어들을 차례로 볼 수 있습니다. Ctrl+G를 누르면 검색을 종료하고 일반 모드로 돌아갑니다. Enter 키를 누르면 선택된 명령어가 실행됩니다.
Bash
복사
터널링을 통해서 ssh에 접속하려고 하는 상황입니다. bastion host가 monitoring 인스턴스로 설정되어 있는 것을 확인했고 접속하였는데, pem키를 통해서 dev-api-chat-push 서버네 ㅇ
메모 언제까지 하겠다라는 계획 - 시간을 설정하고 노력하기
도메인 파트림
공인 ip 알려줘라.
1. 인스턴스 생성 및 보안 그룹 설정 : 1시간 2. vm 생성 스크립트로 컨테이너 생성 : 1시간 3. jenkins pipeline 수정 : 2시간 4. Reverse Proxy 설정 : 1시간 5. 매뉴얼 작성 : 1시간 총 6시간 소요 예정입니다. 앱태스트까지 진행을 고려해서 명일 오후 중(3시 이전)까지 완료해보겠습니다.
Bash
복사
# api 서버 Dev private ip : 10.0.1.127 Dev public ip : 210.109.54.95
Bash
복사
# api 서버 config-Dev
Bash
복사
앱테스트 지원
관련 설치 리포트 - 션이 도와줌
테스트 - 버그 - 리포트
1. api, chat, push 서버를 하나의 vm으로 통합하기 위해 카카오 클라우드 인스턴스를 생성한다. - vm 인스턴스 스팩 - t1.small - 운영체제 : rocky9 - vCPU : 2 - 메모리 : 3 - 스토리지 : 50 - 네트워크 : 2. 하나의 vm에 api, chat, push 컨테이너를 생성하여 관리한다. - api, chat, push 컨테이너 생성후 네트워크 설정 3. Jenkins pipeline을 수정하여 각 컨테이너에서 빌드될 수 있게 한다. 4. DNS 설정을 검토 후 수정이 필요한 경우를 파악한다. 5. Reverse Proxy를 포트번호에 맞게 설정한다. 6. 관련 수정사항 정리하여 매뉴얼을 작성한다. - 생성하기 위해서 인스턴스 사양을 설정할때 램은 3기가로 설정할거야. 다른건 어떻게 설정할지 정해줘.
Bash
복사
API, CHAT, PUSH 서버 통합 프로젝트 상세 계획 1. 카카오 클라우드 인스턴스 생성 인스턴스 스펙: 이름: 통합서버 (혹은 적절한 이름으로 지정) 유형: t1.small 운영체제: Rocky Linux 9 vCPU: 2 메모리: 3GB 스토리지: 50GB (SSD) 네트워크: 퍼블릭 IP 할당, 보안 그룹 설정 (추후 상세 설정) 생성 절차: 카카오 클라우드 콘솔 접속 인스턴스 생성 페이지 이동 위 스펙대로 설정 후 인스턴스 생성 인스턴스 생성 완료 후 퍼블릭 IP 확인 2. 도커 컨테이너 생성 및 네트워크 설정 컨테이너 생성: 통합서버에 SSH 접속 Docker 설치 (설치되어 있지 않은 경우) API, CHAT, PUSH 서버 각각에 대한 Dockerfile 작성 혹은 기존 이미지 활용 Dockerfile을 이용하여 이미지 빌드 이미지를 기반으로 컨테이너 생성 및 실행 네트워크 설정: 각 컨테이너에 필요한 포트를 호스트에 노출 (예: API - 80, CHAT - 3000, PUSH - 8080) 카카오 클라우드 보안 그룹 설정 변경: 컨테이너에 노출된 포트에 대한 인바운드 규칙 추가 방화벽 설정 확인 및 필요 시 수정 3. Jenkins Pipeline 수정 기존 Pipeline 분석: 현재 API, CHAT, PUSH 서버 각각에 대한 빌드 및 배포 과정 파악 수정 방향: 각 컨테이너 이미지 빌드 빌드된 이미지를 통합서버에 배포 통합서버에서 컨테이너 실행 필요 시 롤백 기능 추가 테스트: 수정된 Pipeline을 이용하여 빌드 및 배포 테스트 수행, 문제 발생 시 수정 4. DNS 설정 검토 및 수정 현재 DNS 설정 확인: API, CHAT, PUSH 서버 각각에 대한 도메인 및 IP 정보 확인 수정 필요 여부 판단: 통합 후에도 기존 도메인을 유지할 경우: Reverse Proxy 설정을 통해 트래픽 라우팅 새로운 도메인으로 변경할 경우: DNS 레코드 수정 필요 DNS 레코드 수정 (필요한 경우): 도메인 등록 업체 콘솔 접속 A 레코드 혹은 CNAME 레코드 수정 변경 사항 적용 확인 (전파 시간 소요될 수 있음) 5. Reverse Proxy 설정 Reverse Proxy 도구 선택: Nginx, HAProxy 등 적절한 도구 선택 및 통합서버에 설치 설정 파일 수정: 도메인 및 컨테이너 포트 정보를 기반으로 트래픽 라우팅 규칙 설정 SSL/TLS 설정 (HTTPS 사용 시) 테스트: 설정 적용 후 각 서비스 정상 접속 확인 6. 매뉴얼 작성 수정 사항 정리: 인스턴스 생성 정보 컨테이너 생성 및 실행 방법 Jenkins Pipeline 수정 내용 DNS 설정 변경 내용 Reverse Proxy 설정 내용 기타 관련 정보 및 주의 사항 매뉴얼 작성: 위 정보를 바탕으로 유지보수 담당자가 참고할 수 있는 매뉴얼 작성 추가 고려 사항 데이터 백업 및 마이그레이션: 통합 과정에서 데이터 손실 방지를 위해 백업 및 마이그레이션 계획 수립 모니터링 및 로깅: 컨테이너 및 시스템 자원 모니터링, 로그 관리 시스템 구축 성능 테스트 및 최적화: 부하 테스트를 통한 성능 병목 구간 파악 및 최적화 보안: 시스템 및 컨테이너 보안 설정 강화, 취약점 점검
Bash
복사

8월 마지막 주 과제

# 이번 주 안에 # 전반적인 회사 시스템 구성 파악 DB 서버 구성 확인 - 로드밸런서(haproxy) 패일오버 기능 - port 5000 : 마스터 - port 5001 : 스밴바이 - 해당 포드로의 접속 방법 - - 기본적인 구성 - postgresql cluster (오토 페일오버) - pgbouncer - patroni 수동 패일오버 방법 - 1. 러프하게 기록 - 2. 매뉴얼로 상세하게 기록 # 시스템 장애발생 시 어떻게 복구할 것인지 서버 부하, 장애 발생시 자동 스케일 아웃 되도록 설정 되어있음. - 만약 자동적으로 스케일 아웃이 되지않는 경우, 수동으로 어떻게 처리할 수 있는가? - postgresql, mongoDB, redis 각각 어떻게 처리 할 수 있는지 알아보기. # GitHub: postgresql cluster https://github.com/vitabaks/postgresql_cluster?tab=readme-ov-file # Patroni + etcd + HAproxy를 이용한 HA 구성 https://bstar36.tistory.com/m/411 # 연결풀링 https://xshine.tistory.com/167 DB 서버 동작 확인 - Postgres Cluster Master, Standby 접속 -> 위키 설정 적용 - DBeaver 다운 https://dbeaver.io/download/ - https://wiki.slowplat.com/projects/slow_talk_service/wiki/DB_Server - Postgres Cluster Master - Instance Name: auto failover 기능으로 인해 master 서버 인스턴스는 변경 될 수 있음 - Private IP: 10.0.17.174 (LB 주소) - Port : 5000 - Forwarding port : 10000 - Username: postgres - Password: (Bitwarden - 보안 - 카카오 클라우드 - prod-pg-patroni) - Postgres Cluster Standby - Instance Name: auto failover 기능으로 인해 master 서버 인스턴스는 변경 될 수 있음 - Private IP: 10.0.17.174 (LB 주소) - Port : 5001 - Forwarding port : 10000 - Username: postgres - Password: (Bitwarden - 보안 - 카카오 클라우드 - prod-pg-patroni) - patroni 사용해서 node 확인 - patroni node 접속 - patronictl root 권한 실행 - sudo /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list | Member | Host | Role | State | TL | Lag in MB | +----------+-------------+---------+-----------+----+-----------+ | pgnode01 | 10.0.16.210 | Replica | streaming | 10 | 0 | | pgnode02 | 10.0.17.123 | Leader | running | 10 | | | pgnode03 | 10.0.16.76 | Replica | streaming | 10 | 0 | +----------+-------------+---------+-----------+----+-----------+ DB 서버 failover test - 수동방법 (여러 시나리오 구성) - 수동으로 어떻게 바꿔줄 수 있는가? - 수동으로 패일오버 할 때 얼마만에 복구할 수 있는가? - 데이터 로스가 발생하는가? - 오토방법 (여러 시나리오 구성) - 어떤 시나리오로 자동으로 오토 패일오버를 시킬 것인가? - 얼마만에 복구가 되는가? - 데이터 로스가 발생하는가? * postgreSQL 서비스 중단, 네트워크 연결 문제, 스토리지 장애 마스터 노드 장애 시나리오 및 failover 테스트 Patroni의 failover 기능을 테스트하기 위해 마스터 노드에 발생할 수 있는 다양한 장애 시나리오와 각 시나리오에 대한 failover 테스트 방법을 알아보겠습니다. 주의: 실제 운영 환경에서 테스트를 진행할 때는 반드시 데이터 백업을 먼저 수행하고, 테스트 환경을 분리하여 운영 환경에 영향을 주지 않도록 주의해야 합니다. 1. PostgreSQL 서비스 중단 시나리오: PostgreSQL 서비스가 예기치 않게 중단되거나 수동으로 중지된 경우 테스트 방법: 현재 마스터 노드에서 PostgreSQL 서비스를 중지합니다. (systemctl stop postgresql 또는 service postgresql stop) patronictl list 명령으로 클러스터 상태를 확인하고, 마스터 노드가 변경되었는지 확인합니다. 애플리케이션 또는 클라이언트에서 데이터베이스 연결을 시도하여 새로운 마스터 노드로 자동으로 연결되는지 확인합니다. 2. 노드 시스템 다운 시나리오: 마스터 노드의 시스템이 다운되거나 재부팅되는 경우 테스트 방법: 현재 마스터 노드를 강제로 종료하거나 재부팅합니다. patronictl list 명령으로 클러스터 상태를 확인하고, 마스터 노드가 변경되었는지 확인합니다. 애플리케이션 또는 클라이언트에서 데이터베이스 연결을 시도하여 새로운 마스터 노드로 자동으로 연결되는지 확인합니다. 3. 네트워크 장애 시나리오: 마스터 노드와 다른 노드 간의 네트워크 연결이 끊어지는 경우 테스트 방법: 현재 마스터 노드의 네트워크 인터페이스를 비활성화하거나 방화벽 규칙을 변경하여 다른 노드와의 통신을 차단합니다. patronictl list 명령으로 클러스터 상태를 확인하고, 마스터 노드가 변경되었는지 확인합니다. 애플리케이션 또는 클라이언트에서 데이터베이스 연결을 시도하여 새로운 마스터 노드로 자동으로 연결되는지 확인합니다. 4. 스토리지 장애 시나리오: 마스터 노드의 스토리지 시스템에 장애가 발생하여 데이터베이스 파일에 접근할 수 없는 경우 테스트 방법: (주의: 데이터 손실 가능성이 있으므로 반드시 백업 후 테스트 환경에서만 진행해야 합니다.) 현재 마스터 노드의 데이터 디렉토리를 다른 위치로 이동하거나 삭제하여 데이터베이스 파일에 접근할 수 없도록 만듭니다. patronictl list 명령으로 클러스터 상태를 확인하고, 마스터 노드가 변경되었는지 확인합니다. 애플리케이션 또는 클라이언트에서 데이터베이스 연결을 시도하여 새로운 마스터 노드로 자동으로 연결되는지 확인합니다. 추가 고려 사항 복제 지연 시간: 비동기 복제를 사용하는 경우, failover 시 일부 데이터 손실이 발생할 수 있습니다. 복제 지연 시간을 최소화하여 데이터 손실 가능성을 줄이는 것이 중요합니다. 애플리케이션 연결 관리: 애플리케이션은 failover 발생 시 새로운 마스터 노드로 자동으로 연결을 재설정할 수 있어야 합니다. 연결 풀링 라이브러리나 ORM(Object-Relational Mapping) 프레임워크를 사용하는 경우, failover 처리 기능을 지원하는지 확인해야 합니다. 모니터링 및 알림: Patroni 클러스터의 상태를 지속적으로 모니터링하고, failover 발생 시 알림을 받을 수 있도록 설정해야 합니다. 테스트 결과 분석 각 시나리오에 대한 failover 테스트를 수행한 후에는 다음 사항들을 확인해야 합니다. failover가 예상대로 작동했는지 확인합니다. 새로운 마스터 노드가 정상적으로 서비스를 제공하는지 확인합니다. 애플리케이션 또는 클라이언트가 새로운 마스터 노드에 자동으로 연결되는지 확인합니다. 데이터 손실이 발생했는지 확인합니다. (특히 비동기 복제 사용 시) 결론 Patroni를 사용하면 PostgreSQL 클러스터의 고가용성을 확보하고 데이터 손실 가능성을 최소화할 수 있습니다. 다양한 장애 시나리오에 대한 failover 테스트를 통해 Patroni 설정 및 애플리케이션 연결 관리가 올바르게 동작하는지 확인하고, 문제 발생 시 신속하게 대응할 수 있도록 준비해야 합니다. 시스템 로그 확인 - mongoDB에 접속하여 로그 확인 - mongoDB는 docker로 올라가 있음 - mongo compass 다운 -> 위키에 설정 적용 - https://www.mongodb.com/pt-br/ko-kr/products/tools/compass - https://wiki.slowplat.com/projects/slow_talk_service/wiki/DB_Server - prod - URI : mongodb://slowmgroot:4gFrzsfT2JNeD6@10.0.19.109:27017/admin - Proxy/SSH - SSH Hostname : 210.109.54.69 - SSH Port : 10005 - SSH Username : rocky - SSH Identiy File : slowtalk-prod.pem - dev - URI : mongodb://slowmgroot:mgrtpw4411@10.0.2.254:27017/admin - Proxy/SSH - SSH Hostname : 210.109.54.69 - SSH Port : 10060 - SSH Username : rocky - SSH Identiy File : slowtalk.pem - kafbat ui를 사용하여 kafka 확인 - 토픽 목록 : kafka 클러스터에 존재하는 모든 토픽 목록을 확인 - 토픽 세부 정보 : 각 토픽의 파티션 수, 복제 백터, 메세지 보전 기간 등 세부 정보 확인 - 메시지 조회, 메세지 갱신, 컨슈머 그룹 정보 - kafbat 설명 : https://github.com/kafbat/kafka-ui - 로그 확인 후 어디가 어떻게 장애가 났는지 파악 문자인증 - 클라 api - 응답 - 로그 - 로그 확인 경로 - 로그 확인 후 대응 방법 체크 - 문자인증 api 쓰는 법 : 클라 - push 서버로 어떻게 데이터를 보낼까? - 문장인증 호출 - 로그 : mongoDB - 로그 파악 # sudo 권한 필요한 디렉터리 / 파일 -> 파일 안들어가지거나 명령어 먹지 않을 경우 sudo /usr/local/bin/patronictl -c /etc/patroni/patroni.yml list s pg bouncer - Postges 성능의 부하를 줄어줌 / 연결 풀링의 이해 - https://xshine.tistory.com/167
Bash
복사
# kafka의 핵심 구성 요소 1. 토픽 (Topic) - 메시지 분류 : kafka는 메시지를 토픽이라는 논리적인 단위로 분류하여 관리 - 생산자-소비자 연결 : 토픽은 생산자(Producer)가 메시지를 보내는 곳이자, 소비자(Consumer)가 메시지를 읽어오는 곳 - 파티션 분할 : 각 토픽은 여러 개의 파티션(Partition)으로 나누어 저장. 파티션은 메시지 순서를 보장하는 단위이며, 여러 브로커에 분산 저장 - 복제 : 각 파티션은 여러 브로커에 복제되어 데이터 안정성을 보장 2. 브로커 (Broker) - 메시지 저장 : kafka 클러스터를 구성하는 서버. 토픽의 파티션을 저장하고 관리 - 클러스터 구성 : 여러 브로커가 함께 클러스터를 수성하여 확장성과 가용성을 높임 - ZooKeeper 연동 : ZooKeeper를 사용하여 클러스터 구성 정보, 토픽 정보, 파티션 정보 등을 관리 3. 생산자 (Producer) - 메시지 발행 : 메시지를 특정 토픽에 발행하는 역할 - 파티션 선택 ㅣ 메시지를 어떤 파티션에 저장할지 선택 가능 4. 소비자 (Consumer) - 메시지 구독 : 특정 토픽을 구독하여 메시지를 읽어오는 역할 - 컨슈머 그룹 : 여러 소비자가 하나의 컨슈머 그룹을 형성하여 토픽의 파티션을 분담하여 처리 - 오프셋 관리 : 각 컨슈머는 자신이 읽은 메시지 위치를 오프셋(Offset)으로 관리하여 다음 읽을 위치를 기억함 # kafka의 전반적 개념 - 분산 메시징 시스템 : 대용량 데이터 스트림을 처리하기 위해 사용 - 실시간 처리 : 메시지를 빠르게 처리하여 실시간 데이터 스트림 처리에 적합 # 카프카 구조 알아보기 https://velog.io/@jwpark06/Kafka-%EC%8B%9C%EC%8A%A4%ED%85%9C-%EA%B5%AC%EC%A1%B0-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0
Bash
복사
# 회사 테스트 : 조태연, 010-5767-4411 pin 00000 # 민우 : 010-8695-2201 # 데일리 빌드 후 close → 마켓빌드가 되면 추가적으로 한번 더 테스트 # 240828 앱 테스트 개인, 개인설정, 로그인, 회원가입, 피드, 고객문의 개인 - 사용자1(허진영)과 사용자2(김민우)가 회원가입을 진행 후, 서로의 프로필을 누를 경우 회원이 아니라는 메세지 출력되는 이슈 - 사용자1(허진영)이 사용자2(김민우)를 직접 추가 할 경우, 정상적으로 친구 생성 - 사용자를 직접 추가를 진행할 때, 친구목록에 당 친구가 없는데도 "이미 친구입니다."라는 메세지 출력되며 친구목록에 친구 추가가 되지 않는 이슈 - 슬로우톡 초대 문자의 url을 받은 상대방이 아이폰일 경우, 페이지가 로딩 되지 않는 이슈 : 다이나믹 링크 작동 안됨 채널 - 채널 소식에서 댓글을 등록하면 삭제나 수정이 불가능한 이슈 - 채널 소식에서 댓글 시간이 9시간 전으로 설정 (1326분 등록 -> 04시 26분 등록) 온보딩 - 이미지를 터치해서 넘기는 방식의 불편하여 개선 필요 -> 사용자의 손을 고려했을 때, 전체화면에서 이미지를 넘길 수 있도록 수정 요청. 챗봇 - 240828 1336분 현재 챗봇에게 메시지 남겨도 답변이 없음 채팅 - 사용자1(허진영)이 채팅방을 생성하여 사용자2(김민우)에게 보낼 때, 처음 push되는 메세지가 전달되지 않음 - 채팅방 안에서의 이미지 다운로드 등의 이벤트 기능이 없는 이슈 # 240829 앱 테스트 동네 - 동네 피드에서 다른 사용자가 남긴 글에 댓글 작성이 불가능한 이슈 # 데일리 빌드 후 close → 마켓빌드가 되면 추가적으로 한번 더 테스트
Bash
복사
개인
사용자1(허진영)과 사용자2(김민우)가 회원가입을 진행 후, 서로의 프로필을 누를 경우 회원이 아니라는 메세지 출력되는 이슈
문제 1을 해결하기 위해 직접 추가 진행 시, 사용자가 추가 됨을 확인했으나, 프로필에서 친구 삭제 후 다시 친구 추가를 했을 경우 아래와 같이 “이미 친구입니다.” 라는 메세지가 출력되며 사용자 친구 추가가 진행되지 않음
예) 사용자1(허진영)이 사용자2(김민우)를 추가할 경우 추가 / 다시 친구 삭제 후 친구 추가 하였을 때, “이미 친구입니다.” 메시지 출력되며 친구 추가가 되지 않음
슬로우톡 초대 문자의 url을 받은 상대방이 아이폰일 경우, 페이지가 로딩 되지 않는 이슈 : 다이나믹 링크 작동 안됨
채팅
사용자1(허진영)이 채팅방을 생성하여 사용자2(김민우)에게 메시지를 보냈을 때, 사용자2(김민우) 채팅 리스트 화면에 사용자1(허진영)이 바로 생성되지 않고, 한 번 터치하면 채팅방이 생성 됨.
또한, 처음 사용자1(허진영)이 사용자2(김민우)에게 전송한 메세지 내용이 전달되지 않음.
왼: 사용자1(허진영)이 사용자2(김민우)에게 메시지 전송 / 중, 오: 사용자2(김민우)의 채팅방
_Loading_
# DB - 트랜젝션 - 데드락 전체적인 윤곽을 그리고 여러번 보면서 디테일을 살리기. 오히려 한곳만 봐서 이해하지 못하는 경우가 발생 포커스를 장애상황에 대해서 어떻게 대응할지 파악부터!! - DB, 앱, kafka에 대해서 문제가 생길 경우, 어떻게 장애 복구 CTO 실의 우선순위 - 운영의 포커스!! - 대응을 하지 못할 수 있음 -> 장애복구 시간이 딜레이가 발생 -> 안됨 - 장애 케이스들 - 인터넷에 찾아보기! - 같은 구성의 시스템이 없기 때문에 상황이 다를 수 있음 - 서버의 부하가 생겼을 때 어느 서버가 다운될까? - 실제로 어느 서버가 부하가 걸리는지 어떻게 확인? - 서버는 혼자 동작하지 않음 우선적으로 해야 할 것 - 서버별로 장애를 어떻게 대응할 것인가? - 앱서버 어떻게? - Kafka 어떻게? - Kafka 증설 하는 방법 알아? 모르지 - 알도록! - mongodb, redis 어떻게? - 이중화가 안되어 있으니 이중화 하는 방법도 고민. 페일오버 기능이 되었는지 확인, 빠르게 복구, 기존 성능을 가져가면서 복구 뭐는 어떻게 봐야되는지 서버에 따라 특징이 다르다 예) 앱서버 같은 경우 볼륨보다는 cpu, 메모리 성능을 사용하기 때문에 거기서 장애가 발생한 경우 어떻게 대응할 것인가. 레디스 - 메모리 - 어떤 지표? 문제가 생기기전에 미리 케치 # 장애 대응 방법 예시 문자 - 로그 확인 경로 - 로그 확인 후 대응 방법 체크 - 문자인증 api 쓰는 법 : 클라 - push 서버로 어떻게 데이터를 보낼까? - 문장인증 호출 - 로그 : mongoDB - 로그 파악 # redis conf 파일 찾아보기
Bash
복사
# 용어 정리 커넥션 풀 (Connection Pool): - 애플리케이션에서 데이터베이스에 연결이 필요할 경우 미리 준비된 Connection 객체를 사용하여 애플리케이션의 성능을 향상시킴 스레드 풀은 - 작업처리에 사용되는 스레드를 제한된 개수만큼 정해놓고 작업큐 (Queue)에 들어오는 작업들을 하나씩 스레드가 맡아 처리 - 그렇게 하면 작업처리 요청이 폭증되어도 스레드의 전체개수가 늘어나지 않으므로(제한해서 하나씩 처리하기 때문) 시스템 성능이 급격히 저하되지 않는다. # 앱서버 장애대응 어떻게? 구글링 참고 실제로 어떻게 동작하는지 봐야함. 어떤 api가 있는가 - 대략적인 어떤 기능? - 이 처리는 어떤처리? db조회, 리턴 스웨거 확인 crud로 처리할 수 없는 것에 대한 동작은 어떻게 되는가. 어떻게 이중화 처리가 되는가? 경합처리 - 똑같은 디비를 바라보고 있는데 왜 문제가 안생겨? 두 개의 인스턴스에 같은 컨테이너가 올라가고 DB 서버 커넥션이 같을 때 경합 처리는 다음과 같은 방식으로 이루어질 수 있습니다. 1. DB 서버 측 잠금 (Lock) 메커니즘: 행 수준 잠금 (Row-Level Locking): DB 서버는 동시에 여러 트랜잭션이 같은 데이터에 접근하려고 할 때, 행 수준 잠금을 사용하여 데이터 일관성을 유지합니다. 즉, 한 트랜잭션이 특정 행을 수정 중일 때 다른 트랜잭션은 해당 행에 대한 수정을 대기해야 합니다. 테이블 수준 잠금 (Table-Level Locking): 경우에 따라 DB 서버는 전체 테이블에 대한 잠금을 사용할 수도 있습니다. 이 경우, 한 트랜잭션이 테이블을 수정하는 동안 다른 트랜잭션은 해당 테이블에 대한 모든 작업(읽기 및 쓰기)을 대기해야 합니다. 2. 애플리케이션 측 경합 처리: 낙관적 잠금 (Optimistic Locking): 애플리케이션은 데이터를 읽어올 때 버전 정보 또는 타임스탬프를 함께 가져옵니다. 데이터를 수정하려고 할 때, 가져온 버전 정보 또는 타임스탬프와 현재 DB의 정보를 비교하여 다른 트랜잭션에 의해 데이터가 변경되었는지 확인합니다. 만약 변경되었다면, 충돌을 감지하고 적절한 처리(예: 재시도 또는 오류 처리)를 수행합니다. 비관적 잠금 (Pessimistic Locking): 애플리케이션은 데이터를 읽어올 때 명시적으로 잠금을 획득하고, 수정이 완료될 때까지 잠금을 유지합니다. 이렇게 하면 다른 트랜잭션이 해당 데이터에 접근하는 것을 방지하여 충돌을 예방할 수 있습니다. 그러나 잠금 경합으로 인해 성능 저하가 발생할 수 있습니다. 3. 분산 잠금 (Distributed Locking): Redis, ZooKeeper 등: 여러 인스턴스가 공유하는 외부 저장소를 사용하여 분산 잠금을 구현할 수 있습니다. 이를 통해 여러 인스턴스 간에 데이터 접근을 조정하고 경합을 방지할 수 있습니다. # 앱서버의 특징 - cpu, 메모리 사용량이 중요 - 앱을 구동시키며 컨테이너를 동해서 cpu 및 메모리 작업이 많기 때문. - 앱서버 이중화 처리 - 서버 업그레이드를 하는 시점에서 서비스 중단 시간이 발생하기 때문에 시간 차를 고려해서 배포하는 것이 필요 - 서버의 두대의 인스턴스가 동일한 컨테이너로 작동 - 경합처리? 똑같은 디비를 바라보고 있는데 왜 문제가 생기지 않는가? # 앱 서버별 특징 api, chat : 인바운드 요청에 따른 아웃바운드 응답을 줘야함. push : 인바운드를 직접 받지 않고 다른 서버에서 받은 요청을 가공해서 응답을 줌 # 앱서버의 구성 API - prod-api-1 - api-prod-container - prod-api-2 - api-prod-container CHAT 서버 - prod-chat-1 - chat-prod-container - prod-chat-2 - chat-prod-container PUSH 서버 - prod-push-1 - push-prod-container - prod-push-2 - push-prod-container
Bash
복사
# kafka 문제 발생 로그 파일 깨짐 meta properties, 나머지 파일도 깨지면서 정상작동이 안됨 약간 의심 : 특정 브로커 - 잘 종료가 안되서 깨진 상태로 싱크 된 이유로 보임 카프카 3대가 정보 공유 - 비정상적 데이터 저장시 다른 서버도 비정적 데이터 저장 유사적인 상황에서 파악해야한다. - 구글링 - 러프하게 파악 장상적 메세지 쌓임 채팅 : 웹 소켓 채널 / 한 쪽 안될 시 Push 연결 안될 시 소켓 연결이 되어 있는지 확인 (Redis)에서 연결이 되어 있는 지 연결이 안되어있으면 그게 문제, 아니면 Push (kafka) # kafka 로그 경로 log.dirs=/tmp/kafka-logs 언애 meta.properties 파일 존재 # 해결 방법 카프카 설정파일(카프카 설치 디렉토리/config/server.properties)의 log.dirs 항목에서 설정되어 있는 카프카 로그 path로 가보면 meta.properties라는 파일이 있는데 해당 파일을 지워주고 카프카를 재시작해주면 해결된다. $ cd [log-dir] $ rm -rf meta.properties $ systemctl restart kafka-server # 참고 블로그 https://eg3020.blogspot.com/2020/11/apache-kafka-metapropertie.html https://twofootdog.tistory.com/93 # meta.properties 저장 데이터 cluster.id: 카프카 클러스터를 고유하게 식별하는 ID입니다. 클러스터 내 모든 브로커는 동일한 cluster.id를 가져야 합니다. broker.id: 해당 브로커를 고유하게 식별하는 ID입니다. 클러스터 내 각 브로커는 서로 다른 broker.id를 가져야 합니다.
Bash
복사
dev-postgres port 5432
Bash
복사
# 버전 0.9.1 1. 개인화면s 설정 > 프로필 이미지 등록 문제 (#148) - 정상 동작 d 주소록 친구 추가/삭제 문제 (#160) - 정상동작 주소록 친구 중 회원인 친구 인식 문제 (#150) - 정상 동작 직접 친구 추가 시 발생하는 이슈 (#151) - 정상동작 추가적으로 발생한 이슈 - 주소록 친구 추가를 진행 후, 개인의 친구 목록에서 회원인 친구를 클릭할 경우, 친구 목록 화면에서 "이미 친구입니다" 토스트 메시지와 함께 회원인 친구가 친구 목록에서 보이지 않음 - mongodb에서 해당 친구 정보 삭제를 2번 재진행 후 친구 목록에 회원인 친구 정상 출력 처음 테스트 진행 시, 정상 동작하였으나, 다시 테스트 시 같은 문제 발생 - db에서 정보 삭제 후 재시도 3회만에 다시 추가됨을 확인 2. 채널 화면 채널 소식의 댓글 수정/삭제 문제 (#153) - 정상 동작 댓글 시간 표시 문제 (#154) - 정상 동작 3. 채팅 화면 채팅방 메시지 시간 UI 위치 문제 (#146) - 정상 동작 채팅방 나간 경우의 문제 (#147) - 정상 동작 채팅방 내의 친구 프로필 진입 문제 (#156) - 정상 동작 4. 챗봇 화면 챗봇 대화 응답 없는 문제 (#155) - 정상 동작 # 추가 이슈 1. 프로필 이미지는 정상 등록되어 채팅방 프로필은 업데이트 되나, 친구 목록에서 친구 프로필 확인 시, 빈 이미지 상태로 나옴 2. 162번 수정 - 채팅방 다중 생성 1. 채팅을 받는 사용자 입장에서 두개의 채팅방이 생성되며, 두 개 이상의 채팅방이 한 채팅방 내용을 포함하고 있음(나갔던 채팅방까지 포함) 2. 추가적으로 테스트를 진행하며, 채팅방을 보고 있을 때는 메세지가 전송되지만, 채팅방 밖에 있을 때에는 메세지를 받지 못하는 이슈가 발생 : Mongodb에서 메세지가 정상적으로 전송 됨을 확인
Bash
복사
Bash
복사
# 루트 권한 실행 docker exec -u root -it prometheus sh # 해당 파일 탐색 docker exec -it prometheus cat /etc/hosts # prometheus 설정 적용 (모니터링 서버) my_hosts 파일 수정 > add_hosts_tocontainer.sh 실행 > docker-comose 제시작 # prometheus 설정 적용 (해당 서버) prometheus는 monitoring instance에서 /home/rocky/prometheus_grafana/prometheus/config/prometheus.yml 파일을 편집하고 prometheus cotainer 재시작 # 수정 명령어 sudo vi prometheus/config/prometheus.yml docker-compose restart && ./add_prometheus_hosts.sh # prometheus 참고 블로그 https://magpienote.tistory.com/262 # 앞으로의 과제 이 설정 과정을 자동화할 수 있는가?
Bash
복사
# wikijs 문법 # 이미지 사이즈 지정 ![20240809-101317-283.png](/20240809-101317-283.png =800x400) ![20240809-101317-283.png](/20240809-101317-283.png =800x) # 앵커, 링크 생성 ## 제목2 {#앵커_이름} [[#앵커_이름|표시할 텍스트]] # 파일등록 [공식 칸반 가이드 (PDF 다운로드)](attachment:The-Official-Kanban-Guide_Korean_A4.pdf) # 문법 정리 블로그 https://retr0.wiki/%EC%9C%84%ED%82%A4-%EB%AC%B8%EB%B2%95 # 사용법 정리 블로그 https://www.dongyeon1201.kr/63c594da-135a-48a9-9808-3001ba2a5b3a
Bash
복사
# jenkins 문제 발생 해결 # 로그 확인 https://jenkins.slowplat.com/computer/cloud%2Dslowtalk%2Dnode/log Warning: no key algorithms provided; JENKINS-42959 disabled SSHLauncher{host='210.109.54.69', port=22, credentialsId='jenkins_ssh_agent', jvmOptions='', javaPath='/usr/bin/java', prefixStartSlaveCmd='', suffixStartSlaveCmd='', launchTimeoutSeconds=60, maxNumRetries=10, retryWaitTime=15, sshHostKeyVerificationStrategy=hudson.plugins.sshslaves.verifiers.KnownHostsFileKeyVerificationStrategy, tcpNoDelay=true, trackCredentials=true} [09/05/24 13:37:59] [SSH] Opening SSH connection to 210.109.54.69:22. Searching for 210.109.54.69 in /var/jenkins_home/.ssh/known_hosts Searching for 210.109.54.69:22 in /var/jenkins_home/.ssh/known_hosts [09/05/24 13:37:59] [SSH] WARNING: No entry currently exists in the Known Hosts file for this host. Connections will be denied until this new host and its associated key is added to the Known Hosts file. Key exchange was not finished, connection is closed. # 인스턴스 확인 slowinfra > Infra 인스턴스(젠킨스 마스터) 확인 > jenkins 컨테이너 확인 > monitering 인스턴스(젠킨스 슬레이브) 확인 # Insra (젠킨스 마스터) /var/jenkins_home/.ssh/known_host 작성해야 함 - 수정 방법 - 젠킨스 슬레이브 인스턴스로 ssh 접속하면 자동으로 해쉬값 작성됨 # 또 다른 방법 Dashboard > Nodes > cloud-slowtalk-node > Configure에서 Host Key Verification Strategy를 Non verifying Verification Strategy로 설정
Bash
복사
# 젠킨스 2.462.2 업그레이드 infra 인스턴스 > jenkins-blueocean > ./jenkins_update.sh 2.462.2 # 정상적으로 동작이 안되는 이슈 - Jenkins war 파일이 정상적으로 다운로드 되었는가? - 원하는 버전이 다운로드 되는지 체크 (2.462.2) - #!/bin/bash # 버전 정보 확인 if [ -z "$1" ]; then echo "Usage: $0 <version>" exit 1 fi VERSION=$1 JENKINS_CONTAINER_NAME="jenkins-blueocean" JENKINS_WAR="update/jenkins.war" JENKINS_WAR_SHA="update/jenkins.war.sha256" #if [ -f $JENKINS_WAR ]; then # echo "File exist, delete it" # rm -f $JENKINS_WAR #fi # Jenkins WAR 파일 다운로드 echo "Download jenkins.war & jenkins.war.sha256" if [ ! -e "$JENKINS_WAR" ]; then wget https://ftp.yz.yamagata-u.ac.jp/pub/misc/jenkins/war-stable/$VERSION/jenkins.war -O $JENKINS_WAR fi if [ ! -e "$JENKINS_WAR_SHA" ]; then wget https://ftp.yz.yamagata-u.ac.jp/pub/misc/jenkins/war-stable/$VERSION/jenkins.war.sha256 -O $JENKINS_WAR_SHA fi #curl -L -o $JENKINS_WAR https://updates.jenkins.io/download/war/$VERSION/jenkins.war # Read the expected SHA-256 hash from the jenkins.war.sha256 file expected_hash=$(cut -d ' ' -f 1 $JENKINS_WAR_SHA) # Compute the actual SHA-256 hash of the jenkins.war file actual_hash=$(sha256sum $JENKINS_WAR | cut -d ' ' -f 1) # Compare the expected hash with the actual hash if [ "$expected_hash" == "$actual_hash" ]; then echo "SHA-256 hash verification succeeded: $actual_hash" else echo "SHA-256 hash verification failed!" echo "Expected: $expected_hash" echo "Actual: $actual_hash" exit 1 fi # Jenkins 컨테이너로 파일 복사 echo "copy jenkins.war to container" docker cp $JENKINS_WAR $JENKINS_CONTAINER_NAME:/usr/share/jenkins # Jenkins WAR 파일 소유권 변경 echo "change ownership of jenkins.war" docker exec $JENKINS_CONTAINER_NAME chown jenkins:jenkins /usr/share/jenkins/jenkins.war # Jenkins 컨테이너 재시작 echo "restart container" docker restart $JENKINS_CONTAINER_NAME
Bash
복사
# 버전코드 코드 수정 과제 https://gitlab.slowplat.com/frontend/slowtalk/-/merge_requests/258
Bash
복사