用k8s部署archery1.7.9总结与详细演示

k8s部署archery1.7.9总结与详细演示

最后更新:20200415 愿祖国繁荣富强,人民安居乐业


本文总结在centos7中用k8s安装部署archery及其中间件goinception与inception的考虑与方案,这里先将archery打镜像并修改配置文件跑起来,然后将依赖中间件goinception与inception都重打镜像(覆盖修改配置文件)并调试测试好;

archery项目是一个django2的web项目,根目录下有django配置文件settings.py,里面有配置项目本身使用的mysql、redis以及ldap,这里我们将这三个的配置信息都用k8s的deployment文件的env环境变量传给配置文件,配置文件导了os库,用os.environ()方法就可以获取这些变量,这里将部分修改settings.py文件;
因为之前没有使用过k8s,踩了很多坑,可能接下来又会去做别的事情,为了记录反思,并给更多人带来方便,这里会不吝笔墨将尽可能多的细节记录下来。


1.方案总结

现在最新的archery版本为1.7.8,因为需要自定义setting.py文件,所以需要在archery:1.7.8的基础上重新打镜像,试错的过程中发现nginx.conf给的用户是nginx用户不是root用户,部署后nginx用户没权限读取静态文件,导致前端失效,因此nginx.conf也重新修改拷贝替换。
mysql和redis库都是机子本身安装好的,生产上使用的是已经有的库,直接deployment env配置一个值就好了。

项目 key value
centos7 ip 192.168.255.133
mysql root adqwe123
redis requirepass adqwe123
ldap ad域ip 192.168.255.222

2.mysql、redis处理

2.1.mysql

允许任意ip用root访问虚机mysql数据库,这样宿主机可以访问虚拟机mysql数据库;

 mysql>GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'adqwe123' WITH GRANT OPTION;
 mysql>flush privileges;
// 其中各字符的含义:
// *.* 对任意数据库任意表有效
// "root" "adqwe123" 是数据库用户名和密码
// '%' 允许访问数据库的IP地址,%意思是任意IP,也可以指定IP
// flush privileges 刷新权限信息

数据库迁移与数据初始化,超级管理员创建

【此处需准备的操作】虚拟机数据库创建一个数据库archery_local,/opt/下放从github或gitee下载的最新的archery包,改名为archery,调整结构如下
在这里插入图片描述

# 先驱检查
which mysql_config     #确认命令在 $PATH 中,否则安装包时报错【有问题卸载python重装】
# 根据requirements.txt文件创建项目的虚拟环境venv4archery
pip3 install virtualenv -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
cd /opt/
virtualenv venv4archery --python=python3
source /opt/venv4archery/bin/activate
# 注释掉requirements文件pyodbc
sudo yum install epel-release
sudo yum install python-pip
sudo yum install gcc-c++
sudo yum install python-devel
sudo yum install unixODBC-devel
sudo pip install pyodbc

# 先安装以上 再单独安装yum installpyodbc

pip3 install -r /opt/archery/requirements.txt -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com
# 修改/opt/archery/arcehry/settings.py
mysql数据库那里把库名改成你创建的,连接信息改一下,下一步就利用manage.py在创建的库中生成表格和初始化数据
# 数据库迁移
python3 manage.py makemigrations sql  
python3 manage.py migrate 
# 数据初始化
python3 manage.py dbshell<sql/fixtures/auth_group.sql
python3 manage.py dbshell<src/init_sql/mysql_slow_query_review.sql
# 创建管理用户
python3 manage.py createsuperuser

数据库迁移截图
20200403135531371
创建超管截图
[20200403140701707

2.2.redis

检查下/etc/redis.conf的密码与network设置,后重启redis服务systemctl restart redis

requirepass adqwe123
bind 0.0.0.0

细节介绍:这一段说的很清楚,默认情况下,如果未指定bind配置指令,则redis将侦听服务器上所有可用网络接口的连接。或者写成bind 0.0.0.0,任意网络都可以访问redis,这样主机就可以访问虚机redis了,可以用redis-desktop测试一下能不能连接的上;

################################## NETWORK #####################################

# By default, if no "bind" configuration directive is specified, Redis listens
# for connections from all the network interfaces available on the server.
# It is possible to listen to just one or multiple selected interfaces using
# the "bind" configuration directive, followed by one or more IP addresses.
#
# Examples:
#
bind 0.0.0.0
#
# ~~~ WARNING ~~~ If the computer running Redis is directly exposed to the
# internet, binding to all the interfaces is dangerous and will expose the
# instance to everybody on the internet. So by default we uncomment the
# following bind directive, that will force Redis to listen only into
# the IPv4 lookback interface address (this means Redis will be able to
# accept connections only from clients running into the same computer it
# is running).
#
# IF YOU ARE SURE YOU WANT YOUR INSTANCE TO LISTEN TO ALL THE INTERFACES
# JUST COMMENT THE FOLLOWING LINE.
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

宿主机用redis-desktop测试虚机的redis可以访问的到不
20200403142624884
可以
20200403142651266

3.archery-k8s部署

3.1.本地先拉取好镜像

docker pull hhyo/archery:1.7.8
docker pull hanchuanchuan/goinception:latest

archery自己又会去拉一个hhyo/archery-base:1.2的镜像,这个我们不用管;
如果拉取镜像速度慢,去给docker配置一个阿里源;

3.2.修改settings.py、nginx.conf

位置/opt/archery/src/docker

包含文件

archery-deployment.yaml 下面给出
archery-service.yaml 下面给出
Dockerfile 下面给出
nginx.conf 项目源文件夹下有,只修改了一行user root; # root用户
settings.py /opt/archery/archery/settings.py拷贝过来的,修改部分下面列出,其他远文件夹下问价均不需要
startup.py 默认没动,下面deployemt文件调用
20200403141223564
settings.py 修改的部分

import json		# 导入json包,用来将deployment文件中env传进来的字符串转换为json赋值给AUTH_LDAP_USER_ATTR_MAP变量,是ldap使用的,用来从ad域中将登录的ldap用户的信息映射为archery项目数据库中sql_user表中的对应字段

SECRET_KEY = 'zzzsaf255ot#7)fkw!id6axd(cv0@opwaafx7n#9=7d%x^hpl0'		# 项目创建时候默认的key,修改下

# 该项目本身的mysql数据库地址
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'archery_local',
        'USER': 'root',
        'PASSWORD': os.environ['MYSQL_PWD'],
        'HOST': os.environ['MYSQL_HOST'],
        'PORT': '3306',
        'OPTIONS': {
            'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
            'charset': 'utf8mb4'
        },
        'TEST': {
            'NAME': 'test_archery',
            'CHARSET': 'utf8mb4',
        },
    }
}

# 缓存配置
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.environ['REDIS_LOCATION1'],
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": os.environ['REDIS_PWD'],
        }
    },
    "dingding": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": os.environ['REDIS_LOCATION2'],
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "PASSWORD": os.environ['REDIS_PWD'],
        }
    }
}

# LDAP配置
ENABLE_LDAP = os.environ['LDAP_FLAG']		# ENABLE_LDAP是否开启ldap由deployment传值决定
if ENABLE_LDAP:
    import ldap
    from django_auth_ldap.config import LDAPSearch

    AUTHENTICATION_BACKENDS = (
        'django_auth_ldap.backend.LDAPBackend',  # 配置为先使用LDAP认证,如通过认证则不再使用后面的认证方式
        'django.contrib.auth.backends.ModelBackend',  # django系统中手动创建的用户也可使用,优先级靠后。注意这2行的顺序
    )
    # ldap的连接基础配置
    AUTH_LDAP_SERVER_URI = os.environ['AUTH_LDAP_SERVER_URI']    # ad server address
    AUTH_LDAP_BIND_DN = os.environ['AUTH_LDAP_BIND_DN']    # dn
    AUTH_LDAP_BIND_PASSWORD = os.environ['AUTH_LDAP_BIND_PASSWORD']    # admin pwd
    # 允许认证用户的路径
    LDAP_SCBASE = os.environ['LDAP_SCBASE']    # search base
    AUTH_LDAP_USER_SEARCH = LDAPSearch(LDAP_SCBASE, ldap.SCOPE_SUBTREE, os.environ['LDAP_FILTER'])
    # 同步设置
    AUTH_LDAP_ALWAYS_UPDATE_USER = True  # 每次登录从ldap同步用户信息
    AUTH_LDAP_USER_ATTR_MAP = json.loads(os.environ['AUTH_LDAP_USER_ATTR_MAP'])

nginx.conf只修改了用户

user root;      # root用户

3.3.打镜像,将修改的文件拷贝到源镜像作用位置

作用位置是怎么知道的呢? 试错:先跑起来一个原始的镜像,kubectl exec -it 容器名 sh进容器去看一下;
20200402100540711
因此,我们的Dockerfile这么写,注意COPY命令有一个上下文的概念,如果拷贝的文件目录不正确,打包镜像的时候会一直报文件找不到

FROM hhyo/archery:1.7.8
WORKDIR /opt/archery/archery
COPY settings.py /opt/archery/archery/
COPY nginx.conf /etc/nginx/

如果打算修改相关文档,/opt/archery/docs/下有个docs.md,自定义后放到与Dockerfile同目录下,打镜像的时候会将文件拷贝进去COPY docs.md /opt/archery/docs/
打镜像

docker build -f Dockerfile -t local/archery:1.7.8 .

20200403173552197
下一步写好部署文件和服务文件就可以应用部署和创建archery服务了

3.4.k8s部署文件与部署

命名空间为archery,部署文件为archery-deployment.yaml,src服务文件为archery-service.yaml
关于ldap登录的,如果不需要的话deployment也可以这么写,LDAP_FLAG传一个"False"就好了,ldap的我会单独再写文章模拟根据excel文件创建OU树、通过389非安全连接批量创建用户,而修改AD域用户初始密码会在server2019直接跑powershell脚本
archery-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: archery
  namespace: archery
  labels:
    app: archery
spec:
  replicas: 1
  selector:
    matchLabels:
      app: archery
  template:
    metadata:
      labels:
        app: archery
    spec:
      containers:
      - command:
        - /opt/archery/src/docker/startup.sh
        env:
        - name: NGINX_PORT
          value: "9123" 
        - name: MYSQL_HOST
          value: "192.168.255.133"
        - name: MYSQL_PWD
          value: "adqwe123"
        - name: REDIS_PWD
          value: "adqwe123"
        - name: REDIS_LOCATION1
          value: "redis://192.168.255.133:6379/0"
        - name: REDIS_LOCATION2
          value: "redis://192.168.255.133:6379/1"
        - name: LDAP_FLAG
          value: "True"
        - name: AUTH_LDAP_SERVER_URI
          value: "ldap://192.168.255.222:389"
        - name: AUTH_LDAP_BIND_DN
          value: "CN=Administrator,CN=Users,DC=bilibili,DC=com"
        - name: AUTH_LDAP_BIND_PASSWORD
          value: "QQqq#123"
        - name: LDAP_SCBASE
          value: "DC=bilibili,DC=com"
        - name: LDAP_FILTER
          value: "(&(objectClass=person)(sAMAccountName=%(user)s))"
        - name: AUTH_LDAP_USER_ATTR_MAP
          value: '{"username": "sAMAccountname","display": "displayName","email": "mail","first_name": "givenName","last_name": "sn"}'
        image: local/archery:1.7.8
        name: archery
        ports:
        - containerPort: 9123
        envirment:
      restartPolicy: Always

archery-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: archery
  namespace: archery
  labels:
    app: archery
spec:
  selector:
    app: archery
  ports:
  - name: archery-port
    protocol: TCP
    port: 9123          # 集群内的其他容器组可通过9123端口访问Service
    nodePort: 32600     # 通过任意节点的32600端口访问Service
    targetPort: 9123    # 将请求转发到匹配Pod的9123端口
  type: NodePort        # Serive的类型,ClusterIP/NodePort/LoaderBalancer

执行命令为

kubectl apply -f archery-deployment.yaml
kubectl get pod -n archery					# 查询命名空间archery中的容器列表
kubectl describe pod archery-56dc5b8879-wnj8v -n archery		# 查看容器是不是正常运行
kubectl exec -it archery-56dc5b8879-wnj8v -n archery sh			# 进入容器内部
kubectl logs -f archery-56dc5b8879-wnj8v -n archery				# 查看容器日志,主要在出错时候用

例如这个例子中,第一个archery实例正常运行,第二个状态是终止中(是某一次删容器出错了,一直挂在那里)
20200402110055524
进入容器内部,我们可以看到结构
项目在/opt/目录下的archery文件夹,venv4archery是项目脚本中创建的python项目虚拟环境,里面会有python项目所需要的依赖,如果想在此处执行到dajngo的命令可以source /opt/venv4archery/bin/activate
20200402110418579
查看容器日志,这里是前两天跑成功后没动过,在文章最后将单独留一节用来展示遇到的错误、截图、原因、如何排查。
20200402110954586

4.goinception-k8s重打镜像与部署

先将源goinception的配置文件修改,这里主要将enable_drop_database、enable_drop_table改成false,修改了备份库信息backup_host、backup_port、backup_user、backup_password。【archery前端测试通过并不代表俩inception就配置好了,需要提交sql走一遍流程测试下】

# TiDB Configuration.

# TiDB server host.
host = "0.0.0.0"

# tidb server advertise IP.
advertise_address = ""

# TiDB server port.
port = 4000

# path = ""

[inc]
check_autoincrement_datatype            =true                                     
check_autoincrement_init_value          =true                                     
check_autoincrement_name                =true
check_column_comment                    =true                                      
check_column_default_value              =true            
check_column_position_change            =true
check_column_type_change                =true                         
check_dml_limit                         =true                                     
check_dml_orderby                       =true                                     
check_dml_where                         =true                                     
check_identifier                        =true                                     
check_index_prefix                      =true                                      
check_insert_field                      =true                                     
check_primary_key                       =true                                     
check_table_comment                     =true                                      
check_timestamp_default                 =true                                     
check_timestamp_count                   =false                                      
enable_autoincrement_unsigned           =true                                     
enable_blob_type                        =true                                     
enable_column_charset                   =true                                     
enable_drop_database                    =false                                     
enable_drop_table                       =false                                      
enable_enum_set_bit                     =false                                    
enable_fingerprint                      =true                                      
enable_foreign_key                      =false
enable_json_type                        =true                                    
enable_identifer_keyword                =false                                     
enable_not_innodb                       =false                                     
enable_nullable                         =false
enable_null_index_name                  =false                                     
enable_orderby_rand                     =true                                     
enable_partition_table                  =true                                     
enable_pk_columns_only_int              =true                                     
enable_select_star                      =false                                     
enable_set_charset                      =true 
enable_set_collation                    =false                                    
enable_set_engine                       =false
max_char_length                         =0    
max_insert_rows                         =0                                     
max_keys                                =5                                         
max_key_parts                           =5                                         
max_update_rows                         =5000                                      
max_primary_key_parts                   =1                                         
max_allowed_packet                      =33554432
merge_alter_table                       =true          
check_float_double                      =true
support_charset                         ="utf8,utf8mb4"
support_collation                       ="utf8_general_ci,utf8mb4_general_ci"



backup_host = "192.168.255.133"
backup_port = 3306
backup_user = "root"
backup_password = "adqwe123"


# 安全更新是否开启.
# -1 表示不做操作,基于远端数据库 [默认值]
# 0  表示关闭安全更新
# 1  表示开启安全更新
sql_safe_updates = 0

# lang = "en-US"
lang = "zh-CN"

# 是否记录全量日志
general_log = false

# 开启统计功能
enable_sql_statistic = true


[inc_level]
er_cant_set_engine = 2
er_cant_set_collation = 2
er_table_must_have_comment = 2
er_column_have_no_comment = 2
er_table_must_have_pk = 2
er_index_name_idx_prefix = 1
er_index_name_uniq_prefix =  1
er_autoinc_unsigned = 2
er_alter_table_once = 2
er_pk_too_many_parts = 2

[osc]
osc_on = false
osc_min_table_size = 16
osc_print_none = false
osc_bin_dir = "/usr/local/bin"

[ghost]

ghost_on = false
ghost_allow_on_master = true
ghost_assume_rbr = true
ghost_chunk_size = 1000
ghost_concurrent_rowcount = true
ghost_cut_over = "atomic"
ghost_cut_over_lock_timeout_seconds = 3
ghost_default_retries = 60
ghost_heartbeat_interval_millis = 500
ghost_max_lag_millis = 1500
ghost_approve_renamed_columns = true
ghost_exponential_backoff_max_interval = 64
ghost_dml_batch_size = 10

[log]
# Log level: debug, info, warn, error, fatal.
level = "error"
# Log format, one of json, text, console.
format = "console"

archery的docker使用完成后改名字为Docekrfile_archery,然后写goinception的Dockerfile
在这里插入图片描述
Dockerfile

FROM hanchuanchuan/goinception:latest
WORKDIR /opt/archery/src/docker-compose/inception/
COPY config.toml /etc/

创建镜像

docker build -f Dockerfile -t local/goinception:latest .

在这里插入图片描述
goinception-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: goinception
  namespace: archery
  labels:
    app: goinception
spec:
  replicas: 1
  selector:
    matchLabels:
      app: goinception
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: goinception
    spec:
      containers:
      - name: goinception 
        image: local/goinception:latest
        imagePullPolicy: Never
        resources:
          limits:
            cpu: 500m
            memory: 1Gi
          requests:
            cpu: 100m
            memory: 256m
      restartPolicy: Always

goinception-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: goinception      # Service的名称
  namespace: archery
  labels:                # Service 自己的标签
    app: goinception     # 为该 Service 设置 key 为 app,value 为goinception的标签
spec:                    # 关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
  selector:              # 标签选择器
    app: goinception     # 选择包含标签goinception的Pod
  ports:
  - name: goincption-port  #端口名
    protocol: TCP
    port: 4000             # 集群内的其他容器组可通过4000端口访问Service
    nodePort: 30040		  # 通过任意节点的30040端口访问Service
    targetPort: 4000
  type: NodePort

文件所在位置
20200404000331922
应用部署

kubectl apply -f goinception-deployment.yaml
kubectl apply -f goinception-service.yaml

前端配置并测试,goinception端口填写30040,是service暴露出来给任意ip的端口
20200404000633140

5.inception-k8s重打镜像与部署

5.1.修改inception配置文件、打镜像

源配置文件修改inception_remote_system_password、inception_remote_system_user、inception_remote_backup_port、inception_remote_backup_host。
inc.cnf

[inception]
general_log=1
general_log_file=inception.log
port=6669
socket=/tmp/inc.socket
character-set-client-handshake=0
character-set-server=utf8
inception_language_code=zh-CN
inception_remote_system_password=adqwe123
inception_remote_system_user=root
inception_remote_backup_port=3306
inception_remote_backup_host=192.168.255.133
inception_support_charset=utf8,utf8mb4
inception_enable_nullable=0
inception_check_primary_key=1
inception_check_column_comment=1
inception_check_table_comment=1
inception_osc_on=OFF
inception_osc_bin_dir=/usr/bin
inception_osc_min_table_size=10
inception_osc_chunk_time=0.1
inception_enable_blob_type=1
inception_check_column_default_value=1

inception_enable_select_star=ON
inception_enable_identifer_keyword=ON
inception_enable_autoincrement_unsigned=ON
inception_check_identifier=OFF

打镜像,注意将前面goinception的dockerfile改名字,工作目录和最开始archery打镜像时候一样,都是下载好的archery源码放到opt下改名字进入/opt/archery/src/docker中进行的操作,dockerfile文件有一个文件路径的问题。
Dockerfile

FROM hhyo/inception:latest
WORKDIR /opt/archery/src/docker-compose/inception/
COPY inc.cnf /etc/

打镜像

docker build -f Dockerfile -t local/inception:latest .

在这里插入图片描述

5.2.写inception-deployment与service

inception-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: inception
  namespace: archery
  labels:
    app: inception
spec:
  replicas: 1
  selector:
    matchLabels:
      app: inception
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: inception
    spec:
      #imagePullSecrets:
      #  - name: default-secret
      containers:
      - name: inception
        image: local/inception:latest
        imagePullPolicy: Never
      restartPolicy: Always

inception-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: inception      # Service的名称
  namespace: archery
  labels:                # Service 自己的标签
    app: inception     # 为该 Service 设置 key 为 app,value 为inception的标签
spec:                    # 关于该 Service 的定义,描述了 Service 如何选择 Pod,如何被访问
  selector:              # 标签选择器
    app: inception     # 选择包含标签inception的Pod
  ports:
  - name: incption-port  #端口名
    protocol: TCP
    port: 6669         
    nodePort: 30050
    targetPort: 6669
  type: NodePort

应用部署和之前一样

kubectl apply -f inception-deployement.yaml 
kubectl apply -f inception-service.yaml 

注意:还未做的有,配置文件里面的信息实际上我也想通过deployment的env环境变量传参进去,这里先写死了

6.LDAP登录测试

用ldap用户登录
20200404000915895
这个是LDAP默认用户登陆进来的页面,右上角的姓名是sql_users表里面的真实姓名字段,也对应AD域用户的displayname字段。
20200403180428125

7.错误及解决方案

7.1.因arcehry升级导致的数据库表结构发生改变

例子1
20200320144552113
例子2
20200330224214072
这说明archery项目数据库表缺失,注意archery版本升级后表结构可能发生改变,因为项目没上线,所以直接删库,重新迁移即可,如果项目上线,还需要谨慎操作

7.2.查看archery容器日志

这里是最早的k8s部署文件写的很乱的时候,数据库都没有设置正确,多注意检查启动了的archery容器的项目配置文件settings.py的数据库有没有配置正确;
若配置正确,能连上库,前端登录不了,可以尝试用redis-desktop清理一下redis缓存,之前有一次重跑项目没删除之前错误的缓存报了错误

显示mysql和redis在127.0.0.11:53,很奇怪的ip和端口
20200320171140851
这里的原因是,之前跑项目时向redis存的的脏数据,现在重跑项目识别不了>清理缓存
20200327123542983

7.3.俩inception相关错误

参考archery文档archery FAQ
在这里插入图片描述
archery中的添加的mysql数据库实例想备份sql功能的话,需要对配置的用户开启inception和goinception需要满足的权限
遇到过报错有:
在这里插入图片描述
原因:没给用户REPLICATION CLIENT权限,给了后又报错
在这里插入图片描述
还需要一个REPLICATION SLAVE权限,因为inceptionj的backup需要解析binlog,给了之后备份就成功了
综上,给的所有权限有如下:

GRANT SELECT, INSERT, CREATE, PROCESS, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO '用户'@'%' identified by '密码';

检查权限
show grants for ‘用户’@’%’;
检查binlog配置,前面给用户开好权限之后
show variables like “%binlog%”;

猜你喜欢

转载自blog.csdn.net/qq_33997198/article/details/105304329
今日推荐