Организация плейбуков: - все .yml плейбуки перенесены из корня в playbooks/ - Makefile и entrypoint.sh обновлены — все пути с playbooks/ префиксом - k8s-user.yml переработан: include_tasks → include_role (корректная работа из подкаталога) Сохранение ключей и kubeconfig локально: - k8s-user.yml: новый play сохраняет k8s SSH ключи в ./keys/ на машине запуска - переменная k8s_local_keys_dir: "./keys" (настраивается в group_vars) - .gitignore: keys/k8s_id_rsa исключён (публичный ключ можно коммитить) - kubeconfig уже сохранялся роль k3s (k3s_kubeconfig_local_path: "./kubeconfig") Автоматическая ротация сертификатов K3S (роль k3s-certs): - K3S выпускает сертификаты на 1 год (hardcoded), таймер обеспечивает их обновление - скрипт k3s-cert-check.sh: проверяет срок через openssl, ротирует при k3s_cert_rotate_before_days - systemd service + timer: запуск по расписанию k3s_cert_check_schedule (по умолчанию monthly) - RandomizedDelaySec: снижает нагрузку при одновременном запуске на нескольких нодах - переменные: k3s_cert_validity_years: 5, k3s_cert_rotate_before_days: 90 - добавлен в site.yml (тег certs) и отдельный плейбук playbooks/k3s-certs.yml - make k3s-certs и команда k3s-certs в entrypoint.sh
126 lines
4.9 KiB
YAML
126 lines
4.9 KiB
YAML
---
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
# Безопасное удаление ноды из кластера
|
||
#
|
||
# Использование:
|
||
# make remove-node NODE=worker04
|
||
# make remove-node NODE=master04 (ВНИМАНИЕ: теряется один etcd участник)
|
||
#
|
||
# Порядок:
|
||
# 1. Cordon — запрещает планирование новых подов
|
||
# 2. Drain — вытесняет все поды на другие ноды
|
||
# 3. Delete — удаляет ноду из k8s API
|
||
# 4. Uninstall — удаляет k3s с ноды
|
||
#
|
||
# После удаления мастера рекомендуется добавить новый: make add-node NODE=...
|
||
# ─────────────────────────────────────────────────────────────────────────────
|
||
|
||
- name: Validate and prepare
|
||
hosts: "{{ groups['k3s_master'][0] }}"
|
||
gather_facts: false
|
||
become: true
|
||
tags: [always]
|
||
tasks:
|
||
- name: Validate NODE is specified
|
||
ansible.builtin.assert:
|
||
that: node_to_remove is defined and node_to_remove | length > 0
|
||
fail_msg: "Укажи ноду: make remove-node NODE=<nodename>"
|
||
|
||
- name: Prevent removing the only/first master
|
||
ansible.builtin.assert:
|
||
that:
|
||
- node_to_remove != groups['k3s_master'][0]
|
||
fail_msg: >
|
||
Нельзя удалить первый мастер ({{ groups['k3s_master'][0] }}) —
|
||
он является точкой инициализации кластера.
|
||
Перенести роль первого мастера: поменяй порядок нод в inventory и выполни restore.
|
||
|
||
- name: Warn if removing etcd member
|
||
ansible.builtin.debug:
|
||
msg: >
|
||
ВНИМАНИЕ: {{ node_to_remove }} является мастером (etcd участником).
|
||
После удаления в кластере останется {{ groups['k3s_master'] | length - 1 }} мастер(а).
|
||
Кворум: {{ (groups['k3s_master'] | length - 1) > (groups['k3s_master'] | length - 1) // 2 }}
|
||
when: node_to_remove in groups['k3s_master']
|
||
|
||
- name: Check node exists in cluster
|
||
ansible.builtin.command: k3s kubectl get node {{ node_to_remove }}
|
||
register: node_exists
|
||
changed_when: false
|
||
failed_when: false
|
||
|
||
- name: Cordon node
|
||
ansible.builtin.command: k3s kubectl cordon {{ node_to_remove }}
|
||
changed_when: true
|
||
when: node_exists.rc == 0
|
||
|
||
- name: Drain node (evict pods)
|
||
ansible.builtin.command: >
|
||
k3s kubectl drain {{ node_to_remove }}
|
||
--ignore-daemonsets
|
||
--delete-emptydir-data
|
||
--timeout=180s
|
||
--force
|
||
changed_when: true
|
||
when: node_exists.rc == 0
|
||
register: drain_result
|
||
failed_when: drain_result.rc != 0 and 'not found' not in drain_result.stderr
|
||
|
||
- name: Delete node from Kubernetes
|
||
ansible.builtin.command: k3s kubectl delete node {{ node_to_remove }}
|
||
changed_when: true
|
||
when: node_exists.rc == 0
|
||
|
||
- name: Uninstall K3S from removed node
|
||
hosts: "{{ node_to_remove | default('') }}"
|
||
gather_facts: false
|
||
become: true
|
||
tags: [k3s]
|
||
tasks:
|
||
- name: Run K3S server uninstall script
|
||
ansible.builtin.command: /usr/local/bin/k3s-uninstall.sh
|
||
failed_when: false
|
||
changed_when: true
|
||
when: node_to_remove in groups['k3s_master']
|
||
|
||
- name: Run K3S agent uninstall script
|
||
ansible.builtin.command: /usr/local/bin/k3s-agent-uninstall.sh
|
||
failed_when: false
|
||
changed_when: true
|
||
when:
|
||
- groups['k3s_workers'] is defined
|
||
- node_to_remove in groups['k3s_workers']
|
||
|
||
- name: Clean up k3s data directory
|
||
ansible.builtin.file:
|
||
path: "{{ item }}"
|
||
state: absent
|
||
loop:
|
||
- "{{ k3s_config_dir }}"
|
||
- "{{ k3s_data_dir }}"
|
||
failed_when: false
|
||
|
||
- name: Post-removal verification
|
||
hosts: "{{ groups['k3s_master'][0] }}"
|
||
gather_facts: false
|
||
become: true
|
||
tags: [verify]
|
||
tasks:
|
||
- name: Show remaining nodes
|
||
ansible.builtin.command: k3s kubectl get nodes -o wide
|
||
register: remaining_nodes
|
||
changed_when: false
|
||
|
||
- name: Display cluster nodes
|
||
ansible.builtin.debug:
|
||
msg: "{{ remaining_nodes.stdout_lines }}"
|
||
|
||
- name: Summary
|
||
ansible.builtin.debug:
|
||
msg: >
|
||
Нода {{ node_to_remove }} успешно удалена из кластера.
|
||
Удали её из inventory/hosts.ini.
|
||
{% if node_to_remove in groups['k3s_master'] %}
|
||
Рекомендуется добавить новую мастер-ноду: make add-node NODE=<новая-нода>
|
||
{% endif %}
|