diff --git a/Makefile b/Makefile index cb39fc8..8b3bf0c 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,15 @@ destroy: ansible-setup: ansible-galaxy install -r ansible/ansible-requirements.yml + ansible-master: - cd ansible && ansible-playbook -i ../vagrant/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory master.yml + cd ansible && ansible-playbook -i ../vagrant/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory swarm-master.yml +ansible-workers: + cd ansible && ansible-playbook -i ../vagrant/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory swarm-node.yml +ansible-stack: + cd ansible && ansible-playbook -i ../vagrant/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory swarm-stack.yml +ansible-full: + make ansible-master && make ansible-workers && make ansible-full setup-keys: mkdir -p ./keys @@ -19,4 +26,9 @@ ansible-watch: full-reset: make destroy - make up && make ansible-master + make up && make ansible-full + +swarm-check: + cd vagrant && vagrant ssh swarm-master -c "docker info"|grep -e "Managers" -e "Nodes" +service-ls: + cd vagrant && vagrant ssh swarm-master -c "docker service ls" diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index da9f1bc..f4e454c 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -2,3 +2,5 @@ host_key_checking=False # stdout_callback = minimal color = true +interpreter_python = /usr/bin/python3.9 +deprecation_warnings=False \ No newline at end of file diff --git a/ansible/files/docker-base-stack.yml b/ansible/files/docker-base-stack.yml new file mode 100644 index 0000000..4e499ba --- /dev/null +++ b/ansible/files/docker-base-stack.yml @@ -0,0 +1,30 @@ +version: '3.8' + +services: + portainer: + image: portainer/portainer-ce:latest + command: -H unix:///var/run/docker.sock + ports: + - "9000:9000" + - "9443:9443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + networks: + - portainer_net + deploy: + placement: + constraints: + - node.role == manager + restart_policy: + condition: on-failure + replicas: 1 + +volumes: + portainer_data: + external: true + +networks: + portainer_net: + driver: overlay + attachable: true \ No newline at end of file diff --git a/ansible/master.yml b/ansible/master.yml deleted file mode 100644 index 81aa4cb..0000000 --- a/ansible/master.yml +++ /dev/null @@ -1,52 +0,0 @@ ---- -- hosts: swarm_master - become: true - - - - vars_files: - - group_vars/all.yml - vars: - swap_file_state: present - swap_file_existing_size_mb: 0 - - roles: - - role: geerlingguy.swap - - role: geerlingguy.docker - - role: common - - tasks: - - name: Check memory and swap usage - command: free -m - register: memory_info - changed_when: false - - - name: Ensure Python pip is installed - package: - name: python3-pip - state: present - - - name: Ensure Docker SDK for Python is installed - pip: - name: docker>=5.0.0 - executable: pip3 - - - name: Init a new swarm with default parameters - community.docker.docker_swarm: - state: present - - - name: Debug all variables - debug: - msg: "swap_file_size_mb: {{ swap_file_size_mb }}, swap_file_state: {{ swap_file_state }}" - - name: Debug Docker variables - debug: - msg: "docker_edition: {{ docker_edition }}, docker_packages: {{ docker_packages }}" - # - name: Debug all host variables - # debug: - # var: hostvars[inventory_hostname] - - # - name: Initialize the cluster - # shell: docker swarm init --advertise-addr 192.168.56.10 >> cluster_initialized.txt - # args: - # chdir: $HOME - # creates: cluster_initialized.txt diff --git a/ansible/roles/common/tasks/main.yml b/ansible/roles/common/tasks/main.yml index abc7275..185081c 100644 --- a/ansible/roles/common/tasks/main.yml +++ b/ansible/roles/common/tasks/main.yml @@ -2,6 +2,36 @@ command: free -m register: memory_info changed_when: false -- name: Run the equivalent of "apt-get update" as a separate step + +- name: apt update ansible.builtin.apt: update_cache: yes + +- name: Ensure Python pip is installed + package: + name: python3-pip + state: present + +- name: Ensure Docker SDK for Python is installed + pip: + name: docker>=5.0.0 + executable: pip3 + +- name: Ensure Docker Compose is installed + pip: + name: docker-compose>=1.29.0 + executable: pip3 + +- name: Install 'jsondiff' Python module + pip: + name: jsondiff + executable: pip3 + +- name: wait for docker service + service: + name: docker + state: started + register: docker_service + until: docker_service.status.ActiveState == "active" + retries: 10 + delay: 20 diff --git a/ansible/swarm-master.yml b/ansible/swarm-master.yml new file mode 100644 index 0000000..d748148 --- /dev/null +++ b/ansible/swarm-master.yml @@ -0,0 +1,78 @@ +--- +- hosts: swarm_master + become: true + + roles: + - role: geerlingguy.swap + - role: geerlingguy.docker + - role: common + + tasks: + - name: Debug all relevant variables + debug: + msg: | + === SWARM JOIN DEBUG INFO === + Current host: {{ inventory_hostname }} + Current host IP: {{ ansible_host }} + + Master group hosts: {{ groups['swarm_master'] }} + First master: {{ groups['swarm_master'][0] }} + + Master hostvars: + - ansible_host: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] }} + - inventory_hostname: {{ hostvars[groups['swarm_master'][0]]['inventory_hostname'] }} + + Remote address calculation: + - Raw master ansible_host: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] }} + - Fallback to hostname: {{ groups['swarm_master'][0] }} + - Final address: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] | default(groups['swarm_master'][0]) }} + - With port: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] | default(groups['swarm_master'][0]) }}:2377 + + - name: Init a new swarm with default parameters + community.docker.docker_swarm: + state: present + advertise_addr: "{{ ansible_eth1.ipv4.address }}" + listen_addr: "{{ ansible_eth1.ipv4.address }}" + - name: print listen addr + debug: + msg: "{{ ansible_eth1.ipv4.address }}" + + - name: Get Docker Swarm information + community.docker.docker_swarm_info: + register: swarm_info + + - name: Save worker join token to file + copy: + content: "{{ swarm_info.swarm_facts.JoinTokens.Worker }}" + dest: /tmp/swarm_worker_token + mode: '0600' + + - name: Save manager join token to file + copy: + content: "{{ swarm_info.swarm_facts.JoinTokens.Manager }}" + dest: /tmp/swarm_manager_token + mode: '0600' + + # Copy tokens to host filesystem + # - name: Fetch worker join token to host + # fetch: + # src: /tmp/swarm_worker_token + # dest: ./tokens/swarm_worker_token + # flat: yes + + # - name: Fetch manager join token to host + # fetch: + # src: /tmp/swarm_manager_token + # dest: ./tokens/swarm_manager_token + # flat: yes + # - name: Create Portainer data volume + # community.docker.docker_volume: + # name: portainer_data + # state: present + + # - name: Deploy Portainer stack from compose file + # community.docker.docker_stack: + # name: portainer + # state: present + # compose: + # - "{{ lookup('file', 'files/docker-base-stack.yml') | from_yaml }}" \ No newline at end of file diff --git a/ansible/swarm-node.yml b/ansible/swarm-node.yml index f777a6d..0501ec1 100644 --- a/ansible/swarm-node.yml +++ b/ansible/swarm-node.yml @@ -1,16 +1,68 @@ --- - hosts: swarm_workers become: true + gather_facts: yes vars: roles: - role: geerlingguy.swap - swap_file_size_mb: 1024 - role: geerlingguy.docker - role: common tasks: - - name: Check memory and swap usage - command: free -m - register: memory_info - changed_when: false + - name: Get worker join token from master + slurp: + src: /tmp/swarm_worker_token + register: worker_token_file + delegate_to: "{{ groups['swarm_master'][0] }}" + + - name: Decode worker join token + set_fact: + worker_token: "{{ worker_token_file.content | b64decode | trim }}" + + - name: Debug all relevant variables + debug: + msg: | + === SWARM JOIN DEBUG INFO === + Current host: {{ inventory_hostname }} + Current host IP: {{ ansible_host }} + + Master group hosts: {{ groups['swarm_master'] }} + First master: {{ groups['swarm_master'][0] }} + + Master hostvars: + - ansible_host: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] }} + - inventory_hostname: {{ hostvars[groups['swarm_master'][0]]['inventory_hostname'] }} + + Remote address calculation: + - Raw master ansible_host: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] }} + - Fallback to hostname: {{ groups['swarm_master'][0] }} + - Final address: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] | default(groups['swarm_master'][0]) }} + - With port: {{ hostvars[groups['swarm_master'][0]]['ansible_host'] | default(groups['swarm_master'][0]) }}:2377 + + Join token (first 10 chars): {{ worker_token[:10] }}... + + - name: Gather master facts + ansible.builtin.setup: + delegate_to: "{{ groups['swarm_master'][0] }}" + run_once: true + register: master_facts + + - name: Debug master hostvars + debug: + msg: | + Master hostvars keys: {{ hostvars[groups['swarm_master'][0]].keys() | list }} + Master ansible_eth1: {{ hostvars[groups['swarm_master'][0]].ansible_eth1 | default('Not available') }} + Master node: {{ groups['swarm_master'][0] }} + Master ansible_default_ipv4: {{ hostvars[groups['swarm_master'][0]] }} + Master ansible_default_ipv4: {{ master_facts.ansible_facts }} + FINAL IP: {{ master_facts.ansible_facts ['ansible_eth1']['ipv4']['address'] }} + + - name: Add nodes + community.docker.docker_swarm: + state: join + join_token: "{{ worker_token }}" + remote_addrs: + - "{{ master_facts.ansible_facts ['ansible_eth1']['ipv4']['address'] }}:2377" + advertise_addr: "{{ ansible_eth1.ipv4.address }}" + \ No newline at end of file diff --git a/ansible/swarm-stack.yml b/ansible/swarm-stack.yml new file mode 100644 index 0000000..c6f5d2e --- /dev/null +++ b/ansible/swarm-stack.yml @@ -0,0 +1,18 @@ +--- +- hosts: swarm_master + become: true + + roles: + + tasks: + - name: Create Portainer data volume + community.docker.docker_volume: + name: portainer_data + state: present + + - name: Deploy Portainer stack from compose file + community.docker.docker_stack: + name: portainer + state: present + compose: + - "{{ lookup('file', 'files/docker-base-stack.yml') | from_yaml }}" \ No newline at end of file diff --git a/vagrant/Vagrantfile b/vagrant/Vagrantfile index a1a2824..4166bdf 100644 --- a/vagrant/Vagrantfile +++ b/vagrant/Vagrantfile @@ -1,4 +1,4 @@ -num_workers = 1 +num_workers = 7 nodes = [ { hostname: 'swarm-master', ip: '192.168.56.10', ram: 256, cpus: 1, groups: ['swarm_master'] } @@ -31,7 +31,7 @@ Vagrant.configure('2') do |config| # ansible.limit = "all" # ansible.raw_arguments = ["--timeout=60"] end - + nodes.each do |node| puts "Provisioning node: #{node[:hostname]}" config.vm.define node[:hostname] do |node_config| @@ -40,7 +40,7 @@ Vagrant.configure('2') do |config| # node_config.vm.box = 'generic/archlinux64' # node_config.vm.box_version = "20250415.336224" - # node_config.vm.network "private_network", ip: node[:ip] + node_config.vm.network "private_network", ip: node[:ip] node_config.vm.provider "virtualbox" do |vb| vb.name = node[:hostname] vb.memory = node[:ram]