W16 DevOps
16주차에 학습하였던, DevOps의 개념 및 구현을 위한 도구의 학습내용을 정리하였습니다.
개발
개발 방식의 종류
- 컴파일러
- Compiler: 개발자가 작성한 코드를 기계어로 변환
- 기계어: 0과 1. 실행파일 형태로 작성된 코드
- 실행 효율이 높음
- 컴파일 과정이 필요
- 인터프리터
- Script의 내용을 Interpreter가 해석
- 코드의 내용을 라인 단위로 해석하여 실행
- 별도의 컴파일 과정이 필요하지 않음
- 실행 효율 등은 낮음
개발 과정
요구사항 분석
소프트웨어 설계
구현
테스트
배포
유지보수
- 요구사항 분석
- 필요로 하는 목표를 탐색
- 개발 가능 여부
- 비용/예산 등
- 소프트웨어 설계
- 기능 구현을 위한 논리적 설계, 구조 설계
- 개발 언어 및 운영 플랫폼
- 인터페이스
- 구현
- 설계에 따른 프로그래밍
- 역할 및 업무 분담에 따른 협업
- 테스트
- 기본적인 요구사항에 대한 동작 확인
- 오류 확인
- 변경된 요구사항에 대한 반영
- 배포
- 개발된 제품을 운영환경으로 반영
- 모니터링
- 유지보수
- 추가 요구사항에 대한 반영, 시스템 장애 및 오류에 대한 대응
전통적인 개발 방식의 한계점
- 코드 통합의 문제
- 각자 작성한 코드를 통합하는 과정에서 다수의 문제가 발생
- 테스트 환경 구성 및 코드 통합 작업 등에서 많은 시간이 소요
- 버전 관리
- 소스코드 개발 단계 및 테스트 단계에서 버전의 관리가 되지 않을 경우
- 커뮤니케이션
- 역할 간 소통 부재로 인한 장애 발생
DevOps
- Development(개발) + Operations(운영)
- 전통적인 개발 방식의 문제점을 해결하기 위한 노력
- 문제점을 해결해 나가기 위한 일종의 ‘문화’
- 상호존중, 실패에 대한 비난 금지, 긍정적인 자세
DevOps 실천방안
- 마이크로서비스 아키텍처(MSA) ⇔ 모놀리식 아키텍처
- IaC: Infrastructure as Code
- 모니터링, 로깅
- CI/CD
- Continuous Integration
- 지속적 통합
- 코드 통합 등의 문제(Integration Hell)를 해결하기 위한 과정
- 개발 코드 공유, 수시로 빌드를 통한 테스트, 자동화
- Continuous Deploy
- 지속적 배포
- 변경된 코드에 대한 즉각적인 배포 수행
- 자동화
- Continuous Integration
CI/CD
- 코드 관리(git)
- CI(Jenkins)
- CD(ArgoCD)
Jenkins
- 2004년 Sun Microsystems회사의 코스케 가와구치 개발
- 빌드 및 커밋 등의 불편함을 해결하기 위한 방법
- Java 기반으로 동작하는 오픈소스
- 과거에는 ‘허드슨’ Hudson 이라는 이름을 사용
Jenkins 설치
https://www.jenkins.io/doc/book/installing/linux
설치와 로그인 방법은 생략
Jenkins 환경 구성
- 왼쪽 메뉴 Jenkins 관리 - Global Tool Configuration
- JDK(Java Development Kit)
- Install Automatically 체크 해제
- JDK 설정 이름: JAVA_HOME
- JDK 경로 : /usr/lib/jvm/java-11-openjdk-amd64
- Git
- Install Automatically 체크 해제
- Git 설정 이름: Git
- Git 경로 : git
- Maven
- Install Automatically 체크 해제
- Maven 설정 이름: Maven_Home
- Maven 경로 : /usr/share/maven
- Maven plugin
- Jenkins 관리 - Plugin 관리
- maven integration
- maven invoker
- JDK(Java Development Kit)
Maven
- 빌드 및 테스트 도구
- 수행 단계
- clean : 빌드 관련 내용 정리(청소)
- compile : 컴파일(빌드)
- test : 빌드된 파일 테스트
- package : 빌드된 파일을 JAR/WAR 생성
- verify : 통합테스트
- install : 로컬 저장소에 패키지 배포
- deploy : 원격 저장소에 패키지 배포
Git
- <참고> Git 관련 서적 참고>
- https://www.oss.kr/oss_guide/show/2c619df7-40d6-43de-af7a-2b0db6c16538
git 명령을 사용하여 테스트 코드 데이터를 github로 push
- git init
- git 로컬저장소 초기화
- git config
- git 명령을 사용하여 접근할 계정에 대한 정보 설정
- git config user.name
- git config user.email
- git config user.name
- git 명령을 사용하여 접근할 계정에 대한 정보 설정
- git add .
- git 대상 파일 등록
- . : 현재 디렉토리 내 전체 파일
- git 대상 파일 등록
- git commit -m ‘my first build source code’
- 변경된 내용을 추적하여 등록
- m: 커밋 설명
- 변경된 내용을 추적하여 등록
- git branch -M master
- 현재 git의 branch 설정
- git remote add origin <자신의 github="" repository="">
자신의>
- 원격 저장소(github)의 주소를 origin 이름으로 지정
- git push origin master
- master 브랜치의 데이터를 origin 저장소로 push
- 인증 시 ID와 Access Token을 사용하여야 함
**<참고> git push 실행 시 인증정보 저장**참고>
- git config credential.helper store
- 지속적인 저장
- git config credential.helper cache
- 일시적인 저장 (시간 경과시 삭제)
Tomcat Server를 사용한 WAR 어플리케이션 배포
-
Tomcat EC2 인스턴스 생성 및 SSH 연결
- java jdk 설치
- sudo apt update
- sudo apt install openjdk-11-jdk
- java –version
- Java 환경 구성
- ~/.bashrc 파일 수정
... JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 PATH=$PATH:$JAVA_HOME
- ~/.bashrc 파일 수정
- 쉘 설정 다시 로드
- exec bash
- echo $JAVA_HOME
- echo $PATH
- Tomcat 및 Tomcat admin 설치
- sudo apt -y install tomcat9 tomcat9-admin
- sudo systemctl status tomcat9.service
- /etc/tomcat9/tomcat-users.xml 수정
...
<role rolename="manager-gui"/>
<role rolename="manager-script"/>
<role rolename="manager-jmx"/>
<role rolename="manager-status"/>
<user username="admin" password="admin" roles="manager-gui, manager-script, manager-jmx, manager-status"/>
<user username="deployer" password="deployer" roles="manager-script"/>
<user username="tomcat" password="tomcat" roles="manager-gui"/>
</tomcat-users>
- 사용자 설정을 반영하기 위하여 tomcat9 서비스 재시작
- sudo systemctl restart tomcat9.service
- sudo systemctl is-active tomcat9.service
- 배포 작업 설정을 위한 Jenkins 플러그인 설치
- deploy to container
- github repository, maven을 사용하여 빌드 및 tomcat 배포 작업 생성
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- deploy-to-tomcat - 소스코드 관리
- github
- repository: 자신의 github 레포지토리 주소
- (선택)credential: 앞에서 생성한 credential 사용
- 빌드
- Root POM: pom.xml
- Goals and options: clean install
- 빌드 후 조치
- deploy war/ear to container
- WAR/EAR file : */.war (프로젝트 디렉토리 내 .war파일 지정)
- Container: tomcat 9.x remote
- Credential: deployer/deployer (새로 생성)
- tomcat url: http://192.168.56.102:8080
- deploy war/ear to container
- 배포 확인
- jenkins 작업디렉토리(/var/lib/jenkins/workspace)
- Tomcat 관리자 페이지
- http://
:8080/manager - 배포된 Tomcat 어플리케이션 - http://
:8080/webapp
- 컨텐츠 업데이트 후 갱신된 컨텐츠를 사용한 배포 테스트
- 기존 컨텐츠 수정
- /home/ubuntu/source-java-maven-hello-world/webapp/src/main/webapp/index.jsp
<h1> Hello World </h1> <h2> Tomcat Deploy Test </h2>
- github 소스 업데이트 적용
- git commit -m “index.jsp modified(Tomcat)”
- git push origin master
- 앞 단계에서 생성한 jenkins 작업 재실행(Build Now)
- Tomcat 페이지 접속하여 결과 확인 (http://
:8080/webapp)
Jenkins를 사용한 Docker 컨테이너 환경 사용
- EC2 인스턴스 생성
- 이름: Docker
- IP: 192.168.56.103
- 인스턴스 연결 후 Docker 설치
- sudo apt update
- sudo apt -y install apt-transport-https ca-certificates curl gnupg lsb-release
-
curl -fsSL https://download.docker.com/linux/ubuntu/gpg sudo gpg –dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -
echo “deb [arch=$(dpkg –print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable” sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - sudo apt update
- sudo apt install -y docker-ce docker-ce-cli containerd.io
- 현재 사용자 docker 그룹 추가
- sudo usermod -aG docker $USER
- jenkins에서 docker 시스템으로 빌드 결과물을 전달하기 위한 플러그인 설치
- Publish over SSH
- docker VM을 ssh로 연결하기 위한 ssh 설정 및 계정 패스워드 설정
- sudo vi /etc/ssh/sshd_config
... PasswordAuthentication yes ...
- sudo systemctl restart ssh.service
- sudo passwd ubuntu
- 암호 설정
- sudo vi /etc/ssh/sshd_config
- jenkins 인스턴스에서 docker 인스턴스로 ssh 연결 테스트
- ssh ubuntu@192.168.56.103
- ssh 연결 설정 추가
- 메인 UI - Jenkins 관리 - 시스템 설정- Publish over SSH (가장 아래쪽)
- SSH Servers - 추가
- name: docker-instance
- hostname: 192.168.56.103 (docker VM IP)
- username: ubuntu
- ‘고급’ 버튼 클릭
- Use password authentication, or use a different key : 계정 패스워드 설정 추가
- Passphrase / Password: 암호 입력
- github repository, maven을 사용하여 빌드 및 tomcat 배포 작업 생성
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- copy-war-to-docker - 소스코드 관리
- github
- repository: 자신의 github 레포지토리 주소
- (선택)credential: 앞에서 생성한 credential 사용 - 빌드
- Root POM: pom.xml
- Goals and options: clean install - 빌드 후 조치
- Send build artifacts over SSH
- SSH Server: docker-instance (이전에 생성한)
- Transfer
- Source files: webapp/target/webapp.war
- remove prefix: webapp/target
- remote directory: hello-world
Docker 이미지 생성
- 테스트용 Dockerfile (docker vm의 사용자 홈 디렉토리에서)
FROM tomcat:9 COPY ./hello-world/webapp.war /usr/local/tomcat/webapps
- 빌드 실행
- docker build -t my-hello-world:latest .
- 이미지를 사용한 컨테이너 테스트
- docker run -d –name test -p 8080:8080 my-hello-world:latest
- 빌드된 이미지를 사용한 어플리케이션 연결 테스트
- http://
:8080/webapp
- http://
Docker 컨테이너 배포를 위한 Jenkins 통합
- Docker 이미지 빌드를 위한 Dockerfile을 git에 포함 (git 저장소 위치에서 실행)
- mkdir dockerfile
- vi dockerfile/Dockerfile
FROM tomcat:9 COPY ./webapp.war /usr/local/tomcat/webapps
- git add .
- git commit -m “Dockerfile added”
- git push origin master
- jenkins 작업 생성
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- deploy-to-docker - 소스코드 관리
- github
- repository: 자신의 github 레포지토리 주소
- (선택)credential: 앞에서 생성한 credential 사용 - 빌드
- Root POM: pom.xml
- Goals and options: clean install - 빌드 후 조치
- Send build artifacts over SSH
- SSH Server: docker-instance (이전에 생성한)
- Transfer 1
- Source files: webapp/target/webapp.war
- remove prefix: webapp/target
- remote directory: hello-world
- Transfer 2
- Source files: dockerfile/Dockerfile
- remove prefix: dockerfile
- remote directory: hello-world
- exec command
docker build -t my-hello-world:latest ~/hello-world docker run -d --name my-hello-world-container -p 8080:8080 my-hello-world:latest
- 빌드 전 docker 인스턴스 내 테스트 환경 정리
- 실행중인 컨테이너 제거
- docker rm -f
docker ps -aq
- 빌드한 이미지 제거 - docker rmi my-hello-world:latest - 이전 빌드 시 복사된 파일 및 테스트 파일 제거
- rm -rf ~/hello-world
- rm -f ~/Dockerfile
Ansible을 활용한 이미지 빌드 및 배포
Ansible을 배포작업에 포함하기
- 새로운 EC2 인스턴스 생성
- 이름: Ansible
- IP: 192.168.56.104
- ansible 인스턴스에 ansible 설치
- sudo apt update
- sudo apt -y install ansible
- ansible 인스턴스에 docker 설치
- 이전 설치과정 참고
- ansible을 사용하여 작업을 제어할 수 있는 환경 구성
- ~/.ansible.cfg
[defaults] inventory = ./inventory.ini
- ~/inventory.ini
[ansible_host] 192.168.56.104 ansible_connection=local
- ansible 인스턴스에서 자신에게 ssh 키 기반 인증이 가능하도록 설정
- ssh 데몬 설정에서 PasswordAuthentication 허용
- sudo vi /etc/ssh/sshd_config
- PasswordAuthentication yes
- sudo vi /etc/ssh/sshd_config
- ssh 서비스 재시작
- sudo systemctl restart ssh
- ubuntu 사용자 패스워드 생성
- sudo passwd ubuntu
- ubuntu 사용자 키 생성 및 복사(ssh-keygen/ssh-copy-id)
- ssh-keygen
- ssh-copy-id ubuntu@192.168.56.104
- ssh 패스워드 인증 해제
- sudo vi /etc/ssh/sshd_config
- PasswordAuthentication no
- sudo vi /etc/ssh/sshd_config
- ssh 서비스 재시작
- sudo systemctl restart ssh
- ~/.ansible.cfg
Ansible 을 사용한 이미지 빌드 및 배포 작업 구성
- 간단한 테스트용 플레이북 작성
```
—
- name: Jenkins CI/CD test playbook hosts: ansible_host tasks:
- name: image build command: docker build -t my-hello-world ~/hello-world
- name: container create command: docker run -d –name my-hello-world-container -p 8080:8080 my-hello-world … ```
- 파일을 전달하기 위한 jenkins 작업 생성
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- deploy-to-docker-with-ansible - 소스코드 관리
- github
- repository: 자신의 github 레포지토리 주소
- (선택)credential: 앞에서 생성한 credential 사용 - 빌드
- Root POM: pom.xml
- Goals and options: clean install - 빌드 후 조치
- Send build artifacts over SSH
- SSH Server: ansible-instance (이전에 생성한)
- Transfer 1
- Source files: webapp/target/webapp.war
- remove prefix: webapp/target
- remote directory: hello-world
- Transfer 2
- Source files: dockerfile/Dockerfile
- remove prefix: dockerfile
- remote directory: hello-world
- 생성한 플레이북 실행 및 재실행
- ansible-playbook cicd.yaml
- 플레이북 수정
---
- name: Jenkins CI/CD test playbook
hosts: ansible_host
tasks:
- name: image build
command: docker build -t my-hello-world ~/hello-world
- name: container rm
command: docker rm -f my-hello-world-container
- name: container create
command: docker run -d --name my-hello-world-container -p 8080:8080 my-hello-world
- 모듈을 사용한 방식으로 플레이북 수정
---
- name: cicd with docker module
hosts: ansible_host
tasks:
- name: Build an image
docker_image:
build:
path: ~/hello-world
name: my-hello-world
tag: latest
push: no
source: build
- name: Container started
docker_container:
name: my-hello-world-container
state: started
image: my-hello-world:latest
- docker 모듈 실행을 위한 패키지 설치
- pip3 install docker-py
- docker 모듈을 사용한 플레이북 실행
- ansible-playbook cicd-module.yaml
- 테스트 완료 후 테스트에 사용한 리소스 삭제
- docker rm -f
docker ps -aq
- docker rmi my-hello-world
- rm ~/*.yaml
- docker rm -f
- 작성한 플레이북을 git에 포함 (git 로컬저장소에서)
- mkdir playbook
- vi playbook/cicd-module.yaml
- 위 플레이북 내용 입력 - git add . - git commit -m “ansible” - git push origin master
- jenkins 기존 작업 아래에 transfer 항목 추가
- Transfer 3
- Source files: playbook/cicd-module.yaml
- remove prefix: playbook
- remote directory: hello-world
- exec command
- ansible-playbook ~/hello-world/cicd-module.yaml
쿠버네티스와 jenkins 통합
- jenkins: git로컬저장소 및 관리, 어플리케이션 빌드, CI/CD 구성 담당
- ansible : 이미지 빌드, 이미지 push
- k8s : 어플리케이션 파드 구동
이미지 빌드 후 컨테이너 생성 대신 이미지 업로드를 수행하는 플레이북
---
- name: cicd with docker module
hosts: ansible_host
tasks:
- name: Build an image
docker_image:
build:
path: ~/hello-world
name: encore0511/my-hello-world
tag: latest
push: yes
source: build
# - name: Container started
# docker_container:
# name: my-hello-world-container
# state: started
# image: my-hello-world:latest
이미지 삭제 후 다시 빌드하는 플레이북
---
- name: cicd with docker module
hosts: ansible_host
tasks:
- name: Remove image
docker_image:
state: absent
name: <dockerhub_ID>/my-hello-world
tag: latest
# - name: Log into DockerHub
# docker_login:
# username: docker
# password: rekcod
- name: Build an image
docker_image:
build:
path: ~/hello-world
name: <dockerhub_ID>/my-hello-world
tag: latest
push: yes
source: build
쿠버네티스 리소스를 배포하기 위한 오브젝트 파일 작성 (git 로컬저장소에서)
- mkdir manifest
- vi manifest/deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: my-hello-world-deployment spec: replicas: 3 selector: matchLabels: app: my-hello-world template: metadata: labels: app: my-hello-world spec: containers: - name: my-hello-world-container image: <dockerhub_ID>/my-hello-world ports: - containerPort: 8080 protocol: TCP
- vi manifest/nodeport.yaml
```
apiVersion: v1
kind: Service
metadata:
name: my-hello-world-svc
spec:
selector:
app: my-hello-world
type: NodePort
ports:
- targetPort: 8080 port: 8080 nodePort: 30080 ```
이미지 빌드 작업 및 이미지 빌드 작업에 의해 트리거된 쿠버네티스 배포 작업 생성
- jenkins 작업 생성 (이미지 빌드)
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- docker-image-build - 소스코드 관리
- github
- repository: 자신의 github 레포지토리 주소
- (선택)credential: 앞에서 생성한 credential 사용 - 빌드
- Root POM: pom.xml
- Goals and options: clean install - 빌드 후 조치
- Send build artifacts over SSH
- SSH Server: ansible-instance
- Transfer 1
- Source files: webapp/target/webapp.war
- remove prefix: webapp/target
- remote directory: hello-world
- Transfer 2
- Source files: dockerfile/Dockerfile
- remove prefix: dockerfile
- remote directory: hello-world
- Transfer 3
- Source files: playbook/build.yaml
- remove prefix: playbook
- remote directory: hello-world
- exec command
- ansible-playbook ~/hello-world/build.yaml
- jenkins 작업 생성 (쿠버네티스 배포)
- jenkins 메뉴에서 새로운 item - Maven 프로젝트
- deploy-to-k8s - 빌드 유발
- Build after other projects are built
- project to watch: docker-image-build
- 실행옵션: Trigger only if build is stable - 빌드 후 조치
- Send build artifacts over SSH
- SSH Server: k8s-instance
- Transfer 1
- Source files: manifest/*.yaml
- remove prefix: 없음
- remote directory: 없음
- exec command
- kubectl apply -f ~/manifest
- 현재까지 작업된 내용을 git에 반영하고 docker-image-build 작업 실행 및 트리거된 배포 작업 확인
Github 업데이트에 따른 빌드 유발 설정 (Github Webhook)
- jenkins VM에서 인증에 사용할 키 설정
- ssh-keygen -t rsa -f ~/.ssh/jenkins-github
- 생성된 키 중 public key 내용을 github에 저장
- cat ~/.ssh/jenkins-github.pub
- github 레포지토리 - setting - Deploy key에서 항목 생성하여 키 추가
- jenkins에서 생성한 키 등록
- jenkins 관리 - manage credential
- global 우측 화살표 클릭 - add credential
- SSH username and private key 선택
- ID: 키 이름 (임의로 입력)
- username: 키 생성시 사용한 사용자
- private key:
- Enter directly
- add 버튼 클릭 후 개인키 값 입력
- cat ~/.ssh/jenkins-github
- Enter directly
- SSH username and private key 선택
-
jenkins 플러그인 설치: github integration
- 빌드 작업 구성에서 빌드 유발 항목 추가
- 항목 체크: GitHub hook trigger for GITScm polling
- github webhook 생성
- 레포지토리 설정 - webhook
- URL: http://
:8080/github-webhook/
- git 로컬저장소의 파일을 수정 후 push하여 webhook에 의한 docker-image-build 작업이 트리거되는지 확인
Leave a comment