feat: добавлен пользователь devops по аналогии с k8s-user

Роль k8s-user сделана универсальной:
- generate_keys.yml: имена фактов стали динамическими — {{ k8s_service_user }}_ssh_private_key
  вместо захардкоженных k8s_ssh_private_key (поддержка любого пользователя)
- distribute_keys.yml: обращение к фактам через [k8s_service_user + '_ssh_private_key']

playbooks/k8s-user.yml переработан — 12 plays (6 для k8s + 6 для devops):
- devops plays вызывают ту же роль k8s-user с vars-переопределением k8s_service_user
- теги k8s/k8s_user и devops/devops_user — можно запустить одного пользователя
- ключи сохраняются: ./keys/k8s_id_rsa, ./keys/devops_id_rsa (приватные в .gitignore)
- имя файла ключа динамическое: {{ k8s_service_user }}_id_rsa

group_vars/all/main.yml:
- добавлены devops_service_user, devops_service_user_comment, devops_service_user_sudo и др.

Запуск только devops: ansible-playbook playbooks/k8s-user.yml --tags devops
This commit is contained in:
Sergey Antropoff
2026-04-24 07:05:50 +03:00
parent 437d0cce34
commit 7c71b69333
5 changed files with 170 additions and 36 deletions

3
.gitignore vendored
View File

@@ -16,8 +16,9 @@ id_rsa
id_ed25519 id_ed25519
id_ecdsa id_ecdsa
# Локально сохранённые ключи k8s пользователя (публичный ключ — ок коммитить) # Локально сохранённые приватные ключи (публичные ключи *_id_rsa.pub — ок коммитить)
keys/k8s_id_rsa keys/k8s_id_rsa
keys/devops_id_rsa
# Docker артефакты # Docker артефакты
.docker/ .docker/

View File

@@ -207,8 +207,18 @@ k8s_service_user_key_comment: "k8s@cluster"
k8s_service_user_ssh_dir: ".ssh" k8s_service_user_ssh_dir: ".ssh"
k8s_service_user_sudo: true k8s_service_user_sudo: true
# Локальная директория для сохранения сгенерированных SSH ключей k8s пользователя # ─── devops-user ──────────────────────────────────────────────────────────────
# Дополнительный пользователь для инженеров DevOps
# Создаётся на тех же серверах что и k8s, та же RSA 4096 схема с ключами
devops_service_user: devops
devops_service_user_shell: /bin/bash
devops_service_user_comment: "DevOps Engineer"
devops_service_user_key_comment: "devops@cluster"
devops_service_user_sudo: true
# Локальная директория для сохранения сгенерированных SSH ключей
# Сохраняется на машине запуска Ansible (./keys/ относительно корня проекта) # Сохраняется на машине запуска Ansible (./keys/ относительно корня проекта)
# Файлы: keys/k8s_id_rsa, keys/k8s_id_rsa.pub, keys/devops_id_rsa, keys/devops_id_rsa.pub
k8s_local_keys_dir: "./keys" k8s_local_keys_dir: "./keys"
# ─── k3s-certs — автоматическая ротация сертификатов K3S ───────────────────── # ─── k3s-certs — автоматическая ротация сертификатов K3S ─────────────────────

View File

@@ -1,9 +1,13 @@
--- ---
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# k8s-user: создание сервисного пользователя k8s на всех серверах # k8s-user: создание сервисных пользователей на всех серверах
# #
# Последовательность: # Роль k8s-user универсальна — вызывается дважды:
# 1. Создать пользователя k8s + sudo на всех нодах кластера # • для пользователя k8s (автоматизация кластера)
# • для пользователя devops (инженеры DevOps)
#
# Для каждого пользователя:
# 1. Создать пользователя + sudo на всех нодах кластера
# 2. Сгенерировать RSA 4096 ключевую пару на первом мастере (один раз) # 2. Сгенерировать RSA 4096 ключевую пару на первом мастере (один раз)
# 3. Сохранить ключи локально в ./keys/ # 3. Сохранить ключи локально в ./keys/
# 4. Разложить ключи на все ноды кластера (SSH в любую сторону) # 4. Разложить ключи на все ноды кластера (SSH в любую сторону)
@@ -11,32 +15,36 @@
# 6. То же самое для lab_hosts (через пароль из vault) # 6. То же самое для lab_hosts (через пароль из vault)
# #
# Запуск: ansible-playbook playbooks/k8s-user.yml --ask-vault-pass # Запуск: ansible-playbook playbooks/k8s-user.yml --ask-vault-pass
# Только кластер: ansible-playbook playbooks/k8s-user.yml --limit k3s_cluster # Только один пользователь: ansible-playbook playbooks/k8s-user.yml --tags k8s
# ───────────────────────────────────────────────────────────────────────────── # ─────────────────────────────────────────────────────────────────────────────
# ── 1. Создать пользователя k8s на всех нодах кластера ─────────────────────── # ════════════════════════════════════════════════════════════════════════════
- name: Create k8s service user on cluster nodes # ПОЛЬЗОВАТЕЛЬ k8s
# ════════════════════════════════════════════════════════════════════════════
- name: "[k8s] Create service user on cluster nodes"
hosts: k3s_cluster hosts: k3s_cluster
gather_facts: true gather_facts: true
become: true become: true
tags: [k8s, k8s_user]
roles: roles:
- role: k8s-user - role: k8s-user
# ── 2. Сгенерировать ключевую пару на первом мастере ───────────────────────── - name: "[k8s] Generate SSH key pair (first master only)"
- name: Generate k8s SSH key pair (first master only)
hosts: "{{ groups['k3s_master'][0] }}" hosts: "{{ groups['k3s_master'][0] }}"
gather_facts: false gather_facts: false
become: true become: true
tags: [k8s, k8s_user]
tasks: tasks:
- name: Generate RSA key pair and store facts - name: Generate RSA key pair and store facts
ansible.builtin.include_role: ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: generate_keys.yml tasks_from: generate_keys.yml
# ── 3. Сохранить ключи локально в ./keys/ ──────────────────────────────────── - name: "[k8s] Save SSH keys to local machine"
- name: Save k8s SSH keys to local machine
hosts: "{{ groups['k3s_master'][0] }}" hosts: "{{ groups['k3s_master'][0] }}"
gather_facts: false gather_facts: false
tags: [k8s, k8s_user]
tasks: tasks:
- name: Create local keys directory - name: Create local keys directory
ansible.builtin.file: ansible.builtin.file:
@@ -48,52 +56,51 @@
- name: Save private key locally - name: Save private key locally
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ k8s_ssh_private_key }}" content: "{{ lookup('vars', k8s_service_user + '_ssh_private_key') }}"
dest: "{{ k8s_local_keys_dir }}/k8s_id_rsa" dest: "{{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa"
mode: '0600' mode: '0600'
delegate_to: localhost delegate_to: localhost
become: false become: false
- name: Save public key locally - name: Save public key locally
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ k8s_ssh_public_key }}\n" content: "{{ lookup('vars', k8s_service_user + '_ssh_public_key') }}\n"
dest: "{{ k8s_local_keys_dir }}/k8s_id_rsa.pub" dest: "{{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa.pub"
mode: '0644' mode: '0644'
delegate_to: localhost delegate_to: localhost
become: false become: false
- name: Show where keys were saved - name: Show where keys were saved
ansible.builtin.debug: ansible.builtin.debug:
msg: "SSH keys saved to {{ k8s_local_keys_dir }}" msg: "SSH keys saved to {{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa"
# ── 4. Разложить ключи на все ноды кластера ────────────────────────────────── - name: "[k8s] Distribute SSH keys to all cluster nodes"
- name: Distribute k8s SSH keys to all cluster nodes
hosts: k3s_cluster hosts: k3s_cluster
gather_facts: false gather_facts: false
become: true become: true
tags: [k8s, k8s_user]
tasks: tasks:
- name: Deploy keys to node - name: Deploy keys to node
ansible.builtin.include_role: ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: distribute_keys.yml tasks_from: distribute_keys.yml
# ── 5. Обновить /etc/hosts на нодах кластера ───────────────────────────────── - name: "[k8s] Update /etc/hosts on cluster nodes"
- name: Update /etc/hosts on cluster nodes
hosts: k3s_cluster hosts: k3s_cluster
gather_facts: false gather_facts: false
become: true become: true
tags: [k8s, k8s_user]
tasks: tasks:
- name: Update hosts file - name: Update hosts file
ansible.builtin.include_role: ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: update_hosts.yml tasks_from: update_hosts.yml
# ── 6. Bootstrap lab_hosts: создать пользователя, разложить ключи, обновить hosts - name: "[k8s] Setup user on lab hosts"
# Подключение через логин/пароль из host_vars/<host>/vault.yml
- name: Setup k8s user on lab hosts
hosts: lab_hosts hosts: lab_hosts
gather_facts: true gather_facts: true
become: true become: true
tags: [k8s, k8s_user]
vars: vars:
ansible_user: "{{ bootstrap_user }}" ansible_user: "{{ bootstrap_user }}"
ansible_password: "{{ bootstrap_password }}" ansible_password: "{{ bootstrap_password }}"
@@ -103,17 +110,133 @@
-o PasswordAuthentication=yes -o PasswordAuthentication=yes
-o PubkeyAuthentication=no -o PubkeyAuthentication=no
tasks: tasks:
- name: Create k8s user on lab host - ansible.builtin.include_role:
ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: create_user.yml tasks_from: create_user.yml
- ansible.builtin.include_role:
name: k8s-user
tasks_from: distribute_keys.yml
- ansible.builtin.include_role:
name: k8s-user
tasks_from: update_hosts.yml
- name: Distribute k8s SSH keys to lab host # ════════════════════════════════════════════════════════════════════════════
# ПОЛЬЗОВАТЕЛЬ devops
# ════════════════════════════════════════════════════════════════════════════
- name: "[devops] Create service user on cluster nodes"
hosts: k3s_cluster
gather_facts: true
become: true
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
k8s_service_user_comment: "{{ devops_service_user_comment }}"
k8s_service_user_key_comment: "{{ devops_service_user_key_comment }}"
k8s_service_user_sudo: "{{ devops_service_user_sudo }}"
k8s_service_user_shell: "{{ devops_service_user_shell }}"
roles:
- role: k8s-user
- name: "[devops] Generate SSH key pair (first master only)"
hosts: "{{ groups['k3s_master'][0] }}"
gather_facts: false
become: true
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
tasks:
- name: Generate RSA key pair and store facts
ansible.builtin.include_role:
name: k8s-user
tasks_from: generate_keys.yml
- name: "[devops] Save SSH keys to local machine"
hosts: "{{ groups['k3s_master'][0] }}"
gather_facts: false
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
tasks:
- name: Create local keys directory
ansible.builtin.file:
path: "{{ k8s_local_keys_dir }}"
state: directory
mode: '0700'
delegate_to: localhost
become: false
- name: Save private key locally
ansible.builtin.copy:
content: "{{ lookup('vars', k8s_service_user + '_ssh_private_key') }}"
dest: "{{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa"
mode: '0600'
delegate_to: localhost
become: false
- name: Save public key locally
ansible.builtin.copy:
content: "{{ lookup('vars', k8s_service_user + '_ssh_public_key') }}\n"
dest: "{{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa.pub"
mode: '0644'
delegate_to: localhost
become: false
- name: Show where keys were saved
ansible.builtin.debug:
msg: "SSH keys saved to {{ k8s_local_keys_dir }}/{{ k8s_service_user }}_id_rsa"
- name: "[devops] Distribute SSH keys to all cluster nodes"
hosts: k3s_cluster
gather_facts: false
become: true
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
tasks:
- name: Deploy keys to node
ansible.builtin.include_role: ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: distribute_keys.yml tasks_from: distribute_keys.yml
- name: Update /etc/hosts on lab host - name: "[devops] Update /etc/hosts on cluster nodes"
hosts: k3s_cluster
gather_facts: false
become: true
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
tasks:
- name: Update hosts file
ansible.builtin.include_role: ansible.builtin.include_role:
name: k8s-user name: k8s-user
tasks_from: update_hosts.yml tasks_from: update_hosts.yml
- name: "[devops] Setup user on lab hosts"
hosts: lab_hosts
gather_facts: true
become: true
tags: [devops, devops_user]
vars:
k8s_service_user: "{{ devops_service_user }}"
k8s_service_user_comment: "{{ devops_service_user_comment }}"
k8s_service_user_key_comment: "{{ devops_service_user_key_comment }}"
k8s_service_user_sudo: "{{ devops_service_user_sudo }}"
k8s_service_user_shell: "{{ devops_service_user_shell }}"
ansible_user: "{{ bootstrap_user }}"
ansible_password: "{{ bootstrap_password }}"
ansible_become_password: "{{ bootstrap_sudo_password | default(bootstrap_password) }}"
ansible_ssh_common_args: >-
-o StrictHostKeyChecking=no
-o PasswordAuthentication=yes
-o PubkeyAuthentication=no
tasks:
- ansible.builtin.include_role:
name: k8s-user
tasks_from: create_user.yml
- ansible.builtin.include_role:
name: k8s-user
tasks_from: distribute_keys.yml
- ansible.builtin.include_role:
name: k8s-user
tasks_from: update_hosts.yml

View File

@@ -2,27 +2,27 @@
# Раскладывает приватный и публичный ключ k8s пользователя на текущий хост # Раскладывает приватный и публичный ключ k8s пользователя на текущий хост
# Ключи берутся из hostvars первого мастера (сгенерированы там play'ем generate_keys) # Ключи берутся из hostvars первого мастера (сгенерированы там play'ем generate_keys)
- name: Deploy private key to k8s user - name: Deploy private key to {{ k8s_service_user }} user
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ hostvars[groups['k3s_master'][0]]['k8s_ssh_private_key'] }}" content: "{{ hostvars[groups['k3s_master'][0]][k8s_service_user + '_ssh_private_key'] }}"
dest: "/home/{{ k8s_service_user }}/{{ k8s_service_user_ssh_dir }}/id_rsa" dest: "/home/{{ k8s_service_user }}/{{ k8s_service_user_ssh_dir }}/id_rsa"
owner: "{{ k8s_service_user }}" owner: "{{ k8s_service_user }}"
group: "{{ k8s_service_user }}" group: "{{ k8s_service_user }}"
mode: '0600' mode: '0600'
become: true become: true
- name: Deploy public key to k8s user - name: Deploy public key to {{ k8s_service_user }} user
ansible.builtin.copy: ansible.builtin.copy:
content: "{{ hostvars[groups['k3s_master'][0]]['k8s_ssh_public_key'] }}\n" content: "{{ hostvars[groups['k3s_master'][0]][k8s_service_user + '_ssh_public_key'] }}\n"
dest: "/home/{{ k8s_service_user }}/{{ k8s_service_user_ssh_dir }}/id_rsa.pub" dest: "/home/{{ k8s_service_user }}/{{ k8s_service_user_ssh_dir }}/id_rsa.pub"
owner: "{{ k8s_service_user }}" owner: "{{ k8s_service_user }}"
group: "{{ k8s_service_user }}" group: "{{ k8s_service_user }}"
mode: '0644' mode: '0644'
become: true become: true
- name: Add k8s public key to authorized_keys - name: Add {{ k8s_service_user }} public key to authorized_keys
ansible.posix.authorized_key: ansible.posix.authorized_key:
user: "{{ k8s_service_user }}" user: "{{ k8s_service_user }}"
key: "{{ hostvars[groups['k3s_master'][0]]['k8s_ssh_public_key'] }}" key: "{{ hostvars[groups['k3s_master'][0]][k8s_service_user + '_ssh_public_key'] }}"
state: present state: present
become: true become: true

View File

@@ -45,6 +45,6 @@
- name: Store key content as persistent facts (доступны во всех последующих plays) - name: Store key content as persistent facts (доступны во всех последующих plays)
ansible.builtin.set_fact: ansible.builtin.set_fact:
k8s_ssh_private_key: "{{ k8s_private_key_raw.content | b64decode }}" "{{ k8s_service_user }}_ssh_private_key": "{{ k8s_private_key_raw.content | b64decode }}"
k8s_ssh_public_key: "{{ k8s_public_key_raw.content | b64decode | trim }}" "{{ k8s_service_user }}_ssh_public_key": "{{ k8s_public_key_raw.content | b64decode | trim }}"
cacheable: true cacheable: true