Aprann kijan pou deplwaye mikwosèvis. Pati 1. Spring Boot ak Docker

Aprann kijan pou deplwaye mikwosèvis. Pati 1. Spring Boot ak Docker

Hey Habr.

Nan atik sa a, mwen vle pale sou eksperyans mwen nan kreye yon anviwònman aprantisaj pou fè eksperyans ak mikwosèvis. Lè mwen te aprann chak nouvo zouti, mwen te toujou vle eseye li pa sèlman sou machin lokal la, men tou, nan kondisyon ki pi reyalis. Se poutèt sa, mwen deside kreye yon aplikasyon mikwosèvis senplifye, ki ka pita dwe "kouvri" ak tout kalite teknoloji enteresan. Kondisyon prensipal la pou pwojè a se maksimòm pwoksimite fonksyonèl li nan sistèm reyèl la.

Okòmansman, mwen kase kreyasyon an nan pwojè a nan plizyè etap:

  1. Kreye de sèvis - 'backend' (backend) ak 'gateway' (gateway), pake yo nan imaj docker epi mete yo kanpe pou travay ansanm.

    Mo kle: Java 11, Spring Boot, Docker, optimize imaj

  2. Devlopman konfigirasyon Kubernetes ak deplwaman sistèm nan Google Kubernetes Engine

    Mo kle: Kubernetes, GKE, jesyon resous, autoscaling, sekrè

  3. Kreye yon tablo ak Helm 3 pou pi bon jesyon gwoup

    Tags: Helm 3, deplwaman tablo

  4. Mete kanpe Jenkins ak tiyo pou livrezon otomatik nan kòd nan gwoup la

    Mo kle: Jenkins konfigirasyon, grefon, depo konfigirasyon separe

Mwen planifye konsakre yon atik separe nan chak etap.

Konsantre nan seri atik sa a se pa fason pou ekri mikwosèvis, men ki jan fè yo travay nan yon sèl sistèm. Malgre ke tout bagay sa yo anjeneral deyò responsablite nan pwomotè a, mwen panse ke li toujou itil yo dwe abitye ak yo omwen 20% (ki, kòm ou konnen, bay 80% nan rezilta a). Gen kèk sijè enkondisyonèl enpòtan, tankou sekirite, yo pral kite soti nan pwojè sa a, depi otè a konprann ti kras sou sistèm sa a se kreye sèlman pou itilizasyon pèsonèl. Mwen akeyi nenpòt opinyon ak kritik konstriktif.

Kreye mikwosèvis

Sèvis yo te ekri nan Java 11 lè l sèvi avèk Spring Boot. Entèraksyon entèsèvis òganize lè l sèvi avèk REST. Pwojè a pral gen ladan yon kantite minimòm tès (pou pita gen yon bagay yo teste nan Jenkins). Kòd sous la pou sèvis yo disponib sou GitHub: backend и Gateway.

Pou kapab tcheke estati chak nan sèvis yo, yo te ajoute yon Spring Actuator nan depandans yo. Li pral kreye yon pwen final / actuator / sante epi li pral retounen yon estati 200 si sèvis la pare pou resevwa trafik, oswa 504 si gen yon pwoblèm. Nan ka sa a, sa a se yon chèk olye fiktiv, depi sèvis yo trè senp, ak nan ka ta gen kèk fòs majeure, yo gen plis chans yo vin konplètman disponib pase rete pasyèlman operasyonèl. Men, nan sistèm reyèl, Actuator ka ede dyagnostike yon pwoblèm anvan itilizatè yo kòmanse batay sou li. Pou egzanp, si gen pwoblèm ak aksè nan baz done a, nou ka otomatikman reponn a sa a lè nou sispann trete demann ak yon egzanp sèvis kase.

Sèvis dèyè dèyè

Sèvis backend la ap tou senpleman konte epi retounen kantite demann yo aksepte.

Kòd kontwolè:

@RestController
public class RequestsCounterController {

    private final AtomicLong counter = new AtomicLong();

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

Tès kontwolè:

@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"));
    }
}

Sèvis Gateway

Pòtay la pral voye demann lan bay sèvis backend la, pou l ajoute enfòmasyon sa yo:

  • id gateway. Li nesesè pou li posib pou fè distenksyon ant yon egzanp pòtay la ak yon lòt pa repons sèvè a
  • Gen kèk "sekrè" ki pral jwe wòl yon modpas trè enpòtan (kantite kle chifreman yon bonbon enpòtan)

Konfigirasyon nan application.properties:

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

Adaptè backend:

@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();
    }
}

Kontwolè:

@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);
    }
}

Lanse:

Nou kòmanse backend la:

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

Kòmanse pòtay la:

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

Nou tcheke:

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

Tout bagay ap travay. Yon lektè atantif pral remake ke pa gen anyen ki anpeche nou jwenn aksè nan backend la dirèkteman, kontourne pòtay la (http://localhost:8081/requests). Pou ranje sa a, sèvis yo dwe konbine nan yon sèl rezo, epi sèlman pòtay la ta dwe "kole deyò" deyò.
Epitou, tou de sèvis pataje yon sèl sistèm dosye, pwodwi kouran ak nan yon moman ka kòmanse entèfere youn ak lòt. Li ta bon pou izole mikwosèvis nou yo. Sa a ka reyalize lè yo distribye aplikasyon sou diferan machin (anpil lajan, difisil), lè l sèvi avèk machin vityèl (resous entansif, demaraj long), oswa lè l sèvi avèk containerization. Kòm espere, nou chwazi twazyèm opsyon a ak Koupre kòm yon zouti pou containerization.

Koupre

Nan ti bout tan, Docker kreye resipyan izole, youn pou chak aplikasyon. Pou itilize Docker, ou bezwen ekri yon Dockerfile - enstriksyon pou bati ak kouri aplikasyon an. Apre sa, ou ka bati imaj la, telechaje li nan rejis imaj la (No. Dockerhub) epi deplwaye mikwosèvis ou a nan nenpòt anviwònman dockerized nan yon sèl lòd.

dockerfile

Youn nan karakteristik ki pi enpòtan nan yon imaj se gwosè li. Yon imaj kontra enfòmèl ant ap telechaje pi vit soti nan yon depo aleka, pran mwens espas, epi sèvis ou a ap kòmanse pi vit. Nenpòt imaj bati sou baz imaj la baz, epi li rekòmande yo chwazi opsyon ki pi minimalist. Yon bon opsyon se Alpine, yon distribisyon Linux konplè ak pakè minimòm.

Premyèman, ann eseye ekri yon Dockerfile "sou fwon an" (mwen pral di touswit ke sa a se yon move fason, pa fè li):

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"]

Isit la nou ap itilize yon imaj baz Alpine ki baze ak JDK a deja enstale yo bati pwojè nou an. Avèk lòd ADD la, nou ajoute anyè src aktyèl la nan imaj la, make li kòm k ap travay (WORKDIR) epi kòmanse bati a. Kòmand EXPOSE 8080 la fè konnen aplikasyon an nan veso a pral sèvi ak pò 8080 li (sa pa pral fè aplikasyon an aksesib soti deyò a, men li pral pèmèt aplikasyon an jwenn aksè, pa egzanp, nan yon lòt veso sou menm rezo docker la. ).

Pou pake sèvis yo nan imaj, ou bezwen kouri kòmandman ki soti nan rasin chak pwojè:

docker image build . -t msvc-backend:1.0.0

Rezilta a se yon imaj 456 MB (ki baz JDK imaj la te okipe 340 MB). Ak tout malgre lefèt ke klas yo nan pwojè nou an ka konte sou yon dwèt. Pou redwi gwosè imaj nou an:

  • Nou itilize asanble milti-etap. Nan premye etap la nou pral bati pwojè a, nan dezyèm etap la nou pral enstale JRE a, ak nan twazyèm etap la nou pral kopye li tout nan yon nouvo imaj Alpine pwòp. An total, sèlman eleman ki nesesè yo pral nan imaj final la.
  • Ann itilize modularizasyon java. Kòmanse ak Java 9, ou ka itilize zouti jlink la pou kreye yon JRE apati modil ou bezwen yo

Pou fouyan yo, isit la se yon bon atik sou apwòch rediksyon imaj. https://habr.com/ru/company/ruvds/blog/485650/.

Dockerfile final la:

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"]

Nou rkree imaj la, epi kòm yon rezilta, li pèdi 6 fwa pwa li, ki montan 77 MB. Pa move. Apre sa, imaj ki pare yo ka telechaje nan rejis imaj la pou imaj ou yo disponib pou telechaje sou entènèt la.

Ko-kouri sèvis nan Docker

Pou kòmanse, sèvis nou yo dwe sou menm rezo a. Gen plizyè kalite rezo nan Docker, epi nou itilize pi primitif nan yo - pon, ki pèmèt ou rezo kontenè kouri sou menm lame a. Kreye yon rezo ak lòd sa a:

docker network create msvc-network

Apre sa, kòmanse veso backend ki rele 'backend' ak imaj microservices-backend:1.0.0:

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

Li enpòtan pou remake ke rezo pon an bay dekouvèt sèvis soti nan bwat pou resipyan pa non yo. Sa vle di, sèvis backend la ap disponib andedan rezo docker la nan http://backend:8080.

Kòmanse pòtay la:

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

Nan lòd sa a, nou endike ke nou ap voye pò 80 nan lame nou an nan pò 8080 nan veso a. Nou itilize opsyon env yo pou mete varyab anviwònman ki pral otomatikman li pa prentan epi pase sou pwopriyete yo nan application.properties.

Apre kòmanse, nou rele http://localhost/ epi asire w ke tout bagay ap travay, tankou nan ka anvan an.

Konklizyon

Kòm yon rezilta, nou te kreye de mikwosèvis senp, pake yo nan resipyan docker epi lanse yo ansanm sou menm machin nan. Sepandan, sistèm ki lakòz rezilta a gen yon kantite dezavantaj:

  • Pòv tolerans fòt - tout bagay ap travay pou nou sou yon sèl sèvè
  • Pòv évolutivité - lè chaj la ogmante, li ta bon pou otomatikman deplwaye ka sèvis adisyonèl epi balanse chaj la ant yo.
  • Konpleksite nan lansman an - nou te bezwen antre nan omwen 3 kòmandman, ak ak sèten paramèt (sa a se sèlman pou 2 sèvis)

Pou ranje pwoblèm ki anwo yo, gen yon kantite solisyon tankou Docker Swarm, Nomad, Kubernetes oswa OpenShift. Si tout sistèm lan ekri nan Java, ou ka gade nan direksyon Spring Cloud (bon atik).

В pwochen pati Mwen pral pale sou fason mwen mete kanpe Kubernetes ak deplwaye pwojè a nan Google Kubernetes Engine.

Sous: www.habr.com

Add nouvo kòmantè