15. URL for sample project
15
https://github.com/uengine-oss/msa-tutorial-class-management-monolith
https://github.com/uengine-oss/msa-tutorial-class-management-msa
https://github.com/uengine-oss/msa-tutorial-class-management-frontend
16. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
20. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
21. DevOps: Issues
Continuous Delivery
21
Company Deploy Frequency Deploy Lead Time Reliability Customer
Responsiveness
Amazon 23,000 / day Minutes High High
Google 5,500 / day Minutes High High
Netflix 500 / day Minutes High High
Facebook 1 / day Hours High High
Twitter 3 / week Hours High High
Typical enterprise Once every 9 months Months or quarters Low / Medium Low / Medium
출처: 도서 The Phoenix Project
Amazon, Google, Netflix, Facebook, Twitter는 얼마나 자주 배포할까요?
28. 28
2. 배포 주기
• 매일 마이너 업데이트
• 메이저 업데이트 (매주 화요일 오후)
3. Deployment Pipeline
출처: http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6449236
Supporting Continuous Delivery
Facebook
29. 29
4. Canary를 통해서 확신 갖기
• Canary란? 실제 production 환경에서 small subset에서 새로운 코드를 돌려보고 옛
날 코드와 비교해서 새로운 코드가 어떻게 돌아가는 지 보는 것
• Canary 분석 작업(HTTP status code, response time, 실행수, load avg 등이 옛날
코드랑 새로운 코드랑 비교해서 어떻게 다른 지 확인하는 것)은 1000개 이상의
metric을 비교해서 100점 만점에 점수를 주고 일정 점수일 경우만 배포할 수 있음.
출처: http://techblog.netflix.com/2013/08/deploying-netflix-api.html
Supporting Continuous Delivery
Netflix
30. 출처 : 2010 architecting for the cloud (http://www.slideshare.net/simone.brunozzi/2010-architecting-for-the-cloud-4719195)
DevOps: Issues
Managing Scalability
33. Top 9 Rules for Cloud Applications (IBM)
33
1
1. Don't code your application directly to a specific topology
2. Don't assume the local file system is permanent
3. Don't keep session state in your application
4. Don't log to the file system
5. Don't assume any specific infrastructure dependency
6. Don't use infrastructure APIs from within your application
7. Don't use obscure protocols
8. Don't rely on OS-specific features
9. Don't manually install your application
39. Micro Service Architecture
Contract based, Polyglot Programming
Separation of Concerns, Parallel Development, Easy Outsourcing
Written in Java
Written in Node
Written in PHP
40. Jeff Bezos Mandate
1. All teams will henceforth expose their data and functionality through
service interfaces.
2. Teams must communicate with each other through these interfaces.
3. There will be no other form of interprocess communication allowed:
no direct linking, no direct reads of another team's data store, no
shared-memory model, no back-doors whatsoever. The only
communication allowed is via service interface calls over the network.
…
4. The team must plan and design to be able to expose the interface to
developers in the outside world. No exceptions.
5. Anyone who doesn't do this will be fired.
40
47. Level 0: Swamp of POX
▪ Use as a RPC, returns full serialized document. e.g. SOAP
47
<openSlotList>
<slot start = "1400" end = "1450">
<doctor>
<name>mark jones</name>
</doctor>
</slot>
<slot start = "1600" end = "1650">
<doctor>
<name>rick jang</name>
</doctor>
</slot>
</openSlotList>
48. Level 1: Resources
Level 1 tackles the question of handling complexity by using divide and
conquer, breaking a large service endpoint down into multiple
resources.
48
<openSlotList>
<slot id=”http://openslots/1234"/>
<slot id=”http://openslots/1235"/>
</openSlotList>
# http://openslots/1234
<slot start = "1400" end = "1450">
<doctor id = "mjones"/>
</slot>
# http://openslots/1235/
<slot start = "1600" end = "1650">
<doctor id = ”rjang"/>
</slot>
i.e. GET /companies/3/employees/123/address
# http://openslots/1234/doctor
<doctor>
<name>mark jones</name>
</doctor>
# http://doctors/rjones
<doctor>
<name>rick jang</name>
</doctor>
49. Level 2: HTTP Verbs
Level 2 introduces a standard set of verbs so that we handle similar
situations in the same way, removing unnecessary variation.
49
Operation HTTP / REST
Create PUT / POST
Read (Retrieve) GET
Update (Modify) PUT / PATCH
Delete (Destroy) DELETE
# POST http://openslots/1234 start=1400 end=1450
# PUT http://openslots/1234 start=1430 end=1450
# PATCH http://openslots/1234 end=1520
# PATCH http://openslots/1234 doctor=http://doctors/rjang
# DELETE http://openslots/1234
50. Level 3: Hypermedia Controls
50
<appointment>
<slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/> <patient id = "jsmith"/>
<link rel = "/linkrels/appointment/cancel" uri = "/slots/1234/appointment"/>
<link rel = "/linkrels/appointment/addTest" uri = "/slots/1234/appointment/tests"/>
<link rel = "self" uri = "/slots/1234/appointment"/>
<link rel = "/linkrels/appointment/changeTime" uri =
"/doctors/mjones/slots?date=20100104@status=open"/>
<link rel = "/linkrels/appointment/updateContactInfo" uri = "/patients/jsmith/contactInfo"/>
<link rel = "/linkrels/help" uri = "/help/appointment"/>
</appointment>
Level 3 introduces discoverability, providing a way of making a protocol more self-
documenting.
진료예약정보
오흐 2시
오후 2시 50분
취소 검사
연락처
변경
53. REST API Design Guidelines
▪ https://hackernoon.com/restful-api-designing-guidelines-the-
best-practices-60e1d954e7c9
▪ REST in Practice, Jim Webber 외
53
56. Netflix
넷플릭스는 수백개의 마이크로서비스를 운영하고 있는 것으로 유명하다. 각
마이크로서비스간에는 REST 방식의 호출을 통하여 연동되며 이들간의 자동화된 식별과 동적
연동을 위하여 자체적인 플랫폼을 구축했고 이를 Netflix OSS 라는 이름으로 오픈소스화 하였다.
57. AWS 기반 마이크로 서비스 전환
사례
Gaming Platform
Mobile Apps and
Serverless Microservices
IoT Service
Serverless Microservices
From Monolithic to
Microservices
Pure Play Video OTT- A
Video & Broadcasting
58. ▪가장 작고 독립적인 서비스로 부터
마이그래이션
▪순차적 레거시의 마이크로서비스 전환을
위한 API GW 적용한 “스트랭글러 패턴”
적용
▪서비스 폴백 테스트 및 자동화가 필수 조건
59. ▪새로 추가/변경 필요한 기능부터 분리
▫안정된 레거시는 가능한 손대지 않음
▫적은 리스크 업무 영역부터
▫기술보다 노하우와 팀의 문화 정립 우선시
▪Business Domain 단위 서비스구성
▫팀단위 분리 X, 기술적 단위 분리 X
▫비즈니스 서브 도메인 단위로의 구성
Separation of Concerns
▫응집도
▪서비스 존재 목적은 재사용되어지는 것
▫표준화된 API I/F
▫자동화된 문서화
60. Success story & Fail story
▪ 카카오의 Digital Transformation 전략
▫ 레퍼런스 은행의 레거시를 수정하지 않고 REST API 화 (스트랭글러)
▫ 모바일 앱 개발에만 집중
▫ 프로젝트 기간 총 2년 내에 완성
vs.
▪ 실패사례 (찾는중, 안알려줌)
▫ 기존의 레거시를 너무 큰 단위로 그대로 도커에 올림
▫ 장애 복구 등 Resilence 를 위한 상황에 전혀 대응하지 못함
▫60
61. Tip: monolithic and MSA
61
monolithic MSA
Aggregation
(데이터 통합)
Backend 가 주도 Front 가 주도
Database 통합 데이터베이스 서비스 별 데이터베이스
필수 환경 WAS DevOps, PaaS (Grid Engine)
서비스 굵기 업무 비즈니스 기능별 구현 팀별, 10000 라인 이하로?,
관심사별
Front 기술 JSP, Struts 등 Server-side
rendering
MVVM, AJAX 등 Client-side
rendering
Container / Packaging WAS / WAR Spring-Boot, Docker
65. Conclusion
▪MSA 는 성공적인 SaaS 의 디자인 패턴:
▪Back-end API 설계가 중요
▫ REST MM Level 3 – HATEOAS
▫ Aggregation of data from multi micro-services
▪MSA 를 적용하려면 작은 단위의 배포를 위한
운영 자동화 환경이 제공되어야 함
▫ Container Orchestrator
▫ DevOps Platform
65
67. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM67
68. 10 Attributes of Cloud Native Applications
68
1. Packaged as lightweight containers
2. Developed with best-of-breed languages and frameworks
3. Designed as loosely coupled microservices
4. Centered around APIs for interaction and collaboration
5. Architected with a clean separation of stateless and stateful services
6. Isolated from server and operating system dependencies
7. Deployed on self-service, elastic, cloud infrastructure
8. Managed through agile DevOps processes
9. Automated capabilities
10. Defined, policy-driven resource allocation
https://thenewstack.io/10-key-attributes-of-cloud-native-applications/
72. Domain-Driven Design
72
• Use Ubiquitous
Language (Domain
Language) as class
names
• Service Decomposition
by Sub-Domain:
1. Course Service
2. Customer Service
3. Class Service
4. Subject Matter Expert
Service
74. Netflix OSS 와 Spring Cloud 의 등장
넷플릭스는 수백개의 마이크로서비스를 운영하고 있는 것으로 유명하다. 각
마이크로서비스간에는 REST 방식의 호출을 통하여 연동되며 이들간의 자동화된 식별과 동적
연동을 위하여 자체적인 플랫폼을 구축했고 이를 Netflix OSS 라는 이름으로 오픈소스화 하였다.
76. Tools: Evolution of Module Systems
76
Java Module System Hypervisors Containers
77. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
78. Domain-Driven Design & MSA
▫어떤 단위가 마이크로 서비스가 될 수 있는가?
: Bounded Context 마이크로 서비스 크기 식별
▫서비스를 결합 할 때는 어떻게 결합할 것인가?
: Aggregate REST 데이터의 Aggregation
▫도메인 이벤트의 식별 Event-driven Architecture 도출
▫잦은 변화에 유연한 설계 동적 서비스 발견과 연동
▫레거시 시스템의 단계적 폐기 모더나이징
▫리팩터링 전략 지속적 딜리버리와 개선
DDD for MSA
Applicable Practices:
ㄱ. 이벤트 스토밍과 BPMN: 이벤트, 커맨드, 액터, 어그리게이트 식별
ㄴ. UML 과 컨텍스트 맵: 보편언어, 바운디드 컨텍스트 식별
80. DDD: Domain Object Classifications
80
Classification Description Example
Entity ▪ Objects that have a distinct identity that
runs through time and different
representations.
▪ Usually big things like Customer, Ship, Rental
Agreement.
Business
Event
▪ Captures the memory of something
interesting which affects the domain
▪ I go to Babur's for a meal on Tuesday, and pay
by credit card. This might be modeled as an
event, whose event type is 'make purchase',
whose subject is my credit card, and whose
occurred date is Tuesday. If Babur's uses an
old manual system and doesn't transmit the
transaction until Friday, the noticed date would
be Friday.
Service ▪ A standalone operation within the context
of your domain. A Service Object collects
one or more services into an object.
Typically you will have only one instance of
each service object type within your
execution context.
▪ Services are usually accesses to external
resources like Database Connection,
Messaging Gateway, Repository, Product
Factory.
81. Modeling Domain Classes and Generate
Code
81
Code
Model
In UML Modeling Tool
(i.e. Visual Paradigm)
In IDE
(i.e. Eclipse)
82. Event Storming
▪이벤트스토밍은 시스템에서 발생하는 이벤트를 중심 (Event-First) 으로 분석하는 기법으로 특히 Non-blocking, Event-driven 한 MSA 기반 시스템을
분석에서 개발까지 필요한 도메인에 대한 탁월하게 빠른 이해를 도모하는데 유리하다.
▪기존의 유즈케이스나 클래스 다이어그래밍 방식은 고객 인터뷰나 엔티티 구조를 인지하는 방식과 다르게 별다른 사전 훈련된 지식과 도구 없이 진행할 수
있다.
▪진행과정은 참여자 워크숍 방식의 방법론으로 결과는 스티키 노트를 벽에 붙힌 것으로 결과가 남으며, 오랜지색 스티키 노트들의 연결로 비즈니스
프로세스가 도출되며 이들을 이후 BPMN과 UML 등으로 정재하여 전환할 수 있다.
vs.
83. Event Storming – Event 들을
먼저 도출
과정이등록됨 강의가등록됨
강사가매핑됨
수강이신청됨
강의일정변경
됨
강의가 취소됨
수강승인됨
지불요청됨
우리 서비스에는 어떤 비즈니스 이벤트들이 발생하는가?
현업이 사용하는 용어를 그대로 사용 (Ubiquitous Language)
용어의 namespace 를 구지 나누려는 노력을 하지 않음
84. Event Storming – Command
도출
과정정보
입력
강의정보
입력
강사매핑
수강정보
등록
일정변경
Event를 발생시키는 명령은 무엇인가? UI를 통해? or 시간도래? or 다른 이벤트에 의해?
강의취소
축하메시
지발송
과정이등록됨 강의가등록됨
강사가매핑됨
수강이신청됨
강의일정변경
됨
강의가 취소됨
수강승인됨
지불요청됨
강사달력
에 추가
취소
안내메일
발송
변경
안내메일
발송
85. Event Storming – Entity 도출
과정
• 이름
• 기간
• 비용
강의
• 일정
• 강사
수강
• 고객
• 강의
과정정보
입력
강의개설
정보입력
강사매핑
수강정보
등록
일정변경
강의취소
축하메시
지발송
과정이등록됨 강의가등록됨
강사가매핑됨
수강이신청됨
강의일정변경
됨
강의가 취소됨
수강승인됨
지불요청됨
강사달력
에 추가
취소
안내메일
발송
변경
안내메일
발송
86. Event Storming – Sub domains
과정
• 이름
• 기간
• 비용
강의
• 일정
• 강사
수강
• 고객
• 강의
과정정보
입력
강의개설
정보입력
강사매핑
수강정보
등록
일정변경
강의취소
축하메시
지발송
과정이등록됨 강의가등록됨
강사가매핑됨
수강이신청됨
강의일정변경
됨
강의가 취소됨
수강승인됨
지불요청됨
강사달력
에 추가
취소
안내메일
발송
변경
안내메일
발송
과정강의관리 고객수강관리
마케팅
88. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
89. Service Implementation
▪ You have Powerful Tool:
Domain-Driven Design and Spring Boot / Spring Data REST
▪ Domain Classes : Entity or Value Object
▪ Resources can be bound to Repositories Full HATEOAS service can be generated!
▪ Services can be implemented with Resource model firstly
▪ Low-level JAX-RS can be used if not applicable above
89
91. Spring Boot: A MSA Chassis
91
• Simple Java (POJO)
• Minimal Understanding Of Frameworks and Platforms
(Using Annotations)
• No Server-side GUI rendering
(Only Exposes REST Service)
• No WAS deployment required
(Code is server; Tomcat embedded)
• No XML-based Configuration
Main Application
Domain Classes
Services and Repositories
Settings
92. Lab: Create a Spring boot application
92
Go to start.spring.io
Set metadata:
- Group: com.education
- Artifact: education
- Dependencies:
H2
Rest Repositories
JPA
Press “Generate Project”
Extract the downloaded zip file
Build the project:
./mvnw spring-boot:run
Port 충돌시:
./mvnw spring-boot:run -Dserver.port=8081
93. Running Spring Boot Application
93
$ mvn spring-boot:run # 혹은 ./mvnw spring-boot:run
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building ….
[INFO] ------------------------------------------------------------------------
[INFO] Downloading: https://repo.maven.apache.org/maven2/org/springframework/security/spring-security-core/maven-
metadata.xml
[INFO] Downloading: https://oss.sonatype.org/content/repositories/snapshots/org/springframework/security/spring-security-
core/maven-metadata.xml
[INFO] Downloading: https://repo.spring.io/libs-release
:
Started Application in 11.691 seconds (JVM running for 14.505)
Source code:
$ git clone https://github.com/uengine-oss/software-modeling-class-management-monolith.git
95. Entity Class 작성
과정 강의 수강
@Entity
public class Clazz{
@Id
@GeneratedValue
Long id;
String states;
int evaluationRate;
String title;
@ManyToOne @JoinColumn(name="cid")
Course course;
}
@Entity
public class Course {
@Id
@GeneratedValue
Long id;
String title;
int duration;
String description;
int maxEnrollment;
int minEnrollment;
Double unitPrice;
@OneToMany( cascade = CascadeType.ALL,
fetch = FetchType.EAGER, mappedBy = "course")
List<Clazz> clazzes;
}
@Entity
public class Enrollment {
@Id
@GeneratedValue
Long id;
@OneToOne
Customer customer;
}
96. Service Object* 와 API의 생성
Repository Pattern 으로 생성된 것 사용할 수
있는 경우
과정과 강의 API 는 Order Repository 에서
생성된 CRUD actions 들 중 POST Service
를 그대로 사용할 수 있으므로 별도 구현할
필요 없다. 마찬가지 주문서 수정, 삭제도
각각 PATCH, DELETE 로 API 생성
전체의 약 7~80% 커버
Repository 에서 생성된 API 를 사용 못하는 경우, 별도
Spring MVC Service 로 생성
강사매핑, 지불 등을 위한 백엔드 API 는 Order
Repository 에 생성된 PUT-POST-PATCH-DELETE 중
적합한 것이 없으므로 별도 추가 action URI를 만드는
것이 적합
나머지 2~30% 수준
@Service
public interface SharedCalendarService {
@RequestMapping(method = RequestMethod.GET, path="/calendar/{instructorId}/{date}"
Resources getSchedules(@PathVariable("instructorId") Long instructorId,
@PathVariable("date") String date);
}
public interface CourseRepository extends PagingAndSortingRepository<Course, Long> {
List<Course> findByTitleContaining(@Param("title") String title);
}
과정정보
C.R.U.D
강의정보
C.R.U.D
강사매핑
수강정보
C.R.U.D
일정변경수강취소
…. 등등등
지불 축하메시
지발송
101. Create new course
101
$ http localhost:8080/courses title="SOA" duration=5 maxEnrollment=50 minEnrollment=10
{
"_links": {
"self": {
"href": "http://localhost:8080/courses/1"
}
},
"courseId": null,
"description": null,
"duration": 5,
"maxEnrollment": 5,
"minEnrollment": 1,
"title": "SOA"
}
URI of the new course
102. Create a class of the course
102
$ http POST localhost:8080/clazzes date=“2018-12-5” course="http://localhost:8080/courses/1"
$ http "http://localhost:8080/courses/1/clazzes"
URI of the SOA course
{
"_embedded": {
"clazzes": [
{
"_links": {
"self": {
"href": "http://localhost:8080/clazzes/2"
}
},
"evaluationRate": 0,
"states": null
}
]
},
Course is aggregation root
103. Mapping an instructor to the class
103
$ http "http://localhost:8080/instructors" firstName="진영" lastName="장” # 강사 등록
$ http "http://localhost:8080/clazzDays" clazz="http://localhost:8080/clazzes/3" date="2012-04-23T18:25:43.511Z”
# 클래스의 일정 등록
# 다른 클래스 하나 더 생성
$ http localhost:8080/clazzes course="http://localhost:8080/courses/1"
$ http "http://localhost:8080/clazzDays" clazz="http://localhost:8080/clazzes/5" date="2012-04-23T18:25:43.511Z”
# 일정이 중복되는 강의로
104. Mapping an instructor to the class
104
$ http PATCH "http://localhost:8080/clazzes/3" instructor="http://localhost:8080/instructors/2" #
장진영 강사에게 첫 클래스를 지정
$ http PATCH "http://localhost:8080/clazzes/5" instructor="http://localhost:8080/instructors/2" #
두번째 클래스는 같은 날에 있기 때문에 장진영 강사 일정이 중복되어 오류가 날 것.
$ http "http://localhost:8080/instructors" firstName="상철" lastName="황” # 강사 2 등록
$ http PATCH "http://localhost:8080/clazzes/5" instructor="http://localhost:8080/instructors/8" # 이
요청은 성공 해야 함. 황상철 강사는 일정이 가능하기 때문에...
105. Enroll in the class and approve the
enrollment
105
$ http localhost:8080/customers firstName="진영" lastName="장" #수강생 회원 등록
$ http localhost:8080/enrollments clazz="http://localhost:8080/clazzes/2"
customer="http://localhost:8080/customers/3" #수강 예약
$ http "http://localhost:8080/customers/3/enrollments" #수강 목록 조회
$ http PATCH "http://localhost:8080/enrollments/4" status="approved" #수강 승인
106. Not applicable to Entity / Repository ?
use “Service”
▪ For Shared Calendar Service, this is not en entity
▪ In this case, we introduce ‘Service’
▪ Define interface first by using JAX-RS (contract)
▪ Uses return type as “ResourceSupport” for HATEOAS link and
loose coupling
106
107. Create a Service Interface
107
public interface SharedCalendarService {
@RequestMapping(
method = RequestMethod.GET,
path="/instructors/{instructorId}/schedule/{date}”
)
ResourceSupport getSchedules(
@PathVariable("instructorId") Long instructorId,
@PathVariable("dateStr") String dateStr
);
}
108. Create a Service Implementation
108
@Component
public class SharedCalendarServiceImpl implements SharedCalendarService {
@Autowired
ScheduleRepository scheduleRepository;
@Override
public ResourceSupport getSchedules(Long instructorId, String dateStr) {
List<Schedule> schedules = scheduleRepository.findByInstructorIdAndDate(instructorId, date);
return new ScheduleResource(schedules);
}
}
111. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM111
HATEOAS API
112. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
113. “
▪From Monolith to Microservices
113
https://github.com/jinyoung/software-modeling-class-management-monolith
https://github.com/jinyoung/software-modeling-class-management-msa
115. A Sub-domain = A Microservice = A
Spring Boot App
115
Source:
Alpha Code: https://www.youtube.com/channel/UCmbnw2hZFf6JzWICZIPe9cg
116. Example of Context Map
▪ U: Up-stream
▪ D: Down-stream
▪ AR: Aggregation Root
116
117. Context Map – Capstone Project
117
• Sub-Domains:
1. Core Domains:
Course, Class and Subject
Matter Expert Service
2. Supportive Domains:
Customer Service
• Bounded Context and
Aggregation Root:
1. Course Class
2. Customer Class
3. Class Class
4. SME Class
SHARED KERNEL
CONFORMIST
SHARED KERNEL
SHARED KERNEL
U D
U
D
CONFORMIST
119. 검증: 트랜잭션 검증 매트릭스*
Customer Order Inventory
고객 주문이력 입출고
이력
재고량
Customer 가입 CU
Order
주문 R C C U
취소 D C U
Inventory
입고 C U
출고 C U
119 ACID Transaction Don’t care Eventual Transaction
Domain /
Entities
Domain/
Command
120. 검증: 트랜잭션 유형 결정
120
ACID Transaction Don’t care Eventual Transaction
▪ 이벤트의 발생 MS 와 Entity 접근의 CUD 가 완전히 동일한 MS
내에서만 벌어지면 ACID Transaction
▪ 이벤트의 발생 MS 와 Entity 접근의 MS 가 R (read) 수준에서만
분산되어 벌어지면 값 참조 호출만으로 문제없음(don’t care)
▪ 이벤트의 발생 MS 와 Entity 접근의 MS 가 CUD 차원에서 걸쳐지면
Eventual Transaction 비용 발생
122. Sharing Core-Domain Classes
(It doesn’t mean database sharing!)
122
Shared-kernel
(shared classes and
interfaces)
Course
Clazz
SME
Maven depency
Maven depency
Maven depency
123. Problems in separating services in
Spring-data-rest:
▪ JPA Association (i.e. ManyToOne) annotations are not available
for generating HATEOAS links anymore if the associated class
doesn’t have it’s Repository in the same application.
▪ We need to create HATEOAS link by our-selves for every
associations, that is so cumbersome and error-prone.
▪ Let’s Develop a new annotation for RestAssocation!
123
124. Changing ORM Relations to REST
Association
124
@Entity
public class Course {
@OneToMany( cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "course")
List<Clazz> clazzes;
}
@Entity
public class Course {
@RestAssociation(serviceId="clazz" path="/clazzes/search/findByCourseId?courseId={courseId}", joinColumn = "courseId")
List<Clazz> clazzes;
}
NOTE: @RestAssociation annotation is not a spring-related annotation, it’s provided by third-party framework uEngine developed
125. Tip: Installing HATEOAS Resource
Processor
125
@Bean
public ResourceProcessor<Resource<?>> resourceProcessorForRestAssociation() {
return new ResourceProcessor<Resource<?>>() {
@Override
public Resource<?> process(Resource<?> resource) {
// additional processing only for entities that have rest resources
Map<String, String> links = new HashMap<String, String>();
Field[] fields = resource.getContent().getClass().getDeclaredFields();
for (Field field : fields) {
RestAssociation restAssociation = field.getAnnotation(RestAssociation.class);
if (restAssociation != null && resource.getId() != null) {
String resourceId = resource.getId().getRel();
if (resourceId != null) {
// construct a REST endpoint URL from the annotation properties and entity id
String path = restAssociation.path();
path = evaluatePath(path, resource.getContent());
if (path == null) continue;
if (!path.startsWith("/")) path = "/" + path;
Code:
https://github.com/uengine-
oss/metaworks4/blob/master/src/main/java/org/metaworks/springboot
/configuration/Metaworks4WebConfig.java
Hints from:
https://objectpartners.com/2016/02/18/mapping-jpa-
entities-to-external-rest-resources-in-spring-data-rest/
126. Loose coupling: HATEOAS links are
changed but same usage in API!
▪ Changing URI patterns doesn’t matter!
▪ From consumer’s point of view (i.e. UIs, 3rd-party apps), following the
links, results are always same
126
$ http localhost:8088/courses/1
{
"_links": {
”clazzes": {
"href": "http://localhost:8088/courses/1/clazzes"
“http://localhost:8089/clazzes/findByCourseId?courseId=1”
}
},
"maxEnrollment": 5,
"minEnrollment": 1,
"title": "SOA"
}
127. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM127
Loose coupled design (HATEOAS API,
Service Decomposition)
131. Running an Eureka server
131
@SpringBootApplication
@EnableEurekaServer
public class RegistryServiceApplication {
public static void main(String[] args) {
….
}
}
#application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
registerWithEureka: false
fetchRegistry: false
serviceUrl:
defaultZone:
http://${eureka.instance.hostname}:${server.port}/eureka/
132. Running Registry and Proxy
132
1. 가장 먼저 실행할 것은 Registry (Eureka 서버) 임. [동사무소]
2. 다음으로 실행할 것은 Proxy (Zuul 서버) 임. [이정표 서비스]
$ cd uengine-proxy-server/
$ mvn spring-boot:run
$ cd uengine-registry-server/
$ mvn spring-boot:run
133. Running Micro Services in local machine
133
2. Run and test Class Service
1. Run and test Course Service
$ cd clazz-service/
$ mvn spring-boot:run –Dserver.port=8088
Launch another shell and confirm server is up:
$ http localhost:8088/clazzes
$ cd course-service/
$ mvn spring-boot:run –Dserver.port=8089
Launch another shell and check the server is up:
$ http localhost:8089/courses
134. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
135. “
135
Service Composition
with User Interface
▪ Extended Role of Front-end in MSA Architecture: Service
Aggregation
▪ Why MVVM?
▪ W3C Web Components Standard – Domain HTML Tags
▪ Implementation: Polymer and VueJS
▪ Another: ReactJS and Angular2
▪ Micro-service Mashups with Domain Tags: i.e. IBM bluetags
▪ Cross-Origin Resource Sharing
▪ API Gateway (Netflix Zuul)
https://www.youtube.com/watch?v=djQh8XKRzRg
https://github.com/IBM-Cloud/bluetag
136. 아마존 닷컴은 다양한 서비스 제공과 효율적인 운영 환경 전환을 위해 분산 서비스 플랫폼으로 전환
하였습니다.
2001년 아마존은 주요한 아키텍쳐 변화가 있었는데
기존 모놀리식(Monolitic) 기반에서
서로 다른 어플리케이션 기능을 제공하는
분산 서비스 플랫폼으로 변화 하였습니다.
현재의 Amazon.com의 첫 화면에 들어 온다면,
그 페이지를 생성하기 위해
100여개가 넘는 서비스를 호출하여 만들고 있습니다.
137. W3C Web Components
137
<style>
style for A
style for B
style for C
</style>
<html>
element for A
element for B
element for C
</html>
<script>
script for A
script for B
script for C
</script>
#A.html
<style>
style for A
</style>
<html>
element for A
</html>
<script>
script for A
</script>
#B.html
<style>
style for B
</style>
<html>
element for B
</html>
<script>
script for B
</script>
#C.html
<style>
style for C
</style>
<html>
element for C
</html>
<script>
script for C
</script>
#index.html
<A> <A>
<B> <B> <B>
<C>
▪ Custom elements
▪ HTML imports
▪ Template
▪ Shadow DOM
139. Frameworks supporting Web
Components
139
• Provides Cohesive Component Model
• Component Composition by HTML
markup
• Dynamic Data Binding
• Responsive Web by Material Design
• Standard
Polymer VueJS
141. Custom tag for Domain Class: <course> tag
141
<template>
<div>
<h1>Course Management</h1>
<course v-model="courses[index]" v-for='(course, index) in courses'
@change="updateCourse" @remove="removeCourse"
@classes="jumpToClasses"></course>
<h2>Add New Course</h2>
<course v-model="newCourse" editMode=true isNew=true
@add="addCourse"></course>
</div>
</template>
142. Custom Tag for Domain Class: <class>
tag
142
<template>
<div>
<h1>Class Management</h1>
<clazz v-model="clazzes[index]" v-for='(clazz, index) in clazzes'
@remove="removeClazz"></clazz>
<clazz v-model="newClazz" editMode=true isNew=true @add="addClazz"></clazz>
</div>
</template>
143. Data binding to Domain Class Tags
143
<script>
var courses = [];
var me = this;
backend.$bind("courses", courses);
courses.$load().then(function(courses){
me.courses = courses; // set the view's data with the loaded data obtained from backend.
});
</script>
<course v-model="courses[index]" v-for='(course, index) in courses'
@change="updateCourse" @remove="removeCourse"
@classes="jumpToClasses"></course>
144. Tenant UI Customization (Composition)
by Tag composition
144
Domain HTML Tags
<clazz>
<course>
<instructor>
<clazz-day>
….
Tenant A
Tenant B
Tenant C
145. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM145
147. 147
API Gateway: Edge Service
Acting like “Skin” to access our services :
• Re-Routes to multiple services
• Allows CORS
• Checks ACLs
• Prevent DDOS etc.
148. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM148
149. Securing, Routing and Load-balancing
149
Front-End
API GW (ZUUL)
Clazz SME 1Course 1
EUREKA
http://abc.com/courses/** http://abc.com/clazzes/** http://abc.com/instructors/**
Course-service: ip1, ip2
Clazz-service: ip3
Sme-service: ip4, ip5
Course 2 SME 2
Ip1:port1/instructors/** Ip2:port2/instructors/**
Ip3:port3-1/clazzes/**
Ip4:port4-1/smes/**
Ip5:port5-1/smes/**
• Add CORS Header
• Routes actual backend service
• Load Balancing
• Fallback
SME 3 Ip6:port6-1/smes/**
By container orchestrator something
151. Authenticating Microservices
151
Front-end or 3rd-party Apps
API GW (ZUUL)
Clazz SMECourse
EUREKA
/courses/** /clazzes/** /instructors/**
IAM
(Oauth
token
provider)
1
2
3
• Request Access Token with
Permission scopes
• Acquire Access Token
• Request with Token (Header)
• API Gateway validates the token
• Easy and integrated way to provide
APIs for 3rd Party Apps
Stateless 한 인증 정보 관리
Memory 사용 최적
152. 152
Zuul API Gateway for Security
▪ Authorizing Microservices with OAuth2 and PreFilter of Zuul
zuul:
routes:
courses:
path: /courses/**
serviceId: course-service
stripPrefix: false
iam-scopes:
- catalog-access/GET
- catalog-manage/POST-PATCH-DELETE
https://github.com/TheOpenCloudEngine/uEngine-
cloud/blob/master/uengine-cloud-
zuul/src/main/java/org/uengine/zuul/pre/IAMFilter.java
153. 153
OAuth2 Authorization Server
implemented by Spring Security
• https://github.com/Baeldung/spring-security-oauth
• https://www.keycloak.org/
• https://github.com/TheOpenCloudEngine/uEngine-cloud/tree/master/uengine-cloud-iam
154. 154
Exposing New APIs
▪ Exposing New API from existing microservices
▪ For more complicated services, BPM can be another option
zuul:
routes:
courses:
path: /courses/**
serviceId: course-service
stripPrefix: false
iam-scopes:
- catalog-access/GET
- catalog-manage/POST-PATCH-DELETE
156. 서비스의 호출 방식 2가지
▪ 외부에서
156
마이크로 서비스 간
(inter-microservice call)
HTTPClient 로 REST 호출 혹은 Event 로 pub/sub
Feign 을 사용, @Autowired 로 proxy 객체리턴 혹은
MOM (Apache Kafka), Spring Cloud Stream
Ribbon 이 Eureka 를 통하여 직접 마이크로
서비스가 로드밸런싱 된 대상을 선택
AJAX 로 REST 호출
Hybind 를 사용, 자바스크립트객체와
Resource 바인딩
Zuul 을 경유하여 Eureka 에서 발견된
path 에 따른 서비스가 라우팅
157. Inter-microservices Call
157
Front-end
API GW (ZUUL)
ScheduleCalendar Clazz
Course
EUREKA
Course: ip1, ip2
Clazz: ip3
ScheduleCalendar: ip4, ip5
Ribbon
Zuul 을 경유하지 않고 직접 내부 IP
로 접근
159. Consumer Code: Clazz
159
@Entity
public class Clazz {
@Autowired
SharedCalendarService sharedCalendarService;
@PrePersist
public void beforeSave() {
if(getInstructor()!=null){
if(getClazzDays()==null)
throw new RuntimeException("Instructor can be mapped after adding class days for this class.");
for(ClazzDay clazzDay : getClazzDays()){
List<ClazzDay> schedules = sharedCalendarService.getSchedules(clazzDay.getDate(), getInstructor());
if(schedules!=null && schedules.size() > 0){
throw new RuntimeException("Instructor " + getInstructor().getFirstName() + " already have another class for that time slot.");
}
}
}
}
}
160. Service Interface: mark as @FeignClient
- EUREKA 버전
160
---- Service Id
이걸로, Autowired 시에
식별됨
@FeignClient("calendar")
public interface SharedCalendarService {
@RequestMapping(method = RequestMethod.GET, path="/calendar/{instructorId}/{date}")
Resources getSchedules(@PathVariable("instructorId") Long instructorId, @PathVariable("date") String date);
}
161. Service Interface: mark as @FeignClient
- Kube-DNS 버전
161
---- url 이 부여되면
우선으로 url 을 직접호출함
@FeignClient(name = "calendar-service”, url=“http://calendar-service:8080”)
public interface SharedCalendarService {
@RequestMapping(method = RequestMethod.GET, path="/calendar/{instructorId}/{date}")
Resources getSchedules(@PathVariable("instructorId") Long instructorId, @PathVariable("date") String date);
}
163. Event Consumer
163
@Component
public class EventListener {
/** version 1. callback version **/
@StreamListener(Streams.INPUT)
public void handleClazzDay(@Payload ClazzDay clazzDay) {
System.out.println("Received: "+ clazzDay.getDate()); //db 에 저장.
}
}
164. Event Publisher
164
@PrePersist
public void publishEvent() throws JsonProcessingException {
Streams streams = Application.getApplicationContext().getBean(Streams.class);
MessageChannel messageChannel = streams.outboundChannel();
messageChannel.send(MessageBuilder
.withPayload(this) // POJO 를 그대로 보낸다.
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
.build());
System.out.println("Event published");
}
169. 분산 트랜잭션 처리 –
Monolothic
총구매액: 500 총마일리지: 5
총구매액: 600 총마일리지: 6
Consistent
In-consistent
조회화면서비스구성 (모놀로씩)
Mileage
(MongoDB)
Order
(MySQL)
Client (Web/Mobile)
POST
Order Mileage
총구매액: 700 총마일리지: 7
170. 분산 트랜잭션 처리 – MS 화,
순차 호출
총구매액: 500 총마일리지: 5
총구매액: 600 총마일리지: 5
총구매액: 600 총마일리지: 6
총구매액: 700 총마일리지: 6
Consistent
In-consistent
조회화면서비스구성 (클라이언트가 순차 호출)
Mileage
(MongoDB)
Order
(MySQL)
Client (Web/Mobile)
POST (성공시) - POST
171. CQRS 를 통한 분산 트랜잭션
처리
총구매액: 500 총마일리지: 5
총구매액: 600 총마일리지: 5
총구매액: 600 총마일리지: 6
총구매액: 700 총마일리지: 6
총구매액: 700 총마일리지: 7
Consistent
In-consistent
조회화면서비스구성 (CQRS)
Mileage
(MongoDB)
Order
(MySQL)
Kafka
OrderPlaced
(pub)
OrderPlaced
(sub)
Client (Web/Mobile)
POST
172. 여기서 선택의 길을 만남
• 내 서비스에서 데이터 불일치가 얼마나 미션 크리티컬 한가?
• 크리티컬 하다고 응답한다면, 내 서비스의 성능과 확장성에 비하여
크리티컬 한가?
• 성능과 확장성 보다 크리티컬 하다면, 성능과 확장성을 포기할 수 있는가?
• 성공한 내 서비스의 경쟁자들은 무엇을 포기했는가?
• 강력한 의사결정 필요 (무엇으로 태어날 것인가…)
173. CQRS 를 통한 분산 트랜잭션
처리 – 불일치가 Mission Critical
한 경우
총구매액: 500 총마일리지: 5
총구매액: 600 총마일리지: 5 (PENDING)
총구매액: 600 총마일리지: 6
총구매액: 700 총마일리지: 6 (PENDING)
총구매액: 700 총마일리지: 7
Consistent
In-consistent
조회화면서비스구성 (CQRS)
Mileage
(MongoDB)
Order
(MySQL)
Kafka
OrderPlaced
(pub, PENDING)
OrderPlaced
(sub)
Client (Web/Mobile)
POST
All-done
(pub)
All-done
(sub, CLEAR PENDING)
174. CQRS 를 통한 분산 트랜잭션
처리 – Rollback (Saga Pattern)
총구매액: 500 총마일리지: 5
총구매액: 600 총마일리지: 5 (PENDING)
총구매액: 600 총마일리지: 6
총구매액: 700 총마일리지: 6 (PENDING)
총구매액: 700 총마일리지: 7 실패
Consistent
In-consistent
조회화면서비스구성 (CQRS)
Mileage
(MongoDB)
Order
(MySQL)
Kafka
OrderPlaced
(pub, PENDING)
OrderPlaced
(sub)
Client (Web/Mobile)
POST
All-done
(pub)
FAILED
(sub, DELETE or CANCEL)
FAILED
(pub)
If~else
총구매액: 600 총마일리지: 6
176. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM176
177. “
177
Service Composition:
Orchestration with BPMN
▪ The highest level of SOA Maturity Model:
Dynamically reconfigurable
▪ Dynamic Application Assembly by Business
Process Modeling (BPMN 2.0)
▪ BPMN 2.0 Tools: Camunda BPM, uEngine5
▪ Cloud Service Brokerage with BPM: Intergration
CSB
▪ IBM BPM on Cloud, Mendix and Appian
https://www.youtube.com/watch?v=imS_51Ypnro
https://mikethearchitectblog.wordpress.com/2009/09/19
/soa-maturity-models/
179. BPMN Tool: Camunda BPM
▪ Full-support of BPMN 2.0
▪ Web based BPMN designer
▪ Micro service architecture based
runtime – Spring boot
▪ Open Source!
179
180. BPMN Tool: uEngine 5 BPM
▪ Almost full-support of BPMN 2.0
▪ Web based BPMN designer
▪ Micro service architecture based
runtime – Spring boot
▪ Open Source!
▪ Support Spring Cloud & Netflix
OSS for dynamic discovery &
binding
180
182. Process Modeling
▪ Go to http://front-end-dev.pas-mini.io/#/definition/Course Enrollment
182
183. Process Modeling: Pools from EUREKA
▪ Double-click the title of pool ”Class-Course” or “Class-Class”
▪ Pools can be selected from the service list from EUREKA server
183
184. Process Modeling: REST Invocation
▪ Double-click the "Search Courses” task and see the detail settings how to make a REST
invocation:
184
CLASS-COURSE
185. Process Execution & Monitoring
▪ Press the execution button
▪ Go to ‘Workspace’ menu
▪ Confirm work-items assigned to me
▪ Complete the task
▪ Confirm process status by
switching the tab to ‘INFO’
▪ Follow the process
185
186. Process Modeling: Exposing a REST Service
▪ Go to http://front-end-dev.pas-mini.io/#/definition/Course Enrollment Chatbot
▪ Change the type of start event to ‘Message Start Event’
▪ Set the ‘Service Path’ for the URI of service
▪ Deploying the process will create a new
micro service for accepting the request
to begin the process.
186
188. Connect the process service with a chatbot
interface
▪ Go to https://center-pf.kakao.com/login
▪ Create an account or login
▪ 관리 상세설정 공개 설정
▫ 홈 공개 On
▫ 검색허용 On
▫ 노출 허용 On
▪ 스마트채팅 API형 설정하기
▫ 앱 url: http://uengine5-router.pas-mini.io/services/course-
enroll
▫ Check the API test
188
189. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM189
190. “
Table of Content
Microservice and SOA
Programming+Microservice-Based
DevOps Project
1. Review for the Domain Problem: A Public Education Service
2. Architecture and Approach Overview
3. Domain Analysis with DDD and Event Storming
4. API Design and Service Decomposition
5. Service Implementation with Spring Boot and Netflix OSS
6. Monolith to Microservices
7. Service Composition with UI, Composite Services, and BPM
8. Implementing DevOps Environment with Kubernetes, Istio and Gitlab
191. “
191
DevOps
▪ DevOps Process and Tools
▪ Deploy Strategies
▪ Containers and Orchestrators
▪ Cloud Foundry, Bluemix, and Kubernetes
https://www.youtube.com/watch?v=_I94-tJlovg
193. Devops Deploy Strategies
▪ https://thenewstack.io/deployment-strategies/
▪ Recreate: Version A is terminated then version B is rolled out.
▪ Ramped (also known as rolling-update or incremental): Version B is slowly
rolled
out and replacing version A.
▪ Blue/Green: Version B is released alongside version A, then the traffic is
switched
to version B.
▪ Canary: Version B is released to a subset of users, then proceed to a full
rollout.
▪ A/B testing: Version B is released to a subset of users under specific
condition.193
207. Running apps anywhere and reliably
▪ 개발, 스테이징, 운영에서 최대한 동일하게 동작하기
위해서는
▫ 죽였다 살려내면 복구되는 (Immutable Image)
▫ 어디서나 실행되는
▫ 그러면서 가벼운 환경
208. Tools: Evolution of Module Systems
208
Java Module System Hypervisors Containers
209. Container 의 간략한 설명
▪Image: a lightweight, stand-alone,
executable package that includes
everything needed to run a piece of
software, including the code, a runtime,
libraries, environment variables, and
config files.
▪Container: a runtime instance of an
image—what the image becomes in
memory when actually executed. It runs
completely isolated from the host
environment by default, only accessing
host files and ports if configured to do so.
209
211. Labtime: 도커 이미지 스크립트
# 기반 이미지
FROM openjdk:8u111-jdk-alpine
# 볼륨 연결
VOLUME /tmp
# 애플리케이션 복사
ADD /target/*.jar app.jar
# 포트노출
EXPOSE 8080
# 자바 실행
ENTRYPOINT ["java","-Xmx256M","-jar","/app.jar"]
211
220. Kubernetes Object Model
Service
(name: serviceId)
Deployment
ReplicaSet
(Blue)
redirects
Creates / manages
Pod
Contai
ner
Contai
ner
Pod
Contai
ner
Contai
ner
ReplicaSet
(Green)
Pod
Contai
ner
Contai
ner
Pod
Contai
ner
Contai
ner
• Keep replica count as
desired (replicas=2)
• Dynamic Service Binding
• e.g. http://serviceId:8080
• Zero-down time deployment
e.g. Blue / Green
• Service Hosting
Responsible for:
http://serviceId:8080
222. Kubernetes Object Model
▪ apiVersion : mentions the API endpoint on the API
server which we want to connect to.
▪ kind : mentions the object type – example
has Deployment.
▪ metadata : has the basic information to objects,
like the name.
▪ spec (spec and spec.template.spec) : defines the desired
state of the deployment. In our example, we want to
make sure that, at any point in time, at least 3
Pods are running, which are created using the Pods
Template defined in spec.template.
▪ spec.template.spec : defines the desired state
of the Pod. The example Pod would be created
using nginx:1.7.9.
Once the object is created, the Kubernetes system attaches
the status field to the object
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
Deployment object Example
223. Lab Time: 기본적인 kubectl명령어
▪객체 목록 불러오기
▫ “kubectl get [객체 타입]“
Ex) kubectl get pods : pod 목록 불러온다.
▪객체 삭제하기
▫ “kubectl delete [객체 타입] [객체 이름]”
Ex) “kubectl delete pods wordpress-5bb5dddcff-kwgf8”
▫ “kubectl delete [객체타입,객체타입,…] --all“
Ex) “kubectl delete services,depeloyments,pods –-all”
- 실습 중에 잘못 생성되었거나 초기화가 필요할 경우 사용
▪객체 상세 설명 확인하기
▫ “kubectl describe [객체 타입] [객체 이름] ”
Ex) “kubectl describe service wordpress”
224. 이미지를 통한 어플리케이션 배포
• 현재 작동 중인 pod들이 없는지 확인
▫ kubectl get pods
▪ Nginx이미지 예제로 배포하기
▫ kubectl run first-deployment --image=nginx
▪ 실행된 Pods 확인
▫ kubectl get pods
(검색된 Pod의 이름을 복사한다. (각 pod들은 고유한 이름을 갖는다.)
225. Pod에 접속하기
▪ 복사된 pod이름으로 접속하기
▫ Kubectl exec -it [복사된 pod 이름] -- /bin/bash
▪ Pod 내에서 접속하기 (위 명령어로 진입후에는 리눅스 명령어를
받는다)
▫ 해당 경로에 있는 html 파일을 호출하는 어플리케이션이다.
echo Hello nginx
▫ Curl 명령어를 사용하기 위한 업데이트를 한다.
apt-get update
apt-get curl
▫ Curl 명령어로 호출하기
curl localhost
226. 설정 파일을 통한 pod 배포
▪ 아래 내용으로 nano editor 를 이용하여 declarative-pod.yaml 파일을 만든다.
▫ Nginx 이미지를 기반으로 pod를 배포하는 설정파일이다
apiVersion: v1
kind: Pod
metadata:
name: declarative-pod
spec:
containers:
- name: memory-demo-ctr
image: nginx
228. 설정 파일을 통한 pod 배포
▪ nano declarative-pod.yaml 파일로 배포를 한다.
▫ kubectl create -f declarative-pod.yaml
( -f 는 파일 경로를 설정해서 배포할 수 있는 옵션이다.)
▪ 배포된 pods들을 검색하여 접속을 해보자
▫ 이름이 설정대로 declarative-pod 로 생성되었다.
kubectl get pods
▫ 접속해보자
kubectl exec -it declarative-pod -- /bin/bash
apt-get update
apt-get install curl
curl localhost
229. 원하는 노드 타입에 pod 몰기
▪Node를 확인하여 label 붙이기
▫kubectl get nodes
kubectl label nodes [노드이름] disktype=ssd
▪Label과 함께 노드 목록을 불러오기
▫kubectl get nodes --show-labels
▪설정 파일생성(오른쪽 내용)
▫nano dev-pod.yaml
▪설정파일을 기반으로 pod 배포
▫kubectl create -f dev-pod.yaml
▪생성된 pod의 상세 내용 확인
▫kubectl get pods -o wide
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd #여기가 중요
230. ReplicaSets
▪A ReplicaSet (rs) is the next-generation ReplicationController.
ReplicaSets support both equality- and set-based selectors,
whereas ReplicationControllers only support equality-based
Selectors.
231. ReplicaSets
▪The ReplicaSet will detect that the current state is no longer matching the
desired state.
▫(In the given scenario, the ReplicaSet will create one more Pod)
▪ReplicaSets can be used independently, but they are mostly used by
Deployments to orchestrate the Pod creation, deletion, and updates.
▪A Deployment automatically creates the ReplicaSets, and we do not have to
worry about managing them.
232. Deployments
▪Deployment objects provide
declarative updates to Pods and
ReplicaSets.
▪The DeploymentController is part
of the master node's controller
manager, and it makes sure that
the current state always matches
the desired state.
▪In the following example, we
have a Deployment which
creates
a ReplicaSet A. ReplicaSet
A then creates 3 Pods. In each
Pod, one of the containers uses
the nginx:1.7.9 image.
233. Deployments
▪Now, in the Deployment, we change the Pods Template and we
update the image for the nginx container
from nginx:1.7.9 to nginx:1.9.1. As have modified the Pods Template,
a new ReplicaSet B gets created. This process is referred to as
a Deployment rollout.
▪A rollout is only triggered when we update the Pods Template for a
deployment. Operations like scaling the deployment do not trigger the
deployment.
234. Deployments
▪Once ReplicaSet B is ready,
the Deployment starts pointing
to it.
▪On top of ReplicaSets,
Deployments provide features
like Deployment recording, with
which, if something goes wrong,
we can rollback to a previously
known state.
235. Lab time: ReplicaSet
▪ReplicaSet 파일 생성
▫nano frontend.yaml
▪파일을 기반으로 ReplicaSet 배포
▫kubectl create -f frontend.yaml
▪ReplicaSet을 확인
▫kubectl get pods
kubectl describe rs/frontend
▪RsplicaSet을 삭제
▫kubectl delete rs/frontend
(관련된 pod 전부 제거한다.)
▫kubectl delete rs/frontend --cascade=false
(ReplicaSet 은 제거하지만 Pod 는 유지)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: frontend
labels:
app: guestbook
tier: frontend
spec:
replicas: 3
selector:
matchLabels:
tier: frontend
matchExpressions:
- {key: tier, operator: In, values: [frontend]}
template:
metadata:
labels:
app: guestbook
tier: frontend
spec:
containers:
- name: php-redis
image: gcr.io/google_samples/gb-frontend:v3
ports:
- containerPort: 80
237. Scaling
▪Deployment의 replica의 개수를 확인한다.
▫kubectl get pods
▪Deplyment의 이름을 복사한다.
▫kubectl get deployments
▪해당 Deployment의 scale 조정
▫kubectl scale deployments [deployment 이름] --replicas=3
▪변경을 확인
▫kubectl get pods
238. Deployments 의 변경
▪Deployment 파일을 변경
▫kubectl get deployments nano nginx-deployment.yaml
( spec 아래 항목에 replica: 3 속성을 추가)
▪변경한 파일을 적용
▫kubectl apply -f nginx-deployment.yaml
▪변경 내용을 확인
▫kubectl get pods
▪설정파일에 추가된 replica 속성을 삭제 후 다시 적용
▫nano nginx-deployment.yaml (replica)
▫kubectl apply -f nginx-deployment.yaml
▫kubectl delete pods --all
▫kubectl get pods
239. Connecting Users to Pods
To access the application, a user/client needs to connect
to the Pods. As Pods are ephemeral in nature, resources
like IP addresses allocated to it cannot be static. Pods
could die abruptly or be rescheduled based on existing
requirements.
240. Connecting Users to Pods
▪When user/client is connected to a Pod using its IP address. Unexpectedly,
the Pod to which the user/client is connected can die, and a new Pod is
created by the controller.
▪The new Pod will have a new IP address, which will not be known
automatically to the user/client of the earlier Pod.
▪To overcome this situation, Kubernetes provides a higher-level abstraction
called Service, which logically groups Pods and a policy to access them.
(This grouping is achieved via Labels and Selectors)
241. Services
▪Using selectors, we can group them into two logical groups: one with 3 Pods, and one
with just one Pod.
▪We can assign a name to the logical grouping, referred to as a Service name.
▪The user/client now connects to a service via the IP address, which forwards the traffic
to one of the Pods attached to it.
▫ The IP address attached to each Service is also known as the ClusterIP for that Service.
▪A service does the load balancing while selecting the Pods for forwarding the data/traffic.
▫If the target port is not defined explicitly, then traffic will be forwarded to Pods on the port on which the Service
receives traffic.
▫A tuple of Pods, IP addresses, along with the targetPort is referred to as a Service endpoint
242. Service Discovery
As Services are the primary mode of communication in Kubernetes, we need a way to
discover them at runtime.
Kubernetes supports two methods of discovering a Service:
▪Environment Variables
As soon as the Pod starts on any worker node, the kubelet daemon running on that
node adds a set of environment variables in the Pod for all active Services.
▪DNS
Kubernetes has an add-on for DNS, which creates a DNS record for each Service and
its format is like my-svc.my-namespace.svc.cluster.local. Services within the same
Namespace can reach to other Services with just their name. Pods from other
Namespaces can reach the Service by adding the respective Namespace as a suffix.
EX) namespace2.pod1.
This is the most common and highly recommended solution.
243. ServiceType: LoadBalancer
▪With the LoadBalancer ServiceType:
▫NodePort and ClusterIP Services are automatically created, and the external load
balancer will route to them
▫The Services are exposed at a static port on each worker node
▫The Service is exposed externally using the underlying cloud provider's load balancer
feature.
The LoadBalancer ServiceType will only work if the underlying infrastructure supports the automatic
creation of Load Balancers and have the respective support in Kubernetes, as is the case with the Google
Cloud Platform and AWS.
244. Ingress
▪With Services, routing rules are attached to a given Service.
▪They exist for as long as the Service exists.
▪If we can somehow decouple the routing rules from the application,
we can then update our application without worrying about its external
access. This can be done using the Ingress resource.
According to kubernetes.io,
"An Ingress is a collection of rules that allow inbound connections to
reach the cluster Services."
245. Ingress
▪To allow the inbound connection to reach the cluster Services, Ingress
configures a Layer 7 HTTP load balancer for Services and provides the following:
▫TLS (Transport Layer Security)
▫Name-based virtual hosting
▫Path-based routing
▫Custom rules.
246. Ingress
▪With Ingress, users don't connect directly to a Service.
▪Users reach the Ingress endpoint, and, from there, the request is forwarded to
the respective Service.
▪The Ingress resource does not do any request forwarding by itself. It is done
using the Ingress Controller
247. Ingress
▪In the example, users requests to both
blue.example.com and green.example.com
would go to the same Ingress endpoint,
and, from there, they would be forwarded
to webserver-blue-svc, and webserver-green-svc,
respectively. (Name-Based Virtual Hosting Ingress rule.)
▪We can also have Fan Out Ingress rules,
in which we send requests like
example.com/blue and example.com/green, which
would be forwarded to
webserver-blue-svc and webserver-green-svc,
respectively.
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: web-ingress
namespace: default
spec:
rules:
- host: blue.example.com
http:
paths:
- backend:
serviceName: webserver-blue-svc
servicePort: 80
- host: green.example.com
http:
paths:
- backend:
serviceName: webserver-green-svc
servicePort: 80
Ingress definition example
248. Ingress Controller
▪An Ingress Controller is an application which watches the Master
Node's API server for changes in the Ingress resources and updates
the Layer 7 Load Balancer accordingly.
▪Kubernetes has different Ingress Controllers, and, if needed, we can
also build our own.
▫GCE L7 Load Balancer and Nginx Ingress Controller are examples of Ingress
Controllers.
▪Start the Ingress Controller with Minikube
▫Minikube v0.14.0 and above ships the Nginx Ingress Controller setup as an add-on.
$ minikube addons enable ingress
249. Deploy an Ingress Resource
▪Once the Ingress Controller is deployed, we can create an Ingress
resource using the kubectl create command.
▪If we create a webserver-ingress.yaml file with the content that we
saw on the Ingress II page, then, we will use the following command to
create an Ingress resource:
$ kubectl create -f webserver-ingress.yaml
250. Access Services Using
Ingress
▪With the Ingress resource we just created, we can access
the webserver-blue-svc or webserver-green-svc services using
the blue.example.com and green.example.com URLs.
▫As our current setup is on Minikube, we will need to update the host configuration file
(/etc/hosts on Mac and Linux) on our workstation to the Minikube IP for those URLs.
Once this is done, we can open
blue.example.com and green.example.com
on the browser and access the application.
$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost
192.168.99.100 blue.example.com green.example.com
251. Liveness and Readiness
Probes
▪While we are discussing application deployment, let's talk
about Liveness and Readiness Probes. These probes
are very important, because they allow the kubelet to
control the health of the application running inside a Pod's
container.
252. Liveness
▪If a container in the Pod is running, but the application running inside this
container is not responding to our requests, then that container is of no use to
us.
▫This kind of situation can occur, for example, due to application deadlock or memory pressure.
▫In such a case, it is recommended to restart the container to make the application available.
▪Rather than doing it manually, we can use Liveness Probe. Liveness probe
checks on an application's health, and, if for some reason, the health check fails, it
restarts the affected container automatically.
▪Liveness Probes can be set by defining:
▫Liveness command
▫Liveness HTTP request
▫TCP Liveness Probe.
253. Liveness HTTP Request
▪In the following example, the kubelet sends the HTTP GET request to
the /healthz endpoint of the application, on port 8080.
▪ If that returns a failure, then the kubelet will restart the affected container; otherwise, it
would consider the application to be alive.
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
256. Running mi-services in the
kubernetes cluster
• 현재 작동 중인 pod들이 없는지 확인
▫kubectl get pods
▪이미지로 배포하기
▪kubectl run course --image=gcr.io/<projectId>/course
▪실행된 Pods 확인
▫kubectl get pods
(검색된 Pod의 이름을 복사한다. (각 pod들은 고유한 이름을 갖는다.)
257. Scaling
▪Deployment의 replica의 개수를 확인한다.
▫kubectl get pods
▪Deplyment의 이름을 복사한다.
▫kubectl get deployments
▪해당 Deployment의 scale 조정
▫kubectl scale deployments [deployment 이름] --replicas=3
▪변경을 확인
▫kubectl get pods
258. Rolling update
▪작동중인 pod와 deployments 확인
▫kubectl get pods
kubectl get deployments
▪새로운 버전의 deployments 배포 및 배포 상태 확인
▫kubectl set image deployment/course course=gcr.io/<projectId>/course:v2
kubectl rollout status deployment/course
▪변경을 확인
▫kubectl get deployments
kubectl get pods
kubectl describe pods [pod 이름]
259. Rollback
▪현재 실행중인 객체들을 확인
▫kubectl get pods
kubectl get deployments -o wide
▪객체를 롤백 처리
▫kubectl rollout undo deployment/course
▪진행을 확인
▫kubectl get deployments -o wide
263. Advanced Routing & Deployment
Strategy
▪ Ingress / Egress Gateway
▪ Canary Deploy
▫ 특정 유저의 신상, 지역, 권한, 접근 단말에 따른 다른 버전의 노출
▪AB Testing / Shadow Deploy
▫ 신규 버전의 오류 노출 없는 실질적 테스트
264. Advanced Resilience
▪ Retry (Kubernetes X, Spring Cloud O)
▫ 서비스간 호출의 실패에 대한 재시도
▪ Circuit Breaking (Spring Cloud O) / Rate Limiting
▫ 인스턴스의 보호
▫ 전체 서비스 장애 차단
▪ Pool Ejection (Spring Cloud / Eureka)
▫ 죽은 인스턴스의 제외
▪ Circuit Breaking + Pool Ejection + Retry = High Resilience
265. Advanced Security
▪ TLS based Inter-Mi-services Communication
▫ By Auth (신규모듈)
▪ Whitelist and Blacklist
269. After Istio
좋은점:
1. L7 레이어를 사용, 성능이 높음
2. Code 변경 없이 Cross-cutting 이슈를 다루어줌
3. Polyglot 다양한 언어에 무관하게 적용가능
4. Main 서비스의 재배포 없이 Sidecar 를 관리 가능함
270. Recommended Book
• Java (Spring Boot) based example
• Source code available
• Concise
• Free
271. Lab time:
▪ Customer (고객정보서비스)
Preference (고객선호서비스)
Recommendation (추천서비스)
▪ 무정지 배포 & 다양한 배포 시나리오
(e.g. 단말, 브라우저별 별도 버전의 배포)
▪ 전체 서비스의 Up-time 유지 방법
272. 단계4: Auto DevOps
Gitlab CI/CD
Kubernetes 와의 연동
Build Runner
Staging / Production
Service Expose by Ingress
274. Gitlab Auto DevOps
Gitlab 은 현존 CI/CD 툴 중 가장 많은 기능과 Production 수준의 기능을 제공함
기존 Gitlab 기능을 Kubernetes 엔진과 강력하게 통합하여 PaaS 의 기능에 근접한 기능 제공을
내어놓게 되는데, 바로 Auto-DevOps 임.
1.Auto Build
2.Auto Test
3.Auto Code Quality
4.Auto SAST (Static Application Security Testing)
5.Auto Dependency Scanning
6.Auto License Management
7.Auto Container Scanning
8.Auto Review Apps
9.Auto DAST (Dynamic Application Security Testing)
10.Auto Deploy
11.Auto Browser Performance Testing
12.Auto Monitoring
275. 플랫폼 별 Boilerplate & Pipeline
Auto generated Docker build script and pipelines (gitlab-ci.yml) for each platform
276. Kubernetes Cluster 를 빌드
Runner로 활용
Gitlab pods
DevOps Tool Cluster
Application Cluster
(Kubernetes)
Runner
(build job)
Runner
(build job)
Runner
(build job)
Staging pod Production pod
Ingress
빌드명령
배포명령
279. Install Gitlab on K8S
▪ Helm 을 이용하여 간단히 설치 가능
helm repo add gitlab https://charts.gitlab.io/
helm repo update
helm upgrade --install gitlab gitlab/gitlab
--timeout 600
--set global.hosts.domain=example.com
--set global.hosts.externalIP=10.10.10.10
--set certmanager-issuer.email=email@example.com
--set gitlab-runner.runners.privileged=true
• 패스워드 확인
https://docs.gitlab.com/ee/install/kubernetes/gitlab_chart.html
kubectl get secret gitlab-gitlab-initial-root-password -ojsonpath={.data.password} | base64 --decode ; echo
280. Install Helm
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get | bash
# add a service account within a namespace to segregate tiller
kubectl --namespace kube-system create sa tiller
# create a cluster role binding for tiller
kubectl create clusterrolebinding tiller
--clusterrole cluster-admin
--serviceaccount=kube-system:tiller
echo "initialize helm"
# initialized helm within the tiller service account
helm init --service-account tiller
# updates the repos for Helm repo integration
helm repo update
echo "verify helm"
# verify that helm is installed in the cluster
kubectl get deploy,svc tiller-deploy -n kube-system
https://medium.com/google-cloud/installing-helm-in-google-kubernetes-engine-
7f07f43c536e
281. Requirements / Check
Category Requirement Solution
Maintainability
& Scalability
24*365 Zero Down time Self-Healing, Horizontally Scale
Minimal Dev-Ops, Dev-Dev team side
effects in deploy time
(more than 100 deploys per day)
Loose coupled design (HATEOAS API,
Service Decomposition), PubSub
Auto Provisioning (by docker
containerizing)
DevOps CI/CD
Scalability &
Reusability
Multi-channel Support Responsive Web, Chat Bot
Dynamic Service Composition Dynamic Discovery/Composition, BPM
Usability &
Performance
Fast browsing, Single Page, DDoS
protection, Inter-microservice integration
Client-side UI rendering, API Gateway,
Circuit Breaker, Event-driven Arch.
Security For all services including 3rd-party ACL Access Token, IAM281