閱讀723 返回首頁    go 技術社區[雲棲]


雲上DevOps-CodePipeline,Packer和Terraform集成實踐探索

1.簡介

        DevOps越來越火,各種產品層出不窮,技術人員如果不談談這個詞,就會顯得很落伍了,在這種形勢下,阿裏雲也推出了自己的DevOps公共雲產品CodePipeline,本文並不想介紹已經鋪天蓋地的DevOps概念,而是結合阿裏雲的產品CodePipeline和開源工具Packer,Terraform來實踐一種全新雲上的DevOps方案,從構建代碼,創建自定義鏡像,然後基於包含新應用的鏡像來創建運行應用的整個基礎設施,包括ECS,VPC網絡,安全組等等,然後發布應用,從無到有一鍵完成。下麵我們以CodePipeline示例Web項目為實例來實踐整個方案。

2.開通CodePipeline

2.1登錄阿裏雲控製如後,通過如下導航找到CodePipeline。

image.png

2.2點擊圖中菜單按鈕來到服務開通頁麵,

image

點擊開通服務按鈕,由於當前產品處於公測期,開通服務前需要申請,按照要求提交申請,後台人員審核後,出現CodePipeline的產品主界麵,就可以開始使用CodePipeline了。

3.創建項目和運行項目

3.1登錄阿裏雲控製台後,通過菜單導航到CodePipeline後,出現如下界麵。

image

3.2點擊新建按鍵,來到創建項目導航頁麵。

輸入項目名稱Cloud_DevOps,並選擇Java項目,點擊下一步,
image

3.3來到代碼配置構建頁麵,

在“倉庫地址”中輸入如下代碼,這是一個普通的Java Web示例項目,可以通過Git Clone後查看其內容

 https://code.aliyun.com/CodePipeline/java-demo.git

然後在構“建命令中”輸入如下命令後結果如下圖

 mvn package -DskipTests 
 export ALICLOUD_ACCESS_KEY=<你的阿裏雲AK_KEY>
 export ALICLOUD_SECRET_KEY=<你的阿裏雲AK_SECRET_KEY>
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/packer
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/demo.json
 chmod 755 packer
 ./packer build demo.json
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/terraform
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/main.tf
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/variables.tf
 chmod 755 terraform
./terraform apply .

image
點擊“下一步”,來到部署頁麵,選擇“不部署”,點擊“下一步”,在項目確定頁麵點擊“確定”創建項目後來到項目構建頁麵,點擊“立即構建”按鈕來運行項目。

image

大約20多分鍾後,整個項目運行完成,我們可以通過點擊“構建曆史”下麵的構建號例如“#3”構建日誌來查看所生成的ECS的IP和訪問端口
image
然後在瀏覽器中輸入

https://47.93.214.116/demo/

就可以看到我們的應用可以訪問了。

image

4.原理分析

通過上麵簡單的幾條命令,我們就在阿裏雲的環境上,編譯好了我們的示例應用,並且生成了阿裏雲的自定義鏡像,然後生成了運行應用所必須的基礎環境,包括ECS,VPC,端口映射等,使得我們可以一鍵完成從零到可以訪問的應用。這個功能包含三個關鍵的組件

4.1 CodePipeline

        DevOps阿裏雲CodePipeline是兼容Jenkins標準的、提供快速可靠的持續集成與持續交付服務。基於容器技術和阿裏雲基礎服務架構,提供穩定和安全的代碼/Docker編譯構建,測試,掃描和部署的工具服務,並提供Pipeline As Code的編碼級配置模式,滿足應用程序和基礎設施快速可靠的交付和更新。在本實例中,起到任務管理和調用命令執行的功能,它負責構建的容器資源,然後根據項目的配置從Github上將源代碼下載構建的容器中,執行構建命令,並調用packer來創建包含所構建應用的阿裏雲鏡像,調用Terraform來創建整個ECS,VPC網絡,設置端口映射等全部基礎設施。

4.2 Packer

        DevOpsPacker是HashiCorp公司出品的一個從單一的模板文件來創建多平台一致性鏡像的輕量級開源工具,它能夠運行在常用的主流操作係統如Windows、Linux和Mac os上,能夠高效的並行創建多平台例如AWS、Azure和Alicloud的鏡像,它的目的並不是取代Puppet/Chef等配置管理工具,實際上,當製作鏡像的時候,Packer可以使用Chef或者Puppet等工具來安裝鏡像所需要的軟件。通過Packer自動化的創建各種平台的鏡像是非常容易的。關於更多的packer的知識,請訪問Pakcer的官網或者阿裏雲Packer官方插件站點

在構建命令中的下麵部分是packer相關的,運行packer首先需要在環境變量或者模板文件中導出阿裏雲的AK信息,然後下載packer程序和packer模板文件,執行packer命令,packer就會根據模板文件的內容來構建了裏雲鏡像。

export ALICLOUD_ACCESS_KEY=<你的阿裏雲AK_KEY>
export ALICLOUD_SECRET_KEY=<你的阿裏雲AK_SECRET_KEY>
wget https://alideployclient.oss-cn-beijing.aliyuncs.com/packer
wget https://alideployclient.oss-cn-beijing.aliyuncs.com/demo.json
chmod 755 packer
./packer build demo.json

下麵就是demo.json的內容。

 {
  "variables": {
        "access_key": "{{env `ALICLOUD_ACCESS_KEY`}}",
        "secret_key": "{{env `ALICLOUD_SECRET_KEY`}}"
      },
  "builders": [{
        "type":"alicloud-ecs",
        "access_key":"{{user `access_key`}}",
        "secret_key":"{{user `secret_key`}}",
        "region":"cn-beijing",
        "image_name":"codepipe_demo",
        "source_image":"ubuntu_16_0402_64_40G_alibase_20170711.vhd",
        "ssh_username":"root",
        "instance_type":"ecs.n1.medium",
        "io_optimized":"true",
        "image_force_delete":"true",
        "ssh_password":"Test12345"
      }],
  "provisioners": [{
       "type": "shell",
       "inline": [
              "apt-get update -yy",
              "apt-get install openjdk-8-jdk tomcat8  -yy",
              "mkdir -p /var/lib/tomcat8/webapps/"
             ]
       },
       {
              "type": "file",
              "source": "target/demo.war",
              "destination": "/var/lib/tomcat8/webapps/" 
       }]
}                   

其中關鍵是Provisioners部分,它會安裝運行應用所需要的軟件,並將構建的應用demo.war包含進創建的鏡像。

4.3 Terraform

        DevOpsTerraform是HashiCorp公司出品的,著名Vagrant、Packer工具也出自於該公司。Terraform是“基礎設施即代碼”的開源工具,通過模板定義“基礎設施”,目前已支持AWS、Azure、OpenStack、Alicloud等主流雲平台。更多的關於Terraform的知識,請訪問Terraform官網或者阿裏雲的Teffaform插件站點

構建命令中的如下命令是Terraform相關的。它也需要先設置AK,然後下載terraform命令和模板文件,然後應用模板文件,就會根據模板文件內容來創建整個基礎設施。

 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/terraform
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/main.tf
 wget https://alideployclient.oss-cn-beijing.aliyuncs.com/variables.tf
 chmod 755 terraform
./terraform apply .

下麵就是main.tf的內容:

provider "alicloud" {
    region = "cn-beijing"
}

data "alicloud_instance_types" "1c2g" {
    cpu_core_count = 1
    memory_size = 2
}

data "alicloud_zones" "default" {
    "available_instance_type"= "${data.alicloud_instance_types.1c2g.instance_types.1.id}"
    "available_disk_category"= "${var.disk_category}"
}

resource "alicloud_vpc" "default" {
    name = "pipeline_vpc"
    cidr_block = "${var.vpc_cidr}"
}

resource "alicloud_vswitch" "default" {
    vpc_id = "${alicloud_vpc.default.id}"
    cidr_block = "${var.vswitch_cidr}"
    availability_zone = "${data.alicloud_zones.default.zones.0.id}"
}

resource "alicloud_nat_gateway" "default" {
    vpc_id = "${alicloud_vpc.default.id}"
    spec = "Small"
    name = "bosh_micro_nat"
    bandwidth_packages = [{
        ip_count = 2
        bandwidth = 5
        zone = "${data.alicloud_zones.default.zones.0.id}"
    }]
    depends_on = [
        "alicloud_vswitch.default"]
}
resource "alicloud_snat_entry" "default"{
    snat_table_id = "${alicloud_nat_gateway.default.snat_table_ids}"
    source_vswitch_id = "${alicloud_vswitch.default.id}"
    snat_ip = "${element(split(",", alicloud_nat_gateway.default.bandwidth_packages.0.public_ip_addresses),0)}"
}

resource "alicloud_forward_entry" "default"{
    forward_table_id = "${alicloud_nat_gateway.default.forward_table_ids}"
    external_ip = "${element(split(",", alicloud_nat_gateway.default.bandwidth_packages.0.public_ip_addresses),1)}"
    external_port = "80"
    ip_protocol = "tcp"
    internal_ip = "${alicloud_instance.default.private_ip}"
    internal_port = "8080"
}

resource "alicloud_forward_entry" "ssh"{
    forward_table_id = "${alicloud_nat_gateway.default.forward_table_ids}"
    external_ip = "${element(split(",", alicloud_nat_gateway.default.bandwidth_packages.0.public_ip_addresses),1)}"
    external_port = "22"
    ip_protocol = "tcp"
    internal_ip = "${alicloud_instance.default.private_ip}"
    internal_port = "22"
}

resource "alicloud_security_group" "sg" {
    name = "bosh_micro_sg"
    description = "tf_sg"
    vpc_id = "${alicloud_vpc.default.id}"
}

resource "alicloud_security_group_rule" "http-in" {
    type = "ingress"
    ip_protocol = "tcp"
    nic_type = "intranet"
    policy = "accept"
    port_range = "80/80"
    priority = 1
    security_group_id = "${alicloud_security_group.sg.id}"
    cidr_ip = "0.0.0.0/0"
}

resource "alicloud_security_group_rule" "tomcat-in" {
    type = "ingress"
    ip_protocol = "tcp"
    nic_type = "intranet"
    policy = "accept"
    port_range = "8080/8080"
    priority = 1
    security_group_id = "${alicloud_security_group.sg.id}"
    cidr_ip = "0.0.0.0/0"
}

resource "alicloud_security_group_rule" "ssh" {
    type = "ingress"
    ip_protocol = "tcp"
    nic_type = "intranet"
    policy = "accept"
    port_range = "22/22"
    priority = 1
    security_group_id = "${alicloud_security_group.sg.id}"
    cidr_ip = "0.0.0.0/0"
}


resource "alicloud_security_group_rule" "codepipeline_deploy" {
    type = "egress"
    ip_protocol = "tcp"
    nic_type = "intranet"
    policy = "accept"
    port_range = "4505/4506"
    priority = 1
    security_group_id = "${alicloud_security_group.sg.id}"
    cidr_ip = "0.0.0.0/0"
}

resource "alicloud_security_group_rule" "codepipeline_deploy_ingress" {
    type = "ingress"
    ip_protocol = "tcp"
    nic_type = "intranet"
    policy = "accept"
    port_range = "4505/4506"
    priority = 1
    security_group_id = "${alicloud_security_group.sg.id}"
    cidr_ip = "0.0.0.0/0"
}


resource "alicloud_instance" "default" {
    availability_zone = "${data.alicloud_zones.default.zones.0.id}"
    security_groups = ["${alicloud_security_group.sg.id}"]

    vswitch_id = "${alicloud_vswitch.default.id}"

    password = "${var.ecs_password}"

    # series II
    instance_charge_type = "PostPaid"
    instance_type = "${data.alicloud_instance_types.1c2g.instance_types.1.id}"
    internet_max_bandwidth_out = 0
    io_optimized = "${var.io_optimized}"

    system_disk_category = "cloud_efficiency"
    image_id = "${data.alicloud_images.multi_image.images.0.id}"
    instance_name = "pipeline_ubuntu_1604_64"
}


data "alicloud_images" "multi_image" {
  owners     = "self"
  name_regex = "codepipe_demo"
}

下麵是variables.tf的內容,這一部分是定義Terraform模板所需要的變量:

variable "vpc_cidr" {
  default = "10.1.0.0/21"
}
variable "vswitch_cidr" {
  default = "10.1.1.0/24"
}
variable "rule_policy" {
  default = "accept"
}
variable "instance_type" {
  default = "ecs.n1.small"
}
variable "io_optimized" {
  default = "optimized"
}
variable "disk_category"{
  default = "cloud_efficiency"
}
variable "ecs_password"{
  default = "Test12345"
}

在main.tf模板中,通過如下部分來引用上一步packer創建的鏡像。

data "alicloud_images" "multi_image" {
  owners     = "self"
  name_regex = "codepipe_demo"
}

5.展望

        DevOps本文是對雲上DevOps的一種探索,希望讓讀者能夠意識到相對於傳統的環境下的DevOps,雲上環境能夠提供許多傳統環境下不能提供的能力,起到一個拋磚引玉的作用。從CodePipeline這個產品來說,接下來我們會針對用戶的場景來深度的集成Packer,Terraform,使其能夠更加符合雲上DevOps的特點,也歡迎廣大的讀者提出自己的應用場景和需求,來共同探討雲上DevOps的最佳實踐。

最後更新:2017-08-13 22:36:06

  上一篇:go  應用Quick BI實現首購用戶和用戶首購的三種運營場景監控
  下一篇:go  PostgreSQL入門到精通——世界上功能最強大的開源數據庫