feat: add worker nodes to docker swarm setup
This commit is contained in:
parent
22d7e4a318
commit
d318880600
10 changed files with 252 additions and 112 deletions
|
|
@ -1,5 +1,12 @@
|
||||||
[homelab]
|
[homelab:children]
|
||||||
|
docker
|
||||||
|
|
||||||
|
[docker:children]
|
||||||
|
docker_managers
|
||||||
|
docker_workers
|
||||||
|
|
||||||
|
[docker_managers]
|
||||||
10.0.10.50
|
10.0.10.50
|
||||||
|
|
||||||
[docker]
|
[docker_workers]
|
||||||
10.0.10.50 docker_swarm_manager=true
|
10.0.10.[51:52]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/playbook.json
|
||||||
|
|
||||||
# > /COPILOT_GENERATE I'm writing an ansible playbook to setup a new alpine server, I want you to help me to generate some tasks
|
---
|
||||||
|
|
||||||
- name: Setup an alpine machine
|
- name: Setup an alpine machine
|
||||||
hosts: homelab
|
hosts: homelab
|
||||||
user: root
|
user: root
|
||||||
|
|
@ -41,24 +41,12 @@
|
||||||
line: 'permit persist :wheel'
|
line: 'permit persist :wheel'
|
||||||
state: present
|
state: present
|
||||||
|
|
||||||
- name: Install Docker
|
|
||||||
ansible.builtin.package:
|
|
||||||
state: present
|
|
||||||
name:
|
|
||||||
- docker
|
|
||||||
- docker-cli-compose
|
|
||||||
- py3-yaml
|
|
||||||
- py3-pip
|
|
||||||
- py3-docker-py
|
|
||||||
|
|
||||||
- name: Common setup
|
- name: Common setup
|
||||||
hosts: homelab
|
hosts: homelab
|
||||||
user: root
|
user: root
|
||||||
roles:
|
roles:
|
||||||
- role: common
|
- role: common
|
||||||
vars:
|
vars:
|
||||||
extra_groups:
|
|
||||||
- docker
|
|
||||||
robo_allowed_commands:
|
robo_allowed_commands:
|
||||||
- "docker system dial-stdio"
|
- "docker system dial-stdio"
|
||||||
|
|
||||||
|
|
@ -67,3 +55,27 @@
|
||||||
user: root
|
user: root
|
||||||
roles:
|
roles:
|
||||||
- docker
|
- docker
|
||||||
|
vars:
|
||||||
|
users:
|
||||||
|
- aleidk
|
||||||
|
- robo
|
||||||
|
|
||||||
|
- name: Setup docker swarm manager
|
||||||
|
hosts: docker_managers
|
||||||
|
user: root
|
||||||
|
tasks:
|
||||||
|
- name: Setup swarm manager
|
||||||
|
include_role:
|
||||||
|
name: docker
|
||||||
|
tasks_from: swarm_manager.yaml
|
||||||
|
|
||||||
|
- name: Setup docker swarm workers
|
||||||
|
hosts: docker_workers
|
||||||
|
user: root
|
||||||
|
tasks:
|
||||||
|
- name: "Setup swarm workers"
|
||||||
|
include_role:
|
||||||
|
name: docker
|
||||||
|
tasks_from: swarm_worker.yaml
|
||||||
|
vars:
|
||||||
|
managers_group: docker_managers
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ argument_specs:
|
||||||
type: "list"
|
type: "list"
|
||||||
elements: "str"
|
elements: "str"
|
||||||
required: false
|
required: false
|
||||||
|
default: []
|
||||||
description:
|
description:
|
||||||
- "Additional groups that will be added to each user"
|
- "Additional groups that will be added to each user"
|
||||||
robo_allowed_commands:
|
robo_allowed_commands:
|
||||||
|
|
@ -1,10 +1,5 @@
|
||||||
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
||||||
|
|
||||||
- name: Create a user group named docker
|
|
||||||
loop: "{{ extra_groups }}"
|
|
||||||
ansible.builtin.group:
|
|
||||||
name: "{{ item }}"
|
|
||||||
|
|
||||||
- name: Setup users
|
- name: Setup users
|
||||||
loop: "{{ users }}"
|
loop: "{{ users }}"
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
|
|
@ -14,7 +9,7 @@
|
||||||
shell: "{{ item.shell }}"
|
shell: "{{ item.shell }}"
|
||||||
create_home: true
|
create_home: true
|
||||||
password: "{{ (item.password != '!' or item.password != '*') | ternary(item.password | password_hash('sha512'), item.password) }}"
|
password: "{{ (item.password != '!' or item.password != '*') | ternary(item.password | password_hash('sha512'), item.password) }}"
|
||||||
groups: "{{ item.groups + extra_groups }}"
|
groups: "{{ item.groups + (extra_groups | default([])) }}"
|
||||||
|
|
||||||
- name: Add SSH public key to users
|
- name: Add SSH public key to users
|
||||||
loop: "{{ users }}"
|
loop: "{{ users }}"
|
||||||
|
|
|
||||||
61
roles/docker/files/openrc.sh
Executable file
61
roles/docker/files/openrc.sh
Executable file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/sbin/openrc-run
|
||||||
|
supervisor=supervise-daemon
|
||||||
|
|
||||||
|
name="Docker Daemon"
|
||||||
|
description="Persistent process that manages docker containers"
|
||||||
|
description_reload="Reload configuration without exiting"
|
||||||
|
|
||||||
|
command="${DOCKERD_BINARY:-/usr/bin/dockerd}"
|
||||||
|
command_args="${DOCKER_OPTS}"
|
||||||
|
|
||||||
|
DOCKER_LOGFILE="${DOCKER_LOGFILE:-/var/log/${RC_SVCNAME}.log}"
|
||||||
|
DOCKER_ERRFILE="${DOCKER_ERRFILE:-${DOCKER_LOGFILE}}"
|
||||||
|
DOCKER_OUTFILE="${DOCKER_OUTFILE:-${DOCKER_LOGFILE}}"
|
||||||
|
if [ "$DOCKER_ERRFILE" = "$DOCKER_OUTFILE" ]; then
|
||||||
|
LOGPROXY_OPTS="$LOGPROXY_OPTS -m"
|
||||||
|
fi
|
||||||
|
export \
|
||||||
|
LOGPROXY_CHMOD="${LOGPROXY_CHMOD:-0644}" \
|
||||||
|
LOGPROXY_LOG_DIRECTORY="${LOGPROXY_LOG_DIRECTORY:-/var/log}" \
|
||||||
|
LOGPROXY_ROTATION_SIZE="${LOGPROXY_ROTATION_SIZE:-104857600}" \
|
||||||
|
LOGPROXY_ROTATION_TIME="${LOGPROXY_ROTATION_TIME:-86400}" \
|
||||||
|
LOGPROXY_ROTATION_SUFFIX="${LOGPROXY_ROTATION_SUFFIX:-.%Y%m%d%H%M%S}" \
|
||||||
|
LOGPROXY_ROTATED_FILES="${LOGPROXY_ROTATE_FILES:-5}"
|
||||||
|
|
||||||
|
output_logger="log_proxy $LOGPROXY_OPTS $DOCKER_OUTFILE"
|
||||||
|
error_logger="log_proxy $LOGPROXY_OPTS $DOCKER_ERRFILE"
|
||||||
|
|
||||||
|
extra_started_commands="reload"
|
||||||
|
|
||||||
|
rc_ulimit=""
|
||||||
|
RC_ULIMIT=""
|
||||||
|
if [ "$1" = "start" ]; then
|
||||||
|
if [ $BASH ]; then
|
||||||
|
rc_ulimit="${DOCKER_ULIMIT:--c unlimited -n 1048576 -u unlimited}"
|
||||||
|
else
|
||||||
|
ulimit -c unlimited
|
||||||
|
ulimit -n 1048576
|
||||||
|
ulimit -p unlimited
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
retry="${DOCKER_RETRY:-TERM/60/KILL/10}"
|
||||||
|
|
||||||
|
if [ -e /etc/profile.d/proxy.sh ]; then
|
||||||
|
. /etc/profile.d/proxy.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
depend() {
|
||||||
|
need sysfs cgroups net
|
||||||
|
after firewall
|
||||||
|
}
|
||||||
|
|
||||||
|
start_pre() {
|
||||||
|
checkpath -f -m 0644 -o root:docker "$DOCKER_ERRFILE" "$DOCKER_OUTFILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
reload() {
|
||||||
|
ebegin "Reloading configuration"
|
||||||
|
$supervisor $RC_SVCNAME --signal HUP
|
||||||
|
eend $?
|
||||||
|
}
|
||||||
25
roles/docker/meta/argument_specs.yml
Normal file
25
roles/docker/meta/argument_specs.yml
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
argument_specs:
|
||||||
|
main:
|
||||||
|
short_description: Main entrypoint
|
||||||
|
author:
|
||||||
|
- aleidk
|
||||||
|
options:
|
||||||
|
users:
|
||||||
|
type: "list"
|
||||||
|
elements: "str"
|
||||||
|
default: []
|
||||||
|
description:
|
||||||
|
- "list of users to add to the docker group"
|
||||||
|
|
||||||
|
swarm_workers:
|
||||||
|
short_description: Docker swarm workers setup
|
||||||
|
author:
|
||||||
|
- aleidk
|
||||||
|
options:
|
||||||
|
managers_group:
|
||||||
|
type: "str"
|
||||||
|
required: true
|
||||||
|
description:
|
||||||
|
- "The host group of the managers"
|
||||||
|
- "Used to obtain the advertised address and join tokens"
|
||||||
20
roles/docker/tasks/docker_alpine.yaml
Normal file
20
roles/docker/tasks/docker_alpine.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
||||||
|
---
|
||||||
|
- name: Install Docker
|
||||||
|
ansible.builtin.package:
|
||||||
|
state: present
|
||||||
|
name:
|
||||||
|
- docker
|
||||||
|
- docker-cli-compose
|
||||||
|
- py3-yaml
|
||||||
|
- py3-pip
|
||||||
|
- py3-docker-py
|
||||||
|
|
||||||
|
- name: Copy openrc.sh to /etc/init.d/docker
|
||||||
|
copy:
|
||||||
|
src: files/openrc.sh
|
||||||
|
dest: /etc/init.d/docker
|
||||||
|
mode: '0755'
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
|
||||||
|
|
@ -1,94 +1,23 @@
|
||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
||||||
|
---
|
||||||
|
- name: Create a user group named docker
|
||||||
|
ansible.builtin.group:
|
||||||
|
name: "docker"
|
||||||
|
|
||||||
|
- name: Add users to docker group
|
||||||
|
loop: "{{ users }}"
|
||||||
|
ansible.builtin.user:
|
||||||
|
state: present
|
||||||
|
append: true
|
||||||
|
name: "{{ item }}"
|
||||||
|
groups: "docker"
|
||||||
|
|
||||||
|
- name: Install docker in Alpine
|
||||||
|
import_tasks: docker_alpine.yaml
|
||||||
|
when: ansible_facts['os_family']|lower == 'alpine'
|
||||||
|
|
||||||
- name: Start docker service
|
- name: Start docker service
|
||||||
ansible.builtin.service:
|
ansible.builtin.service:
|
||||||
name: docker
|
name: docker
|
||||||
state: started
|
state: started
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
- name: Setup Docker Swarm
|
|
||||||
when: docker_swarm_manager | bool
|
|
||||||
block:
|
|
||||||
- name: Enable Docker Swarm mode
|
|
||||||
community.docker.docker_swarm:
|
|
||||||
state: present
|
|
||||||
|
|
||||||
- name: Create Traefik network
|
|
||||||
community.docker.docker_network:
|
|
||||||
name: reverse-proxy
|
|
||||||
driver: overlay
|
|
||||||
attachable: true
|
|
||||||
|
|
||||||
- name: Deploy Traefik service
|
|
||||||
community.docker.docker_compose_v2:
|
|
||||||
remove_orphans: true
|
|
||||||
project_name: reverse-proxy
|
|
||||||
definition:
|
|
||||||
networks:
|
|
||||||
reverse-proxy:
|
|
||||||
external: true
|
|
||||||
services:
|
|
||||||
traefik:
|
|
||||||
container_name: traefix-proxy
|
|
||||||
image: 'traefik:latest'
|
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
|
||||||
- reverse-proxy
|
|
||||||
ports:
|
|
||||||
# listen on host ports without ingress network
|
|
||||||
- target: 80
|
|
||||||
published: 80
|
|
||||||
protocol: tcp
|
|
||||||
mode: host
|
|
||||||
- target: 443
|
|
||||||
published: 443
|
|
||||||
protocol: tcp
|
|
||||||
mode: host
|
|
||||||
- target: 8080
|
|
||||||
published: 8080
|
|
||||||
protocol: tcp
|
|
||||||
mode: host
|
|
||||||
volumes:
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
|
||||||
healthcheck:
|
|
||||||
test: 'wget -qO- http://localhost:80/ping || exit 1'
|
|
||||||
interval: 4s
|
|
||||||
timeout: 2s
|
|
||||||
retries: 5
|
|
||||||
command:
|
|
||||||
- '--ping=true'
|
|
||||||
- '--ping.entrypoint=http'
|
|
||||||
- '--api.dashboard=true'
|
|
||||||
- '--api.insecure=true'
|
|
||||||
- '--entrypoints.http.address=:80'
|
|
||||||
- '--entryPoints.http.forwardedHeaders.trustedIPs=10.0.10.0/24'
|
|
||||||
- '--entrypoints.http.http.encodequerysemicolons=true'
|
|
||||||
- '--entryPoints.http.http2.maxConcurrentStreams=50'
|
|
||||||
# - "--providers.swarm.endpoint=tcp://{{ ansible_default_ipv4.address }}:2375"
|
|
||||||
- --providers.swarm.exposedByDefault=false
|
|
||||||
- --providers.swarm.network=reverse-proxy
|
|
||||||
deploy:
|
|
||||||
mode: global
|
|
||||||
placement:
|
|
||||||
constraints:
|
|
||||||
- node.role==manager
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.traefik.entrypoints=http
|
|
||||||
- traefik.http.routers.traefik.service=api@internal
|
|
||||||
- traefik.http.services.traefik.loadbalancer.server.port=8080
|
|
||||||
|
|
||||||
- name: Check if Docker context exists
|
|
||||||
local_action: ansible.builtin.command docker context inspect {{ ansible_hostname }}
|
|
||||||
register: context_exists
|
|
||||||
ignore_errors: true
|
|
||||||
|
|
||||||
- name: Create Docker context for each Swarm manager machine
|
|
||||||
local_action: >
|
|
||||||
ansible.builtin.command docker context create {{ ansible_hostname }} --docker "host=ssh://{{ ansible_default_ipv4.address }}"
|
|
||||||
when: context_exists.stderr != ''
|
|
||||||
|
|
||||||
- name: Join Docker Swarm as a worker
|
|
||||||
community.docker.docker_swarm:
|
|
||||||
state: join
|
|
||||||
join_token: "{{ hostvars['manager']['docker_swarm_worker_token'] }}"
|
|
||||||
remote_addrs: ["{{ hostvars['manager']['ansible_default_ipv4']['address'] }}"]
|
|
||||||
when: not docker_swarm_manager | bool
|
|
||||||
|
|
|
||||||
81
roles/docker/tasks/swarm_manager.yaml
Normal file
81
roles/docker/tasks/swarm_manager.yaml
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
||||||
|
---
|
||||||
|
- name: Enable Docker Swarm mode
|
||||||
|
register: swarm_info
|
||||||
|
community.docker.docker_swarm:
|
||||||
|
state: present
|
||||||
|
|
||||||
|
- name: Create Traefik network
|
||||||
|
community.docker.docker_network:
|
||||||
|
name: reverse-proxy
|
||||||
|
driver: overlay
|
||||||
|
attachable: true
|
||||||
|
|
||||||
|
- name: Check if Docker context exists
|
||||||
|
local_action: ansible.builtin.command docker context inspect {{ ansible_hostname }}
|
||||||
|
register: context_exists
|
||||||
|
ignore_errors: true
|
||||||
|
|
||||||
|
- name: Create Docker context for each Swarm manager machine
|
||||||
|
local_action: >
|
||||||
|
ansible.builtin.command docker context create {{ ansible_hostname }} --docker "host=ssh://{{ ansible_default_ipv4.address }}"
|
||||||
|
when: context_exists.stderr != ''
|
||||||
|
|
||||||
|
- name: Deploy Traefik service
|
||||||
|
community.docker.docker_compose_v2:
|
||||||
|
remove_orphans: true
|
||||||
|
project_name: reverse-proxy
|
||||||
|
definition:
|
||||||
|
networks:
|
||||||
|
reverse-proxy:
|
||||||
|
external: true
|
||||||
|
services:
|
||||||
|
traefik:
|
||||||
|
container_name: traefix-proxy
|
||||||
|
image: 'traefik:latest'
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- reverse-proxy
|
||||||
|
ports:
|
||||||
|
# listen on host ports without ingress network
|
||||||
|
- target: 80
|
||||||
|
published: 80
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 443
|
||||||
|
published: 443
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
- target: 8080
|
||||||
|
published: 8080
|
||||||
|
protocol: tcp
|
||||||
|
mode: host
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||||
|
healthcheck:
|
||||||
|
test: 'wget -qO- http://localhost:80/ping || exit 1'
|
||||||
|
interval: 4s
|
||||||
|
timeout: 2s
|
||||||
|
retries: 5
|
||||||
|
command:
|
||||||
|
- '--ping=true'
|
||||||
|
- '--ping.entrypoint=http'
|
||||||
|
- '--api.dashboard=true'
|
||||||
|
- '--api.insecure=true'
|
||||||
|
- '--entrypoints.http.address=:80'
|
||||||
|
- '--entryPoints.http.forwardedHeaders.trustedIPs=10.0.10.0/24'
|
||||||
|
- '--entrypoints.http.http.encodequerysemicolons=true'
|
||||||
|
- '--entryPoints.http.http2.maxConcurrentStreams=50'
|
||||||
|
# - "--providers.swarm.endpoint=tcp://{{ ansible_default_ipv4.address }}:2375"
|
||||||
|
- --providers.swarm.exposedByDefault=false
|
||||||
|
- --providers.swarm.network=reverse-proxy
|
||||||
|
deploy:
|
||||||
|
mode: global
|
||||||
|
placement:
|
||||||
|
constraints:
|
||||||
|
- node.role==manager
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.routers.traefik.entrypoints=http
|
||||||
|
- traefik.http.routers.traefik.service=api@internal
|
||||||
|
- traefik.http.services.traefik.loadbalancer.server.port=8080
|
||||||
9
roles/docker/tasks/swarm_worker.yaml
Normal file
9
roles/docker/tasks/swarm_worker.yaml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/ansible/ansible-lint/refs/heads/main/src/ansiblelint/schemas/tasks.json
|
||||||
|
---
|
||||||
|
- name: Join Docker Swarm as a worker
|
||||||
|
vars:
|
||||||
|
key: "{{ groups[managers_group] | map('extract', hostvars, ['swarm_info', 'swarm_facts', 'JoinTokens', 'Worker']) | list | first }}"
|
||||||
|
community.docker.docker_swarm:
|
||||||
|
state: join
|
||||||
|
join_token: "{{ key }}"
|
||||||
|
remote_addrs: "{{ groups[managers_group] | map('extract', hostvars, ['ansible_default_ipv4', 'address']) }}"
|
||||||
Loading…
Add table
Add a link
Reference in a new issue