
Há dois anos, publicamos o artigo "
Criando projetos com o GitLab CI: um .gitlab-ci.yml para centenas de aplicativos ", e agora falaremos sobre a solução de um problema semelhante hoje. O novo material é sobre como você pode criar processos de CI / CD para um grande número de aplicativos semelhantes com o advento de
include
no
.gitlab-ci.yml
e o advento do werf para substituir o dapp.
Introdutório
Nas instruções adicionais fornecidas no artigo, a seguinte situação é considerada:
- Há um aplicativo cliente grande, dividido em vários repositórios.
- Cada repositório é um aplicativo separado que deve ser executado em um cluster Kubernetes.
- Como um sistema de IC, o GitLab CI é usado.
- A implantação (a infraestrutura na qual o código é implantado) é descrita pelos gráficos Helm.
- Crie imagens e implante no Kubernetes usando o werf .
Por simplicidade e conveniência (e como uma homenagem à moda), continuaremos chamando esses microsserviços de aplicativos.
Todos esses microsserviços são montados, implementados e lançados da mesma maneira , e configurações específicas são definidas usando variáveis de ambiente.
Claramente, copiar
.gitlab-ci.yml
,
werf.yaml
e
.helm
traz muitos problemas. Afinal, qualquer edição no IC, o processo de montagem ou a descrição do Helm-chart devem ser adicionados a outros repositórios ...
Conectando modelos em .gitlab-ci.yml
Com o advento da diretiva
include:file
no GitLab CE (
desde a versão 11.7 ), tornou-se possível criar um IC comum.
include
próprio
include
apareceu um pouco antes (na 11.4), mas permitiu conectar modelos apenas a partir
de URLs
públicas , o que limitou um pouco sua funcionalidade. A documentação do GitLab
descreve perfeitamente todos os recursos e exemplos de uso.
Assim, foi possível se recusar a copiar
.gitlab-ci.yml
entre repositórios e dar suporte à sua relevância. Aqui está um exemplo
.gitlab-ci.yml
com
include
:
include: - project: 'infra/gitlab-ci' ref: 1.0.0 file: base-gitlab-ci.yaml - project: 'infra/gitlab-ci' ref: 1.0.0 file: cleanup.yaml
É altamente recomendável que você use nomes de filiais em
ref
com cuidado . As inclusões são calculadas no momento em que o pipeline foi criado, para que as alterações no IC possam cair automaticamente no pipeline de produção no momento mais inoportuno. Mas o
uso de tags em ref
facilita a versão da descrição dos processos de CI / CD. Ao atualizar, tudo parece o mais transparente possível e você pode acompanhar facilmente o histórico de alterações nas versões de pipeline se usar o controle de versão semântico para tags.
Conecte .helm a partir de um repositório separado
Como esses microsserviços são implantados e executados da mesma maneira, é necessário o mesmo conjunto de modelos do Helm. Para evitar a cópia do diretório
.helm
entre repositórios,
.helm
o repositório no qual os modelos do Helm foram armazenados e verificados na tag desejada. Parecia algo assim:
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.example.com/infra/helm.git .helm - cd .helm && git checkout tags/1.0.0 - type multiwerf && source <(multiwerf use 1.0 beta) - type werf && source <(werf ci-env gitlab --tagging-strategy tag-or-branch --verbose) - werf deploy --stages-storage :local
Também houve variações usando os submódulos git, mas tudo parece mais uma solução alternativa ...
E agora, com o recente lançamento do werf, ele
tem a oportunidade de conectar gráficos de repositórios externos. O suporte total para as funções do gerenciador de pacotes, por sua vez, tornou possível descrever de forma
transparente as dependências para a implantação do aplicativo.
Sequência de ações
Vamos voltar a resolver nosso problema com microsserviços. Vamos aumentar nosso repositório para armazenar gráficos Helm - por exemplo,
ChartMuseum . Ele é implantado facilmente em um cluster Kubernetes:
helm repo add stable https://kubernetes-charts.storage.googleapis.com helm install stable/chartmuseum --name flant-chartmuseum
Adicionar entrada:
apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.class: nginx nginx.ingress.kubernetes.io/force-ssl-redirect: "false" nginx.ingress.kubernetes.io/proxy-body-size: 10m nginx.ingress.kubernetes.io/ssl-redirect: "false" name: chart-museum spec: rules: - host: flant-chartmuseum.example.net http: paths: - backend: serviceName: flant-chartmuseum servicePort: 8080 path: / status: loadBalancer: {}
A implantação
flant-chartmuseum
precisa alterar a variável de ambiente
DISABLE_API
para
false
. Caso contrário (por padrão), as solicitações da API do ChartMuseum não funcionarão e não será possível criar novos gráficos.
Agora, descrevemos o repositório no qual os gráficos Helm compartilhados serão armazenados. A estrutura de seus diretórios é a seguinte:
. ├── charts │ └── yii2-microservice │ ├── Chart.yaml │ └── templates │ ├── app.yaml └── README.md
Chart.yaml
pode ficar assim:
name: yii2-microservice version: 1.0.4
O diretório de
templates
deve conter todas as primitivas necessárias do Kubernetes necessárias para implantar o aplicativo no cluster. Como você já deve ter adivinhado, neste caso, o microsserviço é um aplicativo PHP baseado na estrutura yii2. Vamos descrever sua implantação mínima com dois contêineres nginx e php-fpm que são criados usando o werf:
--- apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Values.global.werf.name }} spec: replicas: 1 revisionHistoryLimit: 3 template: metadata: labels: service: {{ .Values.global.werf.name }} spec: imagePullSecrets: - name: registrysecret containers: - name: backend {{ tuple "backend" . | include "werf_container_image" | indent 8 }} command: [ '/usr/sbin/php-fpm7', "-F" ] ports: - containerPort: 9000 protocol: TCP name: http env: {{ tuple "backend" . | include "werf_container_env" | indent 8 }} - name: frontend command: ['/usr/sbin/nginx'] {{ tuple "frontend" . | include "werf_container_image" | indent 8 }} ports: - containerPort: 80 name: http lifecycle: preStop: exec: command: ["/usr/sbin/nginx", "-s", "quit"] env: {{ tuple "frontend" . | include "werf_container_env" | indent 8 }} --- apiVersion: v1 kind: Service metadata: name: {{ .Values.global.werf.name }} spec: selector: service: {{ .Values.global.werf.name }} ports: - name: http port: 80 protocol: TCP
A variável
.Values.global.werf.name
contém o nome do projeto no arquivo
werf.yaml
, que permite obter os nomes necessários de serviços e Implantações.
Vamos fazer a automação mais simples para enviar push no ChartMuseum de nossos gráficos ao confirmar na ramificação mestre. Para fazer isso, descrevemos
.gitlab-ci.yml
:
Build and push to chartmuseum: script: - for i in $(ls charts); do helm package "charts/$i"; done; - for i in $(find . -type f -name "*.tgz" -printf "%f\n"); do curl --data-binary "@$i" http://flant-chartmuseum.example.net/api/charts; done; stage: build environment: name: infra only: - master tags: - my-shell-runner-tag
Os gráficos são versionados alterando a
version
no
Chart.yaml
. Todos os novos gráficos serão adicionados automaticamente ao ChartMuseum.
Vamos para a linha de chegada! No repositório do projeto em
.helm/requirements.yaml
escrevemos as dependências para o gráfico:
dependencies: - name: yii2-microservice version: "1.0.4" repository: "@flant"
... e execute no diretório com o repositório:
werf helm repo init werf helm repo add flant http://flant-chartmuseum.example.net werf helm dependency update
Entramos nele
.helm/requirements.lock
. Agora, para implantar o aplicativo no cluster, basta executar o
werf helm dependency build
do
werf helm dependency build
antes de executar o
werf deploy
.
Para atualizar a descrição da implementação do aplicativo, agora você precisa percorrer os repositórios com microsserviços e aplicar pequenos patches com alterações nos hashes e tags em
requirements.yaml
e
requirements.lock
. Se desejar, essa operação também pode ser automatizada por meio do IC: já descrevemos como fazer isso no
artigo mencionado .
Conclusão
Espero que a sequência descrita de ações para atender a aplicativos semelhantes seja útil para engenheiros que enfrentam problemas semelhantes. E teremos o maior prazer em compartilhar outras receitas práticas para usar o
werf . Portanto, se você tiver dificuldades que parecem intransponíveis ou simplesmente incompreensíveis de implementar, sinta-se à vontade para entrar em contato com o
Telegram ou deixar solicitações de materiais futuros aqui nos comentários.
PS
Leia também em nosso blog: