dokumentacja-plannaplan/dokumentacja-wdrozeniowa/dokumentacja-wdrozeniowa.tex

595 lines
16 KiB
TeX
Raw Normal View History

\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{\chaptermark}[1]{%
%\markboth{\MakeUppercase{%
%\chaptername}\ \thechapter.%
%\ #1}{}}
\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 \\
- Java 14 \\
- 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,
]
% git clone git@git.plannaplan.pl:filipizydorczyk/backend.git
\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}
\item \textbf{Krok 11:} Włączenie aby aplikacja uruchamiała się przy starcie
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 \\
- Java 14 \\
- 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}
\item \textbf{Krok 8:} Włączenie aby aplikacja uruchamiała się przy starcie
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
Platform\footnote{Źródło: \url{https://cloud.google.com}}. Dodatkowo ze względów
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}
Serwer znajduje się w chmurze Vultr. Pełni on role serwera
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]
\item 1vCPU
\item 1.7 GB pamięci RAM
\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]
\item 1vCPU
\item 600 MB pamięci RAM
\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}