ansible笔记(5):常用模块之文件操作(二)

前文中已经总结了一些文件操作类的模块,如果你需要了解它们,可以点击直达链接 http://www.zsythink.net/archives/2542

这篇文章我们继续来了解一些文件操作类模块。

find模块

find模块可以帮助我们在远程主机中查找符合条件的文件,就像find命令一样。

此处我们介绍一些find模块的常用参数,你可以先对这些参数有一个大概了解,然后再看小示例。

paths参数 :必须参数,指定在哪个目录中查找文件,可以指定多个路径,路径间用逗号隔开,此参数有别名,使用别名path或者别名name可以代替paths。

recurse参数 : 默认情况下,只会在指定的目录中查找文件,也就是说,如果目录中还包含目录,ansible并不会递归的进入子目录查找对应文件,如果想要递归的查找文件,需要使用recurse参数,当recurse参数设置为yes时,表示在指定目录中递归的查找文件。

hidden参数 :默认情况下,隐藏文件会被忽略,当hidden参数的值设置为yes时,才会查找隐藏文件。

file_type参数 : 默认情况下,ansible只会根据条件查找”文件”,并不会查找”目录”或”软链接”等文件类型,如果想要指定查找的文件类型,可以通过file_type指定文件类型,可指定的文件类型有any、directory、file、link 四种。

patterns参数 : 使用此参数指定需要查找的文件名称,支持使用shell(比如通配符)或者正则表达式去匹配文件名称,默认情况下,使用shell匹配对应的文件名,如果想要使用python的正则去匹配文件名,需要将use_regex参数的值设置为yes。

use_regex参数 :默认情况下,find模块不会使用正则表达式去解析patterns参数中对应的内容,当use_regex设置为yes时,表示使用python正则解析patterns参数中的表达式,否则,使用glob通配符解析patterns参数中的表达式。

contains参数 :使用此参数可以根据文章内容查找文件,此参数的值为一个正则表达式,find模块会根据对应的正则表达式匹配文件内容。

age参数 :使用此参数可以根据时间范围查找文件,默认以文件的mtime为准与指定的时间进行对比,比如,如果想要查找mtime在3天之前的文件,那么可以设置age=3d,如果想要查找mtime在3天以内的文件,可以设置age=-3d,这里所说的3天是按照当前时间往前推3天,可以使用的单位有秒(s)、分(m)、时(h)、天(d)、星期(w)。

age_stamp参数 :文件的时间属性中有三个时间种类,atime、ctime、mtime,当我们根据时间范围查找文件时,可以指定以哪个时间种类为准,当根据时间查找文件时,默认以mtime为准。

size参数 :使用此参数可以根据文件大小查找文件,比如,如果想要查找大于3M的文件,那么可以设置size=3m,如果想要查找小于50k的文件,可以设置size=-50k,可以使用的单位有t、g、m、k、b。

get_checksum参数 :当有符合查找条件的文件被找到时,会同时返回对应文件的sha1校验码,如果要查找的文件比较大,那么生成校验码的时间会比较长。

对应上述参数的ad-hoc示例命令如下:

在test70主机的/testdir目录中查找文件内容中包含abc字符串的文件,隐藏文件会被忽略,不会进行递归查找。

ansible test70 -m find -a 'paths=/testdir contains=".*abc.*" '

在test70主机的/testdir目录以及其子目录中查找文件内容中包含abc字符串的文件,隐藏文件会被忽略。

ansible test70 -m find -a 'paths=/testdir contains=".*abc.*" recurse=yes '

在test70主机的/testdir目录中查找以.sh结尾的文件,包括隐藏文件,但是不包括目录或其他文件类型,不会进行递归查找。

ansible test70 -m find -a 'paths=/testdir patterns="*.sh" hidden=yes'

在test70主机的/testdir目录中查找以.sh结尾的文件,包括隐藏文件,包括所有文件类型,比如文件、目录、或者软链接,但是不会进行递归查找。

ansible test70 -m find -a 'paths=/testdir patterns="*.sh" file_type=any hidden=yes'

在test70主机的/testdir目录中查找以.sh结尾的文件,包括隐藏文件,包括所有文件类型,比如文件、目录、或者软链接,但是不会进行递归查找。

ansible test70 -m find -a 'paths=/testdir patterns="*.sh" file_type=any hidden=yes'

在test70主机的/testdir目录中查找以.sh结尾的文件,只不过patterns对应的表达式为正则表达式,查找范围包括隐藏文件,包括所有文件类型,但是不会进行递归查找,不会对/testdir目录的子目录进行查找。

ansible test70 -m find -a 'paths=/testdir patterns=".*.sh" use_regex=yes file_type=any hidden=yes'

在test70主机的/testdir目录中以及其子目录中查找mtime在4天以内的文件,不包含隐藏文件,不包含目录或软链接文件等文件类型。

ansible test70 -m find -a "path=/testdir age=-4d recurse=yes"

在test70主机的/testdir目录中以及其子目录中查找atime在2星期以内的文件,不包含隐藏文件,不包含目录或软链接文件等文件类型。

ansible test70 -m find -a "path=/testdir age=-2w age_stamp=atime recurse=yes"

在test70主机的/testdir目录中以及其子目录中查找大于2G的文件,不包含隐藏文件,不包含目录或软链接文件等文件类型。

ansible test70 -m find -a "paths=/testdir size=2g recurse=yes"

在test70主机的/testdir目录中以及其子目录中查找以.sh结尾的文件,并且返回符合条件文件的sha1校验码,包括隐藏文件

ansible test70 -m find -a "paths=/testdir patterns=*.sh get_checksum=yes  hidden=yes recurse=yes"

replace模块

replace模块可以根据我们指定的正则表达式替换文件中的字符串,文件中所有被正则匹配到的字符串都会被替换。

此处我们介绍一些replace模块的常用参数,你可以先对这些参数有一个大概了解,然后再看小示例。

path参数 :必须参数,指定要操作的文件,2.3版本之前,只能使用dest, destfile, name指定要操作的文件,2.4版本中,仍然可以使用这些参数名,这些参数名作为path参数的别名使用。

regexp参数 : 必须参数,指定一个python正则表达式,文件中与正则匹配的字符串将会被替换。

replace参数 : 指定最终要替换成的字符串。

backup参数 :是否在修改文件之前对文件进行备份,最好设置为yes。

对应上述参数的ad-hoc示例命令如下:

把test70主机中的/testdir/test文件中的所有ASM替换成asm

ansible test70 -m replace -a 'path=/testdir/test regexp="ASM" replace=asm'

把test70主机中的/testdir/test文件中的所有ASM替换成asm,但是在操作文件之前进行备份。

ansible test70 -m replace -a 'path=/testdir/test regexp="ASM" replace=asm backup=yes'

ansible安装k8s步骤及注意事项(在线安装)

以下步骤都经本人实测,可以完美运行。

官方参考网址:https://github.com/gjmzj/kubeasz/

Ansible了解

ansible是个什么东西呢?官方的title是“Ansibleis Simple IT Automation”——简单的自动化IT工具。这个工具的目标有这么几项:

自动化部署APP;

自动化管理配置项;

自动化的持续交互;

自动化的(AWS)云服务管理;

所有的这几个目标从本质上来说都是在一个台或者几台服务器上,执行一系列的命令而已。通俗的说就是批量的在远程服务器上执行命令。当然,最主要的是它是基于 paramiko 开发的。这个paramiko是什么呢?它是一个纯Python实现的ssh协议库。因此fabric和ansible还有一个共同点就是不需要在远程主机上安装client/agents,因为它们是基于ssh来和远程主机通讯的。

未分类

由上面的图可以看到 Ansible 的组成由 5 个部分组成:

  • Ansible : 核心

  • Modules : 包括 Ansible 自带的核心模块及自定义模块

  • Plugins : 完成模块功能的补充,包括连接插件、邮件插件等

  • Playbooks : 剧本;定义 Ansible 多任务配置文件,由Ansible 自动执行

  • Inventory : 定义 Ansible 管理主机的清单

具体的命令可以查看参考(中文权威指南):http://www.ansible.com.cn/docs/intro_installation.html

安装k8s

1. 安装依赖工具

# 文档中脚本默认均以root用户执行# 安装 epel 源并更新
yum install epel-release –y(最好每台机器装一下)
yum install net-tools
yum update# 删除不要的默认安装
yum erase firewalld firewalld-filesystem python-firewall -y# 安装python
yum install python -y

2. 安装ansible

# CentOS 7
yum install git python-pip -y# pip安装ansible(国内如果安装太慢可以直接用pip阿里云加速)#pip install pip --upgrade#pip install ansible
pip install pip --upgrade -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
pip install --no-cache-dir ansible -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com

3. 在deploy节点配置免密码登陆

ssh-keygen -t rsa -b 2048 回车 回车 回车
ssh-copy-id $IPs #$IPs为所有节点地址包括自身,按照提示输入yes 和root密码
(即使是本机也需要配置)

4. 在deploy节点编排k8s安装

# 下载项目文件
git clone https://github.com/gjmzj/kubeasz.git
mv kubeasz /etc/ansible# 下载已打包好的binaries,并且解压缩到/etc/ansible/bin目录# 国内请从我分享的百度云链接下载 https://pan.baidu.com/s/1c4RFaA # 如果你有合适网络环境也可以按照/down/download.sh自行从官网下载各种tar包到 ./down目录,并执行download.sh
tar zxvf k8s.191.tar.gz
mv bin/* /etc/ansible/bin
cd /etc/ansible
cp example/hosts.m-masters.example hosts# 根据上文实际规划修改此hosts文件
vi hosts

验证ansible安装

在deploy 节点使用如下命令

ansible all -m ping

如果配置正确可以看到类似输出:

192.168.1.42 | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}
192.168.1.43 | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}
192.168.1.44 | SUCCESS => {
    "changed": false, 
    "failed": false, 
    "ping": "pong"
}

5. 安装集群

注意:

1)如何重复安装时,注意在执行完卸载命令后,将/etc/kubernetes目录删除

2)安装02.etcd时往往不能够一次性成功安装,如何执行过程中有错误应执行第二遍02.etcd.yml(不管使用90.setup.yml或是02.etcd.yml安装)

#ansible-playbook 01.prepare.yml
#ansible-playbook 02.etcd.yml
#ansible-playbook 03.kubectl.yml
#ansible-playbook 04.docker.yml
#ansible-playbook 05.kube-master.yml
#ansible-playbook 06.kube-node.yml
#ansible-playbook 07.calico.yml 或者 ansible-playbook 07.flannel.yml 只能选择一种网络插件
#ansible-playbook 90.setup.yml # 一步安装
#ansible-playbook 99.clean.yml # 一步安装

source /etc/profile(环境变量设置未生效,kubectl工具不能使用)

自动安装时没有环境变量,需要source一下;

单主单节点

发现问题:ansible1.8在重新安装并没有完全删除掉/etc/kubernetes中的东西,1.9没啥问题,所以1.8需要将/etc/kubernetes中的东西全部删掉再运行;否则在安装06node时csr验证会报错。

还有装02.etcd时配置文件读不到的问题,运行两次就好了;

ansible 1.9没有问题

安装DNS/dashboard时,注意dashboard-controller.yaml中deployment的版本为extensions/v1beta1

规律,可以先执行90.setup,然后执行2.etcd

卸载的时候注意删除掉/etc/kubernetes目录

注意:api-server是以https(用户名密码启动的),所以最后需要为用户配置角色才可以通过url进行访问:

绑定api-server的权限(否则是注册不上的)

kubectlcreate clusterrolebinding kubelet-node-clusterbinding1 --clusterrole=cluster-admin--user=admin

使用 Ansible 自动部署项目

未分类

如今部署代码真的是一件天大的事。

开发人员努力敲代码,基本没有时间登录服务器并逐个运行部署脚本。但是开发人员知道他们的部署所需要花费的大概时间,对部署各个工作的轻重缓急十分了解。

因此,开发人员与运维人员一起参与部署工作将真正有助于产品发布成功。

未分类

下面我们谈谈用Git的方式更轻松的部署应用。

使用 Git 来自动部署

如果让开发人员使用自己的 Git 仓库工具做部署,这必须在Git配置文件中添加额外的远程Git 仓库地址。

就像这样:

[remote "origin"]
    url = [email protected]:company/project.git
    url = git@remote-server:project.git
    fetch = +refs/heads/*:refs/remotes/origin/*

或者这样

[remote "deploy"]
    url = git@remote-server:project.git      

开发人员只需要在同一时间在推送代码到不同的地方就可以了。如代码示例,一个放在Codebase,另一个用于生产环境部署。

下面是具体操作

我们只需要配置我们的git服务器,使得每当 git push 事件触发时,Git 服务器就远程或本地自动运行部署脚本。

所以,我们需要先配置git 服务器。

首先在 git 服务器上安装 git-core

sudo apt-get install git-core

然后我们需要创建一个用于Git操作用户

sudo useradd git
passwd git

然后添加开发人员的主机的公钥文件,以便开发人员的电脑能够有权限访问 Git 服务器。

cat〜/ .ssh / id_rsa.pub | ssh git @ remote-server“mkdir -p〜/ .ssh && cat >>〜/ .ssh / authorized_keys”

然后在Git服务器上创建一个空的仓库

mkdir -p /home/user/project.git
cd /home/swapnil/project-1.git
git init --bare

这将创建一个git仓库,您可以看到名为 hooks文件夹,这里会存脚本用于接收文件后自动部署项目。

开发人员只需要在最开始的时候将 Git 服务器的项目仓库地址添加到他的项目中即可。

git remote add deploy git @ remote-server:project.git
git push deploy master

这样就直接部署了开发人员的代码。不过这似乎浪费了开发人员不必要的时间,所以我们应该使用 Ansible 来让部署更加轻松。

未分类

首先运行下列命令

ansible-galaxy install PrabhuVignesh.push_to_deploy

然后将开发机器的公钥保存在中即可。

$ cat publickeys.txt

ssh-rsa AAuyFUVFY65tYTFV567YTYTytytYTYTfyuV56FUYTVYTFYTVyTFYUG877686V767R76R67R76R6YTYTfyuVFUYTVYTFYTVyTFYUG877686V767R76R67R76R676V767676V76V768V876V76576V768V876V76Vv76V876VB76v7V76V76V6VBT9LLlNGtLo5pnEXIOPiz9X42ZdxBD721bG5XqDfPnz0JfgAYl6Zw4CXM0F6q0jiAQNJrtrfSNS92x1KMLY8CcVLKOZbpWdUHnouLdKCeM6dBHStpX7yjlb90fRKVZFch87eO0dyAoGWS3oBEYttFYL7s5dm/QV [email protected]

ssh-rsa AAuyFUVFY65tYTFV567YTYTytytYTYTfyuV56FUYTVYTFYTVyTFYUG877686V767R76R67R76R6YTYTfyuVFUYTVYTFYTVyTFYUG877686V767R76R67R76R676V767676V76V768rrtrt54t46Vv76V876VB76v7V76V76V6VBT9LLlNGtLo5pnEXIOPiz9X42ZdxBD721bG5XqDfPnz0JfgAYl6Zb6sevtrrtyyw4CXM0F6q0jiAQNJrtrfSNS92x1KMLY8CcVLKOZbpWdUHnouLdKCeM6dBHStpX7yjlb90fRKVZFch87eO0dyAoGWS3oBEYttFYL7s5dm/QV [email protected]

ssh-rsa AAuyFUVFY65tYTFV567YTYTytytYTYTfyuV56FUYTVYTFYTVyTFYUG877686V767R76R67R76R6YTYTfyuVFUYTVYTFYTVyTFYUG877686V767R76R67R76R63435343r4r3453434r34r34f34356trfhgjhgkjmnhi87t665rg6dvrdxdcser536c5456yvu675678br56er56v5v7y5y5gbr5576un8n78i8it0F6q0jiAQNJrtrfSNS92x1KMLY8CcVLKOZbpWdUHnouLdKCeM6dBHStpX7yjlb90fRKVZFch87eO0dyAoGWS3oBEYttFYL7s5dm/QV [email protected]

接着在环境变量中添加 path_for_authorized_keys,git_repository_path,post_receive_script,pre_receive_script 中的路径。

---
  roles:
    - role: PrabhuVignesh.push_to_deploy
      path_for_authorized_keys: /path/to/public_key/file
      git_repository_path: /home/path/to/your/repo.git
      post_receive_script: "script to deploy the code"
      pre_receive_script: "Prepare storing code"

git服务器的所有配置将通过 Ansible 来完成。

当开发人员将代码推送到 git 服务器时,应用程序就会执行用于后接收和预接收运行的脚本,如“puppet deploy script”,“cap deploy …”等,并且将自动部署。

另外使用这样的方式,只有在推送Master分支的时候才会运行部署脚本,这就避免不必要的部署。

#!/bin/bash
do
    if [[ $ref =~ .*/master$ ]];
    then
        echo "I am master branch push and i will run deployment script"
        # Run deployment script.....
    else
        echo "Ref $ref successfully received.  Doing nothing: only the master branch may be deployed on this server."
    fi
done

结论

GIT真的是一个令人赞叹的IT自动化工具,特别让开发和运维更好的协作,让发布新版本更加轻松。

Ansible 批量创建用户 密码注意事项

user模块是请求的是useradd, userdel, usermod三个指令,goup模块请求的是groupadd, groupdel, groupmod 三个指令。

user模块

home:指定用户的家目录,需要与createhome配合使用

groups:指定用户的属组

uid:指定用的uid

password:指定用户的密码

name:指定用户名

createhome:是否创建家目录 yes|no

system:是否为系统用户

remove:当state=absent时,remove=yes则表示连同家目录一起删除,等价于userdel -r

state:是创建还是删除(present,absent) 

shell:指定用户的shell环境

generate_ssh_key:是否为相关用户生成SSH密钥。 这不会覆盖现有的SSH密钥。 

ssh_key_bits:可选择指定要创建的SSH密钥中的位数。

ssh_key_passphrase:设置SSH密钥的密码。 如果没有提供密码,SSH密钥将默认没有密码。 

ssh_key_file:指定SSH密钥文件名(可选)。 如果这是一个相对的文件名,那么它将是相对于用户的主目录。 

ssh_key_type:指定要生成的SSH密钥的类型(可选)。 可用的SSH密钥类型将取决于目标主机上的实现。

使用ansibile创建用户有两种方法

方法1:使用user 模块,更简单,命令如下:

[root@ansible ~]# ansible ansible_group -m user -a 'name=test password=-18SyrVeFt/xU uid=1000 shell=/bin/bash home=/home/admin_group/test group=admin_group state=present' --sudo

验证创建的用户:

[root@ansible ~]# ansible ansible_group -m raw -a 'tail /etc/passwd|grep test'

online-web-asset-3 | SUCCESS | rc=0 >>
test:x:1000:501::/home/admin_group/test:/bin/bash
Shared connection to 192.168.5.1 closed.

注意:passwd的值不能是明文,passwd关键字后面应该是密文,且密文将被保存在/etc/shadow文件中,密文的生成命令为:

[root@ansible ~]# openssl passwd -salt -1 "you passwd"

然后将生成的密文,如: 填写到ansible ansible_group -m user -a ‘name=username password= ’ 中的passwd关键字后面即可。

方法2:使用playbook

创建playbook文件 useradd.yml,内容如下:

[root@ansible ansible]# more useradd.yml 

---
- hosts: "{{hosts}}"
  gather_facts: false
  user: centos
  sudo: yes
  vars:
#    user: test123
  tasks:
    - name: add user
      user: name={{user}} password={{passwd}} home=/home/admin_group/{{user}} group=admin_group shell=/bin/bash
      state: present
  tags:
    - user

保存后执行如下命令检测:

[root@ansible ~]# ansible-playbook --syntax-check useradd.yml -e "hosts=qsh_test user=test1 passwd=-11Fe1z.bZ5o."

然后运行playbook,使用 -e选项传入参数

[root@ansible ~]# ansible-playbook useradd.yml -e "hosts=qsh_test user=test1 passwd=-11Fe1z.bZ5o."

gitlab 403 forbidden 并发引起ip被封问题解决方法

步骤:

  • 打开/etc/gitlab/gitlab.rb文件。
  • 查找gitlab_rails[‘rack_attack_git_basic_auth’]关键词。
  • 取消注释
  • 修改ip_whitelist白名单属性,加入Gitlab部署的IP地址。
gitlab_rails[‘rack_attack_git_basic_auth’] = {
‘enabled’ => true,
‘ip_whitelist’ => [“127.0.0.1″,”Gitlab部署的IP地址”],
‘maxretry’ => 300,
‘findtime’ => 5,
‘bantime’ => 60
}
  • 配置好后,执行gitlab-ctl reconfigure即可。

修复群晖 GitLab 升级失败的问题

如果你最近使用群晖套件中心的 GitLab( 9.4.4-0050 ) ,并且勾选转换数据库( MariaDB => postgresql ),那么你很可能遇到丢失数据的问题( Version: 10.6.4-0051 ).表现为打开 GitLab 首页提示设置 root 密码,登录后台显示所有项目丢失.

故障的原因是群晖”借鉴”的 MySQL to PostgreSQL Converter 项目存在一些问题 .群晖内的具体路径为/volume1/@appstore/Docker-GitLab/mysql-postgresql-converter/db_converter.py,转换时会发生UnicodeDecodeError: ‘utf8’ codec can’t decode byte 0x9c错误.截至目前尚有 30 个 PR 未处理.群晖科技在自家稳定版产品中未确认方案普适性,原项目首页强调 use with care 被无视,置客户数据安全于不顾,最终导致悲剧发生.后续我会专门谈一谈为什么 synology NAS 是危险的产品,选购群晖是对数据的不负责行为.本篇只说怎么找回你宝贵的数据.

修改 docker 环境变量,使用原 MariaDB 数据库

1.使用 admin 组的账户登录群晖 SSH .警告: 如果你不知道这步怎么操作,本修复指南可能对你来说较复杂,极易出现数据丢失.请向技术人员求助.

2.如果之前没有执行过备份( bundle exec rake gitlab:backup:create RAILS_ENV=production ),那么执行下备份.路径类似/volume1/docker/gitlab/.

3.为 gitlab_user 授权.如果不熟悉 SQL 可以在套件中心中安装 phpMyAdmin ,然后在权限中增加用户账户的 host name 为 172.17.0.% .

4.测试数据库权限:

docker exec -it synology_gitlab bash  # 进入容器终端
mysql -u gitlab_user -p -h 172.17.0.1 -P 3307  # 测试数据库链接情况
exit  # 退出容器

5.套件中心 => 已安装 => GitLab => 停止.

6.docker => synology_gitlab => 编辑 => 环境变量

DB_PORT 3307
DB_TYPE mysql
DB_HOST 172.17.0.1

7.套件中心 => 已安装 => GitLab => 启动.

修复数据库故障

GitLab 官方明确表示不推荐使用 MariaDB / MySQL 数据库. 群晖由于某种原因仍然在使用 MariaDB 10 .本部分重点解决各类数据库问题.

1.停止 GitLab 服务service gitlab stop.
2.登录 MariaDB 或直接使用 phpMyAdmin .让数据库支持长索引.

use gitlab;
SET storage_engine=INNODB;
SET GLOBAL innodb_file_per_table=1, innodb_file_format=Barracuda, innodb_large_prefix=1;
SET GLOBAL log_bin_trust_function_creators = 1;

3.转换原有数据使用 utf8mb4 编码.注意下面的命令每一条的回显都要作为 SQL 语句再执行.

SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` ROW_FORMAT=DYNAMIC;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlab" AND TABLE_TYPE="BASE TABLE" AND ROW_FORMAT!="Dynamic";

回显类似

ALTER TABLE `abuse_reports` ROW_FORMAT=DYNAMIC;
ALTER TABLE `appearances` ROW_FORMAT=DYNAMIC;
ALTER TABLE `application_settings` ROW_FORMAT=DYNAMIC;
ALTER TABLE `audit_events` ROW_FORMAT=DYNAMIC;
ALTER TABLE `award_emoji` ROW_FORMAT=DYNAMIC;
ALTER TABLE `boards` ROW_FORMAT=DYNAMIC;
ALTER TABLE `broadcast_messages` ROW_FORMAT=DYNAMIC;
ALTER TABLE `chat_names` ROW_FORMAT=DYNAMIC;
ALTER TABLE `chat_teams` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_build_trace_section_names` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_build_trace_sections` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_builds` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_group_variables` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_job_artifacts` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_pipeline_schedule_variables` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_pipeline_schedules` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_pipeline_variables` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_pipelines` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_runner_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_runners` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_stages` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_trigger_requests` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_triggers` ROW_FORMAT=DYNAMIC;
ALTER TABLE `ci_variables` ROW_FORMAT=DYNAMIC;
ALTER TABLE `cluster_platforms_kubernetes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `cluster_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `cluster_providers_gcp` ROW_FORMAT=DYNAMIC;
ALTER TABLE `clusters` ROW_FORMAT=DYNAMIC;
ALTER TABLE `clusters_applications_helm` ROW_FORMAT=DYNAMIC;
ALTER TABLE `container_repositories` ROW_FORMAT=DYNAMIC;
ALTER TABLE `conversational_development_index_metrics` ROW_FORMAT=DYNAMIC;
ALTER TABLE `deploy_keys_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `deployments` ROW_FORMAT=DYNAMIC;
ALTER TABLE `emails` ROW_FORMAT=DYNAMIC;
ALTER TABLE `environments` ROW_FORMAT=DYNAMIC;
ALTER TABLE `events` ROW_FORMAT=DYNAMIC;
ALTER TABLE `feature_gates` ROW_FORMAT=DYNAMIC;
ALTER TABLE `features` ROW_FORMAT=DYNAMIC;
ALTER TABLE `fork_network_members` ROW_FORMAT=DYNAMIC;
ALTER TABLE `fork_networks` ROW_FORMAT=DYNAMIC;
ALTER TABLE `forked_project_links` ROW_FORMAT=DYNAMIC;
ALTER TABLE `gcp_clusters` ROW_FORMAT=DYNAMIC;
ALTER TABLE `gpg_key_subkeys` ROW_FORMAT=DYNAMIC;
ALTER TABLE `gpg_keys` ROW_FORMAT=DYNAMIC;
ALTER TABLE `gpg_signatures` ROW_FORMAT=DYNAMIC;
ALTER TABLE `group_custom_attributes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `identities` ROW_FORMAT=DYNAMIC;
ALTER TABLE `issue_assignees` ROW_FORMAT=DYNAMIC;
ALTER TABLE `issue_metrics` ROW_FORMAT=DYNAMIC;
ALTER TABLE `issues` ROW_FORMAT=DYNAMIC;
ALTER TABLE `keys` ROW_FORMAT=DYNAMIC;
ALTER TABLE `label_links` ROW_FORMAT=DYNAMIC;
ALTER TABLE `label_priorities` ROW_FORMAT=DYNAMIC;
ALTER TABLE `labels` ROW_FORMAT=DYNAMIC;
ALTER TABLE `lfs_objects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `lfs_objects_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `lists` ROW_FORMAT=DYNAMIC;
ALTER TABLE `members` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_request_diff_commits` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_request_diff_files` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_request_diffs` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_request_metrics` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_requests` ROW_FORMAT=DYNAMIC;
ALTER TABLE `merge_requests_closing_issues` ROW_FORMAT=DYNAMIC;
ALTER TABLE `milestones` ROW_FORMAT=DYNAMIC;
ALTER TABLE `namespaces` ROW_FORMAT=DYNAMIC;
ALTER TABLE `notes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `notification_settings` ROW_FORMAT=DYNAMIC;
ALTER TABLE `oauth_access_grants` ROW_FORMAT=DYNAMIC;
ALTER TABLE `oauth_access_tokens` ROW_FORMAT=DYNAMIC;
ALTER TABLE `oauth_applications` ROW_FORMAT=DYNAMIC;
ALTER TABLE `oauth_openid_requests` ROW_FORMAT=DYNAMIC;
ALTER TABLE `pages_domains` ROW_FORMAT=DYNAMIC;
ALTER TABLE `personal_access_tokens` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_authorizations` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_auto_devops` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_custom_attributes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_features` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_group_links` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_import_data` ROW_FORMAT=DYNAMIC;
ALTER TABLE `project_statistics` ROW_FORMAT=DYNAMIC;
ALTER TABLE `projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `protected_branch_merge_access_levels` ROW_FORMAT=DYNAMIC;
ALTER TABLE `protected_branch_push_access_levels` ROW_FORMAT=DYNAMIC;
ALTER TABLE `protected_branches` ROW_FORMAT=DYNAMIC;
ALTER TABLE `protected_tag_create_access_levels` ROW_FORMAT=DYNAMIC;
ALTER TABLE `protected_tags` ROW_FORMAT=DYNAMIC;
ALTER TABLE `push_event_payloads` ROW_FORMAT=DYNAMIC;
ALTER TABLE `redirect_routes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `releases` ROW_FORMAT=DYNAMIC;
ALTER TABLE `routes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `schema_migrations` ROW_FORMAT=DYNAMIC;
ALTER TABLE `sent_notifications` ROW_FORMAT=DYNAMIC;
ALTER TABLE `services` ROW_FORMAT=DYNAMIC;
ALTER TABLE `snippets` ROW_FORMAT=DYNAMIC;
ALTER TABLE `spam_logs` ROW_FORMAT=DYNAMIC;
ALTER TABLE `subscriptions` ROW_FORMAT=DYNAMIC;
ALTER TABLE `system_note_metadata` ROW_FORMAT=DYNAMIC;
ALTER TABLE `taggings` ROW_FORMAT=DYNAMIC;
ALTER TABLE `tags` ROW_FORMAT=DYNAMIC;
ALTER TABLE `timelogs` ROW_FORMAT=DYNAMIC;
ALTER TABLE `todos` ROW_FORMAT=DYNAMIC;
ALTER TABLE `trending_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `u2f_registrations` ROW_FORMAT=DYNAMIC;
ALTER TABLE `uploads` ROW_FORMAT=DYNAMIC;
ALTER TABLE `user_agent_details` ROW_FORMAT=DYNAMIC;
ALTER TABLE `user_custom_attributes` ROW_FORMAT=DYNAMIC;
ALTER TABLE `user_synced_attributes_metadata` ROW_FORMAT=DYNAMIC;
ALTER TABLE `users` ROW_FORMAT=DYNAMIC;
ALTER TABLE `users_star_projects` ROW_FORMAT=DYNAMIC;
ALTER TABLE `web_hook_logs` ROW_FORMAT=DYNAMIC;
ALTER TABLE `web_hooks` ROW_FORMAT=DYNAMIC;');

4.转换原有数据使用新的表空间( tablespace )格式.注意下面的命令每一条的回显都要作为 SQL 语句再执行.

SET foreign_key_checks = 0;
SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;') AS 'Copy & run these SQL statements:' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="gitlab" AND TABLE_COLLATION != "utf8mb4_general_ci" AND TABLE_TYPE="BASE TABLE";

回显类似

ALTER TABLE `abuse_reports` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `appearances` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `application_settings` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `audit_events` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `award_emoji` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `boards` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `broadcast_messages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `chat_names` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `chat_teams` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_build_trace_section_names` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_build_trace_sections` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_builds` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_group_variables` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_job_artifacts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_pipeline_schedule_variables` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_pipeline_schedules` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_pipeline_variables` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_pipelines` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_runner_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_runners` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_stages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_trigger_requests` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_triggers` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `ci_variables` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `cluster_platforms_kubernetes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `cluster_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `cluster_providers_gcp` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `clusters` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `clusters_applications_helm` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `container_repositories` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `conversational_development_index_metrics` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `deploy_keys_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `deployments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `emails` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `environments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `events` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `feature_gates` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `features` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `fork_network_members` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `fork_networks` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `forked_project_links` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `gcp_clusters` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `gpg_key_subkeys` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `gpg_keys` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `gpg_signatures` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `group_custom_attributes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `identities` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `issue_assignees` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `issue_metrics` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `issues` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `keys` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `label_links` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `label_priorities` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `labels` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `lfs_objects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `lfs_objects_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `lists` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `members` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_request_diff_commits` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_request_diff_files` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_request_diffs` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_request_metrics` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_requests` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `merge_requests_closing_issues` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `milestones` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `namespaces` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `notes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `notification_settings` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `oauth_access_grants` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `oauth_access_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `oauth_applications` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `oauth_openid_requests` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `pages_domains` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `personal_access_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_authorizations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_auto_devops` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_custom_attributes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_features` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_group_links` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_import_data` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `project_statistics` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `protected_branch_merge_access_levels` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `protected_branch_push_access_levels` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `protected_branches` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `protected_tag_create_access_levels` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `protected_tags` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `push_event_payloads` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `redirect_routes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `releases` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `routes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `schema_migrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `sent_notifications` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `services` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `snippets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `spam_logs` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `subscriptions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `system_note_metadata` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `taggings` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `tags` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `timelogs` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `todos` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `trending_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `u2f_registrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `uploads` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `user_agent_details` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `user_custom_attributes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `user_synced_attributes_metadata` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `users_star_projects` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `web_hook_logs` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE `web_hooks` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
SET foreign_key_checks = 1;

5.执行数据库限制任务.

bundle exec rake add_limits_mysql RAILS_ENV=production

6.修改数据库迁移任务.由于 GitLab 官方要求不允许跨多个小版本升级,所以我们会遇到一些奇怪的错误,这里给出一些修复方案,我只遇到了一个.

Mysql2::Error: Index column size too large. The maximum column size is 767 bytes.: CREATE UNIQUE INDEX `index_lfs_file_locks_on_project_id_and_path`  ON `lfs_file_locks` (`project_id`, `path`)

解决方案:

use gitlab;
DROP TABLE lfs_file_locks;
# db/migrate/20180116193854_create_lfs_file_locks.rb
# create_table :lfs_file_locks do |t| 修改为
create_table :lfs_file_locks, options: 'ROW_FORMAT=DYNAMIC'  do |t|

7.执行数据库迁移.

bundle exec rake db:migrate

预编译资源

bundle exec rake gettext:compile RAILS_ENV=production
bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production
bundle exec rake cache:clear RAILS_ENV=production

备份与恢复

bundle exec rake gitlab:backup:create RAILS_ENV=production  # 你会找到一个类似 /home/git/data/backups/1531046569_2018_07_14_10.6.4_gitlab_backup.tar 的文件
bundle exec rake gitlab:backup:restore RAILS_ENV=production

cnpm+gitlab-ci 模块自动发布方案

为什么会探讨这个主题

在我司现有web前端项目构建过程中,一直使用gulp + rjs的方案进行项目打包,由于整站项目过于庞大,即使是以相当好的机器多核打包,也需要4分钟+的时间,遂产生了将模块全部使用npm管理,并拆分子项目,达到每个通用模块都可自动构建,单元测试,保证质量并稳步迭代的目的。

项目其余细节

公司内部内容,略过

cnpm与cnpmjs.org的部署

cnpm原理

为npm原有的一些命令设置了代理,让你可以方便的连接到自己的私有服务,并同时使用npm上的资源包,您可以选择使用命令直接同步npm官方包(实质是向您的cnpmjs.org私有服务发送命令,并同步线上资源,存储下来),也可以直接通过cnpm接洽的原生npm直接下载,取决于您的需求

部署

cnpm官方通过开源项目cnpmjs.org整合了cnpm.registry和cnpm.web两个服务,让用户可以通过cnpm指定registry使用私有服务。

这里只介绍使用sqlite3作为存储私有包的记录数据库,即官方wiki中的5分钟部署cnpmjs。

Deploy-a-private-npm-registry-in-5-minutes

直接根据以上链接阐述内容,您可以立刻配置起一个cnpmjs.org服务.

配置cnpmjs.org

值得注意的是,您如果没有配置云存储服务器,将会默认使用fs-cnpm的配置,默认将publish的包存放在~/.cnpmjs.org/downloads下

默认的sqlite数据库位于~/.cnpmjs.org/data.sqlite

cnpmjs.org相关配置位于cnpmjs.org的包的config/index.js中

注意:bindingHost默认为127.0.0.1,请置空字符串或已注册的具名地址或内网可访问的ip地址,以便在内网其他机器上访问该服务

如果需使用其他云存储配置,已有数据库,请按照官方wiki修改相应配置。

# 后台启动cnpmjs.org服务,如有需要,可使用其他守护进程
nohup cnpmjs.org start --admins='myname,othername' 
  --scopes='@my-company-name,@other-name' &

当安装好cnpmjs.org并配置好后,需要使用命令写入或者直接配置(至少运行一次)私有仓库作用域(scopes)以及私有仓库管理员名称。不明白的可以去npm官方文档了解一下

cnpmjs.org的registry服务和web服务默认位于7001,7002两个端口,7002即是cnpmjs.org的web网页,可以查看发布的相关私有包或同步的包

配置cnpm

cnpm set registry http://bindingHost:7001

将registry服务地址设置为你启动的cnpmjs.org registry服务地址

第一次登录

也就是注册。

原因是调用cnpm login的时候,走到cnpmjs.org服务,会通过以下路由

app.put('/-/user/org.couchdb.user::name', addUser);

输入下面内容开始创建

cnpm login myname

测试私有npm是否畅通

新建一个项目,cnpm init之

name设置为'@my-company-name/test'

cnpm publish尝试,上传成功

数据备份

相应包如果由于宕机或其他原因消失了是一件很麻烦的事情,请定时去默认数据存储文件夹备份一份(如果使用了其他已有的数据库,云存储,请自行备份),以便恢复。

gitlab的部署

这里使用的是ce-11.0.3版本,按照官方傻瓜式部署,直接可以部署上

请区分ce和ee两个不同版本

EXTERNAL_URL配置与上步骤配置bindingHost类似

其余邮件配置,其他数据库配置(如不用默认数据库),以及其他配置,请自行搜索或寻找官方文档。

gitlab首次启动

使用10 11等版本,首次启动的默认管理员用户密码不再如同以前一样是root 5iveL!fe了,

在新版本中,gitlab-rails web服务于auth中间件中判断了用户是否为第一次登陆,如果为第一次登陆,将会跳转到修改密码页,只需简单进入布置好的网页服务设置root密码即可。

gitlab首次进入修改不了密码?

。。。虽然我是个低级前端工程师,并且我chrome打开了f12,但是我没看到报错,查看了各种权限是否分配错误,查看了是不是编译出错,查看了web服务的auth中间件以及 changepassword服务,查看了数据库,各种可能都找了一遍,就差没直接改数据库,没找到原因。。。

然后我看到了这篇文章修改GitLab Web服务默认端口和初次登录密码报错问题 https://ykzm.in/archives/1010

尝试换了个浏览器,好了。。。没有继续深究为什么

安装gitlab-runner

请直接参考官方文档 在任意一台机器上无脑安装即可

配置gitlab-runner

也请直接参考官方文档

或参考我的渣文档最底部的资料链接

重头戏

gitlab-ci cnpm配合做到一键发布。

gitlab-ci cnpm配合前情提要

首先,用户需要保证runner机器上也装了cnpm,至于怎么装就随便了。

cnpm登录后并不会直接颁布给你一个_authtoken,所以想直接通过在gitlab中的ci配置里写入_authtoken私密变量并进行私有包的发布是不现实的。

cnpm的源码中将publish命令直接拿给原生npm执行了,自己只是对参数进行了一些包装,最终执行 npm publish argv命令

cnpm可以做到的就是修改配置路径(–userconfig参数配置项),读取用户cnpmrc配置。

在设置了–userconfig路径以后,cnpm会将一系列参数直接传递给npm , npm通过 core包中的Conf模块会将你的config文件解析掉,生成一个token并执行publish的put操作。

基于这点我们就可以做到测试完毕并且自动发布私有包了

具体实施步骤

如果您没有修改过指定的.cnpmrc客户配置,当您登陆过cnpm后,会在用户目录下,也就是~/下发现.cnpmrc配置文件。

他大概是这样的

registry=http://yourbindingRegistryServerHost
//yourbindingHost:always-auth=false
//yourbindingRegistryServiceHost:_password=加密过的密码串
//yourbindingRegistryServiceHost:username=myname
//yourbindingRegistryServiceHost:[email protected]

那么思路就很明白了,我们可以这样写我们的发布脚本脚本

// publish.js
const fs = require('fs');
const argv = process.argv;
const un = argv[2];
const pw = argv[3];
const em = argv[4];
const r = argv[5];
const exec = require('child_process').exec;

if (un && pw && em && r) {
    const or = r.replace(/^https?:/, '')
    const result = `
registry=${r}
${or}:always-auth=false
${or}:_password=${pw}
${or}:username=${un}
${or}:email=${em}
`;
    fs.writeFileSync('./.cnpmrc', result);
    exec('cnpm publish --userconfig=' + process.cwd() + '/.cnpmrc', (error, stdout, stderr) => {
        console.log(`stdout: ${stdout}`);
        console.log(`stderr: ${stderr}`);
        if (error) {
            console.error(`exec error: ${error}`);
            process.exit(1);
        }
    })
}

这样写我们的ci配置

before_script:
  - npm i
stages:
  - test
  - publish
job1:
  stage: test
  script:
    - npm run test
  only:
    - master
  tags:
    - qie
job2:
  stage: publish
  script:
    - 'node ./publish.js $CNPM_UN $CNPM_PW $CNPM_EM $CNPM_R'

$CNPM_UN $CNPM_PW $CNPM_EM $CNPM_R为在gitlab仓库中设置的CI私密变量

效果

未分类

未分类

未分类

Gitlab 8.x runner安装与配置

介绍

  Gitlab 8.x之后默认集成了Gitlab CI,意味着支持了持续集成相关功能。每一次集成操作都需要对应的runner来跑代码构建、测试、发布等操作。Runner实际上就是为Gitlab的持续集成指定一个环境。

安装

官方文档地址:https://docs.gitlab.com/runner/install/
  Gitlab Runner的版本需要跟Gitlab对应,这里有一个对照表。最新的版本对照表中并没有Gitlab8.X对应的Runner版本,查了一下Gitlab8.X对应的Runner版本为1.X,所以这里选择runner 1.11.2版本。

  这里运行Gitlab与Runner的环境均为CentOS,之前尝试在windows上安装runner,对接Linux上的Gitlab,发现在Gitlab runner运行的控制台出现乱码问题。

0. 准备

在opt下创建gitlab-runner目录并进入该目录,后续执行的操作与所有的资源都放在这个目录中

cd /opt
mkdir gitlab-runner
cd gitlab-runner/

1. 下载

下载安装资源到gitlab-runner目录中

sudo wget https://gitlab-ci-multi-runner-downloads.s3.amazonaws.com/v1.11.2/binaries/gitlab-ci-multi-runner-linux-386

2. 添加运行权限

sudo chmod +x gitlab-ci-multi-runner-linux-386

3. 创建用户

sudo useradd --comment 'GitLab Runner' --create-home gitlab-runner --shell /bin/bash

4. 安装

./gitlab-ci-multi-runner-linux-386 install --user=gitlab-runner --working-directory=/opt/gitlab-runner
sudo gitlab-ci-multi-runner-linux-386 start

配置

  经过上面的步骤,Runner就已经跑起来了,剩下的还需要Runner与项目对接起来。Runner的类型分为Shared, specific and group Runners。这里选择specific类型,即单独的项目使用。

  在Gitlab项目的setting-runner中,配置过程中会使用到url和token如下所示:

未分类

1.运行register命令

./gitlab-ci-multi-runner-linux-386 register

之后就按照提示就行了

2.输入url地址
3.输入token
4.输入描述,任意即可
5.输入标签,这里直接Enter跳过
6.选择Runner executor,这里选择shell

到这里就已经注册成功了,输入./gitlab-ci-multi-runner-linux-386 list就能看到上面的注册的条目。

官方文档地址:https://docs.gitlab.com/runner/register/index.html

其它

  上面两个步骤做完后,此时按理说Gitlab就能调用Runner跑持续集成了,实际当中还会碰到其它问题,整理如下。

权限问题

  如果在Gitlab的Build控制台上报无法创建文件夹、无法运行bash等,证明创建的GitLab Runner权限不够。
此时,我这里是修改GitLab Runner的权限跟root保持一致。

vim /etc/passwd

通过上面命令可以编辑用户对应的权限,我这里打开默认为gitlab-runner:x:601:601:GitLab Runner:/home/gitlab-runner:/bin/bash,权限组修改为跟root的一致gitlab-runner:x:0:0:GitLab Runner:/home/gitlab-runner:/bin/bash。(root的权限组名为0)

这里在另外一台机器上还碰到这样修改了也不好使的问题,最终gitlab-runner install的时候,直接指定为root,而不新创建用户。

环境问题

由于Runner运行需要环境支撑,比如git、node、npm等,需要在Runner所在的服务器上准备好所有的依赖。

Linux Node安装

# 下载
wget https://nodejs.org/dist/v8.11.3/node-v8.11.3-linux-x64.tar.xz
# 解压
tar -xf  node-v8.11.3-linux-x64.tar.xz
# 建立软链接,实现全局访问
ln -s /opt/gitlab-runner/node-v8.11.3-linux-x64/bin/node /usr/local/bin/node
ln -s /opt/gitlab-runner/node-v8.11.3-linux-x64/bin/npm /usr/local/bin/npm

此时,输入node -v就能看到node的版本了。

使用软连接方式可能对非root用户无效,可以转而使用配置环境变量的方式

# 修改配置文件
vim /etc/profile
#set for nodejs,新增NODE_HOME并放到PATH上
export JAVA_HOME=/opt/soft/java
export NODE_HOME=/opt/gitlab-runner/node-v8.11.3-linux-x64  
export CLASSPATH=$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$PATH:$JAVA_HOME/bin:$NODE_HOME/bin

在vim环境下点击i进入插入状态,编辑完成后按Esc键,然后输入 :wq 按回车保存退出。
备注:内外环境还需修改NPM的镜像源,比如修改为npm config set registry https://registry-npm.daojia-inc.com/

附录 部分GitLab-Runner常用命令

1.gitlab-runner帮助:gitlab-runner –help

2.gitlab-runner指定命令帮助:gitlab-runner –help

3.注册runner:gitlab-runner register

4.注销runner:gitlab-runner unregister

5.当前运行的runner:gitlab-runner list

6.启动runner:gitlab-runner start

7.停止runner:gitlab-runner stop

8.重启runner:gitlab-runner restart

9.查询runner状态:gitlab-runner status

docker compose实战部署django

第一步,因为应用将要运行在一个满足所有环境依赖的 Docker 容器里面,那么我们可以通过编辑 Dockerfile 文件来指定 Docker 容器要安装内容。内容如下:

FROM python:3

ENV PYTHONUNBUFFERED 1

RUN mkdir /code

WORKDIR /code

ADD requirements.txt /code/

RUN pip install -r requirements.txt

ADD . /code/

第二步,在 requirements.txt 文件里面写明需要安装的具体依赖包名。

Django>=1.8,<2.0

psycopg2

第三步, docker-compose.yml 文件将把所有的东西关联起来。它描述了应用的构成(一个web 服务和一个数据库)、使用的 Docker 镜像、镜像之间的连接、挂载到容器的卷,以及服务开放的端口。

version: "3"

services:

    db:

        image: postgres

    web:

        build: .

        command: python3 manage.py runserver 0.0.0.0:8000

        volumes:

            – .:/code

        ports:

            – "8000:8000"

        links:

            – db

现在我们就可以使用 docker-compose run 命令启动一个 Django 应用了。

$ docker-compose run web django-admin.py startproject django_example .

Compose 会先使用 Dockerfile 为 web 服务创建一个镜像,接着使用这个镜像在容器里运行django-admin.py startproject composeexample 指令。这将在当前目录生成一个 Django 应用。

$ ls

Dockerfile docker-compose.yml django_example manage.py requ

irements.txt

如果你的系统是 Linux,记得更改文件权限。

sudo chown -R $USER:$USER .

首先,我们要为应用设置好数据库的连接信息。用以下内容替换 django_example/settings.py文件中 DATABASES = … 定义的节点内容。

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.postgresql',

         'NAME': 'postgres',

         'USER': 'postgres',

         'HOST': 'db',

         'PORT': 5432,

    }

}

这些信息是在 postgres 镜像固定设置好的。然后,运行 docker-compose up :

$ docker-compose up

django_db_1 is up-to-date

Creating django_web_1 …

Creating django_web_1 … done

Attaching to django_db_1, django_web_1

db_1 | The files belonging to this database system will be owned by user "postgres".

db_1 | This user must also own the server process.

db_1 |

db_1 | The database cluster will be initialized with locale "en_US.utf8".

db_1 | The default database encoding has accordingly been set to "UTF8".

db_1 | The default text search configuration will be set to "english".

web_1 | Performing system checks…

web_1 |

web_1 | System check identified no issues (0 silenced).

web_1 |

web_1 | November 23, 2017 – 06:21:19

web_1 | Django version 1.11.7, using settings 'django_example.settings'

web_1 | Starting development server at http://0.0.0.0:8000/

web_1 | Quit the server with CONTROL-C.

这个 Django 应用已经开始在你的 Docker 守护进程里监听着 8000 端口了。打开127.0.0.1:8000 即可看到 Django 欢迎页面。

你还可以在 Docker 上运行其它的管理命令,例如对于同步数据库结构这种事,在运行完docker-compose up 后,在另外一个终端进入文件夹运行以下命令即可:

$ docker-compose run web python manage.py syncdb

docker-compose up 时提示挂载目录open permission denied

docker-compose up 时提示挂载目录open permission denied

[root@localhost nginx-php]# docker-compose up
Creating php-fpm ... 
Creating php-fpm ... done
Creating nginx ... 
Creating nginx ... done
Attaching to php-fpm, nginx
php-fpm    | [15-Dec-2017 06:53:36] NOTICE: fpm is running, pid 1
php-fpm    | [15-Dec-2017 06:53:36] NOTICE: ready to handle connections
nginx      | nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (13: Permission denied)
nginx      | 2017/12/15 06:53:36 [emerg] 1#1: open() "/var/log/nginx/error.log" failed (13: Permission denied)
nginx exited with code 1
^CGracefully stopping... (press Ctrl+C again to force)
Stopping php-fpm ... done
[root@localhost nginx-php]#

原因是SELinux搞的鬼,禁用就好了

#查看SELinux状态(如果SELinux status参数为enabled即为开启状态)
/usr/sbin/sestatus -v 

#临时关闭
setenforce 0

#修改配置文件重启机器禁用(将SELINUX=enforcing改为SELINUX=disabled)
vim /etc/selinux/config