尝试使用Ansible部署Tomcat容器

Ansible是什么?

Ansible是一种用于自动化配置管理、操作系统和软件设置的工具。从Ansible服务器连接到管理目标服务器,并执行部署操作。部署使用名为Playbook的YAML格式指令文件。

本次所构成的环境

Untitled.png

大致的流程如下:
1. 安装Ansible
2. 创建和分发密钥对
3. 创建清单文件
4. 创建Dockerfile
5. 创建Playbook
6. 执行Playbook
7. 进行操作确认

服务器环境如下:
Ansible服务器:RHEL8.2
管理目标服务器:RHEL8.2

在RHEL8中,管理用户将使用普通用户而不是root用户。此外,容器引擎将使用Podman而不是Docker。

安装Ansible

Ansible是一个用Python编写的应用程序,安装使用pip而不是dnf(yum)。Python可以使用2.x和3.x版本,但这次我想使用3.x版本进行安装。

我要安装pip。

$ sudo yum install python3-pip

使用安装的pip工具来安装Ansible。
为了将Ansible的使用用户更改为常规用户(ec2-user),我们将使用–user选项。

$ pip3 install ansible --user
$ ansible --version
ansible 2.10.5
  config file = None
  configured module search path = ['/home/ec2-user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ec2-user/.local/lib/python3.6/site-packages/ansible
  executable location = /home/ec2-user/.local/bin/ansible
  python version = 3.6.8 (default, Aug 18 2020, 08:33:21) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]

一切顺利完成了安装。

创建和分发密钥对

为了通过SSH通信进行部署,Ansible会预先向受管服务器分发公钥,以实现在SSH通信中无需密码的连接。

首先,使用ssh-keygen命令创建密钥对。

$ ssh-keygen -t rsa

生成将会产生私钥id_rsa和公钥id_rsa.pub。

$ ls -l /home/ec2-user/.ssh/
total 12
-rw-------. 1 ec2-user ec2-user  388 Feb 11 04:11 authorized_keys
-rw-------. 1 ec2-user ec2-user 2655 Feb 11 04:19 id_rsa
-rw-r--r--. 1 ec2-user ec2-user  611 Feb 11 04:19 id_rsa.pub

将公钥添加到管理服务器。
虽然可以使用带有密码的SSH通信在管理服务器上进行SCP或SSH分发,但由于这次刚刚创建了EC2实例,所以只能使用通过下载私钥文件进行SSH通信的方式。
我认为在EC2实例上放置私钥文件在安全上是不可取的,因此我决定直接使用Teraterm连接到管理服务器,并将先前创建的id_rsa内容直接添加到authorized_keys中。
如果考虑到完全自动化的部署,如AutoScaling等,这些事情需要认真考虑。
我认为考虑采用在EC2实例启动时下载保存在S3中的公钥的方法是不错的。

这次将跳过手动注册公钥的步骤。
请注册完公钥后先进行一次SSH连接,以更新known_hosts文件。
如果不进行known_hosts文件的注册,似乎在执行ansible命令时会因为需要注册指纹而导致处理失败。

创建库存文件

创建用于定义 Ansible 受管服务器的清单文件。

$ mkdir /home/ec2-user/ansible
$ cd /home/ec2-user/ansible

我创建了一个名为”hosts”的清单文件。
内容如下:

[tomcatservers]
172.31.44.229
172.31.34.31

172.31.XX.XX是管理服务器的私有IP地址。
我们将两台管理服务器归属于名为tomcatservers的组。

为了确认成功创建了清单文件,我们尝试执行Ansible的ping模块。

$ ansible -u ec2-user -i /home/ec2-user/ansible/hosts tomcatservers -m ping
172.31.34.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}
172.31.44.229 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/libexec/platform-python"
    },
    "changed": false,
    "ping": "pong"
}

如果收到了”pong”的响应,则表示通信成功。

编写Dockerfile

我們接下來將創建一個Dockerfile,用於在管理服務器上分發。
這次我們創建Dockerfile是為了在容器啟動時下載sample.war文件。

以下是创建Dockerfile的内容:

FROM docker.io/library/tomcat
RUN cd /usr/local/tomcat/webapps && wget http://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war

创建Playbook

Playbook中定义的任务如下:
1. 安装podman
2. 分发Dockerfile
3. 构建Docker镜像
4. 启动Docker容器

在Docker容器启动时,将根据Dockerfile定义的指令下载示例应用程序,并进行应用程序构建。

具体的的Playbook(tomcat.yml)的内容如下。

- hosts: tomcatservers
  remote_user: ec2-user

  tasks:
  - name: install podman
    yum:
      name: podman
      state: present
    become: yes
  - name: copy Dockerfile
    copy:
      src: /home/ec2-user/ansible/Dockerfile
      dest: /home/ec2-user
  - name: build image
    command: podman build -t tomcat:1 /home/ec2-user
    notify:
    - run container
  handlers:
  - name: run container
    command: podman run -d -p 8081:8080 tomcat:1

为了仅在管理员权限下安装Podman,我们使用”become: yes”进行指定。(类似于sudo执行)

执行Playbook

执行已创建的Playbook。

$ ansible-playbook -i /home/ec2-user/ansible/hosts /home/ec2-user/ansible/tomcat.yml

PLAY [tomcatservers] ***************************************************************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************************************************************
ok: [172.31.34.31]
ok: [172.31.44.229]

TASK [install podman] **************************************************************************************************************************************************
changed: [172.31.34.31]
changed: [172.31.44.229]

TASK [copy Dockerfile] *************************************************************************************************************************************************
changed: [172.31.34.31]
changed: [172.31.44.229]

TASK [build image] *****************************************************************************************************************************************************
changed: [172.31.34.31]
changed: [172.31.44.229]

RUNNING HANDLER [run container] ****************************************************************************************************************************************
changed: [172.31.34.31]
changed: [172.31.44.229]

PLAY RECAP *************************************************************************************************************************************************************
172.31.34.31               : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
172.31.44.229              : ok=5    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

确认动作

在Ansible服务器上使用curl命令来运行示例应用程序。
别忘记在AWS安全组中允许8081端口。

$ curl -XGET http://172.31.34.31:8081/sample/
<html>
<head>
<title>Sample "Hello, World" Application</title>
</head>
<body bgcolor=white>

<table border="0">
<tr>
<td>
<img src="images/tomcat.gif">
</td>
<td>
<h1>Sample "Hello, World" Application</h1>
<p>This is the home page for a sample application used to illustrate the
source directory organization of a web application utilizing the principles
outlined in the Application Developer's Guide.
</td>
</tr>
</table>

<p>To prove that they work, you can execute either of the following links:
<ul>
<li>To a <a href="hello.jsp">JSP page</a>.
<li>To a <a href="hello">servlet</a>.
</ul>

</body>
</html>
$ curl -XGET http://172.31.44.229:8081/sample/
<html>
<head>
<title>Sample "Hello, World" Application</title>
</head>
<body bgcolor=white>

<table border="0">
<tr>
<td>
<img src="images/tomcat.gif">
</td>
<td>
<h1>Sample "Hello, World" Application</h1>
<p>This is the home page for a sample application used to illustrate the
source directory organization of a web application utilizing the principles
outlined in the Application Developer's Guide.
</td>
</tr>
</table>

<p>To prove that they work, you can execute either of the following links:
<ul>
<li>To a <a href="hello.jsp">JSP page</a>.
<li>To a <a href="hello">servlet</a>.
</ul>

</body>
</html>

确认无事sample应用程序已经成功运行。

广告
将在 10 秒后关闭
bannerAds