Jenkins 是目前最流行的 CI/CD(持续集成和持续部署)工具之一。它在技术社区中广受喜爱,因为它是免费、开源且自托管的。您可能有很多原因想要部署 Jenkins 服务器,例如构建个人项目、练习使用该软件、用于公司生产用途等。 无论出于何种原因,有一点是肯定的:使用 Ansible 部署您的服务器将使该过程自动化、可重复、可重用、可版本控制和可共享。今天,我们将逐步了解如何创建一个 Ansible playbook,将 Jenkins 部署到远程服务器,并配有免费的 Letsencrypt SSL 证书(会自动续订)。
iTip+
我已经将该项目的整个代码库上传到 这里的 Github 上。
让我们开始吧 🚀
1. 获取远程服务器
在服务器上部署 Jenkins 的第一步是获取服务器本身。可以从许多不同的地方配置远程服务器。诸如 DigitalOcean、Google Cloud、AWS 等云提供商提供了市场上最具成本效益的 VPS(虚拟专用服务器)计划。 根据您的需求,您可以手动或通过 IaC(基础设施即代码)从这些提供商中的任何一个配置服务器。
iTip+
出于本教程的目的,请确保在配置服务器实例时使其能够访问公共互联网(因此需要一个公共 IPv4 地址)。
iTip+
通过专用用户在节点上运行 ansible 命令被认为是一种最佳实践。为了帮助加快创建具有 Ansible 适当权限的专用用户的过程,请使用以下 userdata 启动脚本来启动您的 VPS。
#cloud-config
ssh_pwauth: false
users:
- name: ansible
gecos: Ansible User
groups: users,admin,wheel
sudo: ALL=(ALL) NOPASSWD:ALL
shell: /bin/bash
lock_passwd: true
ssh_authorized_keys:
- "ssh-public-key"将 "ssh-public-key" 替换为连接到您服务器的适当的 SSH 公钥。
2. 为 Ansible 进行设置
在深入创建我们的 Playbook 之前,我们需要设置一些东西以确保我们的工作流程能够成功。
2.1 验证与远程服务器的 SSH 连接
Ansible 通过 SSH 连接到节点服务器。由于本教程我们只处理单个服务器,我们需要最初手动连接到它,以验证连通性。
iTip+
部署 VPS 过程的一部分是为其设置 SSH 访问。无论您在哪里部署 VPS,您都应该能够访问用于与服务器进行 SSH 连接的私钥文件。
使用以下命令启动与服务器的 SSH 连接
ssh -i location/to/keyfile username@server_ip iTip+
请确保将您的 SSH 私钥安全地存储在您的 Ansible 主机上,并记录其位置,因为它将在下一步中用于授予 Ansible 访问您的 VPS 的权限。
2.2 为我们的 Jenkins 域名设置 DNS 记录
为了确保从适当的域名访问您的 Jenkins 服务器,您需要将您的域名指向您服务器的 IP 地址。这可以通过创建 DNS 的 A record 来实现。这可以通过各种不同的方式(通过各种接口)完成,具体取决于负责您域名的域名服务。具体细节超出了本教程的范围。
iWarning+
如果没有设置正确的 DNS 记录,您的 Playbook 将无法为您的 Jenkins 服务器颁发 SSL,因为 Certbot(用于颁发证书的客户端)将无法验证您控制着要为其颁发 SSL 证书的域。这将导致您的部署失败,因此请确保设置适当的 DNS 记录。
2.3 创建 Ansible 配置文件
为了正常工作,Ansible 需要配置一些重要的东西。我们在 ansible.cfg 文件中执行此操作。Ansible 在执行之前会自动查找此文件,以找到其运行所需的重要内容。我们的 ansible.cfg 文件将包含以下内容。
[defaults]
inventory = inventory.txt
private_key_file = key.txt
remote_user = ansible此文件配置了以下重要内容:
- 它告诉 Ansible 我们的清单文件(列出我们希望 ansible 管理的所有服务器地址的文件)是一个名为
inventory.txt的文件,并且在当前目录中找到。 - 它告诉 ansible,用于主机 SSH 连接的私钥文件是一个名为
key.txt的文件,同样位于当前目录中。 - 它配置用于服务器 SSH 连接的用户名
ansible。如果您使用前面提供的 cloud-init 脚本配置了服务器,就会是这种情况。如果没有,请随时将此值更改为您的实际username。
iTip+
为了保持与此配置一致,您应该将用于连接到服务器的 SSH 私钥文件存储在当前目录中名为 key.txt 的文件中,以便 Ansible 能够找到它。
iWarning+
请记住,不要将您的 key.txt 文件签入版本控制。特别是 Github 上的公共存储库。
验证了与服务器的 SSH 连接、设置了适当的 DNS 记录并创建了配置文件后,您就可以创建您的 Playbook 了。
3. 创建 Playbook
是时候创建您的 Ansible Playbook 了。为了保持我们的解决方案简单和模块化,我们将使用 Ansible 角色 (roles)。以下是达到我们期望结果的步骤摘要:
- 为 Jenkins 设置 Nginx 代理
- 为我们的服务器获取 SSL 证书
- 安装 Jenkins
现在来看代码:
---
- hosts: all
become: true
roles:
- nginx-proxy
- hosts: all
become: true
roles:
- certbot
- hosts: all
become: true
roles:
- jenkins4. 创建随附的角色
接下来,您需要为工作流的不同方面创建角色。 您的角色的目录结构应如下所示:
4.1 在 nginx-proxy 角色内部
创建一个 tasks/mail.yml 文件
包含以下内容:
- name: Install NginX
tags: nginx,install
ansible.builtin.apt:
name: nginx
state: latest
update_cache: true
- name: Enable NginX
ansible.builtin.service:
name: nginx
enabled: true
- name: Config Jenkins Proxy
ansible.builtin.template:
src: "jenkins-proxy.j2"
dest: /etc/nginx/sites-available/jenkins-proxy.conf
owner: root
group: root
mode: 0644
notify: restart_nginx
- name: Enable Proxy
ansible.builtin.file:
src: /etc/nginx/sites-available/jenkins-proxy.conf
dest: /etc/nginx/sites-enabled/jenkins-proxy.conf
state: link
notify: restart_nginx创建一个 handlers/mail.yml 文件
包含以下内容:
- name: restart_nginx
ansible.builtin.service:
name: nginx
state: restarted创建一个 templates/jenkins-proxy.j2 文件
包含以下内容:
server {
listen 80; # Port for incoming traffic (e.g., 80 for HTTP, 443 for HTTPS)
server_name {{ server_name }}; # Your domain name or IP address
# Location block for handling proxied requests
location / {
proxy_pass {{ jenkins_localhost }}; # Upstream server address (e.g., http://127.0.0.1:8080)
# Optional settings:
proxy_set_header Host $host; # Preserve host header for upstream server
proxy_set_header X-Real-IP $remote_addr; # Forward client IP address
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Forward proxy chain
# Additional settings as needed (e.g., caching, rewrites)
}
}
4.2 在 certbot 角色内部
创建一个 tasks/mail.yml 文件
包含以下内容:
- name: Install Snapd
ansible.builtin.apt:
name: snapd
state: latest
- name: Install Certbot
community.general.snap:
name: certbot
classic: true
state: present
- name: Create symlink
ansible.builtin.file:
src: /snap/bin/certbot
dest: /usr/bin/certbot
state: link
- name: Run certbot
ansible.builtin.shell:
cmd: certbot --nginx -n --agree-tos --email {{ server_email }} --domains {{ server_name }}4.3 在 jenkins 角色内部
创建一个 tasks/mail.yml 文件
包含以下内容:
- name: Install JDK
ansible.builtin.apt:
pkg:
- fontconfig
- openjdk-17-jre
- name: Get Jenkins Repo Key
ansible.builtin.get_url:
url: https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
dest: /usr/share/keyrings/jenkins-keyring.asc
- name: Set Jenkins Source
ansible.builtin.lineinfile:
path: /etc/apt/sources.list.d/jenkins.list
line: deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/
create: yes
- name: Install Jenkins
ansible.builtin.apt:
name: jenkins
state: present
update_cache: true
- name: Enable Jenkins
ansible.builtin.service:
name: jenkins
enabled: true5. 配置 Jenkins 调试输出
在您第一次设置 Jenkins 服务器时,为了开始使用 Web UI,您必须从 Jenkins 服务器上的一个文件中检索一个密钥,以证明您控制着该服务器。我们可以检索这个密钥,并通过在我们的 role/jenkins/tasks/main.yml 文件中添加以下行,让 Ansible 将其输出给我们:
- name: Check Jenkins Status
ansible.builtin.shell:
cmd: systemctl status jenkins
register: check_jens
- name: Debug
debug:
msg: "{{ check_jens.stdout_lines }}"iTip+
此添加将打印以下命令的值:
systemctl status jenkins6. 部署您的 playbook
这就是您部署 Playbook 并让 Jenkins 为您自动设置的地方。要部署您的 Playbook,您必须为我们角色中定义的 3 个变量提供适当的值。
{{jenkins_localhost}}变量指向 Jenkins 的 localhost 地址。这通常是http://localhost:8080{{server_name}}变量提供了要访问 Jenkins 服务器的域名。这是您之前为其设置 DNS 记录的域。{{server_email}}变量提供了服务器管理员的电子邮件地址(这是必需的)。
iTip+
您可以选择以多种不同的方式为这些变量提供值。您可以在运行时提供它们,在这种情况下,您将使用以下命令部署您的 Playbook:
ansible-playbook --extra-vars "server_name=domain-name jenkins_localhost=http://127.0.0.1:8080
server_email=email" playbook.yml 将 domain-name 和 email 替换为适当的值。
下面是一个例子:
ansible-playbook --extra-vars "server_name=jen.obimadu.pro
jenkins_localhost=http://127.0.0.1:8080
server_email=hello@obimadu.pro" playbook.yml有关提供变量值的其他方法,请访问 Using Variables
就是这样 🎉 🎉 您现在拥有一种完全自动化的方式来部署(和/或重新部署)您的 Jenkins 服务器!
继续阅读
Self Hosting 项目 (从零开始的 DevOps 基础设施)
使用 Terraform、Ansible 和 Docker 从零开始构建自托管 DevOps 基础设施的全面指南。
通过 Github Pull Requests、Actions、Bot、Environments 和远程后端(Remote Backend)协作实现 Terraform 核心工作流。
使用 GitHub Actions、pull requests 和远程后端为生产团队实现协作式 Terraform 工作流。
通过 Terraform 在 Digital Ocean 上部署服务器 (指南)
使用 Terraform 和基本的“基础设施即代码”(IaC) 实践来配置 DigitalOcean droplet 的分步指南。
