Ansible 是一个非常灵活的自动化工具,可以轻松地用于自动化基础架构的任何方面。在过去几年中,基于容器的工作负载和云工作负载变得越来越流行,因此,我们将研究如何使用 Ansible 自动化与这些工作负载相关的任务。在本章中,我们将从使用 Ansible 设计和构建容器开始。然后,我们将研究如何运行这些容器,最后,我们将研究使用 Ansible 管理各种云平台的方法。
具体来说,我们将在本章中讨论以下主题:
- 使用行动手册设计和构建容器
- 管理多个容器平台
- 用 Ansible 实现码头工人自动化
- 探索以容器为中心的模块
- 针对亚马逊网络服务的自动化
- 用自动化补充谷歌云平台
- 无缝自动化集成到 Azure
- 借助 Rackspace 云扩展您的环境
- 使用 Ansible 编排 OpenStack
我们开始吧!
本章假设您已经使用 Ansible 设置了您的控制主机,详见第 1 章、ansi ble 入门,并且正在使用最新的可用版本-本章中的示例已使用 Ansible 2.9 进行了测试。虽然我们将在本章中给出主机名的具体示例,但是您可以用自己的主机名和/或 IP 地址来替换它们。如何做到这一点的细节将在适当的地方提供。本章还假设您可以访问 Docker 主机,尽管可以在大多数(如果不是全部的话)操作系统上安装 Docker,但本章中提供的所有命令都是针对 GNU/Linux 的,并且仅在该平台上进行了测试。
本章中的所有示例都可以在本书的 GitHub 资源库中找到,网址为https://GitHub . com/PacktPublishing/Practical-ansi ble-2/tree/master/Chapter % 2010。
用 Dockerfiles 构建容器可能是最常见的方法,但这并不意味着这是最好的方法。
首先,即使您处于自动化道路上的一个非常好的位置,并且您有许多为您的基础架构编写的 Ansible 角色,您也不能在 Dockerfiles 中利用它们,因此您最终会复制您的工作来创建容器。除了完成这项工作所需的时间,以及您需要学习一门新语言来完成这项工作的事实之外,一家公司能够在一夜之间放弃所有基础架构并切换到容器是非常罕见的。这意味着您需要保持同一个自动化部分的两个副本是活动的和最新的,从而使您自己处于犯错的位置,并且在不同的环境之间有不一致的行为。
如果这还不足以解决问题,那么当您开始考虑云环境时,这种情况会迅速恶化。所有云环境都有自己的控制平面和本地自动化语言,因此在很短的时间内,您会发现自己一遍又一遍地为相同的操作重写自动化,从而浪费时间并降低环境的一致性。
Ansible 提供了ansible-container
,这样您就可以使用与创建机器相同的组件来创建容器。你要做的第一件事就是确保你已经安装了ansible-container
。有几种方法可以安装它,但最直接的是使用pip
。为此,您可以运行以下命令:
$ sudo pip install ansible-container[docker,k8s]
ansible-container
工具在编写时附带了三个受支持的引擎:
docker
:如果你想和 Docker Engine 一起使用(也就是在你的本地机器上),这是需要的。k8s
:如果您想将其用于本地(即 MiniKube)或远程(即生产集群)的 Kubernetes 集群,这是必需的。openshift
:如果您想将其用于 OpenShift 集群,无论是本地集群(即 MiniShift)还是远程集群(即生产集群),这都是需要的。
按照以下步骤使用行动手册构建容器:
- 发出
ansible-container init
命令将给出如下输出:
$ ansible-container init
Ansible Container initialized.
运行此命令还将创建以下文件:
- 让我们尝试使用此工具构建我们自己的容器–用以下内容替换
container.yml
的内容:
version: "2"
settings:
conductor:
base: centos:7
project_name: http-server
services:
web:
from: "centos:7"
roles:
- geerlingguy.apache
ports:
- "80:80"
command:
- "/usr/bin/dumb-init"
- "/usr/sbin/apache2ctl"
- "-D"
- "FOREGROUND"
dev_overrides:
environment:
- "DEBUG=1"
我们现在可以运行ansible-container build
来启动构建。
在构建过程的最后,我们将构建一个应用了geerlingguy.apache
角色的容器。ansible-container
工具执行多阶段构建功能,构建一个 Ansible 容器,然后用于构建真正的容器。
如果我们指定了多个要应用的角色,输出将是一个具有更多层的映像,因为 Ansible 将为每个指定的角色创建一个层。通过这种方式,可以使用现有的 Ansible 角色而不是 Dockerfiles 轻松构建容器。
既然您已经学习了如何使用行动手册设计和构建容器,那么您将学习如何管理多个容器平台。
在当今世界,仅仅能够运行一个映像并不被认为是一个生产就绪的设置。
为了能够将部署称为“生产就绪”,您需要能够证明您的应用正在提供的服务将合理运行,即使是在单个应用崩溃以及硬件故障的情况下。通常,您会受到客户更多的可靠性限制。
幸运的是,您的软件并不是唯一有这些需求的数据,因此已经为此目的开发了编排解决方案。
今天,最成功的是 Kubernetes,因为它有各种发行版/版本,所以我们将主要关注它。
Kubernetes 的想法是,您通知 Kubernetes 控制平面您想要 X 个您的 Y 应用的实例,Kubernetes 将计算在 Kubernetes 节点上运行的 Y 应用的实例数量,以确保实例数量为 X 个。如果实例太少,Kubernetes 将注意启动更多的实例,而如果实例太多,将停止超过的实例。
由于 Kubernetes 不断检查请求数量的实例是否正在运行,因此在应用故障或节点故障的情况下,Kubernetes 将重新启动丢失的实例。
由于安装和管理 Kubernetes 的复杂性,多家公司已经开始销售 Kubernetes 的发行版,这些发行版简化了他们的操作,并且他们愿意提供支持。
目前最广泛使用的发行版是 OpenShift:红帽 Kubernetes 发行版。
为了简化开发人员和操作团队的生活,Ansible 提供了ansible-container
,正如我们在上一节中看到的,它是一个用来创建容器的工具,同时也支持容器本身的整个生命周期。
让我们学习如何运行我们刚刚用ansible-container
构建的映像。
首先,我们需要映像本身,你应该有它,因为这是前一节的输出!
我们将假设您可以访问 Kubernetes 或 OpenShift 集群进行测试。设置这些不在本书的讨论范围之内,因此您可能想看一下 Minikube 或 Minishift 之类的发行版,这两种发行版都旨在快速轻松地进行设置,以便您可以快速开始学习这些技术。我们还需要有kubectl
客户端或oc
客户端,基于我们已经部署了 Kubernetes 或 OpenShift 的事实,进行适当的配置。让我们开始吧:
- 要将您的应用部署到您的集群,您需要更改
container.yml
文件,以便可以添加一些附加信息。更具体地说,我们需要添加一个名为settings
的部分和一个名为k8s_namespace
的部分来声明我们的部署设置。这个部分看起来像这样:
k8s_namespace:
name: http-server
description: An HTTP server
display_name: HTTP server
- 现在我们已经添加了关于 Kubernetes 部署的必要信息,我们可以继续部署了:
$ ansible-container --engine kubernetes deploy
一旦 Ansible 完成了它的执行,您将能够在您的 Kubernetes 集群上找到http-server
部署。
幕后发生的是,Ansible 有一组用于驱动 Kubernetes 集群的模块(其名称通常以k8s
开头),它使用这些模块自动部署应用。
基于我们在上一节中构建的映像和我们在本节开头添加的附加信息,Ansible 能够填充一个部署模板,然后使用k8s
模块进行部署。
既然您已经学习了如何在 Kubernetes 集群上部署您的容器,那么您将学习如何使用 Ansible 与 Kubernetes 集群进行交互。
现在您已经用ansible-container
部署了第一个应用,与这个应用交互将会很有用。它可以方便地获取关于 Kubernetes 对象状态的信息,或者向其部署应用,更一般地说,无需ansible-containers
即可与 Kubernetes APIs 交互。
首先需要安装 Python openshift
包(可以通过 pip 安装,也可以通过你的 OS 打包系统安装)。
我们现在准备好了我们的第一本库本内斯剧本!
一个 Kubernetes 集群内部有多个名称空间,你通常可以用kubectl get namespaces
找到一个集群拥有的名称空间。通过创建一个名为k8s-ns-show.yaml
的文件,您可以对 Ansible 执行同样的操作,该文件包含以下内容:
---
- hosts: localhost
tasks:
- name: Get information from K8s
k8s_info:
api_version: v1
kind: Namespace
register: ns
- name: Print info
debug:
var: ns
我们现在可以执行如下操作:
$ ansible-playbook k8s-ns-show.yaml
现在,您将在输出中看到关于名称空间的信息。
请注意,在代码的第七行(kind: Namespace
),我们正在指定我们感兴趣的资源类型。您可以指定其他 Kubernetes 对象类型来查看它们(例如,您可以尝试使用部署、服务和 Pods)。
到目前为止,我们已经学习了如何显示现有的名称空间,但是通常情况下,Ansible 是以声明的方式使用的,以实现所需的状态。因此,让我们创建一个名为k8s-ns.yaml
的新剧本,其内容如下:
---
- hosts: localhost
tasks:
- name: Ensure the myns namespace exists
k8s:
api_version: v1
kind: Namespace
name: myns
state: present
在运行它之前,我们可以执行kubectl get ns
,这样我们就可以确保myns
不存在。在我的例子中,输出如下:
$ kubectl get ns
NAME STATUS AGE
default Active 69m
kube-node-lease Active 69m
kube-public Active 69m
kube-system Active 69m
我们现在可以使用以下命令运行行动手册:
$ ansible-playbook k8s-ns.yaml
输出应该类似于以下内容:
PLAY [localhost] *******************************************************************
TASK [Gathering Facts] *************************************************************
ok: [localhost]
TASK [Ensure the myns namespace exists] ********************************************
changed: [localhost]
PLAY RECAP *************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如您所见,Ansible 报告它更改了命名空间状态。如果我再次执行kubectl get ns
,很明显 Ansible 创建了我们期望的命名空间:
$ kubectl get ns
NAME STATUS AGE
default Active 74m
kube-node-lease Active 74m
kube-public Active 74m
kube-system Active 74m
myns Active 22s
现在,让我们创建一个服务。
到目前为止,我们已经看到了如何从 Ansible 创建名称空间,所以现在,让我们在刚刚创建的名称空间中放置一个 Service。让我们创建一个名为k8s-svc.yaml
的新剧本,内容如下:
---
- hosts: localhost
tasks:
- name: Ensure the Service mysvc is present
k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: mysvc
namespace: myns
spec:
selector:
app: myapp
service: mysvc
ports:
- protocol: TCP
targetPort: 800
name: port-80-tcp
port: 80
在运行它之前,我们可以执行kubectl get svc
来确保命名空间没有服务。在运行它之前,请确保您在正确的命名空间中!在我的例子中,输出如下:
$ kubectl get svc
No resources found in myns namespace.
我们现在可以使用以下命令运行它:
$ ansible-playbook k8s-svc.yaml
输出应该类似于以下内容:
PLAY [localhost] *******************************************************************
TASK [Gathering Facts] *************************************************************
ok: [localhost]
TASK [Ensure the myns namespace exists] ********************************************
changed: [localhost]
PLAY RECAP *************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如您所见,Ansible 报告它更改了服务状态。如果我再次执行kubectl get svc
,很明显 Ansible 创建了我们期望的服务:
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
mysvc ClusterIP 10.0.0.84 <none> 80/TCP 10s
如您所见,我们遵循了在名称空间案例中使用的相同过程,但是我们指定了不同的 Kubernetes 对象类型,并指定了服务类型所需的各种参数。您可以对所有其他 Kubernetes 对象类型执行相同的操作。
既然您已经学习了如何处理 Kubernetes 集群,那么您将学习如何使用 Ansible 自动处理 Docker。
Docker 现在是一个非常常见且无处不在的工具。在生产中,它通常由一个指挥者管理(或者至少在大多数情况下应该如此),但是在开发中,环境通常被直接使用。
使用 Ansible,您可以轻松管理您的 Docker 实例。
由于我们要管理一个 Docker 实例,我们需要确保手头有一个,并且机器上的docker
命令配置正确。我们需要这样做,以确保这足以在终端上运行docker images
。假设您得到类似以下的结果:
REPOSITORY TAG IMAGE ID CREATED SIZE
这意味着一切工作正常。如果您已经克隆了映像,可能会提供更多行作为输出。
另一方面,假设它返回如下内容:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
这意味着我们没有运行 Docker 守护程序,或者我们的 Docker 控制台配置不正确。
此外,确保您拥有docker
Python 模块也很重要,因为 Ansible 将尝试使用它与 Docker 守护程序进行通信。让我们来看看:
- 首先,我们需要创建一个名为
start-docker-container.yaml
的剧本,它将包含以下代码:
---
- hosts: localhost
tasks:
- name: Start a container with a command
docker_container:
name: test-container
image: alpine
command:
- echo
- "Hello, World!"
- 现在我们有了 Ansible 行动手册,我们只需要执行它:
$ ansible-playbook start-docker-container.yaml
如您所料,它会给您一个类似如下的输出:
PLAY [localhost] *********************************************************************
TASK [Gathering Facts] ***************************************************************
ok: [localhost]
TASK [Start a container with a command] **********************************************
changed: [localhost]
PLAY RECAP ***************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
- 我们现在可以检查我们的命令是否正确执行,如下所示:
$ docker container list -a
这将显示运行的容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c706ec55fc0d alpine "echo Hello, World!" 3 minutes ago Exited (0) About a minute ago test-container
这证明一个容器被执行了。
要检查echo
命令是否被执行,我们可以运行以下代码:
$ docker logs c706ec55fc0d
这将返回以下输出:
Hello, World!
在本节中,我们执行了docker_container
模块。这不是 Ansible 必须控制 Docker 守护程序的唯一模块,但它可能是最广泛使用的模块之一,因为它用于控制在 Docker 上运行的容器。
其他模块包括:
docker_config
:用于更改 Docker 守护程序的配置docker_container_info
:用于收集(检查)集装箱的信息docker_network
:用于管理 Docker 网络配置
也有许多模块以docker_
开始,但实际上用于管理 Docker Swarm 集群,而不是 Docker 实例。一些例子如下:
docker_node
:用于管理 Docker Swarm 集群中的节点docker_node_info
:用于检索 Docker Swarm 集群中特定节点的信息docker_swarm_info
:用于检索码头工人集群的信息
正如我们将在下一节中看到的,有更多的模块可以用来管理以各种方式编排的容器。
现在,您已经学习了如何使用 Ansible 自动化 Docker,您将探索以容器为中心的模块。
通常,当组织成长时,他们开始在组织的不同部分使用多种技术。另一个经常发生的事情是,在一个部门发现一个供应商对他们很好之后,他们会更倾向于尝试这个供应商提供的新技术。这两个因素和时间的混合(通常,更少的技术周期)将最终为同一组织内的同一问题创建多个解决方案。
如果您的组织正处于这种使用容器的情况下,由于 Ansible 能够与大多数(如果不是全部的话)容器平台进行互操作,因此它可以前来救援。
很多时候,使用 Ansible 做一些事情的最大问题是找到你需要用来实现你想要实现的目标的模块的名称。在本节中,我们将尝试在这方面提供帮助,主要是在容器化空间方面,但这可能会帮助您寻找不同类型的模块。
所有 Ansible 模块研究的起点应该是 module 索引(https://docs . ansi ble . com/ansi ble/latest/modules/modules _ by _ category . html)。很多时候,你可以找到一个类别,显然是一个匹配你正在寻找的,但这并不总是这样。
容器是其中的一个例外(至少在撰写本文时是这样),因此不存在“容器”类别。解决方法是转到所有模块。从这里,您可以使用浏览器的内置功能进行搜索(通常,这可以通过使用 Ctrl + F 来找到可能与包名或简短描述匹配的字符串)。
Ansible 中的每个模块都被归入一个类别,但通常情况下,模块符合多个类别,因此不总是容易找到它们。
例如,许多与容器服务相关的 Ansible 模块属于云模块类别(ECS、Docker、LXC、LXD 和波德曼),而其他模块属于集群模块类别(Kubernetes、OpenShift 等)。
为了进一步帮助您,让我们看看一些主要的容器平台和 Ansible 提供的主要模块。
早在 2014 年,亚马逊网络服务就推出了弹性容器服务 ( ECS ),这是一种在其基础架构内部署和编排 Docker 容器的方式。第二年,亚马逊 Web Services ( AWS )也推出了弹性容器注册 ( ECR ),一个托管的 Docker Registry 服务。这项服务并没有像 AWS 希望的那样变得无处不在,所以在 2018 年,AWS 推出了弹性 Kubernetes 服务 ( EKS )让想在 AWS 上运行 Kubernetes 的人拥有托管服务。如果您正在使用或计划使用 EKS,这只是一个标准的托管 Kubernetes 集群,因此您可以使用我们稍后将介绍的特定于 Kubernetes 的模块。如果您决定使用 ECS,有几个模块可以帮助您。最重要的是ecs_cluster
,可以创建或终止 ECS 集群;ecs_ecr
,可以管理 ECRecs_service
,允许您在 ECS 中创建、终止、启动或停止服务;和ecs_task
,允许您在 ECS 中运行、启动或停止任务。除此之外,还有ecs_service_facts
允许 Ansible 在 ECS 中列出或描述服务。
微软 Azure,2018 年宣布 Azure 容器服务 ( ACS ),之后又宣布 Azure Kubernetes 服务 ( AKS )。这些服务由 Kubernetes 解决方案管理,因此它们都可以用 Kubernetes 模块来管理。除此之外,Ansible 还提供了两个特定的模块:azure_rm_acs
模块允许我们创建、更新和删除 Azure 容器服务实例,而azure_rm_aks
模块允许我们创建、更新和删除 Azure Kubernetes 服务实例。
谷歌云在 2015 年推出了谷歌 Kubernetes 引擎 ( GKE )。GKE 是托管 Kubernetes 的谷歌云平台版本,因此与 Ansible Kubernetes 模块兼容。除此之外,还有各种针对 GKE 的模块,其中一些如下:
gcp_container_cluster
:允许您创建 GCP 集群gcp_container_cluster_facts
:允许您为 GCP 集群收集事实gcp_container_node_pool
:允许您创建 GCP 节点池gcp_container_node_pool_facts
:允许您为 GCP 节点池收集事实
Red Hat 在 2011 年启动了 OpenShift,当时它是基于自己的容器运行时。在 2015 年发布的版本 3 中,它完全基于 Kubernetes,因此所有 Ansible Kubernetes 模块都可以工作。除此之外,还有oc
模块,该模块目前仍然存在,但处于弃用状态,优先于 Kubernetes 模块。
2015 年,谷歌发布了 Kubernetes,很快,一个庞大的社区开始围绕它构建。Ansible 允许您使用一些模块来管理 Kubernetes 集群:
k8s
:允许你管理任何种类的 Kubernetes 对象k8s_auth
:允许您向需要明确登录步骤的 Kubernetes 集群进行身份验证k8s_facts
:允许你检查 Kubernetes 对象k8s_scale
:允许您为部署、复制集、复制控制器或作业设置新的大小k8s_service
:允许您管理 Kubernetes 上的服务
LXC 和 LXD 也是可以用来在 Linux 中运行容器的系统。由于以下模块,Ansible 也支持这些系统:
lxc_container
:允许您管理 LXC 集装箱lxd_container
:允许您管理 LXD 集装箱lxd_profile
:允许您管理 LXD 档案
既然您已经学习了如何探索以容器为中心的模块,那么您将学习如何针对亚马逊网络服务实现自动化。
在许多组织中,云供应商正在被广泛使用,而在其他组织中,他们刚刚被引入。然而,无论如何,你可能不得不处理一些云供应商做你的工作。AWS 是最大和最古老的,也许是你将不得不与之合作的东西。
为了能够使用 Ansible 来自动化你的亚马逊网络服务,你需要安装boto
库。为此,请运行以下命令:
$ pip install boto
现在您已经安装了所有必要的软件,可以设置身份验证了。
boto
库在~/.aws/credentials
文件中查找必要的凭证。有两种不同的方法可以确保凭据文件配置正确。
可以使用 AWS 命令行界面工具。或者,也可以使用您选择的文本编辑器,通过创建具有以下结构的文件来完成此操作:
[default]
aws_access_key_id = [YOUR_KEY_HERE]
aws_secret_access_key = [YOUR_SECRET_ACCESS_KEY_HERE]
现在,您已经使用必要的凭据创建了文件,boto
将能够在您的 AWS 环境中工作。由于 Ansible 在与 AWS 系统的每次通信中使用boto
,这意味着 Ansible 将被适当配置,即使您不必更改任何 Ansible 特定的配置。
现在,Ansible 能够连接到您的 AWS 环境,您可以按照以下步骤继续实际的行动手册:
- 创建包含以下内容的
aws.yaml
行动手册:
---
- hosts: localhost
tasks:
- name: Ensure key pair is present
ec2_key:
name: fale
key_material: "{{ lookup('file', '~/.ssh/fale.pub') }}"
- name: Gather information of the EC2 VPC net in eu-west-1
ec2_vpc_net_facts:
region: eu-west-1
register: aws_simple_net
- name: Gather information of the EC2 VPC subnet in eu-west-1
ec2_vpc_subnet_facts:
region: eu-west-1
filters:
vpc-id: '{{ aws_simple_net.vpcs.0.id }}'
register: aws_simple_subnet
- name: Ensure wssg Security Group is present
ec2_group:
name: wssg
description: Web Security Group
region: eu-west-1
vpc_id: '{{ aws_simple_net.vpcs.0.id }}'
rules:
- proto: tcp
from_port: 22
to_port: 22
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 80
to_port: 80
cidr_ip: 0.0.0.0/0
- proto: tcp
from_port: 443
to_port: 443
cidr_ip: 0.0.0.0/0
rules_egress:
- proto: all
cidr_ip: 0.0.0.0/0
register: aws_simple_wssg
- name: Setup instance
ec2:
assign_public_ip: true
image: ami-3548444c
region: eu-west-1
exact_count: 1
key_name: fale
count_tag:
Name: ws01.ansible2cookbook.com
instance_tags:
Name: ws01.ansible2cookbook.coms
instance_type: t2.micro
group_id: '{{ aws_simple_wssg.group_id }}'
vpc_subnet_id: '{{ aws_simple_subnet.subnets.0.id }}'
volumes:
- device_name: /dev/sda1
volume_type: gp2
volume_size: 10
delete_on_termination: True
- 使用以下命令运行它:
$ ansible-playbook aws.yaml
该命令将返回如下内容:
PLAY [localhost] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [localhost]
TASK [Ensure key pair is present] *****************************************************************
ok: [localhost]
TASK [Gather information of the EC2 VPC net in eu-west-1] *****************************************
ok: [localhost]
TASK [Gather information of the EC2 VPC subnet in eu-west-1] **************************************
ok: [localhost]
TASK [Ensure wssg Security Group is present] ******************************************************
ok: [localhost]
TASK [Setup instance] *****************************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************
localhost : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如果您检查 AWS 控制台,您将看到您现在有一台机器启动并运行!
要在 AWS 中启动虚拟机,我们需要准备一些东西,如下所示:
- 一个 SSH 密钥对
- 网络
- 子网
- 安全小组
默认情况下,您的帐户中已经有一个网络和一个子网,但是您需要检索它们的标识。
这就是为什么我们首先将 SSH 密钥的公共部分上传到 AWS,然后查询网络和子网的信息,然后确保我们想要使用的安全组存在,最后触发机器构建。
现在您已经学习了如何针对亚马逊网络服务进行自动化,您将学习如何用自动化来补充谷歌云平台。
另一个全球云供应商是谷歌,拥有谷歌云平台。谷歌的云方法与其他供应商的方法相对不同,因为谷歌不试图在虚拟环境中模拟数据中心。这是因为谷歌希望重新思考云供应的概念,以简化它。
在开始使用带有 Ansible 的谷歌云平台之前,您需要确保安装了正确的组件。更具体地说,您将需要 Python requests
和google-auth
模块。要安装这些模块,请运行以下命令:
$ pip install requests google-auth
现在您已经有了所有的依赖项,可以开始身份验证过程了。
在谷歌云平台中,有两种不同的方法可以获得一组有效的凭证:
- 服务帐户
- 机器帐户
第一种方法是大多数情况下建议的方法,因为第二种方法仅适用于 Ansible 直接在谷歌云平台环境中运行的情况。
创建服务帐户后,您应该设置以下环境变量:
GCP_AUTH_KIND
GCP_SERVICE_ACCOUNT_EMAIL
GCP_SERVICE_ACCOUNT_FILE
GCP_SCOPES
现在,Ansible 可以使用正确的服务帐户。
第二种方法是迄今为止最简单的,因为如果您在谷歌云实例中运行机器帐户,Ansible 将能够自动检测它。
现在,Ansible 能够连接到您的 GCP 环境,您可以继续实际的行动手册:
- 创建包含以下内容的
gce.yaml
行动手册:
---
- hosts: localhost
tasks:
- name: create a instance
gcp_compute_instance:
name: TestMachine
machine_type: n1-standard-1
disks:
- auto_delete: 'true'
boot: 'true'
initialize_params:
source_image: family/centos-7
disk_size_gb: 10
zone: eu-west1-c
auth_kind: serviceaccount
service_account_file: "~/sa.json"
state: present
使用以下命令执行它:
$ ansible-playbook gce.yaml
这将创建如下所示的输出:
PLAY [localhost] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [localhost]
TASK [create a instance] **************************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
至于 AWS 的例子,使用 Ansible 在云中运行一台机器非常容易。
在 GCE 的情况下,您不需要预先设置网络,因为 GCE 默认值将会生效,并提供一个功能机器。
至于 AWS,你可以使用的模块列表非常庞大。你可以在https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Google找到完整的列表。
现在您已经学习了如何用自动化来补充谷歌云平台,您将学习如何无缝地执行自动化集成到 Azure。
Ansible 可以管理的另一个全球云是微软 Azure。
像 AWS 集成一样,Azure 集成需要在行动手册中执行相当多的步骤。
您需要做的第一件事是设置身份验证,以便允许 Ansible 控制您的 Azure 帐户。
为了让 Ansible 管理 Azure 云,您需要为 Python 安装 Azure SDK。通过执行以下命令来完成此操作:
$ pip install 'ansible[azure]'
现在您已经有了所有的依赖项,可以开始身份验证过程了。
根据您的 Azure 帐户的设置方式,有不同的方法可以确保 Ansible 能够为您管理 Azure,但它们都可以在~/.azure/credentials
文件中进行配置。
如果希望 Ansible 使用 Azure 帐户的主体凭据,则需要创建一个类似于以下内容的文件:
[default]
subscription_id = [YOUR_SUBSCIRPTION_ID_HERE]
client_id = [YOUR_CLIENT_ID_HERE]
secret = [YOUR_SECRET_HERE]
tenant = [YOUR_TENANT_HERE]
如果您更喜欢使用带有用户名和密码的活动目录,您可以这样做:
[default]
ad_user = [YOUR_AD_USER_HERE]
password = [YOUR_AD_PASSWORD_HERE]
最后,您可以选择使用 ADFS 的活动目录登录。在这种情况下,您需要设置一些附加参数。你会得到这样的结果:
[default]
ad_user = [YOUR_AD_USER_HERE]
password = [YOUR_AD_PASSWORD_HERE]
client_id = [YOUR_CLIENT_ID_HERE]
tenant = [YOUR_TENANT_HERE]
adfs_authority_url = [YOUR_ADFS_AUTHORITY_URL_HERE]
相同的参数可以作为参数传递,或者作为环境变量传递,如果这更有意义的话。
现在,Ansible 能够连接到您的 Azure 环境,您可以继续实际的行动手册:
- 创建包含以下内容的
azure.yaml
行动手册:
---
- hosts: localhost
tasks:
- name: Ensure the Storage Account is present
azure_rm_storageaccount:
resource_group: Testing
name: mysa
account_type: Standard_LRS
- name: Ensure the Virtual Network is present
azure_rm_virtualnetwork:
resource_group: Testing
name: myvn
address_prefixes: "10.10.0.0/16"
- name: Ensure the Subnet is present
azure_rm_subnet:
resource_group: Testing
name: mysn
address_prefix: "10.10.0.0/24"
virtual_network: myvn
- name: Ensure that the Public IP is set
azure_rm_publicipaddress:
resource_group: Testing
allocation_method: Static
name: myip
- name: Ensure a Security Group allowing SSH is present
azure_rm_securitygroup:
resource_group: Testing
name: mysg
rules:
- name: SSH
protocol: Tcp
destination_port_range: 22
access: Allow
priority: 101
direction: Inbound
- name: Ensure the NIC is present
azure_rm_networkinterface:
resource_group: Testing
name: testnic001
virtual_network: myvn
subnet: mysn
public_ip_name: myip
security_group: mysg
- name: Ensure the Virtual Machine is present
azure_rm_virtualmachine:
resource_group: Testing
name: myvm01
vm_size: Standard_D1
storage_account: mysa
storage_container: myvm01
storage_blob: myvm01.vhd
admin_username: admin
admin_password: Password!
network_interfaces: testnic001
image:
offer: CentOS
publisher: OpenLogic
sku: '8.0'
version: latest
- 我们可以使用以下命令运行它:
$ ansible-playbook azure.yaml
这将返回如下内容:
PLAY [localhost] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [localhost]
TASK [Ensure the Storage Account is present] ******************************************************
changed: [localhost] TASK [Ensure the Virtual Network is present] ******************************************************
changed: [localhost]
TASK [Ensure the Subnet is present] ***************************************************************
changed: [localhost]
TASK [Ensure that the Public IP is set] ***********************************************************
changed: [localhost]
TASK [Ensure a Security Group allowing SSH is present] ********************************************
changed: [localhost]
TASK [Ensure the NIC is present] ******************************************************************
changed: [localhost]
TASK [Ensure the Virtual Machine is present] ******************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************
localhost : ok=8 changed=7 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
现在,您的机器已经在 Azure 云中运行了!
如您所见,在 Azure 中,您需要准备好所有资源,然后才能发出机器创建命令。这就是您首先创建存储帐户、虚拟网络、子网、公共 IP、安全组和网卡的原因,并且仅在此时创建计算机本身。
除了市场上的三大玩家之外,还有许多额外的云选项。一个非常有趣的选择是 RackSpace,因为它的历史:Rackspace Cloud。
Rackspace 是最早涉足公共云业务的公司之一。此外,在与美国宇航局的共同努力下,Rackspace 于 2010 年创建了 OpenStack。在过去的 10 年里,Rackspace 一直是云基础设施、OpenStack 以及更广泛的托管领域非常有影响力的供应商。
为了能够从 Ansible 管理 Rackspace,您需要安装pyrax
。
安装它最简单的方法是运行以下命令:
$ pip install pyrax
如果可用,您也可以通过系统软件包管理器安装它。
由于pyrax
没有凭证文件的默认位置,您需要创建一个文件,然后通过指示pyrax
在文件位置设置环境变量。
首先在~/.rackspace_credentials
中创建一个文件,内容如下:
[rackspace_cloud]
username = [YOUR_USERNAME_HERE]
api_key = [YOUR_API_KEY_HERE]
我们现在可以将RAX_CREDS_FILE
变量设置到正确的位置:
$ export RAX_CREDS_FILE=~/.rackspace_credentials
让我们继续使用 Rackspace Cloud 创建一台机器。
在 Rackspace Cloud 中创建机器非常简单,因为这是一个单步操作:
- 创建包含以下内容的
rax.yaml
行动手册:
---
- hosts: localhost
tasks:
- name: Ensure the my_machine exists
rax:
name: my_machine
flavor: 4
image: centos-8
count: 1
group: my_group
wait: True
- 现在,您可以使用以下命令执行它:
$ ansible-playbook rax.yaml
- 这应该会产生如下结果:
PLAY [localhost] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [localhost]
TASK [Ensure the my_machine exists] ***************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如您所见,在 Rackspace Cloud 中创建机器非常简单,默认的 Ansible 模块已经集成了一些有趣的概念,例如组和计数。这些选项允许您像创建单个实例一样创建和管理实例组。
与我们刚刚讨论的各种云服务相反,所有云服务都是公共云,OpenStack 允许您创建自己的(私有)云。
私有云的缺点是,它们会给管理员和用户带来更多的复杂性,但这就是为什么它们可以被定制以完美地适应组织的原因。
能够用 Ansible 控制 OpenStack 集群的第一步是确保安装openstacksdk
。
要安装openstacksdk
,需要执行以下命令:
$ pip install openstacksdk
既然已经安装了openstacksdk
,就可以开始认证过程了。
由于 Ansible 将使用openstacksdk
作为其后端,因此您需要确保openstacksdk
能够连接到 OpenStack 集群。
为此,您可以更改~/.config/openstack/clouds.yaml
文件,确保有您想要使用它的云的配置。
正确的 OpenStack 凭据集可能是什么样子的示例如下:
clouds:
test_cloud:
region_name: MyRegion
auth:
auth_url: http://[YOUR_AUTH_URL_HERE]:5000/v2.0/
username: [YOUR_USERNAME_HERE]
password: [YOUR_PASSWORD_HERE]
project_name: myProject
如果您愿意将OS_CLIENT_CONFIG_FILE
变量导出为环境变量,也可以设置不同的配置文件位置。
现在,您已经设置了所需的安全性,以便 Ansible 可以管理您的集群,您可以创建您的第一个行动手册。
由于 OpenStack 非常灵活,它的许多组件可以有许多不同的实现,这意味着它们的行为可能略有不同。为了能够适应所有不同的情况,与许多公共云相比,管理 OpenStack 的 Ansible 模块往往具有较低的抽象级别。
因此,要创建一台机器,您需要确保 OpenStack 知道公共 SSH 密钥,并确保操作系统映像也存在。完成此操作后,您可以设置网络、子网和路由器,以确保我们要创建的机器可以通过网络进行通信。然后,您可以创建安全组及其规则,以便机器可以接收连接(在本例中是 pings 和 SSH 流量)。最后,您可以创建一个机器实例。
要完成我们刚刚描述的所有步骤,您需要创建一个名为openstack.yaml
的文件,其内容如下:
---
- hosts: localhost
tasks:
- name: Ensure the SSH key is present on OpenStack
os_keypair:
state: present
name: ansible_key
public_key_file: "{{ '~' | expanduser }}/.ssh/id_rsa.pub"
- name: Ensure we have a CentOS image
get_url:
url: http://cloud.centos.org/centos/8/x86_img/CentOS-8-GenericCloud-8.1.1911-20200113.3.x86_64.qcow2
dest: /tmp/CentOS-8-GenericCloud-8.1.1911-20200113.3.x86_64.qcow2
- name: Ensure the CentOS image is in OpenStack
os_image:
name: centos
container_format: bare
disk_format: qcow2
state: present
filename: /tmp/CentOS-8-GenericCloud-8.1.1911-20200113.3.x86_64.qcow2
- name: Ensure the Network is present
os_network:
state: present
name: mynet
external: False
shared: False
register: net_out
- name: Ensure the Subnetwork is present
os_subnet:
state: present
network_name: "{{ net_out.id }}"
name: mysubnet
ip_version: 4
cidr: 192.168.0.0/24
gateway_ip: 192.168.0.1
enable_dhcp: yes
dns_nameservers:
- 8.8.8.8
- name: Ensure the Router is present
os_router:
state: present
name: myrouter
network: nova
external_fixed_ips:
- subnet: nova
interfaces:
- mysubnet
- name: Ensure the Security Group is present
os_security_group:
state: present
name: mysg
- name: Ensure the Security Group allows ICMP traffic
os_security_group_rule:
security_group: mysg
protocol: icmp
remote_ip_prefix: 0.0.0.0/0
- name: Ensure the Security Group allows SSH traffic
os_security_group_rule:
security_group: mysg
protocol: tcp
port_range_min: 22
port_range_max: 22
remote_ip_prefix: 0.0.0.0/0
- name: Ensure the Instance exists
os_server:
state: present
name: myInstance
image: centos
flavor: m1.small
security_groups: mysg
key_name: ansible_key
nics:
- net-id: "{{ net_out.id }}"
现在,您可以运行它,如下所示:
$ ansible-playbook openstack.yaml
输出应如下所示:
PLAY [localhost] **********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [localhost]
TASK [Ensure the SSH key is present on OpenStack] *************************************************
changed: [localhost]
TASK [Ensure we have a CentOS image] **************************************************************
changed: [localhost]
TASK [Ensure the CentOS image is in OpenStack] ****************************************************
changed: [localhost]
TASK [Ensure the Network is present] **************************************************************
changed: [localhost]
TASK [Ensure the Subnetwork is present] ***********************************************************
changed: [localhost]
TASK [Ensure the Router is present] ***************************************************************
changed: [localhost]
TASK [Ensure the Security Group is present] *******************************************************
changed: [localhost]
TASK [Ensure the Security Group allows ICMP traffic] **********************************************
changed: [localhost]
TASK [Ensure the Security Group allows SSH traffic] ***********************************************
changed: [localhost]
TASK [Ensure the Instance exists] *****************************************************************
changed: [localhost]
PLAY RECAP ****************************************************************************************
localhost : ok=11 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
如您所见,这个过程比我们介绍的公共云要长。但是,您确实上传了想要运行的映像,这是许多云不允许的(或者非常复杂的流程不允许)。
在本章中,您学习了如何自动化任务,从使用行动手册设计和构建容器到管理 Kubernetes 上的部署,以及管理 Kubernetes 对象和使用 Ansible 自动化 Docker。您还探索了可以帮助您实现云环境自动化的模块,例如 AWS、谷歌云平台、Azure、Rackspace 和 OpenShift。您还了解了各种云供应商使用的不同方法,包括它们的默认值和您总是需要添加的参数。
现在,您已经了解了 Ansible 如何与云交互,您可以立即开始自动化您的云工作流。另外,记得查看进一步阅读部分的文档,了解 Ansible 支持的所有云模块及其选项。
在下一章中,您将学习如何排除故障和创建测试策略。
- 以下哪一项不是 GKE Ansible 模块?
a)gcp_container_cluster
B)gcp_container_node_pool
C)gcp_container_node_pool_facts
D)gcp_container_node_pool_count
E)gcp_container_cluster_facts
- 对或错:为了管理 Kubernetes 中的容器,需要在设置部分添加
k8s_namespace
。
a)真 B)假
- 是非判断:使用 Azure 时,在创建实例之前,不需要创建网络接口控制器 ( 网卡)。
a)真 B)假
- 真或假:
Ansible-Container
是与库本内斯和多克互动的唯一方式。
a)真 B)假
- 是非判断:在使用 AWS 时,在创建 EC2 实例之前,有必要创建一个安全组。
a)真 B)假
- 更多 AWS 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Amazon
- 更多 Azure 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Azure
- 更多 Docker 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Docker
- 更多 GCP 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Google
- 更多 OpenStack 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # OpenStack
- 更多 Rackspace 模块:https://docs . ansi ble . com/ansi ble/latest/modules/list _ of _ cloud _ modules . html # Rackspace