Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Desafio DevOps #2

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 130 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,52 +1,150 @@
# Desafio DevOps Apiki.
## Documentação - Resultado
Esse projeto tem como objetivo rodar uma aplicação Wordpress em um cluster Kubernetes hospedado em instâncias Amazon EC2. Segue abaixo a stack utilizada:

* PHP 7.4.2
* Wordpress 5.4.2
* Apache/2.4.38
* Nginx Ingress como proxy
* McRouter para cacheamento (protocolo Memcached)

### Tecnologias utilizadas

Objetivo é criar um processo automatizado para construção de um servidor web para [WordPress](https://wordpress.org/) em sua última versão.
- [Kubernetes](https://kubernetes.io/)
- [Helm](https://helm.sh/docs/intro/install/)
- [Kops e Kubectl](https://github.com/kubernetes/kops/blob/master/docs/install.md)
- [Docker](https://www.docker.com/)
- [Amazon EC2](https://aws.amazon.com/pt/ec2/)
- [Amazon S3](https://aws.amazon.com/pt/s3/)

O candidato deve seguir os seguintes **Requisitos**;
---

- O projeto dever ser configurado na [AWS](https://aws.amazon.com/free/), crie uma conta Free.
- A máquina configurada deverar ter às portas 80, 443 e 22 abertas.
- Uso de Shell Script **Linux**.
- [Docker](https://www.docker.com/)
## Criar cluster

### Arquitertura!
1. Criar uma função do IAM na AWS, com as seguintes permissões:

- [Nginx](https://www.nginx.com/) configurado como proxy para o Apache.
- [Apache](https://www.apache.org/) servidor para o WordPress.
- [PHP](https://php.net/) a última versão.
- [MySql](https://www.mysql.com/) Versão mínima requirida 5.7.
- [WordPress](https://wordpress.org) última versão configurada no servidor Apache.
* AmazonEC2FullAccess
* IAMFullAccess
* AmazonS3FullAccess
* AmazonVPCFullAccess

2. Crie uma nova instância para usar como seu CI host. Este nó lidará com o provisionamento e o desmembramento do cluster.
1. Essa instância (Ubuntu 16.04) pode ser pequena (t2.micro por exemplo).
2. Ao criá-lo, atribua a função IAM criada na primeira etapa.
3. Uma vez criada, faça o download das chaves ssh ou adicione a sua própria chave pública do seu computador local na instância.

3. Acesse via SSH o CI host.
4. Instale o kops e o kubectl no CI host. Siga as instruções [aqui](https://github.com/kubernetes/kops/blob/master/docs/install.md).
5. Configure um par de chaves ssh para usar com o cluster
6. Crie as seguintes variáveis pelo terminal
* Como não estamos usando DNS pré-configurado, usaremos o sufixo “.k8s.local”. De acordo com a documentação do k8s, se o nome DNS terminar em .k8s.local, o cluster usará o DNS hospedado interno.

`export NAME=<nome_do_cluster>.k8s.local`

* Crie um bucket S3 para armazenar sua configuração de cluster. É recomendável ativar o controle de versão no bucket S3. Não precisamos passar isso para os comandos do KOPS. Ele detecta automaticamente pela ferramenta kops como uma variável env.

`export KOPS_STATE_STORE=s3://<nome_do_seu_bucket_aqui>`

* Defina a mesma região utilizada na instância CI host.

`export REGION=us-east-2`

* É recomendável configurar essas variáveis no arquivo `/etc/profiles`. As variáveis definidas neste arquivo são carregadas sempre que um shell de login do bash é iniciado. Ao declarar variáveis de ambiente neste arquivo, você precisa usar o comando export também. Igual nos exemplos anteriores.

`sudo nano /etc/profiles`

**Modelo conceitual**
7. Instale a CLI da AWS:

`sudo apt-get update`
`sudo apt-get install awscli`

8. Crie o cluster

`kops create cluster $NAME --zones us-east-2c --authorization RBAC --master-size t2.micro --master-volume-size 10 --node-size t2.medium --node-volume-size 10 --yes`

9. Aguarde a inicialização do cluster.
* A execução do comando 'kops validate cluster' nos dirá qual é o estado atual da instalação. Se você vir "não é possível obter nós" inicialmente, apenas seja paciente, pois o cluster não pode relatar até que alguns serviços básicos estejam em funcionamento.

`time until kops validate cluster; do sleep 15 ; done`

10. Confirme se kubectl está conectado ao seu cluster Kubernetes.

`kubectl get nodes`

11. (Opcional) Se você deseja usar o kubectl e o helm na sua máquina local. Siga esses passos:
* Execute o seguinte comando no CI host:

`kops export kubecfg`

* Copie o conteúdo do arquivo `~/.kube/config` para o mesmo local no sistema local.

* Com isso você poderá orquestrar o seu cluster através da sua máquina local, ao invés de ter que entrar via ssh no CI host.

[![N|Solid](https://apiki.com/wp-content/uploads/2019/05/Screenshot_20190515_174205.png)](https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/)

---

### Se liga!
## Criar os containers e pods
Depois de criar o cluster, você já pode criar todas as implantações necessárias que rodarão nos pods.
1. Caso tenha feito o passo 11, a primeira coisa a se fazer é clonar esse repositório na sua máquina local.
2. Caso tenha pulado o passo 11, é necessário clonar esse repositório no CI host.


### Implantação Wordpress e MySQL
Antes da criação dos containers principais, e obrigatório a criação de um secret para o usuário e senha do banco de dados.

Você também pode usar como **Diferencial**:
Crie a chave secreta db-credentials usando o nome e a senha do usuário do banco de dados de sua escolha:

`kubectl create secret generic db-credentials --from-literal=username=<USUARIO_AQUI> --from-literal=password=<SENHA_AQUI>`

Para implantar o Wordpress, Apache e MySQL vai ser necessário usar o Helm Chart que está no diretório `wp-php-chart` desse repositório.

`helm install wp-php-chart wp-phpchart\`


### Implantação balanceador de carga com Ingress Nginx
Para implantar o Nginx que terá uma função de proxy, siga os passos abaixo:
1. Adicione o repositório abaixo para conseguir utilizar o chart. Caso queira, pode conferir a [documentação](https://hub.kubeapps.com/charts/stable/nginx-ingress) do respectivo chart.

- [Docker Compose](https://docs.docker.com/compose/).
- [Kubernetes](https://kubernetes.io/).
- [Ansible](https://www.ansible.com/).
- [RDS AWS](https://aws.amazon.com/pt/rds/).
- Outras tecnologias para somar no projeto.
`helm repo add stable https://kubernetes-charts.storage.googleapis.com/`

2. Instale o Helm Chart do nginx ingress. Caso queria definir alguma configuração personalizada, mude no arquivo `nginx\values.yaml`. É nesse passo que o balanceador de carga será criado, junto com as implantações do Nginx.

`helm install nginx stable/nginx-ingress -f nginx\values.yaml`

3. Descubra o ip externo do controlador nginx.

`kubectl get services`

4. Altere a entrada spec.rules.host do arquivo `nginx\ingress.yaml` e coloque o ip externo que você descobriu no passo anterior.

5. Implante o ingress

`kubectl apply -f nginx\ingress.yaml`


### Implantação do McRouter - Opcional
O Mcrouter (pronuncia-se "mick router"), um proxy Memcached de código aberto eficiente, permite o agrupamento de conexões. A integração do Mcrouter é perfeita porque ele usa o protocolo padrão Memcached ASCII. Para um cliente do Memcached, o Mcrouter se comporta como um servidor do Memcached normal. Para um servidor do Memcached, o Mcrouter se comporta como um cliente do Memcached normal.

Uma maneira simples de implantar um serviço do Memcached no cluster é usar um gráfico do Helm.

`helm install cache stable/mcrouter --set memcached.replicaCount=2`

Depois de implantar o McRouter, recomendo utilizar o plugin W3 Total Cache para realizar as configurações para começar a utilizar o memcached.

---

### Entrega
## Deletar o cluster
1. Se em algum momento você desejar destruir seu cluster, execute:

1. Efetue o fork deste repositório e crie um branch com o seu nome e sobrenome. (exemplo: fulano-dasilva)
2. Após finalizar o desafio, crie um Pull Request.
3. Aguarde algum contribuidor realizar o code review.
4. Deverá conter a documentação para instalação e configuração README.md.
5. Enviar para o email [email protected] os dados de acesso SSH com permissão root, da máquina configurada na AWS.
`kops delete cluster $NAME --yes`

---

### Validação
## Referências

* Será executado os precessos de instalação e configuração de acordo com a orientação da documentação em um servidor interno da Apiki.
* Será avaliado o processo de automação para criação do ambiente em cloud, tempo de execução e a configuração no server na AWS com os dados fornecidos pelo candidato.
* Deverar constar pelo menos 2 containers.
- [Mcrouter](https://github.com/helm/charts/tree/master/stable/mcrouter)
- [Nginx Ingress](https://hub.kubeapps.com/charts/stable/nginx-ingress)
- [Wordpress Image](https://hub.docker.com/_/wordpress/)
- [Kops](https://kubernetes.io/docs/setup/production-environment/tools/kops/)
- [Kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
- [Kubernetes na AWS](https://kubernetes.io/docs/setup/production-environment/turnkey/aws/)
- [Helm](https://helm.sh/docs/intro/)
17 changes: 17 additions & 0 deletions nginx/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "false"
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: nginx-external-ip-aqui
http:
paths:
- path: /
backend:
serviceName: wordpress
servicePort: 80
5 changes: 5 additions & 0 deletions nginx/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
controller:
extraArgs:
v: 2
proxySetHeaders:
X-Forwarded-For: $proxy_add_x_forwarded_for
70 changes: 70 additions & 0 deletions php/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
FROM wordpress:5.4.2-php7.4-apache

ENV TZ=America/Sao_Paulo
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

RUN apt-get update && apt-get install -y \
libtidy-dev \
zlib1g-dev \
libicu-dev \
libpq-dev \
libmemcached-dev \
locales \
gettext-base \
vim \
gnupg gnupg2 gnupg1

RUN localedef -i pt_BR -c -f UTF-8 -A /usr/share/locale/locale.alias pt_BR.UTF-8

ENV LANG pt_BR.UTF-8
ENV LC_ALL pt_BR.UTF-8

RUN pecl install apcu \
pecl install msgpack \
pecl install igbinary

RUN docker-php-ext-install pdo_mysql \
&& docker-php-ext-install tidy \
&& docker-php-ext-enable apcu \
&& docker-php-ext-enable msgpack \
&& docker-php-ext-enable igbinary

# Instalação da extensão memcached
RUN curl -kL -o /tmp/memcached.tar.gz "https://github.com/php-memcached-dev/php-memcached/archive/v3.1.3.tar.gz" \
&& mkdir -p /usr/src/php/ext/memcached \
&& tar -C /usr/src/php/ext/memcached -zxvf /tmp/memcached.tar.gz --strip 1 \
&& docker-php-ext-configure memcached --enable-memcached-igbinary --enable-memcached-json --enable-memcached-msgpack

RUN docker-php-ext-install memcached

RUN apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*

RUN { \
echo 'memory_limit = 256M'; \
echo 'post_max_size = 50M'; \
echo 'upload_max_filesize = 50M'; \
echo 'max_execution_time = 300'; \
echo 'date.timezone = "America/Fortaleza"'; \
echo 'max_input_vars = 4000'; \
echo 'realpath_cache_size = 1M'; \
echo 'realpath_cache_ttl = 300'; \
echo 'output_buffering = 4096'; \
echo 'short_open_tag = "off"'; \
echo 'expose_php = "off"'; \
echo 'apc.shm_size = 256M'; \
echo 'apc.ttl = 7200'; \
echo 'apc.user_ttl = 7200'; \
echo 'apc.gc_ttl = 3600'; \
echo 'memcached.sess_binary_protocol = "Off"'; \
echo 'session.save_handler = "memcached"'; \
echo 'session.save_path = "memcached-memcached-svc:11211"'; \
} > /usr/local/etc/php/conf.d/extra-conf.ini

COPY php-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/php-entrypoint.sh

WORKDIR /var/www/html

ENTRYPOINT ["php-entrypoint.sh"]
CMD ["apache2-foreground"]
29 changes: 29 additions & 0 deletions php/php-entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

if [ ! -z "$NODE_NAME" ]; then
envsubst '$NODE_NAME' < /var/www/html/wp-content/w3tc-config/master.php > /var/www/html/wp-content/w3tc-config/master.template
mv /var/www/html/wp-content/w3tc-config/master.template /var/www/html/wp-content/w3tc-config/master.php
# configuração para ter um código php imutavél, por causa do cache do opcache. Viável em prod
#echo 'opcache.validate_timestamps = 0' >> /usr/local/etc/php/conf.d/extra-conf.ini

# Replace session.save_path and memcached session config
sed -i -e "s/memcached-memcached-svc:11211/$NODE_NAME:5000/g" /usr/local/etc/php/conf.d/extra-conf.ini

# Check if newrelic should be installed
if [ ! -z "$NR_INSTALL_KEY" ]; then
# Install new relic
newrelic-install install

# Replace PHP Application with our custom name.
sed -i -e "s/PHP Application/$NR_APP_NAME/g" /usr/local/etc/php/conf.d/newrelic.ini
fi
fi

# dev environment
if [ ! -z "$MEMCACHED_SERVER" ]; then
NODE_NAME=$MEMCACHED_SERVER
envsubst '$NODE_NAME' < /var/www/html/wp-content/w3tc-config/master.php > /var/www/html/wp-content/w3tc-config/master.template
mv /var/www/html/wp-content/w3tc-config/master.template /var/www/html/wp-content/w3tc-config/master.php
fi

exec /usr/local/bin/docker-entrypoint.sh "$@"
23 changes: 23 additions & 0 deletions wp-php-chart/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
23 changes: 23 additions & 0 deletions wp-php-chart/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v2
name: wp-php-chart
description: A Helm chart for Wordpress application running on Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
appVersion: 1.16.0
Loading