Aproximación do sistema ás variables en Ansible

estilo de código de devops ansible

Ei! O meu nome é Denis Kalyuzhny Traballo como enxeñeiro no departamento de automatización de procesos de desenvolvemento. Todos os días, lánzanse novas compilacións de aplicacións a centos de servidores de campañas. E neste artigo, comparto a miña experiencia de usar Ansible para estes fins.

Esta guía ofrece un xeito de organizar as variables nun despregamento. Esta guía está deseñada para aqueles que xa utilizan papeis nos seus libros de xogo e len Mellores prácticaspero tendo problemas similares:

  • Despois de atopar unha variable no código, é imposible comprender inmediatamente de que é responsable;
  • Hai varios roles, e as variables deben estar asociadas a un valor, pero non funciona;
  • Tendo dificultades para explicar aos demais como funciona a lóxica das variables dos teus cadernos de xogo

Atopámonos con estes problemas en proxectos da nosa empresa, polo que chegamos ás regras de formato de variables nos nosos playbooks, que en certa medida solucionaron estes problemas.

Aproximación do sistema ás variables en Ansible

Variables nos roles

Un rol é un obxecto de sistema de implementación independente. Como calquera obxecto do sistema, debe ter unha interface para interactuar co resto do sistema. As variables de rol son tal interface.

Tomemos, por exemplo, o papel api, que instala unha aplicación Java no servidor. Que variables ten?

Aproximación do sistema ás variables en Ansible

As variables de función pódense dividir en dous tipos por tipo:

1. Свойства
    a) независимые от среды
    б) зависимые от среды
2. Связи
    a) слушатели 
    б) запросы внутри системы
    в) запросы в среду

Propiedades variables son variables que definen o comportamento dun rol.

Variables de consulta son variables cuxo valor se utiliza para designar recursos externos ao rol.

Oíntes variables son variables cuxo valor se usa para formar variables de consulta.

Por outra banda, 1a, 2a, 2b son variables que non dependen do medio (ferro, recursos externos, etc.) e que se poden encher con valores predeterminados no rol por defecto. Non obstante, variables como 1.b e 2.c non se poden encher con valores distintos de 'exemplo', xa que cambiarán de stand a stand dependendo da contorna.

estilo de código

  • O nome da variable debe comezar co nome do rol. Isto facilitará descubrir no futuro de que función é a variable e de que é responsable.
  • Ao usar variables nos roles, debes asegurarte de seguir o principio de encapsulamento e utilizar variables definidas ben no propio rol ou nos roles dos que depende o actual.
  • Evita usar dicionarios para variables. Ansible non che permite substituír convenientemente valores individuais nun dicionario.

    Un exemplo de variable incorrecta:

    myrole_user:
        login: admin
        password: admin

    Aquí, o inicio de sesión é a variable media e o contrasinal é a variable dependente. Pero
    xa que están combinados nun dicionario, terás que especificalo completo
    Sempre. O que é moi inconveniente. Mellor deste xeito:

    myrole_user_login: admin
    myrole_user_password: admin

Variables nos cadernos de implementación

Ao compilar un manual de implementación (en diante, un libro de xogadas), cumprimos a regra de que debe colocarse nun repositorio separado. Igual que os roles: cada un no seu propio repositorio git. Isto permítelle entender que os papeis e o manual son obxectos independentes diferentes do sistema de despregamento e os cambios nun obxecto non deberían afectar o funcionamento do outro. Isto conséguese cambiando os valores predeterminados das variables.

Ao compilar un playbook, para resumir, é posible anular os valores predeterminados das variables de rol en dous lugares: nas variables do playbook e nas variables de inventario.

mydeploy                        # Каталог деплоя
├── deploy.yml                  # Плейбук деплоя
├── group_vars                  # Каталог переменных плейбука
│   ├── all.yml                 # Файл для переменных связи всей системы
│   └── myapi.yml               # Файл переменных свойств группы myapi
└── inventories                 #
    └── prod                    # Каталог окружения prod
        ├── prod.ini            # Инвентори файл
        └── group_vars          # Каталог для переменных инвентори
            └── myapi           #
                ├── vars.yml    # Средозависимые переменные группы myapi
                └── vault.yml   # Секреты (всегда средозависимы) *

* - Variables e bóvedas

A diferenza é que as variables de playbook sempre se usan cando se chaman playbooks situados no mesmo nivel con el. Isto significa que estas variables son excelentes para cambiar os valores predeterminados de variables que non dependen do entorno. Pola contra, as variables de inventario só se usarán para un ambiente particular, o que é ideal para variables específicas do entorno.

É importante ter en conta que a precedencia das variables non che permitirá redefinir as variables primeiro nas variables do libro de xogos e despois por separado no mesmo inventario.

Isto significa que xa nesta fase cómpre decidir se a variable depende do ambiente ou non e colocala no lugar correcto.

Por exemplo, nun proxecto, a variable responsable de habilitar SSL foi dependente do ambiente durante moito tempo, xa que non puidemos activar SSL por razóns alleas ao noso control nun dos stands. Despois de solucionar este problema, pasou a ser medio independente e pasou ás variables do libro de xogos.

Variables de propiedade para grupos

Ampliemos o noso modelo na Figura 1 engadindo 2 grupos de servidores cunha aplicación Java diferente, pero con configuracións diferentes.

Aproximación do sistema ás variables en Ansible

Imaxina como será o playbook neste caso:

- hosts: myapi
  roles:
    - api

- hosts: bbauth
  roles:
    - auth

- hosts: ghauth
  roles:
    - auth

Temos tres grupos no playbook, polo que se recomenda crear tantos ficheiros de grupo en variables de inventario group_vars e variables de playbook á vez. Neste caso, un ficheiro de grupo é a descrición dun compoñente da súa aplicación no manual. Cando abres o ficheiro de grupo nas variables do libro de xogadas, inmediatamente verás todas as diferenzas co comportamento predeterminado dos roles asignados ao grupo. Nas variables de inventario: diferenzas no comportamento do grupo de caseta a caseta.

Estilo de código

  • Intente non usar as variables host_vars en absoluto, xa que non describen o sistema, senón só un caso especial, que a longo prazo levará a preguntas: "Por que este host é diferente do resto?", A resposta a cal é non sempre é doado de atopar.

Variables de enlace

Non obstante, trátase de variables de propiedade, pero que pasa coas variables de ligazón?
A súa diferenza é que deben ter o mesmo valor en diferentes grupos.

Ao principio houbo a idea use unha construción monstruosa da forma:
hostvars[groups['bbauth'][0]]['auth_bind_port'], pero foi inmediatamente abandonado
porque ten defectos. En primeiro lugar, o volume. En segundo lugar, a dependencia dun anfitrión específico do grupo. En terceiro lugar, é necesario recoller datos de todos os hosts antes de comezar a implantación, se non queremos obter un erro de variable non definido.

Como resultado, decidiuse utilizar variables de ligazón.

Variables de enlace son variables que pertencen ao playbook e son necesarias para vincular obxectos do sistema.

As variables de ligazón enchéganse en variables xerais do sistema group_vars/all/vars e fórmanse eliminando todas as variables de oínte de cada grupo e engadindo o nome do grupo do que se eliminou o oínte ao comezo da variable.

Así, garante a uniformidade e a non intersección dos nomes.

Tentemos ligar variables do exemplo anterior:

Aproximación do sistema ás variables en Ansible

Imaxina que temos variables que dependen unhas das outras:

# roles/api/defaults:
# Переменная запроса
api_auth1_address: "http://example.com:80"
api_auth2_address: "http://example2.com:80"

# roles/auth/defaults:
# Переменная слушатель
auth_bind_port: "20000"

Poñémolo en variables comúns group_vars/all/vars todos os oíntes e engade o nome do grupo ao nome:

# group_vars/all/vars
bbauth_auth_bind_port: "20000"
ghauth_auth_bind_port: "30000"

# group_vars/bbauth/vars
auth_bind_port: "{{ bbauth_auth_bind_port }}"

# group_vars/ghauth/vars
auth_bind_port: "{{ ghauth_auth_bind_port }}"

# group_vars/myapi/vars
api_auth1_address: "http://{{ bbauth_auth_service_name }}:{{ bbauth_auth_bind_port }}"
api_auth2_address: "http://{{ ghauth_auth_service_name }}:{{ ghauth_auth_bind_port }}"

Agora, ao cambiar o valor do conector, estaremos seguros de que a solicitude irá ao mesmo porto.

Estilo de código

  • Dado que os roles e os grupos son obxectos do sistema diferentes, deben ter nomes diferentes para que as variables de ligazón mostren con precisión que pertencen a un grupo de servidores específico e non a un rol no sistema.

Ficheiros do entorno

Os roles poden usar ficheiros que difiren dun ambiente a outro.

Os certificados SSL son un exemplo deste tipo de ficheiros. Gárdaos como texto
nunha variable non é moi conveniente. Pero é conveniente almacenar o camiño ata eles dentro dunha variable.

Por exemplo, usamos a variable api_ssl_key_file: "/path/to/file".

Dado que é obvio que o certificado de chave cambiará dun ambiente a outro, esta é unha variable dependente do ambiente, o que significa que debería estar situada no ficheiro
group_vars/myapi/vars inventario de variables e conteñen o valor "por exemplo".

O xeito máis cómodo neste caso é poñer o ficheiro clave no repositorio do playbook ao longo do camiño
files/prod/certs/myapi.key, entón o valor da variable será:
api_ssl_key_file: "prod/certs/myapi.key". A comodidade reside no feito de que as persoas responsables da implantación do sistema nun stand determinado tamén teñen o seu propio lugar dedicado no repositorio para almacenar os seus ficheiros. Ao mesmo tempo, segue a ser posible especificar a ruta absoluta ao certificado no servidor, no caso de que os certificados sexan subministrados por outro sistema.

Varios postos nun mesmo ambiente

Moitas veces hai que implantar varios postos case idénticos no mesmo ambiente con diferenzas mínimas. Neste caso, dividimos as variables dependentes do ambiente en aquelas que non cambian dentro deste ambiente e as que o fan. E sacamos este último directamente aos propios ficheiros de inventario. Despois desta manipulación, faise posible crear outro inventario directamente no directorio do entorno.

Reutilizará o inventario group_vars e tamén poderá redefinir algunhas variables directamente por si mesmo.

A estrutura de directorio final para o proxecto de implantación:

mydeploy                        # Каталог деплоя
├── deploy.yml                  # Плейбук деплоя
├── files                       # Каталог для файлов деплоя
│   ├── prod                    # Католог для средозависимых файлов стенда prod
│   │   └── certs               # 
│   │       └── myapi.key       #
│   └── test1                   # Каталог для средозависимых файлов стенда test1
├── group_vars                  # Каталог переменных плейбука
│   ├── all.yml                 # Файл для переменных связи всей системы
│   ├── myapi.yml               # Файл переменных свойств группы myapi
│   ├── bbauth.yml              # 
│   └── ghauth.yml              #
└── inventories                 #
    ├── prod                    # Каталог окружения prod
    │   ├── group_vars          # Каталог для переменных инвентори
    │   │   ├── myapi           #
    │   │   │   ├── vars.yml    # Средозависимые переменные группы myapi
    │   │   │   └── vault.yml   # Секреты (всегда средозависимы)
    │   │   ├── bbauth          # 
    │   │   │   ├── vars.yml    #
    │   │   │   └── vault.yml   #
    │   │   └── ghauth          #
    │   │       ├── vars.yml    #
    │   │       └── vault.yml   #
    │   └── prod.ini            # Инвентори стенда prod
    └── test                    # Каталог окружения test
        ├── group_vars          #
        │   ├── myapi           #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   ├── bbauth          #
        │   │   ├── vars.yml    #
        │   │   └── vault.yml   #
        │   └── ghauth          #
        │       ├── vars.yml    #
        │       └── vault.yml   #
        ├── test1.ini           # Инвентори стенда test1 в среде test
        └── test2.ini           # Инвентори стенда test2 в среде test

Resumindo

Despois de organizar as variables segundo o artigo: cada ficheiro con variables é responsable dunha tarefa concreta. E dado que o ficheiro ten determinadas tarefas, fíxose posible asignar un responsable da corrección de cada ficheiro. Por exemplo, o desenvolvedor da implantación do sistema faise responsable do enchemento correcto das variables do libro de xogadas, mentres que o administrador, cuxo posto se describe no inventario, é o responsable directo de cubrir o inventario de variables.

Os roles convertéronse nunha unidade de desenvolvemento autónomo coa súa propia interface, o que permitía ao desenvolvedor de roles desenvolver funcións en lugar de adaptar o rol ao sistema. Este problema foi especialmente certo para os roles comúns para todos os sistemas nunha campaña.

Os administradores do sistema xa non precisan comprender o código de implementación. Todo o que se lles require para unha implantación exitosa é cubrir os ficheiros de variables de ambiente.

Literatura

  1. Documentación

Autor

Kalyuzhny Denis Alexandrovich

Fonte: www.habr.com

Engadir un comentario