๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”. 1๋ถ€. ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ ๋„์ปค

๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์„ธ์š”. 1๋ถ€. ์Šคํ”„๋ง ๋ถ€ํŠธ์™€ ๋„์ปค

ํ—ค์ด ํ•˜๋ธŒ๋ฅด.

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ์‹คํ—˜ํ•˜๊ธฐ ์œ„ํ•œ ํ•™์Šต ํ™˜๊ฒฝ์„ ๋งŒ๋“  ๊ฒฝํ—˜์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์ƒˆ๋กœ์šด ๋„๊ตฌ๋ฅผ ๋ฐฐ์šธ ๋•Œ๋ฉด ํ•ญ์ƒ ๋กœ์ปฌ ์ปดํ“จํ„ฐ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ณด๋‹ค ํ˜„์‹ค์ ์ธ ์กฐ๊ฑด์—์„œ๋„ ์‹œ๋„ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋‚˜์ค‘์— ๋ชจ๋“  ์ข…๋ฅ˜์˜ ํฅ๋ฏธ๋กœ์šด ๊ธฐ์ˆ ๋กœ "๋ฎ์ผ" ์ˆ˜ ์žˆ๋Š” ๋‹จ์ˆœํ™”๋œ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค๊ธฐ๋กœ ๊ฒฐ์ •ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ์ฃผ์š” ์š”๊ตฌ ์‚ฌํ•ญ์€ ์‹ค์ œ ์‹œ์Šคํ…œ์— ๋Œ€ํ•œ ๊ธฐ๋Šฅ์  ๊ทผ์ ‘์„ฑ์ž…๋‹ˆ๋‹ค.

์ฒ˜์Œ์—๋Š” ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ์„ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋กœ ๋‚˜๋ˆ„์—ˆ์Šต๋‹ˆ๋‹ค.

  1. '๋ฐฑ์—”๋“œ'(๋ฐฑ์—”๋“œ) ๋ฐ '๊ฒŒ์ดํŠธ์›จ์ด'(๊ฒŒ์ดํŠธ์›จ์ด)์˜ ๋‘ ๊ฐ€์ง€ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ด๋ฅผ ๋„์ปค ์ด๋ฏธ์ง€๋กœ ์••์ถ•ํ•˜๊ณ  ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

    ํ‚ค์›Œ๋“œ: Java 11, Spring Boot, Docker, ์ด๋ฏธ์ง€ ์ตœ์ ํ™”

  2. Google Kubernetes Engine์—์„œ Kubernetes ๊ตฌ์„ฑ ๋ฐ ์‹œ์Šคํ…œ ๋ฐฐํฌ ๊ฐœ๋ฐœ

    ํ‚ค์›Œ๋“œ: Kubernetes, GKE, ๋ฆฌ์†Œ์Šค ๊ด€๋ฆฌ, ์ž๋™ ํ™•์žฅ, ๋ณด์•ˆ ๋น„๋ฐ€

  3. ๋” ๋‚˜์€ ํด๋Ÿฌ์Šคํ„ฐ ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•ด Helm 3๋กœ ์ฐจํŠธ ๋งŒ๋“ค๊ธฐ

    ํƒœ๊ทธ: Helm 3, ์ฐจํŠธ ๋ฐฐํฌ

  4. ํด๋Ÿฌ์Šคํ„ฐ์— ์ฝ”๋“œ๋ฅผ ์ž๋™์œผ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ Jenkins ๋ฐ ํŒŒ์ดํ”„๋ผ์ธ ์„ค์ •

    ํ‚ค์›Œ๋“œ: Jenkins ๊ตฌ์„ฑ, ํ”Œ๋Ÿฌ๊ทธ์ธ, ๋ณ„๋„์˜ ๊ตฌ์„ฑ ์ €์žฅ์†Œ

๋‚˜๋Š” ๊ฐ ๋‹จ๊ณ„์— ๋ณ„๋„์˜ ๊ธฐ์‚ฌ๋ฅผ ์“ธ ๊ณ„ํš์ž…๋‹ˆ๋‹ค.

์ด ๊ธฐ์‚ฌ ์‹œ๋ฆฌ์ฆˆ์˜ ์ดˆ์ ์€ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์•„๋‹ˆ๋ผ ๋‹จ์ผ ์‹œ์Šคํ…œ์—์„œ ์ž‘๋™ํ•˜๋„๋ก ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด ๋ชจ๋“  ๊ฒƒ๋“ค์€ ๋ณดํ†ต ๊ฐœ๋ฐœ์ž์˜ ์ฑ…์ž„ ๋ฐ–์— ์žˆ์ง€๋งŒ ์ ์–ด๋„ 20% ์ •๋„๋Š” ์ต์ˆ™ํ•ด์ง€๋Š” ๊ฒƒ์ด ์—ฌ์ „ํžˆ ์œ ์šฉํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค(์•„์‹œ๋‹ค์‹œํ”ผ ๊ฒฐ๊ณผ์˜ 80%๋ฅผ ์ค๋‹ˆ๋‹ค). ๋ณด์•ˆ๊ณผ ๊ฐ™์€ ์ผ๋ถ€ ๋ฌด์กฐ๊ฑด์ ์ธ ์ค‘์š”ํ•œ ์ฃผ์ œ๋Š” ์ด ์‹œ์Šคํ…œ์ด ๊ฐœ์ธ์ ์ธ ์šฉ๋„๋กœ๋งŒ ๋งŒ๋“ค์–ด์ง€๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์ž‘์„ฑ์ž๊ฐ€ ๊ฑฐ์˜ ์ดํ•ดํ•˜์ง€ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ”„๋กœ์ ํŠธ์—์„œ ์ œ์™ธ๋ฉ๋‹ˆ๋‹ค. ์–ด๋–ค ์˜๊ฒฌ์ด๋‚˜ ๊ฑด์„ค์ ์ธ ๋น„ํŒ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์ƒ์„ฑ

์„œ๋น„์Šค๋Š” Spring Boot๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Java 11๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„œ๋น„์Šค ๊ฐ„ ์ƒํ˜ธ ์ž‘์šฉ์€ REST๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์—๋Š” ์ตœ์†Œํ•œ์˜ ํ…Œ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค(๋‚˜์ค‘์— Jenkins์—์„œ ํ…Œ์ŠคํŠธํ•  ํ•ญ๋ชฉ์ด ์žˆ์Œ). ์„œ๋น„์Šค์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” GitHub์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฑ์—”๋“œ ะธ ๊ฒŒ์ดํŠธ์›จ์ด.

๊ฐ ์„œ๋น„์Šค์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋„๋ก Spring Actuator๊ฐ€ ์ข…์† ํ•ญ๋ชฉ์— ์ถ”๊ฐ€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. /actuator/health ์—”๋“œํฌ์ธํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์„œ๋น„์Šค๊ฐ€ ํŠธ๋ž˜ํ”ฝ์„ ์ˆ˜๋ฝํ•  ์ค€๋น„๊ฐ€ ๋œ ๊ฒฝ์šฐ 200 ์ƒํƒœ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ 504๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์„œ๋น„์Šค๊ฐ€ ๋งค์šฐ ๊ฐ„๋‹จํ•˜๊ณ  ๋ถˆ๊ฐ€ํ•ญ๋ ฅ์˜ ๊ฒฝ์šฐ ๋ถ€๋ถ„์ ์œผ๋กœ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์™„์ „ํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ ๋  ๊ฐ€๋Šฅ์„ฑ์ด ๋†’๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์€ ๊ฐ€์ƒ์˜ ํ™•์ธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์‹ค์ œ ์‹œ์Šคํ…œ์—์„œ Actuator๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ฌธ์ œ์— ๋Œ€ํ•ด ์‹ธ์šฐ๊ธฐ ์ „์— ๋ฌธ์ œ๋ฅผ ์ง„๋‹จํ•˜๋Š” ๋ฐ ๋„์›€์„ ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์•ก์„ธ์Šคํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์†์ƒ๋œ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋กœ ์š”์ฒญ ์ฒ˜๋ฆฌ๋ฅผ ์ค‘์ง€ํ•˜์—ฌ ์ž๋™์œผ๋กœ ์ด์— ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐฑ์—”๋“œ ์„œ๋น„์Šค

๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋Š” ์ˆ˜๋ฝ๋œ ์š”์ฒญ ์ˆ˜๋ฅผ ์„ธ๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ปจํŠธ๋กค๋Ÿฌ ์ฝ”๋“œ:

@RestController
public class RequestsCounterController {

    private final AtomicLong counter = new AtomicLong();

    @GetMapping("/requests")
    public Long getRequestsCount() {
        return counter.incrementAndGet();
    }
}

์ปจํŠธ๋กค๋Ÿฌ ํ…Œ์ŠคํŠธ:

@WebMvcTest(RequestsCounterController.class)
public class RequestsCounterControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void firstRequest_one() throws Exception {
        mockMvc.perform(get("/requests"))
            .andExpect(status().isOk())
            .andExpect(MockMvcResultMatchers.content().string("1"));
    }
}

์„œ๋น„์Šค ๊ฒŒ์ดํŠธ์›จ์ด

๊ฒŒ์ดํŠธ์›จ์ด๋Š” ์š”์ฒญ์„ ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋กœ ์ „๋‹ฌํ•˜๊ณ  ๋‹ค์Œ ์ •๋ณด๋กœ ๋ณด์™„ํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฒŒ์ดํŠธ์›จ์ด ์•„์ด๋””. ์„œ๋ฒ„ ์‘๋‹ต์œผ๋กœ ๊ฒŒ์ดํŠธ์›จ์ด์˜ ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค์™€ ๊ตฌ๋ณ„ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋งค์šฐ ์ค‘์š”ํ•œ ์•”ํ˜ธ(์ค‘์š”ํ•œ ์ฟ ํ‚ค์˜ ์•”ํ˜ธํ™” ํ‚ค ๋ฒˆํ˜ธ) ์—ญํ• ์„ ํ•  "๋น„๋ฐ€"

application.properties์˜ ๊ตฌ์„ฑ:

backend.url=http://localhost:8081
instance.id=${random.int}
secret="default-secret"

๋ฐฑ์—”๋“œ ์–ด๋Œ‘ํ„ฐ:

@Service
public class BackendAdapter {

    private static final String REQUESTS_ENDPOINT = "/requests";

    private final RestTemplate restTemplate;

    @Value("${backend.url}")
    private String backendUrl;

    public BackendAdapter(RestTemplateBuilder builder) {
        restTemplate = builder.build();
    }

    public String getRequests() {
        ResponseEntity<String> response = restTemplate.getForEntity(
backendUrl + REQUESTS_ENDPOINT, String.class);
        return response.getBody();
    }
}

์ œ์–ด ์žฅ์น˜:

@RestController
@RequiredArgsConstructor
public class EndpointController {

    private final BackendAdapter backendAdapter;

    @Value("${instance.id}")
    private int instanceId;

    @Value("${secret}")
    private String secret;

    @GetMapping("/")
    public String getRequestsCount() {
        return String.format("Number of requests %s (gateway %d, secret %s)", backendAdapter.getRequests(), instanceId, secret);
    }
}

์‹œ์ž‘ํ•˜๋‹ค:

๋ฐฑ์—”๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

./mvnw package -DskipTests
java -Dserver.port=8081 -jar target/microservices-backend-1.0.0.jar

๊ฒŒ์ดํŠธ์›จ์ด ์‹œ์ž‘:

./mvnw package -DskipTests
java -jar target/microservices-gateway-1.0.0.jar

์šฐ๋ฆฌ๋Š” ๋‹ค์Œ์„ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

$ curl http://localhost:8080/
Number of requests 1 (gateway 38560358, secret "default-secret")

๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์˜ ๊นŠ์€ ๋…์ž๋ผ๋ฉด ๊ฒŒ์ดํŠธ์›จ์ด๋ฅผ ์šฐํšŒํ•˜์—ฌ ๋ฐฑ์—”๋“œ์— ์ง์ ‘ ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉํ•ดํ•˜๋Š” ๊ฒƒ์€ ์•„๋ฌด๊ฒƒ๋„ ์—†๋‹ค๋Š” ์ ์— ์œ ์˜ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค(http://localhost:8081/requests). ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๋ฉด ์„œ๋น„์Šค๋ฅผ ํ•˜๋‚˜์˜ ๋„คํŠธ์›Œํฌ๋กœ ๊ฒฐํ•ฉํ•ด์•ผ ํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ์›จ์ด๋งŒ ์™ธ๋ถ€์— "ํŠ€์–ด๋‚˜์™€์•ผ" ํ•ฉ๋‹ˆ๋‹ค.
๋˜ํ•œ ๋‘ ์„œ๋น„์Šค ๋ชจ๋‘ ํ•˜๋‚˜์˜ ํŒŒ์ผ ์‹œ์Šคํ…œ์„ ๊ณต์œ ํ•˜๊ณ  ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜๋ฉฐ ์–ด๋Š ์ˆœ๊ฐ„ ์„œ๋กœ ๊ฐ„์„ญํ•˜๊ธฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค๋ฅผ ๊ฒฉ๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋‹ค๋ฅธ ๋จธ์‹ ์— ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฐฐํฌํ•˜๊ฑฐ๋‚˜(๋ˆ์ด ๋งŽ์ด ๋“ค๊ณ  ์–ด๋ ค์›€) ๊ฐ€์ƒ ๋จธ์‹ ์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜(๋ฆฌ์†Œ์Šค ์ง‘์•ฝ์ , ๊ธด ์‹œ์ž‘ ์‹œ๊ฐ„) ์ปจํ…Œ์ด๋„ˆํ™”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ์ƒ๋Œ€๋กœ ์„ธ ๋ฒˆ์งธ ์˜ต์…˜์„ ์„ ํƒํ•˜๊ณ  ๋„์ปค ์ปจํ…Œ์ด๋„ˆํ™”๋ฅผ ์œ„ํ•œ ๋„๊ตฌ๋กœ.

๋„์ปค

์ฆ‰, docker๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋‹น ํ•˜๋‚˜์”ฉ ๊ฒฉ๋ฆฌ๋œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. docker๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋นŒ๋“œ ๋ฐ ์‹คํ–‰ ์ง€์นจ์ธ Dockerfile์„ ์ž‘์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋นŒ๋“œํ•˜๊ณ  ์ด๋ฏธ์ง€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์—…๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(No. ๋„์ปค ํ—ˆ๋ธŒ) ํ•˜๋‚˜์˜ ๋ช…๋ น์œผ๋กœ ๋ชจ๋“  Dockerํ™”๋œ ํ™˜๊ฒฝ์— ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค.

๋„์ปค ํŒŒ์ผ

์ด๋ฏธ์ง€์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ํฌ๊ธฐ์ž…๋‹ˆ๋‹ค. ์••์ถ• ์ด๋ฏธ์ง€๋Š” ์›๊ฒฉ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ๋” ๋นจ๋ฆฌ ๋‹ค์šด๋กœ๋“œ๋˜๊ณ  ๊ณต๊ฐ„์„ ๋œ ์ฐจ์ง€ํ•˜๋ฉฐ ์„œ๋น„์Šค๊ฐ€ ๋” ๋นจ๋ฆฌ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ด๋ฏธ์ง€๋Š” ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋˜๋ฉฐ ๊ฐ€์žฅ ์ตœ์†Œํ•œ์˜ ์˜ต์…˜์„ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์ข‹์€ ์˜ต์…˜์€ ์ตœ์†Œํ•œ์˜ ํŒจํ‚ค์ง€๋กœ ๊ตฌ์„ฑ๋œ ์™„์ „ํ•œ Linux ๋ฐฐํฌํŒ์ธ Alpine์ž…๋‹ˆ๋‹ค.

๋จผ์ € "์ด๋งˆ์—" Dockerfile์„ ์ž‘์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests
EXPOSE 8080
ENTRYPOINT ["java","-jar","target/microservices-gateway-1.0.0.jar"]

์—ฌ๊ธฐ์„œ๋Š” JDK๊ฐ€ ์ด๋ฏธ ์„ค์น˜๋œ Alpine ๊ธฐ๋ฐ˜ ๊ธฐ๋ณธ ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. ADD ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ํ˜„์žฌ src ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ด๋ฏธ์ง€์— ์ถ”๊ฐ€ํ•˜๊ณ  ์ž‘์—…(WORKDIR)์œผ๋กœ ํ‘œ์‹œํ•œ ๋‹ค์Œ ๋นŒ๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. EXPOSE 8080 ๋ช…๋ น์€ ์ปจํ…Œ์ด๋„ˆ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•ด๋‹น ํฌํŠธ 8080์„ ์‚ฌ์šฉํ•  ๊ฒƒ์ž„์„ ๋„์ปค์— ์•Œ๋ฆฝ๋‹ˆ๋‹ค(์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์™ธ๋ถ€์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์—†์ง€๋งŒ ์˜ˆ๋ฅผ ๋“ค์–ด ๋™์ผํ•œ ๋„์ปค ๋„คํŠธ์›Œํฌ์˜ ๋‹ค๋ฅธ ์ปจํ…Œ์ด๋„ˆ์—์„œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ).

์„œ๋น„์Šค๋ฅผ ์ด๋ฏธ์ง€๋กœ ํŒจํ‚ค์ง•ํ•˜๋ ค๋ฉด ๊ฐ ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ์—์„œ ๋ช…๋ น์„ ์‹คํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

docker image build . -t msvc-backend:1.0.0

๊ฒฐ๊ณผ๋Š” 456MB ์ด๋ฏธ์ง€(๊ธฐ๋ณธ JDK ์ด๋ฏธ์ง€๊ฐ€ 340MB๋ฅผ ์ฐจ์ง€ํ•จ)์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์˜ ํด๋ž˜์Šค๊ฐ€ ์†๊ฐ€๋ฝ์œผ๋กœ ์…€ ์ˆ˜ ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ . ์ด๋ฏธ์ง€ ํฌ๊ธฐ๋ฅผ ์ค„์ด๋ ค๋ฉด:

  • ์šฐ๋ฆฌ๋Š” ๋‹ค๋‹จ๊ณ„ ์กฐ๋ฆฝ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ํ”„๋กœ์ ํŠธ๋ฅผ ๋นŒ๋“œํ•˜๊ณ , ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” JRE๋ฅผ ์„ค์น˜ํ•˜๊ณ , ์„ธ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ๋ชจ๋‘ ๊นจ๋—ํ•œ ์ƒˆ Alpine ์ด๋ฏธ์ง€์— ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ „์ฒด์ ์œผ๋กœ ํ•„์š”ํ•œ ๊ตฌ์„ฑ ์š”์†Œ๋งŒ ์ตœ์ข… ์ด๋ฏธ์ง€์— ํฌํ•จ๋ฉ๋‹ˆ๋‹ค.
  • Java์˜ ๋ชจ๋“ˆํ™”๋ฅผ ์‚ฌ์šฉํ•ฉ์‹œ๋‹ค. Java 9๋ถ€ํ„ฐ jlink ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•„์š”ํ•œ ๋ชจ๋“ˆ์—์„œ๋งŒ JRE๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜ธ๊ธฐ์‹ฌ ๋งŽ์€ ๋ถ„๋“ค์„ ์œ„ํ•ด ์ด๋ฏธ์ง€ ์ถ•์†Œ ์ ‘๊ทผ ๋ฐฉ์‹์— ๋Œ€ํ•œ ์ข‹์€ ๊ธฐ์‚ฌ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. https://habr.com/ru/company/ruvds/blog/485650/.

์ตœ์ข… Dockerfile:

FROM adoptopenjdk/openjdk11:jdk-11.0.5_10-alpine as builder
ADD . /src
WORKDIR /src
RUN ./mvnw package -DskipTests

FROM alpine:3.10.3 as packager
RUN apk --no-cache add openjdk11-jdk openjdk11-jmods
ENV JAVA_MINIMAL="/opt/java-minimal"
RUN /usr/lib/jvm/java-11-openjdk/bin/jlink 
    --verbose 
    --add-modules 
        java.base,java.sql,java.naming,java.desktop,java.management,java.security.jgss,java.instrument 
    --compress 2 --strip-debug --no-header-files --no-man-pages 
    --release-info="add:IMPLEMENTOR=radistao:IMPLEMENTOR_VERSION=radistao_JRE" 
    --output "$JAVA_MINIMAL"

FROM alpine:3.10.3
LABEL maintainer="Anton Shelenkov [email protected]"
ENV JAVA_HOME=/opt/java-minimal
ENV PATH="$PATH:$JAVA_HOME/bin"
COPY --from=packager "$JAVA_HOME" "$JAVA_HOME"
COPY --from=builder /src/target/microservices-backend-*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

์ด๋ฏธ์ง€๋ฅผ ์žฌ์ƒ์„ฑํ•œ ๊ฒฐ๊ณผ ๋ฌด๊ฒŒ๊ฐ€ 6๋ฐฐ ๊ฐ์†Œํ•˜์—ฌ 77MB์— ๋‹ฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜์˜์ง€ ์•Š๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๊ธฐ์„ฑ ์ด๋ฏธ์ง€๋ฅผ ์ด๋ฏธ์ง€ ๋ ˆ์ง€์ŠคํŠธ๋ฆฌ์— ์—…๋กœ๋“œํ•˜์—ฌ ์ธํ„ฐ๋„ท์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Docker์˜ ๊ณต๋™ ์‹คํ–‰ ์„œ๋น„์Šค

์šฐ์„ , ์šฐ๋ฆฌ์˜ ์„œ๋น„์Šค๋Š” ๋™์ผํ•œ ๋„คํŠธ์›Œํฌ์— ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋„์ปค์—๋Š” ์—ฌ๋Ÿฌ ์œ ํ˜•์˜ ๋„คํŠธ์›Œํฌ๊ฐ€ ์žˆ์œผ๋ฉฐ ๊ทธ์ค‘ ๊ฐ€์žฅ ์›์‹œ์ ์ธ ๋ธŒ๋ฆฌ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋™์ผํ•œ ํ˜ธ์ŠคํŠธ์—์„œ ์‹คํ–‰๋˜๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋„คํŠธ์›Œํฌ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ ๋„คํŠธ์›Œํฌ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

docker network create msvc-network

๋‹ค์Œ์œผ๋กœ microservices-backend:1.0.0 ์ด๋ฏธ์ง€๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ 'backend'๋ผ๋Š” ๋ฐฑ์—”๋“œ ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

docker run -dit --name backend --network msvc-net microservices-backend:1.0.0

๋ธŒ๋ฆฌ์ง€ ๋„คํŠธ์›Œํฌ๊ฐ€ ์ด๋ฆ„๋ณ„๋กœ ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ์ฆ‰์‹œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค ๊ฒ€์ƒ‰์„ ์ œ๊ณตํ•œ๋‹ค๋Š” ์ ์€ ์ฃผ๋ชฉํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋Š” ๋„์ปค ๋„คํŠธ์›Œํฌ ๋‚ด์—์„œ ๋‹ค์Œ ์œ„์น˜์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. http://backend:8080.

๊ฒŒ์ดํŠธ์›จ์ด ์‹œ์ž‘:

docker run -dit -p 80:8080 --env secret=my-real-secret --env BACKEND_URL=http://backend:8080/ --name gateway --network msvc-net microservices-gateway:1.0.0

์ด ๋ช…๋ น์—์„œ ํ˜ธ์ŠคํŠธ์˜ ํฌํŠธ 80์„ ์ปจํ…Œ์ด๋„ˆ์˜ ํฌํŠธ 8080์œผ๋กœ ์ „๋‹ฌํ•˜๊ณ  ์žˆ์Œ์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค. env ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ spring์—์„œ ์ž๋™์œผ๋กœ ์ฝ์„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ณ  application.properties์—์„œ ์†์„ฑ์„ ์žฌ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.

์‹œ์ž‘ ํ›„, ์šฐ๋ฆฌ๋Š” ์ „ํ™” http://localhost/ ์ด์ „ ์‚ฌ๋ก€์™€ ๊ฐ™์ด ๋ชจ๋“  ๊ฒƒ์ด ์ž‘๋™ํ•˜๋Š”์ง€ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.

๊ฒฐ๋ก 

๊ฒฐ๊ณผ์ ์œผ๋กœ ์šฐ๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ๊ฐ„๋‹จํ•œ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค์–ด ๋„์ปค ์ปจํ…Œ์ด๋„ˆ์— ํŒจํ‚ค์ง•ํ•˜๊ณ  ๋™์ผํ•œ ์‹œ์Šคํ…œ์—์„œ ํ•จ๊ป˜ ์‹œ์ž‘ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๊ฒฐ๊ณผ ์‹œ์Šคํ…œ์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ๋‹จ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์—ด์•…ํ•œ ๋‚ด๊ฒฐํ•จ์„ฑ - ๋ชจ๋“  ๊ฒƒ์ด ํ•˜๋‚˜์˜ ์„œ๋ฒ„์—์„œ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.
  • ์—ด์•…ํ•œ ํ™•์žฅ์„ฑ - ๋กœ๋“œ๊ฐ€ ์ฆ๊ฐ€ํ•  ๋•Œ ์ถ”๊ฐ€ ์„œ๋น„์Šค ์ธ์Šคํ„ด์Šค๋ฅผ ์ž๋™์œผ๋กœ ๋ฐฐํฌํ•˜๊ณ  ๋กœ๋“œ ๊ท ํ˜•์„ ์กฐ์ •ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
  • ์‹œ์ž‘์˜ ๋ณต์žก์„ฑ - ์ตœ์†Œ 3๊ฐœ์˜ ๋ช…๋ น๊ณผ ํŠน์ • ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ž…๋ ฅํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค(2๊ฐœ์˜ ์„œ๋น„์Šค์—๋งŒ ํ•ด๋‹น).

์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Docker Swarm, Nomad, Kubernetes ๋˜๋Š” OpenShift์™€ ๊ฐ™์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ „์ฒด ์‹œ์Šคํ…œ์ด Java๋กœ ์ž‘์„ฑ๋œ ๊ฒฝ์šฐ Spring Cloud(์ข‹์€ ๊ธฐ์‚ฌ).

ะ’ ๋‹ค์Œ ๋ถ€๋ถ„ Kubernetes๋ฅผ ์„ค์ •ํ•˜๊ณ  ํ”„๋กœ์ ํŠธ๋ฅผ Google Kubernetes Engine์— ๋ฐฐํฌํ•œ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€