Para hacer ciertas tareas, despliego máquinas en la nube EC2 de Amazon. Con ayuda de varios scripts y ssh, desde mi ordenador voy realizando trabajos necesito. Cuando acabo, destruyo las máquinas virtuales para que no tenga coste para la empresa.
Llevaba un tiempo pensando como automatizar de una manera sencilla esta operación. Sé que en Amazon se puede hacer algo similar con CloudFormation e incluso llamar a ese API de Amazon desde scripts escritos en Python, pero quería ver si fuera posible hacer algo más sencillo y con lo que tuviese alguna experiencia previa.
Conozco la herramienta de automatización Ansible de otro proyecto en el que estuve trabajando hace dos años. Hacía bastante tiempo que no la usaba, pero letendo su documentación he visto que tiene dos módulos,ec2 y ec2_instance_facts que me podían servir para lo que quería.
Mi idea era desarrollar un playbook de Ansible, que ejecutándolo en el ordenador local, se encargara de:
- Desplegar una determinada instancia de EC2, si no hay ninguna instancia con un nombre dado.
- Esta instancia se desplegará en una red asociada a una VPC de Amazon determinada, con una clave ssh que se usará para acceder a la misma y con un grupo de seguridad asociado a dicho VPC.
- La imagen AMI que vamos a usar corresponde a Ubuntu 16.04.3 LTS (xenial), usando virtualización de tipo hvm.
- Una vez desplegada la instancia, el playbook entrará en el sistema donde realizará las siguientes operaciones:
- Instarlar el git
- Bajarse el JDK de Java e instalarlo.
- Bajarse el maven e instalarlo.
- Copiar desde el ordenador local la configuración de maven, el fichero situado en $HOME/.m2/settings.xml , al ordenador remoto.
- Clonar varios repositorios desde el git.
Instalar Ansible
Para instalar ansible, lo más cómodo es usar entorno virtual de Python gestionado por un programa como virtualenv. Si se tiene este programa instalado hay que hacer lo siguiente para crear el entorno virtual e instalar dentro del mismo Ansible:
$source vansible/bin/activate
(vansible)$pip install ansible
(vansible)$ansible --version
El script
Al final de esta entrada podéis encontrar el script que he desarrollado para que se despliegue la máquina y me la deje configurada de acuerdo a lo que quiero. El formato del fichero que utiliza los playbooks de Ansible es yaml. Es un poco peculiar como podéis y el parser de ansible a veces hace cosas raras leyéndolo, con lo cual hay que tener bastante cuidado con lo que se pone.
Otra particularidad es que hago uso de los comandos ssh-agent y ssh-keyscan, así como la del reenvío del agente ssh sobre el túnel ssh para no tener que subir claves privadas a la máquina de Amazon.
Tampoco soy un usuario muy hardcode de Ansible. En cierta manera, quería tener algo que me ayudara a realizar mis tareas sin perder demasiado tiempo en la herramienta que fuera a usar. El script admite varias mejoras:
- Comprobar antes de bajarse el JDK o maven que ya están instalados en la máquina.
- Usar algunas opciones ssh para evitar tener que añadir al known_hosts las claves públicas de las máquinas remotas.
- Ver si hay alguna construcción en las expresiones jinja2 que se usan, especialmente aquellas que usan la construccion expresion | default.
- Comprobar si existe los repositorios git antes de bajarlos.
Para ejecutar el script:
Código fuente
- hosts: 127.0.0.1 connection: local gather_facts: False vars: ec2machinename: <<ec2 instance name>> ec2sshkey: <<ssh key name to use in the instance>> ec2instancetype: "t2.xlarge" # instance type ec2region: "us-east-1" # Amazon region ec2ami: "ami-43a15f3e" # AMI (this is the ubuntu one) ec2subnetid: <<subnet id>> ec2securitygroup: <<security group id>> privatekeypath: "~/.ssh/drizzt.key.pem" gitkeypath: "~/.ssh/id_drizzt_bitbucket" mavenconfigpath: "~/.m2/settings.xml" sshoptions: "-oForwardAgent=yes -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null" rcmd: - "sudo apt-get update" - "sudo apt-get -y install git-core" - "curl -L -O -# -H 'Cookie: oraclelicense=accept-securebackup-cookie' http://download.oracle.com/otn-pub/java/jdk/8u162-b12/0da788060d494f5095bf8624735fa2f1/jdk-8u162-linux-x64.tar.gz" - sudo mkdir -p /usr/local/java/ - sudo tar zxvf jdk-8u162-linux-x64.tar.gz -C /usr/local/java/ - sudo ln -sf /usr/local/java/jdk1.8.0_162/bin/* /usr/local/bin/ - curl -L -O -# https://archive.apache.org/dist/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz - curl -L -O -# https://archive.apache.org/dist/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz.asc - sudo tar zxvf apache-maven-3.3.3-bin.tar.gz -C /usr/local/java - sudo ln -sf /usr/local/java/apache-maven-3.3.3/bin/* /usr/local/bin/ - mkdir -p /home/ubuntu/{.m2,prog/atlas} remoterepos: - git@bitbucket.org:repo1/repo1.git - git@bitbucket.org:repo2/repo2.git tasks: - ec2_instance_facts: filters: "tag:Name": "{{ec2machinename}}" "instance-state-name": ["pending","running"] register: result - ec2: region: "{{ec2region}}" key_name: "{{ec2sshkey}}" instance_type: "{{ec2instancetype}}" image: "{{ec2ami}}" wait: yes count: 1 group: "{{ec2securitygroup}}" vpc_subnet_id: "{{ec2subnetid}}" instance_tags: "Name": "{{ec2machinename}}" when: (result["instances"]|length == 0) register: ec2 - name: Wait for SSH to come up wait_for: host: "{{ item.public_ip_address| default(item.public_ip) }}" port: 22 delay: 10 timeout: 60 state: started with_items: "{{ ec2.instances |default(result.instances) }}" - name: Add the keys to ~/.ssh/known_host shell: ssh-keyscan -H {{item.public_ip_address|default(item.public_ip)}} >> ~/.ssh/known_hosts with_items: "{{ ec2.instances |default(result.instances) }}" - name: Install git, java shell: ssh -i "{{privatekeypath}}" -l ubuntu "{{item[0].public_ip_address|default(item[0].public_ip)}}" "{{item[1]}}" with_nested: - "{{ ec2.instances |default(result.instances) }}" - "{{rcmd}}" - name: Copy the Maven config shell: "scp -i {{privatekeypath}} {{mavenconfigpath}} ubuntu@{{item.public_ip_address|default(item.public_ip)}}:.m2/" with_items: "{{ ec2.instances |default(result.instances) }}" - name: Add remote git key to ssh-agent shell: "ssh-add {{gitkeypath}}" - name: Copy the remote repositories shell: ssh -oForwardAgent=yes -i "{{privatekeypath}}" "ubuntu@{{item[0].public_ip_address|default(item[0].public_ip)}}" "cd /home/ubuntu/prog/atlas;env GIT_SSH_COMMAND='ssh {{sshoptions}}' git clone {{item[1]}}" with_nested: - "{{ ec2.instances |default(result.instances) }}" - "{{remoterepos}}"
No hay comentarios:
Publicar un comentario