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 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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"]])

result['changed'] = True
result['msg'] = 'blobstorage config init succeeded'
Expand Down
2 changes: 1 addition & 1 deletion roles/install_ydbd/tasks/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@

- 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
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
Comment on lines +8 to +10
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: []