2021-01-14 15:03:23 +01:00
\documentclass [12pt,oneside,a4paper] { book}
% Język polski
\usepackage { amssymb}
\usepackage { polski}
\usepackage [polish] { babel}
%Opcja dla edytorów kodujących polskie znaki w utf8
\usepackage [utf8] { inputenc}
\usepackage { microtype}
\usepackage { fancyhdr}
\usepackage { pstricks}
\usepackage { blindtext}
\usepackage [T1] { fontenc}
\usepackage { authblk}
\usepackage { placeins}
\usepackage { tocloft}
\usepackage { hyperref}
\usepackage { listings}
\usepackage { chngcntr}
\usepackage { lmodern}
\usepackage { pstricks}
\usepackage { enumitem}
\usepackage { xcolor}
\lstset { basicstyle=\ttfamily ,
showstringspaces=false,
commentstyle=\color { red} ,
keywordstyle=\color { blue}
}
% Włączenie wcięcia w pierwszym akapicie
\usepackage { indentfirst}
% Możliwość dodwania obrazków
\usepackage { graphicx}
% Zmiana nazwy bib
\def \bibname { Literatura}
%\DisableLigatures{encoding = *, family = * }
% Wyłączenie countowania img po chapterze.
\usepackage { chngcntr}
\counterwithout { figure} { chapter}
% Zmiana rozkładu lini w dokumencie
\linespread { 1.3}
\renewcommand * { \lstlistingname } { \textbf { Kod} }
\lstset {
basicstyle=\fontsize { 11} { 13} \selectfont \ttfamily ,
columns=fullflexible,
frame=single,
breaklines=true,
%postbreak=\mbox{\textcolor{red}{$\hookrightarrow$}\space},
}
%--------------- Wydruk jednostronny
\fancyhead [C] { }
\fancyfoot [C] { \thepage }
\fancyhead [L] { \footnotesize \rightmark }
\fancyhead [R] { }
\renewcommand { \sectionmark } [1]{ \markright { \thesection .\ #1} }
\setcounter { secnumdepth} { 3}
\renewcommand * \thesection { \arabic { section} }
\renewcommand * \thesubsection { \arabic { section} .\arabic { subsection} }
\renewcommand * \thesubsubsection { %
\arabic { section} .\arabic { subsection} .\arabic { subsubsection} %
}
\setcounter { tocdepth} { 3}
\setcounter { secnumdepth} { 3}
\pagestyle { fancy}
\begin { document}
%\maketitle
\begin { titlepage}
\centering
\includegraphics [width=0.35\textwidth] { img/uam-logo.pdf} \par
{ \scshape \large Wydział Matematyki i Informatyki \par }
\vspace { 0.75cm}
{ \small Maciej Głowacki \\ Numer albumu: 434689\par }
\vspace { 0.2cm}
{ \small Filip Izydorczyk \\ Numer albumu: 434700\par }
\vspace { 0.2cm}
{ \small Marcin Woźniak \\ Numer albumu: 434812\par }
\vspace { 0.2cm}
{ \small Hubert Wrzesiński \\ Numer albumu: 434813\par }
\vspace { 1.5cm}
{ \large \bfseries PlanNaPlan - Dokumentacja wdrożeniowa}
\vspace { 0.7cm}
\vfill
% Bottom of the page
Poznań, styczeń 2021
\end { titlepage}
\thispagestyle { empty}
\tableofcontents
\newpage
\section { Instalacja}
\subsection { Backend}
\subsubsection { Kompilowanie aplikacji ze źródła}
\begin { itemize}
\item \textbf { Krok 0:} Wymagania: \\
- System operacyjny: Linux \\
2021-01-16 13:51:05 +01:00
- Minimalna wersja: Java 14 \\
2021-01-14 15:03:23 +01:00
- Maven \\
- Baza Danych (np. MariaDB) \\
- Osobny user do uruchamiania aplikacji np. backend
\item \textbf { Krok 1:} Pobranie repozytorium ze źródła:
\begin { lstlisting} [
frame=single,
numbers=none,
]
2021-01-14 15:35:29 +01:00
% git clone http://git.plannaplan.pl/filipizydorczyk/backend.git
2021-01-14 15:03:23 +01:00
\end { lstlisting}
\item \textbf { Krok 2:} Zmiana środowiska backendowego na produkcyjne:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% echo "spring.profiles.active=prod" > restservice/src/main/resources/application.properties
\end { lstlisting}
\item \textbf { Krok 3:} Instalacja pluginów za pomocą \lstinline { maven} :
\begin { lstlisting} [
frame=single,
numbers=none,
]
% mvn clean
% mvn install
\end { lstlisting}
\item \textbf { Krok 4:} Kompilowanie środowiska:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% cd restservice
% mvn clean package spring-boot:repackage
\end { lstlisting}
\item \textbf { Krok 5:} Utworzenie folderu oraz skopiowanie aplikacji:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% mkdir -p /opt/plannaplan-backend/logs
% cp -rv restservice/target/*.jar /opt/plannaplan-backend/backend.jar
\end { lstlisting}
\item \textbf { Krok 6:} Dodanie pustej bazy danych, a także użytkownika dla backend'u.
\item \textbf { Krok 7:} Samo uruchomienie aplikacji - wiąże się z ustawieniem
zmiennych środowiskowych. Polecamy stworzenie skryptu w Bashu aby to wszytsko
było przetrzymywane tylko w tym skrypcie. Przykładowy skrypt \ref { skryptBash} .
\begin { lstlisting} [
language=bash,
label=skryptBash,
frame=single,
numbers=left,
caption={ Skrypt uruchamiający backend aplikacji}
]
#!/bin/sh
SERVICE_ NAME="PlanNaPlan Backend"
DIR="/opt/plannaplan-backend"
export PATH=$ PATH: $ JAVA_ HOME/bin
export PLANNAPLAN_ MYSQL_ DB_ HOST=""
export PLANNAPLAN_ MYSQL_ DB_ PORT=""
export PLANNAPLAN_ MYSQL_ DB=""
export PLANNAPLAN_ MYSQL_ DB_ USERNAME=""
export PLANNAPLAN_ MYSQL_ DB_ PASSWORD=""
export PLANNAPLAN_ EMAIL=""
export PLANNAPLAN_ EMAIL_ HOST=""
export PLANNAPLAN_ EMAIL_ PORT=""
export PLANNAPLAN_ EMAIL_ USERNAME=""
export PLANNAPLAN_ EMAIL_ PASSWORD=""
export PLANNAPLAN_ CONSUMER_ KEY=""
export PLANNAPLAN_ CONSUMER_ SECRET=""
java -jar $ DIR / backend.jar >> $ DIR/log-$ ( / usr / bin / date - I ) .log 2 > & 1
echo $ ! > / tmp / sd - plananplan.pid
\end { lstlisting}
\item \textbf { Krok 8:} Uzupełnienie skryptu (nr. \ref { skryptBash} ) swoimi danymi produkcyjnymi.
\item \textbf { Krok 9:} Utworzenie serwisu, aby backend startował przy
uruchomieniu serwera.
\begin { lstlisting} [
language=bash,
label=systemD,
frame=single,
numbers=left,
caption={ Deamon uruchamiający backend aplikacji.}
]
[Unit]
Description=PlanNaPlan Backend
After=network.target
[Service]
Type=simple
ExecStart="/opt/plannaplan-backend/plannaplan-backend.sh"
WorkingDirectory=/opt/plannaplan-backend
User=backend #WYBRANY USER W KROKU 0
Group=backend #WYBRANY USER W KROKU 0
Environment=PATH=$ PATH: $ JAVA_ HOME/bin
StartLimitInterval=30
[Install]
WantedBy=multi-user.target
\end { lstlisting}
\item \textbf { Krok 10:} Przeładownie \lstinline { systemctl} :
\begin { lstlisting} [
frame=single,
numbers=none,
]
% systemctl daemon-reload
\end { lstlisting}
2021-01-16 13:51:05 +01:00
\item \textbf { Krok 11:} W celu posiadania dodania certyfikatu do backendu
keystore należy umieścić w \lstinline { /keys/keystore.p12}
\item \textbf { Krok 12:} Włączenie aby aplikacja uruchamiała się przy starcie
2021-01-14 15:03:23 +01:00
systemu oraz pierwsze jej uruchomienie, a także status:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% systemctl enable plannaplan-backend
% systemctl start plannaplan-backend
% systemctl status plannaplan-backend
\end { lstlisting}
\end { itemize}
\subsubsection { Binarna wersja aplikacji} \label { sssec:num1}
\begin { itemize}
\item \textbf { Krok 0:} Wymagania: \\
- System operacyjny: Linux \\
2021-01-16 13:51:05 +01:00
- Minimalna wersja Java 14 \\
2021-01-14 15:03:23 +01:00
- Baza Danych (np. MariaDB) \\
- Osobny user do uruchamiania aplikacji np. backend
\item \textbf { Krok 1:} Pobranie binarnej.\\
Wszytskie wersje binarane aplikacji znajdują się \url { https://git.plannaplan.pl/filipizydorczyk/backend}
\item \textbf { Krok 2:} Utworzenie folderu oraz skopiowanie binarnej wersji
aplikacji do folderu \lstinline { /opt/plannaplan-backend/}
\item \textbf { Krok 3:} Dodanie pustej bazy danych, a także użytkownika dla backend'u.
\item \textbf { Krok 4:} Samo uruchomienie aplikacji - wiąże się z ustawieniem
zmiennych środowiskowych. Polecamy stworzenie skryptu w Bashu aby to wszytsko
było przetrzymywane tylko w tym skrypcie. Przykładowy skrypt \ref { skryptBash} .
\item \textbf { Krok 5:} Uzupełnienie skryptu (nr. \ref { skryptBash} ) swoimi danymi produkcyjnymi.
\item \textbf { Krok 6:} Utworzenie serwisu, aby backend startował przy
uruchomieniu serwera. Przykładowy kod nr. \ref { systemD} .
\item \textbf { Krok 7:} Przeładownie \lstinline { systemctl} :
\begin { lstlisting} [
frame=single,
numbers=none,
]
% systemctl daemon-reload
\end { lstlisting}
2021-01-16 13:51:05 +01:00
\item \textbf { Krok 8:} W celu posiadania dodania certyfikatu do backendu
keystore należy umieścić w \lstinline { /keys/keystore.p12}
\item \textbf { Krok 9:} Włączenie aby aplikacja uruchamiała się przy starcie
2021-01-14 15:03:23 +01:00
systemu oraz pierwsze jej uruchomienie, a także status:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% systemctl enable plannaplan-backend
% systemctl start plannaplan-backend
% systemctl status plannaplan-backend
\end { lstlisting}
\end { itemize}
\subsection { Frontend}
\subsubsection { Budowanie strony ze źródła} \label { sssec:num2}
\begin { itemize}
\item \textbf { Krok 0:} Wymagania: \\
- System operacyjny: Linux \\
- Yarn \\
- Httpd \\
-- Zainstalowany certyfikat SSL (np. Let's Encrypt \footnote { Strona Let's Encrypt:
\url { https://letsencrypt.org/} } ) \\
- Osobny user do uruchamiania aplikacji np. frontend
\item \textbf { Krok 1:} Pobranie repozytorium ze źródła:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% git clone http://git.plannaplan.pl/y0rune/frontend.git
\end { lstlisting}
\item \textbf { Krok 2:} Dodanie zmiennej środowiskowej razem z adresem URL
aplikacji backend:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% echo "REACT_APP_API_URL=https://wmi-backend.plannaplan.pl" > .env
\end { lstlisting}
\item \textbf { Krok 3:} Zainstalowanie pluginów za pomocą \lstinline { Yarn} :
\begin { lstlisting} [
frame=single,
numbers=none,
]
% yarn
\end { lstlisting}
\item \textbf { Krok 4:} Zbudowanie statycznej strony:
\begin { lstlisting} [
frame=single,
numbers=none,
]
% yarn run build
\end { lstlisting}
\item \textbf { Krok 5:} Skopiowanie plików z folderu \lstinline { build/} do
lokalizacji strony w \lstinline { Httpd} (np. \lstinline { /var/www/plannaplan.pl} )
\item \textbf { Krok 6:} Przykładowa konfiguracja (Kod nr. \ref { apacheKonf} ) \lstinline { Httpd} dla
statycznej strony w katalogu \lstinline { /var/www/plannaplan.pl} .
\begin { lstlisting} [
language=bash,
label=apacheKonf,
frame=single,
numbers=left,
caption={ Konfiguracja statycznej strony w Httpd.}
]
<VirtualHost *:80>
RewriteEngine on
RewriteCond %{SERVER_NAME} = #URL DO STRONY
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:443>
SSLEngine on
ServerName #URL DO STRONY :443
DocumentRoot /var/www/plannaplan.pl/
ServerAdmin #EMAIL ADMINISTRATORA
SSLCertificateFile /etc/letsencrypt/live/full.plannaplan.pl/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/full.plannaplan.pl/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
<Directory /var/www/plannaplan.pl/>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
Allow from all
Options -Indexes
</Directory>
</VirtualHost>
\end { lstlisting}
\item \textbf { Krok 7:} Restart \lstinline { Httpd} za pomocą \lstinline { systemctl}
\begin { lstlisting} [
frame=single,
numbers=none,
]
% systemctl httpd restart
\end { lstlisting}
\end { itemize}
\newpage
\section { Wdrożenie aplikacji}
\subsection { Pierwsze ręczne wdrożenie}
Każdy z naszych serwisów czyli Backend, Frontend, Baza Danych zostały wdrożone
do serwerów, które znajdują się w chmurze Google Cloud
2021-01-14 15:08:40 +01:00
Platform\footnote { Chmura Google: \url { https://cloud.google.com} } . Dodatkowo ze względów
2021-01-14 15:03:23 +01:00
bezpieczeństwa ruch jest przekierowany przez serwer Proxy.
\begin { figure} [hbt!]
\centering
\includegraphics [width=0.8\textwidth] { img/infra.pdf}
\caption { Infrastruktura naszej aplikacji}
\footnotesize { Źródło: Opracowanie własne}
\label { fig:infra}
\end { figure}
\subsubsection { Proxy}
2021-01-14 15:07:29 +01:00
Serwer znajduje się w chmurze Vultr\footnote { Chmura Vultr: \url { https://www.vultr.com/} } . Pełni on role serwera
2021-01-14 15:03:23 +01:00
proxy \footnote { Definicja serwera proxy. Link:
\url { https://en.wikipedia.org/wiki/Proxy_ server} } .
\vspace { 5px}
Informacje o serwerze:
\begin { itemize} [noitemsep]
\item 1vCPU
\item 1 GB pamięci RAM
\item 25 GB pojemność dysku
\item System Operacyjny: Gentoo Linux \footnote { Strona główna dystrybucji: \url { https://gentoo.org} }
\item Lokalizacja: Frankfurt, Niemcy
\end { itemize}
\subsubsection { Backend}
Wdrożenie backendu aplikacji odbywało się podobnie jak to zostało opisane w
podrozdziale \ref { sssec:num1} .
\vspace { 5px}
Informacje o serwerze:
\begin { itemize} [noitemsep]
2021-01-16 15:59:25 +01:00
\item 2vCPU
\item 2 GB pamięci RAM
2021-01-14 15:03:23 +01:00
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end { itemize}
\subsubsection { Frontend}
Wdrożenie frontendu aplikacji odbywało się podobnie jak to zostało opisane w
podrozdziale \ref { sssec:num2} .
\vspace { 5px}
Informacje o serwerze:
\begin { itemize} [noitemsep]
\item 1vCPU
\item 600 MB pamięci RAM
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end { itemize}
\subsubsection { Baza danych}
Wdrożenie bazy danych (MariaDB\footnote { Strona projektu MariaDB \url { https://mariadb.org/} } w naszym przypadku) polegało na zainstalowaniu jej na osobnej maszynie.
\vspace { 5px}
Informacje o serwerze:
\begin { itemize} [noitemsep]
2021-01-16 15:59:25 +01:00
\item 2vCPU
\item 1.7 GB pamięci RAM
2021-01-14 15:03:23 +01:00
\item 20 GB pojemność dysku
\item System Operacyjny: CentOS 8
\item Lokalizacja: Frankfurt, Niemcy
\end { itemize}
\subsection { Automatyzacja wdrożenia na produkcje}
Z powodu dość czasochłonnej każdorazowej zmiany na produkcję, doszliśmy do
wniosku, że automatyzacja jest czymś koniecznym w naszym projekcie.
Gdy odbywają się prace, które mają na celu poprawę aplikacji, każda taka zmiana
odbywa się na osobnej gałęzi (branchu). Następnie, osoba wykonująca zmianę prosi
o zmianę (w Pull Request) a kolejna osoba sprawdza czy wszystkie testy
przechodzą na lokalnej maszynie użytkownika. W dalszym kroku akceptuje zmiany a
następnie repozytorium klonowane jest do kilku instancji (GitLab, GitHub, Gitea)
w celu zapasowej oraz przeprowadzenia kompilacji i wdrożenie jej na wybrany
serwis.
\subsubsection { Backend}
Automatyzacja backendu odbywa się w kilku krokach:
\begin { itemize}
\item { build - aplikacja jest kompilowana, jeżeli wszytsko przejdzie zgodnie z
planem CI/CD uruchamia kolejny krok.}
\item { deploy\_ production - binarny plik jest wysyłany do serwera, serwis
\lstinline { plannaplan-backend} jest restartowny. W celu przeładowania
aplikacji.}
\end { itemize}
\begin { lstlisting} [
label=backendYaml,
frame=single,
numbers=left,
caption={ Konfiguracja CI/CD backendu}
]
stages:
- build
- deploy
build:
stage: build
image: maven
script:
- echo "Start building App"
- echo "spring.profiles.active=prod" > restservice/src/main/resources/application.properties
- mvn clean
- mvn install
- cd restservice
- mvn clean package spring-boot:repackage
- echo "Build successfully!"
artifacts:
expire_ in: 1 hour
paths:
- restservice/target/
only:
- master
deploy_ production:
stage: deploy
before_ script:
- apt-get update
- apt-get --yes --force-yes install rsync
script:
- 'which ssh-agent || ( apt-get update -y & & apt-get install openssh-client -y )'
- eval $ ( ssh - agent - s )
- ssh-add <(echo "$ SSH _ PRIVATE _ KEY" )
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] & & echo -e "Host *\n \tStrictHostKeyChecking no\n \n " > ~/.ssh/config'
- echo "Deploying to server"
- ssh backend@wmi-backend-gc.plannaplan.pl -t "sudo systemctl stop plannaplan-backend"
- ssh backend@wmi-backend-gc.plannaplan.pl -t "rm -rf /opt/plannaplan-backend/backend.jar"
- rsync --progress restservice/target/*.jar backend@wmi-backend-gc.plannaplan.pl:/opt/plannaplan-backend/backend.jar
- sleep 5
- ssh backend@wmi-backend-gc.plannaplan.pl -t "sudo systemctl start plannaplan-backend"
- echo "Deployed"
only:
- master
\end { lstlisting}
\subsubsection { Frontend}
\begin { itemize}
\item { build - aplikacja jest kompilowana, jeżeli wszytsko przejdzie zgodnie z
planem CI/CD uruchamia kolejny krok.}
\item { deploy\_ production - statyczna strona wysyłana do serwera, serwis
\lstinline { httpd} jest restartowny. W celu przeładowania aplikacji.}
\end { itemize}
\begin { lstlisting} [
label=backendYaml,
frame=single,
numbers=left,
caption={ Konfiguracja CI/CD frontendu}
]
stages:
- build
- deploy
build:
stage: build
image: node
script:
- echo "Start building App"
- echo "REACT_ APP_ API_ URL=https://wmi-backend.plannaplan.pl" > .env
- yarn
- CI= yarn run build
- echo "Build successfully!"
artifacts:
expire_ in: 1 hour
paths:
- build
- node_ modules/
deploy_ production:
stage: deploy
before_ script:
- apt-get update
- apt-get --yes --force-yes install rsync
script:
- 'which ssh-agent || ( apt-get update -y & & apt-get install openssh-client -y )'
- eval $ ( ssh - agent - s )
- ssh-add <(echo "$ SSH _ PRIVATE _ KEY" )
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] & & echo -e "Host *\n \tStrictHostKeyChecking no\n \n " > ~/.ssh/config'
- echo "Deploying to server"
- rsync --progress -r build/* --delete website@wmi-frontend.plannaplan.pl:/var/www/plannaplan.pl
- echo "Deployed"
only:
- master
\end { lstlisting}
\end { document}