
Hace dos años
publicamos el artículo "
Creación de proyectos con GitLab CI: un .gitlab-ci.yml para cientos de aplicaciones ", y ahora hablaremos de resolver un problema similar hoy. El nuevo material trata sobre cómo puede construir procesos CI / CD para una gran cantidad de aplicaciones similares con la llegada de
include
en
.gitlab-ci.yml
y la llegada de werf para reemplazar dapp.
Introductorio
En las instrucciones adicionales dadas en el artículo, se considera la siguiente situación:
- Hay una gran aplicación de cliente, que se divide en muchos repositorios.
- Cada repositorio es una aplicación separada que debe ejecutarse en un clúster de Kubernetes.
- Como sistema de CI, se utiliza GitLab CI.
- La implementación (la infraestructura en la que se implementa el código) se describe en los diagramas de Helm.
- Cree imágenes e impleméntelas en Kubernetes con werf .
Por simplicidad y conveniencia (y como un tributo a la moda), continuaremos llamando a estas aplicaciones microservicios.
Todos estos microservicios se ensamblan, implementan y lanzan de la misma manera , y las configuraciones específicas se configuran utilizando variables de entorno.
Claramente, copiar
.gitlab-ci.yml
,
werf.yaml
y
.helm
trae muchos problemas. Después de todo, cualquier edición en CI, el proceso de ensamblaje o la descripción del Helm-chart deberían agregarse a otros repositorios ...
Conexión de plantillas en .gitlab-ci.yml
Con el advenimiento de la directiva
include:file
en GitLab CE (
desde la versión 11.7 ), se hizo posible hacer un CI común.
include
apareció un poco antes (en 11.4), pero permitió conectar plantillas solo desde URL
públicas , lo que limitó un poco su funcionalidad. La documentación de GitLab
describe perfectamente todas las características y ejemplos de uso.
Por lo tanto, fue posible negarse a copiar
.gitlab-ci.yml
entre repositorios y respaldar su relevancia. Aquí hay un ejemplo
.gitlab-ci.yml
con
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
Recomendamos encarecidamente que utilice los nombres de las sucursales en la
ref
con precaución . Las inclusiones se calculan en el momento en que se creó la tubería, por lo que los cambios de CI pueden caer automáticamente en la tubería de producción en el momento más inoportuno. Pero el
uso de etiquetas en la ref
facilita la versión de la descripción de los procesos de CI / CD. Al actualizar, todo se ve lo más transparente posible y puede seguir fácilmente el historial de cambios en las versiones de canalización si usa el control de versiones semántico para las etiquetas.
Conecte .helm desde un repositorio separado
Dado que estos microservicios se implementan y ejecutan de la misma manera, se requiere el mismo conjunto de plantillas de Helm. Para evitar copiar el directorio
.helm
entre repositorios, solíamos clonar el repositorio en el que se almacenaban las plantillas de Helm y se verificaban en la etiqueta deseada. Se parecía a esto:
- 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
También hubo variaciones usando submódulos git, pero todo parece más una solución alternativa ...
Y ahora, con el reciente lanzamiento de werf,
tiene la oportunidad de conectar gráficos desde repositorios externos. El soporte completo para las funciones del administrador de paquetes, a su vez, nos permitió describir de manera
transparente las dependencias para el despliegue de la aplicación.
Secuencia de acciones
Volvamos a resolver nuestro problema con microservicios. Levantemos nuestro repositorio para almacenar gráficos Helm, por ejemplo,
ChartMuseum . Se implementa fácilmente en un clúster de Kubernetes:
helm repo add stable https://kubernetes-charts.storage.googleapis.com helm install stable/chartmuseum --name flant-chartmuseum
Añadir ingreso:
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: {}
La implementación de
flant-chartmuseum
debe cambiar la variable de entorno
DISABLE_API
a
false
. De lo contrario (de forma predeterminada), las solicitudes de API de ChartMuseum no funcionarán y no será posible crear nuevos gráficos.
Ahora describimos el repositorio en el que se almacenarán los gráficos compartidos de Helm. La estructura de sus directorios es la siguiente:
. ├── charts │ └── yii2-microservice │ ├── Chart.yaml │ └── templates │ ├── app.yaml └── README.md
Chart.yaml
podría verse así:
name: yii2-microservice version: 1.0.4
El directorio de
templates
debe contener todas las primitivas de Kubernetes necesarias que se necesitarán para implementar la aplicación en el clúster. Como ya habrás adivinado, en este caso, el microservicio es una aplicación PHP basada en el marco yii2. Describamos su implementación mínima con dos contenedores nginx y php-fpm que se crean con 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
La variable
.Values.global.werf.name
contiene el nombre del proyecto del archivo
werf.yaml
, que le permite obtener los nombres necesarios de servicios y despliegues.
Hagamos la automatización más simple para empujar en el ChartMuseum de nuestros gráficos cuando nos comprometemos con la rama maestra. Para hacer esto, describimos
.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
Los gráficos se versionan cambiando la
version
en
Chart.yaml
. Todos los gráficos nuevos se agregarán automáticamente al ChartMuseum.
¡Vamos a la meta! En el repositorio del proyecto en
.helm/requirements.yaml
escribimos las dependencias para el gráfico:
dependencies: - name: yii2-microservice version: "1.0.4" repository: "@flant"
... y ejecutar en el directorio con el repositorio:
werf helm repo init werf helm repo add flant http://flant-chartmuseum.example.net werf helm dependency update
Entramos en él
.helm/requirements.lock
. Ahora, para implementar la aplicación en el clúster, es suficiente ejecutar el
werf helm dependency build
antes de ejecutar
werf deploy
.
Para actualizar la descripción de la implementación de la aplicación, ahora debe pasar por los repositorios con microservicios y aplicar pequeños parches con cambios en los hashes y etiquetas en
requirements.yaml
y
requirements.lock
. Si lo desea, esta operación también se puede automatizar a través de CI: ya describimos cómo hacerlo en el
artículo mencionado .
Conclusión
Espero que la secuencia de acciones descrita para dar servicio a aplicaciones similares sea útil para los ingenieros que enfrentan problemas similares. Y estaremos encantados de compartir otras recetas prácticas para usar
werf . Por lo tanto, si tiene dificultades que parecen insuperables o simplemente incomprensibles de implementar, no dude en comunicarse con
Telegram o dejar las solicitudes de materiales futuros aquí en los comentarios.
PS
Lea también en nuestro blog: