定义基础架构即代码

基础架构即代码 (IaC) 理念是 DevOps 的一个关键概念。通过运行自动化工作流程来实现目标。让我们管理基础设施更高效、准确、可重复性强。
Ansible 可以​把环境部署、软件安装、管理服务这些复杂的操作封装在 YAML 格式的 Playbook 剧本文件中。我们可以使用 Git 来管理这些剧本。这样随着项目的不断推进。我们可以轻松溯源。查询修改记录。
Ansible 是实现 Iac 的强力工具。实现部署环境的一致性。并且 Ansible 可以根据需要定制自动化任务,让管理变得更加灵活,拓展更加方便。

Git 简介

Git 是一种分布式版本控制系统 (DVCS),​能够让项目参与者相互协作管理项目中的文件更改。​使用 Git 有许多好处:

  • 可以检查和恢复文件的早期版本。
  • 可以比较同一文件的两个版本来对比查看修改的内容
  • Git 会记录每次更改的详细信息,可以利用日志记录谁在何时做了哪些更改。
  • ​多用户可以同时修改文件、​解决相互冲突的更改,​并且合并各自的更改。​

通过Git,我们可以轻松地管理项目。我们可以从远程仓库中克隆一个已有的共享项目。克隆操作会在本地创建一个存储库,它是远程仓库的完整副本,克隆项目会完全复制远程的仓库内容,且包含完整的历史记录,而不仅仅只是最新的项目文件。
工作树是(working tree) 项目的一个具体版本。当我们在工作树中编辑文件后,可以将修改后的文件添加进暂存区域(staging area) ,准备提交修改到本地存储库。当我们为这次修改做好了说明后,可以提交到远程仓库,通过push 命令,远程存储库的内容就跟本地一模一样了。反之,当我们要把远程存储库的最新状态更新到本地时,我们需要使用拉取 pull 命令。

git 工作树有三种状态: 已修改、已暂存、已提交

状态 描述
已修改 已编辑了工作树中文件的副本,​它与存储库中的最新版本不同。
已暂存 将修改后的文件添加到了已更改文件列表中,​以作为一个集合一起提交,​但还没有提交暂存的文件。
已提交 已将修改后的文件提交到本地存储库。​

Git 管理文件的区域

alt text

我们把 git 管理文件分为 4 个区域:

  • Working tree: 工作树
  • Staging area: 暂存区域
  • Local repository: 本地存储库
  • Remote repository: 远程存储库

初始化 Git 配置

git 会记录每次提交的用户信息,这包括用户名和邮箱。这些内容保存在 ~/.gitconfig 文件中。
在提交前,需要配置推送方式,默认推送方式设为 simple。​这是新手最安全的选项。​

以下是命令配置用户名、邮箱、推送方式的示例

1
2
3
[user@host ~]$ git config --global user.name 'Zhang San'
[user@host ~]$ git config --global user.email zhang@host.example.com
[user@host ~]$ git config --global push.default simple

我们说 git 工作状态有 3 种,可以用 git status 命令查看当前工作状态。如果每次都用命令。实在不是很方便。git 提供了 git-prompt.sh 脚本,它的作用是在命令提示符中显示有关 Git 仓库的状态。

配置 ~/.bashrc 文件来设置shell 提示符来实时查看 git 仓库的状态

1
2
3
4
5
# ~/.bashrc 添加内容
source /usr/share/git-core/contrib/completion/git-prompt.sh
export GIT_PS1_SHOWDIRTYSTATE=true
export GIT_PS1_SHOWUNTRACKEDFILES=true
export PS1='[\u@\h \W$(declare -F __git_ps1 &>/dev/null && __git_ps1 " (%s)")]\$ '
  • \u: 当前用户名
  • \h: 当前主机名
  • \W: 当前工作目录
  • $(...): 获取括号内的命令输出结果
  • declare -F __git_ps1:检测 __git_ps1 函数是否已定义
  • __git_ps1 " (%s)": 显示当前分支名称以及状态(有更改或未跟踪的文件才显示)

git 状态含义:

  • (branch *) 已修改了跟踪的文件。
  • (branch +) 已修改了跟踪的文件并使用 git add 暂存了它。
  • (branch %) 工作树中存在未跟踪的文件。​
  • 标记可组合使用,​例如 (branch *)+。

启动 Git 工作流

在使用 git 时,我们可以 git clone 克隆远程的存储仓库,也可以 git init创建储仓库。

alt text

上图一共出现了 3 条命令 分别是 git initgit init --bare 。详细解释它们的区别:

git init

用于初始化普通 Git 存储库。会创建本地存储库以及工作树。在当前目录下创建 .git 子目录,​该目录包含 Git 存储库所需的文件。​

适用场景:

  • 创建一个新的本地开发项目
  • 将一个已有项目目录转换为 Git 存储库
  • 适合个人开发,直接在工作目录中编辑文件

git init --bare

初始化一个裸存储库,它不会创建工作树。​所以无法添加、删除或修改文件。在当前目录下创建 .git 子目录,​该目录包含 Git 存储库所需的文件。
​裸仓库是不包含工作目录的 Git 仓库,只包含 Git 版本历史和对象数据库,通常用作远程仓库(例如在服务器上托管的仓库)

适用场景:

  • 用于服务器端的共享仓库,多人协作
  • 作为中央仓库,接收用户的推送
  • 需要集中管理代码的场景

以上对比总结: git init 是创建本地仓库的,git init –bare 是创建远程仓库的。

git clone:

从远程仓库克隆一个项目到本地,这个仓库是远程仓库的完整副本。
有 2 种方式克隆远程仓库,分别是 http 方式 和 ssh 方式。

  • http 方式只要有仓库的链接即可克隆
1
[student@workstation ~ (master #%)]$ git clone https://git.lab.example.com/student/develop-git.git
  • ssh 方式需要先配置用户 ssh 密钥到 git 服务器上。才能访问远程仓库进行克隆
1
[student@workstation ~]$ git clone http://git:gitpass@git.lab.example.com/lxh.git

用于添加和更新的 git 命令:

alt text

在工作区编辑文件后,首先提交将修改提交到暂存区,接着提交到本地存储并写好提交日志

  • 用 git add 将修改的文件添加到暂存去
  • 用 git commit 提交暂存文件到本地存储并写好提交日志

简明且有意义且的提交消息是维护 Ansible 项目的清晰历史记录的关键。有以下三个点:

  • 第一行应当是提交原因的简短摘要(通常少于 50 个字符)。​

  • 第一行后跟一个空行,​然后消息的其余部分必须解释所有详细信息、​所执行操作的说明,​以及提交的原因。​

  • 如果可用,​可添加对问题或功能跟踪器的引用。​这些引用使用其他文本、​相关人员或历史记录扩展提交消息。

1
2
3
4
5
[student@workstation ~ (master #%)]$ git clone https://git.lab.example.com/student/develop-git.git
[student@workstation ~ (master #%)]$ cd develop-git/
[student@workstation develop-git (main)]$ touch new.txt
[student@workstation develop-git (main %)]$ git add new.txt
[student@workstation develop-git (main +)]$ git commit -m 'new file'

git commit 仅提交 已暂存(staged) 的更改(即 git add 过的文件)

git commit -a 自动暂存并提交所有 已跟踪(tracked) 文件的修改和删除(等价于先 git add -u 再 git commit),但有例外:新建的文件、被重命名和被移动的文件不会被提交,需要手动先 add。

已跟踪(tracked)文件: 指曾经被 git add 并提交过的文件。​

不推荐使用 git commit -a, 因为容易误操作。

git rm: 从工作目录种移除文件,但暂存到下一次提交时才真正删除。
git reset: 撤销操作,从暂存区域中撤销之前为下一次提交而添加的文件。但是工作区中已经做出的修改是不会改变的。只是删除了暂存区域中的文件。实际已修改内容不会改变。

用于与远程仓库交互的 git 命令:

alt text

git push 作用:将本地仓库内容推送到远程仓库,使远程仓库与本地仓库保持一致
git pull 作用:从远程仓库拉取数据,使本地仓库与远程仓库保持一致

应该经常运行 git pull 命令,​从而获得远程存储库中的最新更改。​

检查 Git 日志

版本控制系统可以跟着每次提交的历史记录:

  • git log 显示所有提交的日志消息和关联的 ID 哈希
  • git show commit-hash 显示指定提交所关联的日志消息和内容。​命令中不需要输入完整的哈希,只需其中的于其他哈希不重复的部分来唯一标识存储库中的特定提交记录。​这些哈希还可用于恢复到之前的提交,​或者探索版本控制系统的历史记录。​

Git 命令参考

命令 描述
git clone URL 将现有的 Git 项目从位于 URL 的远程存储库克隆到当前的目录中。
git status 显示工作树中文件的状态。​
git add file 暂存新的或更改的文件以准备下一次提交。
git rm file 暂存文件删除以准备下一次提交。
git reset 取消暂存已为下一次提交暂存的文件。
git commit 将暂存的文件与描述性消息一起提交到本地存储库。
git push 将本地存储库中的更改推送到远程存储库。
git pull 从远程存储库获取更新到本地存储库,​并将它们合并到工作树中。
git revert commit-hash 创建新的提交,​撤消所引用提交中的更改。​您可以使用标识提交的提交哈希,​尽管还有其他方法可以引用提交。
git init 创建新项目。
git log 显示提交日志消息。
git show commit-hash 显示特定提交哈希的更改集中的内容。

使用 Git 分支和引用

分支可以在不修改主分支的基础上对项目进行修改。完成后可以把修改合并到主分支上。
分支本质上是指向提交树中特定提交的指针。​每个提交都包含它所做的更改,​以及关于如何引用它以及它与提交树中其他提交的关系的信息。​提交中的信息包括:

  • 一个唯一 ID,​采用 40 位十六进制字符串格式。​此 ID 是提交内容的 SHA-1 哈希。​

  • 它所更改的存储库文件的列表,​以及对每个文件的确切更改。​

  • 在应用所涉及提交之前定义存储库状态的父提交的 ID。​

  • 提交数据中有关提交的作者和创建者(或提交者)的信息。​

  • 引用列表。​引用类似于指向提交的命名指针。​最常见的引用是标签和分支。​

alt text

HEAD 引用是本地工作树的当前提交, git branch 命令会从当前的 HEAD 提交创建⼀个新的分⽀。 此命令会为新分⽀创建⼀个引⽤,但它不会将当前 HEAD 设置为此分⽀。 使⽤ git checkout 命令将 HEAD 移到相应的分⽀。

创建分支

如果本地还没有任何提交 git commit 是不能创建分支的,默认的分支名称为 mastermain

git branch 不带参数用来查看当前分支列表,* 符合表示当前分支
git branch 分支名称 基于当前提交创建新分支

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[student@workstation ~ (master #%)]$ git clone https://git.lab.example.com/student/develop-git.git
[student@workstation ~ (master #%)]$ cd develop-git/
[student@workstation develop-git (main)]$ echo "new file" > newfile.txt
[student@workstation develop-git (main %)]$ git add .
[student@workstation develop-git (main +)]$ git commit -m 'new file commit'

# 查看当前分支名称
[student@workstation develop-git (main)]$ git branch
* main

# 创建分支 * 标识当前分支
[student@workstation develop-git (main)]$ git branch test-branch
[student@workstation develop-git (main)]$ git branch
test-branch
* main

切换分支

当我们创建好分支后 * 仍然指向当前的分支,切换到新分支用命令 git checkout

1
2
3
4
[student@workstation develop-git (main)]$ git checkout test-branch
[student@workstation develop-git (main)]$ git branch
* test-branch
main

这时就可以使用新分支了

git checkout-b 选项会创建并切换到新分支。相当于 git branch xxx && git checkout xxx

1
2
3
4
[student@workstation develop-git (main)]$ git checkout -b test-branch
[student@workstation develop-git (test-branch)]$ git branch]
* test-branch
main

合并分支

在分支上完成工作后,需要合并到主分支中。这样可以并行操作新功能和漏洞修复,保持主分支的代码是最新的且经过测试。​

合并分支示例 需要添加

从之前的提交创建分支

现在我们可以了解到, git的分支是基于某个提交创建的,我们的git 会记录每次提交的历史记录。这就是表示,我可以通过任意一次提交来创建新的分支。

当我们的 HEAD 指针不在指向某个分支,而是执行某次提交时,会出现 Dteached HEAD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看提交记录
$ git log

# 通过 log 中的 commit 哈希来切换到某次提交
# 会出现 detached HEAD
$ git checkout commit-hash

# 用当前指向的提交来创建新分支
$ git checkout -b version-1

# 查看分支列表
$ git branch
* version-1
main

将分支推送到远程存储库

本地创建的分支仅存与本地存储库中,远程存储库并没有这个分支的信息。
git push --set-upstream origin <branch-name> 这条命令会将 branch-name 分支推送到远程存储库并做关联。以后在 branch-name 分支上执行 pushpull 命令时,Git 会自动推送或拉取远程 barch-name 分支。

1
2
3
4
5
# 切换分支
[user@host ~]$ git checkout feature/3

# 将分支推送到远程存储库
[user@host ~]$ git push --set-upstream origin feature/3

origin 是远程存储库的名称。执行成功后,会在远程 origin 仓库中创建 feature/3 分支。

在 Git 中构建 Ansible 项目

在 Git 中构建一个 Ansible 项目,需要遵循以下目录结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
site.yml                  # main playbook
webservers.yml # playbook for webserver tier
dbservers.yml # playbook for dbserver tier

collections/ # 放模块、集合
requirements.yml # 指定此项目使用的集合或角色

roles/ # 存放角色目录
common/ # this hierarchy represents a "role"
tasks/ #
main.yml # <-- tasks file can include smaller files if warranted
handlers/ #
main.yml # <-- handlers file
templates/ # <-- files for use with the template resource
ntp.conf.j2 # <------- templates end in .j2
files/ #
bar.txt # <-- files for use with the copy resource
myscript.sh # <-- script files for use with the script resource
vars/ #
main.yml # <-- variables associated with this role
defaults/ #
main.yml # <-- default lower priority variables for this role
meta/ #
main.yml # <-- role dependencies

角色和 Ansible 内容集合

Ansible 模块、集合存放在 collections 目录下,角色 存放在 roles 目录下。这两个目录中的一个或两个中可能还有一个 requirements.yml 文件,​用于指定此项目使用的集合或角色,​可以根据需要使用 ansible-galaxy 命令来下载。​
自动化控制器根据 Ansible 项目中包含的 roles/requirements.yml 和 collections/requirements.yml 文件,​使用角色和集合来自动更新项目。

配置 Git 以忽略文件

并不是所有在 git 项目中的文件都需要被 git 跟踪。
例如,​ansible-navigator 命令可生成或更新 ansible-navigator.log 文件,​在每次运行 playbook 时创建构件文件,​并且创建 .ssh 目录。​这些临时文件都不应提交到 Git 存储库。​
git 可以配置排除项来忽略这些不需要管理的文件。​

在项目的根目录下创建 .gitignore 文件,并配置排除项。
.gitignore 文件每一行代表一个匹配模式

  • 与文件名匹配的行表示 Git 忽略的文件。
  • 以感叹号 (!) 开头的行表示 Git 不应忽略的文件,​即使它们之前匹配为忽略。
  • ​所有以 # 开头的行都是注释。
  • 允许使用空行来提高可读性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 忽略 roles 目录下的所有文件
roles/**

# 不应该忽略 roles/requirements.yml
!roles/requirements.yml

# 忽略 collections 目录下的 ansible_collections 目录
collections/ansible_collections

# 忽略任何名为 ansible-navigator.log 的文件
ansible-navigator.log

# 忽悠文件名中包含 -artifact- 的所有文件
*-artifact-*

# 忽略 .ssh 目录
.ssh