概述
全栈工程师开发手册 (作者:栾鹏)
架构系列文章
我们知道在代码里面创建数据库链接需要先有database, 但是我们刚刚部署的数据库可能还没有database或者没有指定权限的用户,这就要求我们在部署完数据库以后手动链接,创建数据库和用户. 有两种方式来实现自动化, 这里以mysql为例
通过环境变量实现
在k8s中部署mysql时,可以传环境变量指定,例如下面的yaml文件
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-mysql
labels:
app: my-mysql
version: v1.0.0
spec:
selector:
matchLabels:
app: my-mysql
version: v1.0.0
strategy:
type: RollingUpdate
template:
metadata:
labels:
app: my-mysql
version: v1.0.0
spec:
containers:
- image: mysql:5.6
name: my-mysql
args:
- "--ignore-db-dir=lost+found"
- "--character-set-server=utf8" # 指定字符编码
- "--collation-server=utf8_general_ci" # 指定字符编码
env:
- name: MYSQL_ROOT_PASSWORD # 指定root用户的用户名
value: introcks
- name: MYSQL_PASSWORD # 新建用户的用户名
value: introcks
- name: MYSQL_USER # 新建的用户
value: root
- name: MYSQL_DATABASE # 新建的数据库
value: cloudai
ports:
- containerPort: 3306
name: mysql
volumeMounts:
- name: data
mountPath: /var/lib/mysql
- name: config
mountPath: /etc/mysql/mysql.conf.d/mysqld.cnf
subPath: mysqld.cnf
readOnly: False
volumes:
- name: data
persistentVolumeClaim:
claimName: mysql-pvc
- name: config
configMap:
name: mysql-configmap
这样就能在创建的时候创建用户,密码,数据库和指定字符编码, 但是这种通过环境变量超过的有一个问题是操作内容有限. 下面我们来实现第二种方法.
init容器直接执行自定义的sql语句
我们可以添加一个init容器, 并将sql语句挂载进去, init容器中实现执行sql语句的功能. 这里我实现了一个, 镜像源码在github上: https://github.com/626626cdllp/k8s/tree/master/database-tools
不想重新制作的可以直接拉取luanpeng/lp:database-tools-1.0
镜像启动就会执行容器中/root/db_tools/script/文件夹下的所有sql文件. 所以我们只需要将sql语句,以configmap的形式挂载到这个目录下就行.
我们先来创建一个sql语句的configmap
apiVersion: v1
kind: ConfigMap
metadata:
name: hive-metastore-database
labels:
app: yourapp_name
data:
execute.sql: |-
-- create database
CREATE DATABASE IF NOT EXISTS mytable DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
-- create user and grant authorization
GRANT ALL ON mytable.* TO 'luanpeng'@'%' IDENTIFIED BY '${IDENTIFIED}';
上面创建数据库,并将权限授予luanpeng用户.
下面就可以将这个sql语句挂载到init容器中
apiVersion: apps/v1
kind: Deployment
metadata:
name: xxx
labels:
app: xxx
version: v1.0.0
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: xxx
version: v1.0.0
template:
metadata:
labels:
app: xxx
version: v1.0.0
spec:
initContainers:
- name: init-dababase
image: luanpeng/lp:database-tools-1.0
env:
- name: DRIVER_NAME # 链接不同的数据库,使用的驱动名
value: "com.mysql.jdbc.Driver"
- name: URL # 链接地址
value: "jdbc:mysql://hive-metadata-mysql-service:3306/mysql?useUnicode=true&characterEncoding=utf8&useSSL=false"
- name: USERNAME # 用户名
value: "root"
- name: PASSWORD # 密码
value: "admin"
- name: IDENTIFIED
value: "admin"
volumeMounts:
- name: init-dababase-volume
mountPath: /root/db_tools/script # 必须挂载到该目录
containers:
......
volumes:
- name: init-dababase-volume
configMap:
name: hive-metastore-database
这样要实现更加复杂的初始化工作就可以直接在sql里面写了.
注意: 如果init容器运行失败,则会不运行后续的容器,我们可以通过设置sql语句,争取不报错
init容器
在 Pod 启动过程中,Init 容器会按顺序在网络和数据卷初始化之后启动。 每个容器必须在下一个容器启动之前成功退出。 如果由于运行时或失败退出,导致容器启动失败,它会根据 Pod 的 restartPolicy 指定的策略进行重试。 然而,如果 Pod 的 restartPolicy 设置为 Always,Init 容器失败时会使用 RestartPolicy 策略。
在所有的 Init 容器没有成功之前,Pod 将不会变成 Ready 状态。 Init 容器的端口将不会在 Service 中进行聚集。 正在初始化中的 Pod 处于 Pending 状态,但应该会将条件 Initializing 设置为 true。
如果 Pod 重启,所有 Init 容器必须重新执行。
对 Init 容器 spec 的修改,被限制在容器 image 字段中。 更改 Init 容器的 image 字段,等价于重启该 Pod。
因为 Init 容器可能会被重启、重试或者重新执行,所以 Init 容器的代码应该是幂等的。 特别地,被写到 EmptyDirs 中文件的代码,应该对输出文件可能已经存在做好准备。
Init 容器具有应用容器的所有字段。 然而 Kubernetes 禁止使用 readinessProbe,因为 Init 容器不能够定义不同于完成(completion)的就绪(readiness)。 这会在验证过程中强制执行。
在 Pod 上使用 activeDeadlineSeconds,在容器上使用 livenessProbe,这样能够避免 Init 容器一直失败。 这就为 Init 容器活跃设置了一个期限。
在 Pod 中的每个 app 和 Init 容器的名称必须唯一;与任何其它容器共享同一个名称,会在验证时抛出错误。
最后
以上就是懵懂钻石为你收集整理的k8s中实现自动数据库初始化(mysql,postgresql)通过环境变量实现init容器直接执行自定义的sql语句init容器的全部内容,希望文章能够帮你解决k8s中实现自动数据库初始化(mysql,postgresql)通过环境变量实现init容器直接执行自定义的sql语句init容器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复