ansible 实现达梦7数据库初始化数据脚本写入
关于使用ansible 对ARM版达梦7的k8s自动化部署参考我的这篇操作
ansible-playbook 写arm版达梦7数据库的一键安装脚本-CSDN博客文章浏览阅读303次,点赞5次,收藏3次。达梦官方提供镜像目前是dm8_x86 版本,因为众所周知的国产化方面的需求,需要在kylin v10机器上部署一个DM数据库以及其他使用数据库的服务,为了更便捷的交付需要把安装步骤都写入到ansible 脚本里,这里就单说下DM 的部署。https://blog.csdn.net/u011564831/article/details/146979512?spm=1011.2415.3001.5331
下面进入另一个需要解决的问题,如何使用ansbile 实现达梦7数据库初始化数据脚本写入
对于有特定性数据配置的项目会需要在服务安装时候把db_init的初始文件, 根据实际部署的情况修改初始化数据的信息,等待准备好以后直接导入到数据库里,类似于mysql
mysql -u username -p your_database_name < /path/to/your/file.sql
sql数据渲染
因为我本地DM数据库是整个/dm7/data 搬家,所以表结构是不需要重新去创建,只要把一些业务表TRUNCATE 掉就可以, 然后把dm数据库需要动态插入数据的记录动态生成好等待导入
在任务里添加一个 Init DM 的节点
# dm 数据库初始化
- name: Init DM
include_role:
name: deploy_rlstudio
tasks_from: 11.dm_init.yml
when: (deploy_type is not defined) or (deploy_type == "dm_init")
tags: [ "always" ]
在task_from 的文件里先从template sql.jq 为底本生成要导入的 target.sql
---
- name: Render ConfigMap with namespace
ansible.builtin.template:
src: "{{ role_path }}/files/sql.jq2"
dest: "{{ role_path }}/files/target.sql"
mode: '0644'
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
这样可以把已经全局定义的变量写入到target.sql里
比如sql.jq2了定义的,全局inventory下定义 了该变量rl_mysql_node: 10.10.121.12
INSERT INTO USER_QUOTAS_MANAGE.properties VALUES ('argoAddress', 'String', 'http://{{rl_mysql_node}}:30128');
在最后生成的target.sql里就可以动态写入上
还可以把要truncate的表名在Ansible Playbook 中先定义上
vars: arr: ["x1", "x2"]
-
在
sql.jq2
模板文件中使用 Jinja2 语法:
使用上述示例中的代码来遍历arr
变量并生成 SQL 语句。当运行 Ansible Playbook 时,模板将被渲染,target.sql
文件将包含根据arr
生成的 SQL 语句。
-- 清理原来的表数据
{% for item in arr %}
TRUNCATE TABLE USER_QUOTAS_MANAGE.{{ item }};
{% endfor %}
DM 数据库查看 表xx10 外键关联的方法
SELECT
a.table_name AS referencing_table,
a.constraint_name AS foreign_key_name
FROM
user_constraints a
JOIN
user_cons_columns b ON a.constraint_name = b.constraint_name
WHERE
a.constraint_type = 'R'
AND a.r_constraint_name IN (
SELECT constraint_name
FROM user_constraints
WHERE table_name = 'xx10' -- 替换为你的表名
然后是初始化表数据道理也差不多,把动态写入的变量在playbook先定义好然后执行
寻找一个类似mysql的sql文件导入方式
现在我已经有了待执行的sql文件,我的思路就是把这个文件复制到dm的 pod里然后用dm自带的disql 工具把文件导入进去
先把target.sql复制到pod里去
- name: Get DM7 Pod name using kubectl
ansible.builtin.command:
cmd: "kubectl get pods -n {{ dm7_namespace }} -l app=apps.deployment-dm-dm7 -o jsonpath='{.items[0].metadata.name}'"
register: dm7_pod_name
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Fail if no DM7 Pod is found
ansible.builtin.fail:
msg: "No DM7 Pod found in namespace {{ dm7_namespace }} with label app=apps.deployment-dm-dm7"
when: dm7_pod_name.stdout == ""
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Copy SQL file to DM7 Pod using kubectl cp
ansible.builtin.command:
cmd: "kubectl cp {{ role_path }}/files/target.sql {{ dm7_namespace }}/{{ dm7_pod_name.stdout }}:/dm7/data/target.sql"
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
然后调用 ./disql <user>/<password>@localhost:5236 -i /dm7/data/target.sql 做导入
- name: Execute target.sql in DM7 Pod
ansible.builtin.command:
cmd: >
kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} --
cd /dm7/bin && ./disql SYSDBA/123456789012@localhost:5236 -i /dm7/data/target.sql
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
先是报错 无法找到动态链接库 libdmdpi.so
TASK [deploy_rlstudio : Get DM7 Pod name] ************************************************************************************************** fatal: [192.168.107.9]: FAILED! => {"changed": false, "msg": "Failed to find executable libdmdpi.so"}
这个错在cmd里加上 export LD_LIBRARY_PATH=/dm7/bin:$LD_LIBRARY_PATH
- name: Execute target.sql in DM7 Pod
ansible.builtin.command:
cmd: >
kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} --
export LD_LIBRARY_PATH=/dm7/bin:$LD_LIBRARY_PATH && cd /dm7/bin && ./disql SYSDBA/123456789012@localhost:5236 -i /dm7/data/target.sql
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
执行结束ansible 没报错但是数据并没有导入成功
手动进入pod调试了下发现报错了
[root@dm7-7db84c6d-h9dgm /]# /dm7/bin/disql SYSDBA/123456789012@localhost:5236 -i /dm7/data/target.sql
USAGE:CONN[ECT] <logon>
<logon> : {<username>[/<password>][*<MPP_TYPE>][@<connect_identifier>]} | {/ AS <SYSDBA|SYSSSO|SYSAUDITOR|AUTO>}
<connect_identifier> :{[<server>][:<port>][?{UDP|TCP|IPC|RDMA}][#<sslpath>@<sslpwd>]}
<server>: if ipv6 address,[] is needed. For example [fe80::1e6f:65ff:fed1:3724%6]
DISQL usage1:disql -h|help show disql version and help message
DISQL usage2:disql [ [<option>] [{<logon> | /NOLOG}] [<start>] ]
<option> : [-L] [-S]
-L only try to login once
-S set no show model, hidden disql flag
<logon> : {<username>[/<password>][*<MPP_TYPE>][@<connect_identifier>]} | {/ AS <SYSDBA|SYSSSO|SYSAUDITOR|AUTO>}
<connect_identifier> :{[<server>][:<port>][?{UDP|TCP|IPC|RDMA}][#<sslpath>@<sslpwd>]}
<server>: if ipv6 address,[] is needed. For example [fe80::1e6f:65ff:fed1:3724%6]
<start> : `<filename>[<parameter> ...]<direct sql> run disql bash
/NOLOG option can run disql, while not connected to DM server
<direct sql>:-e "<SQL statement>[;<SQL statement>]"
先检查 disql 版本和支持的选项
运行以下命令查看 disql 的帮助信息:
/dm7/bin/disql -h
- 检查输出中是否提到 - arroAddress,如果是,可能是个文档错误(应为 -i),说明版本支持问题。
- 如果没有 -i,说明你的 disql 版本不支持此选项。
结论是我使用的dm7 这个disql 工具没有-i 这个选项
不过这也不是什么大问题, 想办法把target.sql里sql拆成可执行的一条条记录逐条执行就可以了
换个思路
从 DM7 Pod 中读取 SQL 文件内容
- name: Read SQL file content from DM7 Pod
ansible.builtin.command:
cmd: "kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} -- cat {{ sql_file }}"
register: sql_content
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
sql_file: "/dm7/data/target.sql"
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- 执行
kubectl exec
命令,进入指定的 Kubernetes Pod,并读取 SQL 文件的内容。 - 注册变量:将读取的内容保存到变量
sql_content
中。 - 条件执行:只有当
dm7_pod_name.stdout
不为空时,才会执行这个任务。 - 使用的变量:
dm7_namespace
:命名空间。dm7_pod_name.stdout
:Pod 名称。sql_file
:SQL 文件的路径。
在 DM7 Pod 中执行 SQL 语句
- name: Execute SQL statements in DM7 Pod
ansible.builtin.command:
cmd: >
kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} --
sh -c "{{ disql_base_cmd }} \"{{ item | trim }}\""
loop: "{{ (sql_content.stdout | split(';')) | list }}"
delegate_to: "{{ inventory_hostname }}"
run_once: true
when:
- dm7_pod_name.stdout != ""
- item | trim | length > 0
register: disql_result
changed_when: disql_result.rc == 0
failed_when: disql_result.rc != 0
vars:
disql_base_cmd: "export LD_LIBRARY_PATH=/dm7/bin:$LD_LIBRARY_PATH && /dm7/bin/disql SYSDBA/123456789012@localhost:5236 -e"
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- 从第一步读取的 SQL 内容中提取 SQL 语句,并逐一执行。
- 循环:将
sql_content.stdout
按分号 (;
) 分割成列表,遍历每个 SQL 语句。 - 条件执行:只有当 Pod 名称不为空且 SQL 语句非空时才执行。
- 注册结果:将每个执行的结果保存到
disql_result
中。 - 成功与失败条件:
changed_when
:如果返回代码为 0,则标记为成功。failed_when
:如果返回代码不为 0,则标记为失败。
- 执行命令:使用
disql
命令执行 SQL 语句。
调试执行结果
- name: Debug execution result
ansible.builtin.debug:
var: disql_result
when: disql_result is defined
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- 输出
disql_result
的内容,以便查看 SQL 执行的结果。 - 条件执行:只有当
disql_result
被定义时才会执行这个任务。
修改后全部脚本
---
- name: Render ConfigMap with namespace
ansible.builtin.template:
src: "{{ role_path }}/files/sql.jq"
dest: "{{ role_path }}/files/target.sql"
mode: '0644'
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Get DM7 Pod name using kubectl
ansible.builtin.command:
cmd: "kubectl get pods -n {{ dm7_namespace }} -l app=apps.deployment-dm-dm7 -o jsonpath='{.items[0].metadata.name}'"
register: dm7_pod_name
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Fail if no DM7 Pod is found
ansible.builtin.fail:
msg: "No DM7 Pod found in namespace {{ dm7_namespace }} with label app=apps.deployment-dm-dm7"
when: dm7_pod_name.stdout == ""
delegate_to: "{{ inventory_hostname }}"
run_once: true
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Copy SQL file to DM7 Pod using kubectl cp
ansible.builtin.command:
cmd: "kubectl cp {{ role_path }}/files/target.sql {{ dm7_namespace }}/{{ dm7_pod_name.stdout }}:/dm7/data/target.sql"
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Read SQL file content from DM7 Pod
ansible.builtin.command:
cmd: "kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} -- cat {{ sql_file }}"
register: sql_content
delegate_to: "{{ inventory_hostname }}"
run_once: true
when: dm7_pod_name.stdout != ""
vars:
sql_file: "/dm7/data/target.sql"
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Execute SQL statements in DM7 Pod
ansible.builtin.command:
cmd: >
kubectl exec -n {{ dm7_namespace }} {{ dm7_pod_name.stdout }} --
sh -c "{{ disql_base_cmd }} \"{{ item | trim }}\""
#loop: "{{ (sql_content.stdout | split(';')) | select('match', '^(GRANT|SET|DROP|CREATE|INSERT)') | reject('match', '^\\s*--') | list }}"
loop: "{{ (sql_content.stdout | split(';')) | list }}"
delegate_to: "{{ inventory_hostname }}"
run_once: true
when:
- dm7_pod_name.stdout != ""
- item | trim | length > 0
register: disql_result
changed_when: disql_result.rc == 0
failed_when: disql_result.rc != 0
vars:
disql_base_cmd: "export LD_LIBRARY_PATH=/dm7/bin:$LD_LIBRARY_PATH && /dm7/bin/disql SYSDBA/123456789012@localhost:5236 -e"
ansible_python_interpreter: "{{ custom_python_interpreter }}"
- name: Debug execution result
ansible.builtin.debug:
var: disql_result
when: disql_result is defined
vars:
ansible_python_interpreter: "{{ custom_python_interpreter }}"
执行没有错误
输出debug信息
后面检查了初始化的数据都插入成功了