Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

YDBOPS-10613 Dynconfigs #62

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
30 changes: 30 additions & 0 deletions plugins/modules/dynconfig_apply.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.ydb_platform.ydb.plugins.module_utils import cli


def main():
argument_spec=dict(
config=dict(type='str', default=""),
)
cli.YDB.add_arguments(argument_spec)
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False)
configFilename = module.params.get('config')
result = {'changed': False}
try:
ydb_cli = cli.YDB.from_module(module)
rc, stdout, stderr = ydb_cli(['admin', 'config', 'replace','-f',configFilename])
if rc != 0:
result['msg'] = f'command: "ydb admin config replace" failed'
result['stderr'] = stderr
module.fail_json(**result)

result['msg'] = 'command: "ydb admin config replace" succeeded'
module.exit_json(**result)

except Exception as e:
result['msg'] = f'unexpected exception: {e}'
module.fail_json(**result)


if __name__ == '__main__':
main()
38 changes: 38 additions & 0 deletions plugins/modules/dynconfig_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import re

#
# This module returns current version of dynamic config
# The result is stored in 'version' variable of returning dict

from ansible.module_utils.basic import AnsibleModule
from ansible_collections.ydb_platform.ydb.plugins.module_utils import cli

def main():
argument_spec=dict(
timeout=dict(type='int', default=180),
)
cli.YDB.add_arguments(argument_spec)
module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False)
result = {'changed': False, 'version': 0}
try:
ydb_cmd = ['admin', 'config', 'fetch']
ydb_cli = cli.YDB.from_module(module)
rc, stdout, stderr = ydb_cli(ydb_cmd)
if rc != 0:
# We get 1 exit code if no YAML config in cluster
result['msg'] = f'command: "ydb admin config fetch" failed'
else:
match = re.search(r'version:\s*(\d+)', stdout)
if match:
version = int(match.group(1))
result['version'] = version
result['msg'] = ''
module.exit_json(**result)

except Exception as e:
result['msg'] = f'unexpected exception: {e}'
module.fail_json(**result)


if __name__ == '__main__':
main()
8 changes: 8 additions & 0 deletions plugins/modules/init_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ def main():
result['stdout'] = stdout
result['stderr'] = stderr
module.fail_json(**result)

# Check PDisk status
rc, stdout, stderr = ydb_dstool(['pdisk', 'list', '--format=json'])
if rc == 0:
dstool_result = json.loads(stdout)[0]
for pdisk in dstool_result:
if pdisk["Status"] != "ACTIVE":
rc = ydb_dstool(['pdisk', 'set', '--status=ACTIVE','--pdisk-ids',pdisk["NodeId:PDiskId"]])
elabpro marked this conversation as resolved.
Show resolved Hide resolved

result['changed'] = True
result['msg'] = 'blobstorage config init succeeded'
Expand Down
1 change: 1 addition & 0 deletions roles/install_ydbd/tasks/install_ydb_from_version.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- name: Set local path to ydb_archive variable
set_fact:
ydb_archive: "{{ ydb_archive_dest }}ydbd-{{ ydb_version }}-linux-amd64.tar.gz"
when: ydb_archive is not defined

- name: check if YDB release archive present
delegate_to: 127.0.0.1
Expand Down
8 changes: 2 additions & 6 deletions roles/install_ydbd/tasks/install_ydb_using_binary.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,20 @@
dest: "{{ ydb_dir }}/release/{{ ydb_version }}/bin/ydbd"
mode: 0755
follow: true
force: "{{ ydb_force_update }}"

- name: copy YDB cli binary file
ansible.builtin.copy:
src: "{{ ydb_cli_binary }}"
dest: "{{ ydb_dir }}/release/{{ ydb_version }}/bin/ydb"
mode: 0755
follow: true
force: "{{ ydb_force_update }}"

- name: Symlink the YDB binaries
file: path="{{ ydb_dir }}/bin"
src="./release/{{ ydb_version }}/bin"
state=link
force=yes

- name: Create the YDB CLI default binary directory
file: state=directory path={{ ydb_dir }}/home/ydb/bin recurse=true group=ydb owner=ydb mode='0700'

- name: Disable YDB CLI version checks
copy: src=ydb-cli-config.json dest={{ ydb_dir }}/home/ydb/bin/config.json group=ydb owner=ydb mode='0644'
register: ydb_is_installed

9 changes: 8 additions & 1 deletion roles/install_ydbd/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
- name: download and install YDB server binary package from a release version number
import_tasks:
file: install_ydb_from_version.yaml
when: ydb_version is defined and ydbd_binary is not defined
when: ydb_version is defined and ydbd_binary is not defined and ydb_archive is not defined

- name: install YDB server binary package from source code
import_tasks:
Expand All @@ -34,3 +34,10 @@
import_tasks:
file: install_ydb_using_binary.yaml
when: ydbd_binary is defined and ydb_cli_binary is defined

- name: Create the YDB CLI default binary directory
file: state=directory path={{ ydb_dir }}/home/ydb/bin recurse=true group=ydb owner=ydb mode='0700'

- name: Disable YDB CLI version checks
copy: src=ydb-cli-config.json dest={{ ydb_dir }}/home/ydb/bin/config.json group=ydb owner=ydb mode='0644'
register: ydb_is_installed
5 changes: 5 additions & 0 deletions roles/preflight/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@
- name: Check current user
ansible.builtin.command: whoami
register: current_user

- name: Check conditions in variables (1. dynamic config)
ansible.builtin.fail:
msg: "Impossible to use ydb_enforce_user_token_requirement and ydb_request_client_certificate together"
when: ydb_enforce_user_token_requirement|bool and ydb_request_client_certificate|bool
2 changes: 1 addition & 1 deletion roles/ydbd/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
mode: 0440

- name: copy configuration file
copy:
ansible.builtin.template:
src: "{{ ydb_config }}"
dest: "{{ ydb_dir }}/cfg/ydbd-config.yaml"
owner: root
Expand Down
3 changes: 3 additions & 0 deletions roles/ydbd_dynamic/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
ydb_database_groups: 1
ydb_request_client_certificate: false
# ydb_use_dynamic_config - define how to configure dynamic nodes - static or dynamic configs
# Default value: false
ydb_use_dynamic_config: false
2 changes: 2 additions & 0 deletions roles/ydbd_dynamic/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@
- ydb_brokers
- ydb_dbname
- ydb_dynnodes
- ydb_use_dynamic_config

- name: create dynamic node configuration file
command: "{{ ydb_dir }}/home/update_config_file.sh ydbd-config.yaml ydbd-config-dynamic.yaml COMPUTE {{ ydb_cores_dynamic }}"
changed_when: false
when: not ydb_use_dynamic_config|bool

- name: create dynamic node systemd unit
template:
Expand Down
2 changes: 2 additions & 0 deletions roles/ydbd_dynamic/templates/ydbd-dynnode.service
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ UMask=077
PermissionsStartOnly=true
Environment=LD_LIBRARY_PATH={{ ydb_dir }}/lib
ExecStart={{ ydb_dir }}/bin/ydbd server \
{% if not ydb_use_dynamic_config|bool %}
--yaml-config {{ ydb_dir }}/cfg/ydbd-config-dynamic.yaml \
{% endif %}
--grpcs-port {{ 2136 + item.offset }} --grpc-ca {{ ydb_dir }}/certs/ca.crt \
--ic-port {{ 19002 + item.offset }} --ca {{ ydb_dir }}/certs/ca.crt \
--mon-port {{ 8766 + item.offset }} --mon-cert {{ ydb_dir }}/certs/web.pem \
Expand Down
7 changes: 7 additions & 0 deletions roles/ydbd_static/defaults/main.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
ydb_allow_format_drives: false
ydb_skip_data_loss_confirmation_prompt: false
ydb_enforce_user_token_requirement: true
# ydb_use_dynamic_config - define how to configure dynamic nodes - static or dynamic configs
# Default value: false
ydb_use_dynamic_config: false
Comment on lines +4 to +6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's time to introduce the concept of playbook feature flags. I don't think we'd want to keep this setting around long-term: it's more like to test this new approach, make it default at some point and then deprecate the current approach. So it could be like this:

Suggested change
# ydb_use_dynamic_config - define how to configure dynamic nodes - static or dynamic configs
# Default value: false
ydb_use_dynamic_config: false
ydb_ansible_feature_flags:
use_dynamic_config: false

Copy link
Contributor Author

@elabpro elabpro Jan 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good idea for single roles, but we might have problems in our structure
playbook1 (feature_flag: feature1, feature3) -> role1 (feature_flag: feature1)
playbook1 (feature_flag: feature1, feature3) -> role2 (feature_flag: feature1, feature2)
in this case role2 will lost feature2 default value

TASK [role1 : Output] *****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "feature_flags": {
        "feature1": true,
        "feature3": true
    }
}

TASK [role2 : Output] *****************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "feature_flags": {
        "feature1": true,
        "feature3": true
    }
}


# ydb_dynamic_config - path to a custom dynamic config file
# Default value: ansible/roles/ydb_static/ydb-din-config.yaml.j2
ydb_dynamic_config: ydbd-dyn-config.yaml.j2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's drop this setting because it'd limit the evolution of how all this is implemented under the hood. For instance, you don't really need a template here, you could just have the same object constructed in memory and then serialized to yaml. Otherwise, LGTM.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's designed to have possibility to adjust dynamic config for user needs until we have possibility to change all setting by ansible. Right not we do not provide a way to define labels or other requirements for dynamic nodes. IMHO it will be required by users for there production needs. That's why I think we must let them define their own config.

30 changes: 30 additions & 0 deletions roles/ydbd_static/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
- ydb_disks
- ydb_domain
- ydb_user
- ydb_dynamic_config
- ydb_use_dynamic_config

- name: check if required secrets are defined
no_log: true
Expand Down Expand Up @@ -180,3 +182,31 @@
new_password: "{{ ydb_password }}"
token: "{{ ydb_credentials.token }}"
run_once: true

- name: Dynamic configs
block:
- name: Get the current dynconfig version
ydb_platform.ydb.dynconfig_version:
ydb_bin: "{{ ydb_dir }}/bin/ydb"
ld_library_path: "{{ ydb_dir }}/lib"
ca_file: "{{ ydb_dir }}/certs/ca.crt"
endpoint: "grpcs://{{ inventory_hostname }}:2135"
database: "/{{ ydb_domain }}"
token: "{{ ydb_credentials.token }}"
register: ydb_dynconfig_info

- name: Add the dyn config
template: src={{ ydb_dynamic_config }} dest={{ ydb_dir }}/cfg/ydbd-dyn-config.yaml mode='640'

- name: Configure dyn config
ydb_platform.ydb.dynconfig_apply:
ydb_bin: "{{ ydb_dir }}/bin/ydb"
ld_library_path: "{{ ydb_dir }}/lib"
ca_file: "{{ ydb_dir }}/certs/ca.crt"
endpoint: "grpcs://{{ inventory_hostname }}:2135"
database: "/{{ ydb_domain }}"
user: "{{ ydb_user }}"
token: "{{ ydb_credentials.token }}"
config: "{{ ydb_dir }}/cfg/ydbd-dyn-config.yaml"
when: ydb_use_dynamic_config|bool
run_once: true
16 changes: 16 additions & 0 deletions roles/ydbd_static/templates/ydbd-dyn-config.yaml.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
metadata:
cluster: ""
version: {{ ydb_dynconfig_info['version'] }}
config:
# This parameter must be set in 'true'
yaml_config_enabled: true
actor_system_config:
# Auto configure node by using number of CPU cores
use_auto_config: true
# Type of the node (HYBRID, COMPUTE, STORAGE)
node_type: COMPUTE
# Number of CPU cores
cpu_count: {{ ydb_cores_dynamic }}
{{ lookup('ansible.builtin.template', '{{ ydb_config }}') | indent( width=2, first=True) }}
allowed_labels: {}
selector_config: []