IAC工具的五个分类

Terraform Up & Running (Writing Infrastructure as Code)

摘录来自
“Terraform: Up & Running
Second Edition
Writing Infrastructure as Code
Yevgeniy Brikman”
此材料可能受版权保护。

What Is Infrastucture as Code?

IAC背后的核心逻辑是通过编写和执行代码的方式去定义、部署、更新以及销毁基础设施。实际上DevOps的一个重要观点即是通过软件定义一切,包括服务器、数据库、网络、日志、应用配置、文档、自动化测试、以及部署过程等等。

下面是IAC工具的五个大类:

自动化脚本(Ad hoc script)

自动化最直接的方式就是去编写一个自动化脚本。您可以将任何手工操作,通过某种脚本语言如Bash、Ruby、Python等编写成代码,下发到目标机器上执行。下面是一段Bash脚本setup-webserver.sh,用于启动一个Apache Web服务器:

# Update the apt-get cache
sudo apt-get update

# Install PHP and Apache
sudo apt-get install -y php apache2

# Copy the code from the repository
sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app

# Start Apache
sudo service apache2 start

自动化这种便利的、自由度很高的方式即是优势,也同时是它的弱势。因为不同的维护人员会有自己的开发风格,在基础设施规模还不算大的时候,该方法尚且可以应付日常工作。但随着基础设施的种类和规模不断增大,这种脚本的灵活性反而成为它的问题。一种统一的编码风格和规范亟需被引入以应对上述问题。

配置管理工具(Configuration management tools)

Chef、Puppet、Ansible以及SaltStack都是配置管理工具,均可以被用来在服务器上安装管理软件。如下所示,是一段名叫web-server.yml的Ansible Role配置文件,用于实现跟setup-webserver.sh一样的功能:

- name: Update the apt-get cache
  apt:
    update_cache: yes

- name: Install PHP
  apt:
    name: php

- name: Install Apache
  apt:
    name: apache2

- name: Copy the code from the repository
  git: repo=https://github.com/brikis98/php-app.git dest=/var/www/html/app**

- name: Start Apache
  service: name=apache2 state=started enabled=yes”

这段代码虽然跟Bash脚本看起来很类似,甚至显得有点繁琐。但是使用配置管理工具至少带来以下好处:

  • 统一编码风格

Ansible会强制性要求采用上例中的统一编码风格,包括文档结构、明确清晰的参数定义、密钥管理等等。而基于脚本开发会因不同运维人员的编码风格,产生大量不利于阅读和维护的代码。

  • 幂等性

编写一个临时性、一次性运行的脚本并不复杂,但编写一个多次重复可用的脚本就会复杂很多。比如每次创建一个文件夹的脚本,需要在执行前检查该目录是否存在;每次给某项配置文件增加一条规则时,也要先检查该配置是否已经存在;每次去启动一个应用程序时,也同样需要检查相应的进程是否存在。这种无论执行多少次都能保证脚本执行正确的特性称为幂等性。编写一个满足幂等性的脚本,这需要增加大量if语句去确认当前状态。而大部分配置管理工具支持的语句都是默认幂等的。例如上述Ansilbe Role配置文件web-server.yml,仅在Apache没有在目标服务器安装的情况下,才会执行后续的动作。

  • 规模化

临时性脚本更多的用于单一的节点操作,而配置管理工具一般用于管理大规模集群。比如,通过web-server.yml安装五台web服务器,仅需建立一个名为hosts的文本,包含以下服务器信息:

[webservers]
11.11.11.11
11.11.11.12
11.11.11.13
11.11.11.14
11.11.11.15

再定义一个Ansible的playbook:

- hosts: webservers
 roles:
  - webserver

再执行语句:ansible-playbook playbook.yml 即可同时并发的完成五台web服务器的安装部署工作。

同时,还可通过serial参数指定同时执行的并发数,实现滚动发布。而如果通过编写脚本实现上述工作,往往需要上百行的代码量。

镜像管理工具(Server Templating tools)

配置管理工具的替代者也逐渐变得流行,比如Docker、Packer以及Vagrant等。与配置管理工具不同的是,它们不是通过拉起一群服务器后,再通过统一的配置脚本实现部署安装,而是创建一个包含OS、软件、文件以及其它有关细节的全景image,之后再基于某种IaC工具(比如Ansilbe)实现镜像的分发与安装。如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eBmrTsML-1672910886412)(/Users/philo/Pictures/e8906a13-23ed-4a6f-a828-a41ee02d69bb.jpg)]

镜像(image)封装工具总体可以分为两个大类:虚拟机和容器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVIkRFqs-1672910886412)(/Users/philo/Pictures/f5a5310e-0b79-4d21-8bbe-7fddae005635.jpg)]

  • 虚拟机 Virtual Machines

VM模拟一整套计算机系统,包括硬件层。通过运行VMWare、VirtualBox或者Parallels等虚拟家管理程序(hypervisor)实现对底层处理器、内存、硬盘以及网络的虚拟化。该方式的优势在于所有的虚拟机仅能访问到虚拟硬件,它跟宿主机和其它VM是完全隔离的,同时可以保证在各环境下运行的一致性。劣势在于该方式需要对所有的硬件进行虚拟,并且为每一个虚拟机运行一套独立的OS,这带来大量的CPU、内存开销以及较长的启动时间。可以借助于Packer、Vagrant等工具将虚拟机镜像定义成代码。

  • 容器 Containers

容器仅模拟操作系统的用户空间,通过运行容器引擎(container engin)比如Docker、CoreOS rkt以及cri-o等,去创建独立的进程、内存、挂载点以及网络。容器技术的也可以保证跨环境运行的一致性,劣势在于所有的容器共享同一套宿主机的OS核心以及硬件资源,隔离性和安全性要弱于虚拟机。然而,也正由于这种共享,容器的启动时间可以缩短到毫秒级,也没有额外的CPU、内存开销。可以借助于Docker和CoreOS rkt等工具实现容器镜像的代码化。

举个例子,下面的代码是一段名叫web-server.json的Packer template,它可以一个Amazon Machine Image(AMI),运行与AWS上的虚拟机镜像格式。

{
  "builders": [{
    "ami_name": "packer-example",
    "instance_type": "t2.micro",
    "region": "us-east-2",
    "type": "amazon-ebs",
    "source_ami": "ami-0c55b159cbfafe1f0",
    "ssh_username": "ubuntu"
  }],
  "provisioners": [{
    "type": "shell",
    "inline": [
      "sudo apt-get update",
      "sudo apt-get install -y php apache2",
      "sudo git clone https://github.com/brikis98/php-app.git /var/www/html/app"
    ],
    "environment_vars": [
      "DEBIAN_FRONTEND=noninteractive"
    ]
  }]
}

这段代码与setup-webserver.sh的功能基本一致,不同的是Packer不会真正启动Apache WEB服务,而仅仅创建了一个具有Apache WEB服务器的镜像。如果想启动服务还需将该镜像安装到某个特定服务器上。

不同的镜像管理工具的适用场景略有不同。Packer一般构建用于生产环境的镜像,比如Packer封装的AMI可以直击部署在AWS的生产环境。Vagrant一般用于创建开发环境的镜像,比如一个运行在你mac或者windows上的VirtualBox的镜像。Docker一般用于将某个应用封装为容器镜像,既可以用于生产也可以用于开发环境。举一个通用的部署模式为例,通过Packer去封装一个装有容器引擎(container engin)的虚拟机镜像,之后将该镜像部署到AWS的集群中,再将容器镜像部署到该集群,进而完成一整套部署流程。

镜像管理工具的设计思想将资源供给模式带入“不可变基础设施”时代。而这个思想来源于用于函数式编程(functional programming)范式。该范式是已被证明适用于复杂状态管理系统的开发,例如编译器、正则解析器、SQL等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a9Md9OJS-1672910886413)(/Users/philo/Pictures/c8cd30a0-8f8d-4d52-843c-a35822a69d14.jpg)]

在FB程序中,一个关键理念就是赋值的不可变性。这意味着对于某个变量赋值后将不能再次直接改变它。如果想改,那么请再创建一个新变量。以python中的整型变量为例:

# 整型变量
a = 10
print("整形变量a修改之前地址:{}".format(id(a)))
a = 20
print("整形变量a修改之后地址:{}".format(id(a)))
 
==========输出结果============
整形变量a修改之前地址:4401587904
整形变量a修改之后地址:4401588224

可以看到,int类型的变量被再次赋值时,是在内存中重新建立了一个地址用于存储20这个整数,并将这个新地址赋给了整型变量a。这个过程中,并没有触发此前存储10这个整数的内存单元的任何变化,也就是说10依然驻留在内存中。正是由于FP代码会记录程序运行期间所有变量的历史状态,这个给程序测试和问题定位带来了极大便利。

“不可变基础设施”背后的逻辑与FP相同:某台服务器一旦被成功部署就不应再对其进行任何改变。如果非要改变,比如更新应用程序版本,那么请创建一个新镜像并部署到另一台服务器上。这种服务器的不可变性,给基础设施部署带来了极大便利,是让大型数据中心的资源管理从混沌走向确定的关键所在。尽管一个显而易见的开销就是变更时,需要额外的服务器开销,但可以通过控制并发、滚动发布等精细化管理手段去加以应对。同时,不可变基础设施给资源供给带来的敏捷性也大幅提供资源的使用率,所以从整体上讲,同等规模的开发、测试以及生产计算需求,反而可能消耗更少的基础设施资源。

编排工具(Orchestration tools)

镜像管理工具对于创建VM和容器镜像非常适合,但如何管理好它们则是另外一个话题。结合实际用例,这至少包括:

  • 部署虚拟机和容器,提高硬件资源使用率
  • 通过滚动、蓝绿、金丝雀等发布策略去滚动更新现有虚拟机或容器集群
  • 监控虚拟机及容器集群的监控状态并自动替换掉异常节点(auto healing
  • 根据业务负载动态扩缩虚拟机和容器规模(auto scaling
  • 在虚拟机和容器集群上动态分发流量(load balancing
  • 允许虚拟机和容器集群内能够基于网络发现彼此并相互访问(service discovery

上述工作类型正是编排工具的擅长的领域,比如K8s、Marathon/Mesos, Amazon Elastic Container Service (Amazon ECS), Docker Swarm以及Nomad等。以K8s为例,它支持通过代码定义如何管理容器。首先需要部署一套K8s集群,它是Kubernetes将管理和用于运行Docker容器的一组服务器。大多数主要云提供商都支持部署托管Kubernetes集群,例如Amazon Elastic Container Service for Kubernetes(Amazon EKS)、Google Kubernetes Engine(GKE)和Azure Kubernetes Service(AKS)。

K8s工作集群创建后,就可以通过记录在YAML文件中的代码来定义如何启动Docker容器,如下代码example-app.yml所示:

apiVersion: apps/v1

# Use a Deployment to deploy multiple replicas of your Docker
# container(s) and to declaratively roll out updates to them
kind: Deployment

# Metadata about this Deployment, including its name
metadata:
  name: example-app

# The specification that configures this Deployment
spec:
  # This tells the Deployment how to find your container(s)
  selector:
    matchLabels:
      app: example-app

  # This tells the Deployment to run three replicas of your
  # Docker container(s)
  replicas: 3

  # Specifies how to update the Deployment. Here, we
  # configure a rolling update.
  strategy:
    rollingUpdate:
      maxSurge: 3
      maxUnavailable: 0
    type: RollingUpdate

  # This is the template for what container(s) to deploy
  template:

    # The metadata for these container(s), including labels
    metadata:
      labels:
        app: example-app

    # The specification for your container(s)
    spec:
      containers:

        # Run Apache listening on port 80
        - name: example-app
          image: httpd:2.4.39
          ports:
            - containerPort: 80

上述YAML文件采用声明式定义了一次K8s的部署(Deployment),它包括:

  • 一个或多个具有相关性的容器集合(称为Pod),上述代码中在Pod中仅定义了一个容器用于运行Apache
  • Pod中每一个容器的配置。上述代码定义了Apache监听80端口
  • 在K8s中部署多少个Pod的副本,上述代码定义的是三个副本。K8s会根据调度算法在集群中找到最适合部署这三个副本的最佳服务器。调度算法一般会考虑高可用(满足反亲和性,尽量将三个副本部署到不同的服务器上)、资源(端口、CPU、内存以及其它容器所需资源)、性能(选择那些负载低、容器数量最少的服务器)等等。K8s同时会持续监控集群中有三副本在运行,并自动替换那些Crash或者无响应的Pod。
  • 如何部署更新。当需要部署一套新版本的容器镜像时,上述代码要求首先创建三个新版本的Pod,新版本容器可接管服务后,再删除三个旧版本容器。

可见短短几行YAML代码就可以完整的实现一次完整的应用部署,实在太强大。只需执行kubectl apply -f example-app.yml就可以让K8s完成应用部署。也仅需要更改上述YAML文件即可完成容器镜像以及其它配置的变更,这便可实现应用部署全流程的代码化。

资源供给工具(Provisioning Tools)

而配置管理、镜像管理和编排工具定义了在每台服务器上运行的代码,但资源供给工具比如Terraform、CloudFormation和OpenStack Heat等工具是用来创建服务器本身的。事实上,供给工具不仅可以创建服务器,还可以用来创建数据库、缓存、负载均衡器、队列、监控、子网配置、防火墙设置、路由配置、SSL认证以及几乎其它任何类型的基础设施。

下面是通过Terraform平台部署一个WEB服务器的代码:

resource "aws_instance" "app" {
  instance_type     = "t2.micro"
  availability_zone = "us-east-2a"
  ami               = "ami-0c55b159cbfafe1f0"

  user_data = <<-EOF
              #!/bin/bash
              sudo service apache2 start
              EOF
}

其中,ami指定服务器要部署的镜像。该镜像需要提前通过Packer等镜像管理工具制作,包含PHP、Apache以及应用程序源码等。user-data是一段Bash脚本在服务器启动后拉起WEB服务。

这段代码用于演示资源供给和镜像管理工具如何协同,这在不可变基础设施领域是一个常用模式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值