ʻO ka hoʻāʻo ʻana i nā mea hana e like me ke Code me Pulumi. Mahele 1

Aloha ahiahi e nā hoa. I ka kali ʻana i ka hoʻomaka ʻana o kahi kahe hou ma ka wikiwiki "Nā hana a me nā mea hana DevOps" Ke kaʻana nei mākou iā ʻoe i kahi unuhi hou. Hele.

ʻO ka hoʻāʻo ʻana i nā mea hana e like me ke Code me Pulumi. Mahele 1

ʻO ka hoʻohana ʻana i ka Pulumi a me nā ʻōlelo hoʻonohonoho maʻamau no ka code infrastructure (Infrastructure as Code) e hāʻawi i nā pono he nui: ka loaʻa ʻana o nā mākau a me ka ʻike, ka hoʻopau ʻana i ka boilerplate i ke code ma o abstraction, nā mea hana i kamaʻāina i kāu hui, e like me nā IDE a me nā linters. ʻO kēia mau mea hana ʻenehana lako polokalamu ʻaʻole wale e hoʻonui iā mākou, akā hoʻomaikaʻi pū i ka maikaʻi o kā mākou code. No laila, he mea maʻamau wale nō ka hoʻohana ʻana i nā ʻōlelo hoʻolālā kumu nui e ʻae iā mākou e hoʻolauna i kahi hana hoʻomohala polokalamu koʻikoʻi - hoʻāʻo.

Ma kēia ʻatikala, e nānā mākou pehea e kōkua ai ʻo Pulumi iā mākou e hoʻāʻo i kā mākou infrastructure-as-code.

ʻO ka hoʻāʻo ʻana i nā mea hana e like me ke Code me Pulumi. Mahele 1

No ke aha e ho'āʻo ai i ka ʻōnaehana?

Ma mua o ka hele ʻana i nā kikoʻī, pono e nīnau i ka nīnau: "No ke aha e hoʻāʻo ai i ka ʻōnaehana?" Nui nā kumu no kēia a eia kekahi o lākou:

  • ʻO ka hoʻāʻo ʻana o kēlā me kēia hana a i ʻole nā ​​ʻāpana o kāu loiloi papahana
  • Hōʻoia i ke kūlana i makemake ʻia o ka ʻōnaehana kūʻē i kekahi mau kaohi.
  • ʻO ka ʻike ʻana i nā hewa maʻamau, e like me ka nele o ka hoʻopili ʻana o kahi bākeke mālama a i ʻole pale ʻole ʻia, wehe ʻia mai ka Pūnaewele i nā mīkini virtual.
  • Ke nānā ʻana i ka hoʻokō ʻana i ka hoʻolako ʻana i nā ʻōnaehana.
  • Ke hoʻokō nei i ka hoʻāʻo ʻana o ka loiloi noi e holo ana i loko o kāu ʻōnaehana "programmed" e nānā i ka hana ma hope o ka hoʻolako ʻana.
  • E like me kā mākou e ʻike ai, aia kahi ākea o nā koho hoʻāʻo ʻenehana. He mau hana ko Polumi no ka ho'āʻo ʻana i kēlā me kēia wahi ma kēia kiko. E hoʻomaka kākou a ʻike pehea e hana ai.

Hoʻāʻo ʻāpana

Ua kākau ʻia nā papahana Pulumi ma nā ʻōlelo hoʻolālā kumu nui e like me JavaScript, Python, TypeScript a i ʻole Go. No laila, loaʻa iā lākou ka mana piha o kēia mau ʻōlelo, me kā lākou mau mea hana a me nā hale waihona puke, me nā hoʻolālā hoʻāʻo. ʻO ka Pulumi he multi-cloud, ʻo ia hoʻi, hiki ke hoʻohana ʻia no ka hoʻāʻo ʻana mai kekahi mea hāʻawi kapua.

(Ma kēia ʻatikala, ʻoiai ʻo ka lehulehu a me ka multicloud, hoʻohana mākou i ka JavaScript a me Mocha a nānā i ka AWS. Hiki iā ʻoe ke hoʻohana i ka Python. unittest, Go test framework, a i ʻole kekahi ʻano hoʻāʻo ʻē aʻe āu e makemake ai. A, ʻoiaʻiʻo, hana maikaʻi ʻo Pulumi me Azure, Google Cloud, Kubernetes.)

E like me kā mākou i ʻike ai, aia kekahi mau kumu e makemake ai ʻoe e hoʻāʻo i kāu code infrastructure. ʻO kekahi o lākou ka hoʻāʻo ʻokoʻa maʻamau. No ka mea, he mau hana kāu code - no ka laʻana, e helu i ka CIDR, helu dynamically i nā inoa, nā lepili, etc. - makemake paha ʻoe e hoʻāʻo iā lākou. Ua like kēia me ke kākau ʻana i nā hoʻokolohua ʻāpana maʻamau no nā noi ma kāu ʻōlelo papahana punahele.
No ka paʻakikī iki, hiki iā ʻoe ke nānā i ke ʻano o ka hoʻokaʻawale ʻana o kāu polokalamu i nā kumuwaiwai. No ka hoʻohālikelike ʻana, e noʻonoʻo mākou pono mākou e hana i kahi kikowaena EC2 maʻalahi a makemake mākou e hōʻoia i kēia mau mea:

  • Loaʻa i nā hiʻohiʻona kahi hōʻailona Name.
  • ʻAʻole pono ka hoʻohana ʻana i ka palapala inline userData - pono mākou e hoʻohana i kahi AMI (kiʻi).
  • ʻAʻole pono ka SSH i hōʻike ʻia i ka Pūnaewele.

Hoʻokumu ʻia kēia laʻana ma kaʻu hiʻohiʻona aws-js-webserver:

index.js:

"use strict";
 
let aws = require("@pulumi/aws");
 
let group = new aws.ec2.SecurityGroup("web-secgrp", {
    ingress: [
        { protocol: "tcp", fromPort: 22, toPort: 22, cidrBlocks: ["0.0.0.0/0"] },
        { protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
    ],
});
 
let userData =
`#!/bin/bash
echo "Hello, World!" > index.html
nohup python -m SimpleHTTPServer 80 &`;
 
let server = new aws.ec2.Instance("web-server-www", {
    instanceType: "t2.micro",
    securityGroups: [ group.name ], // reference the group object above
    ami: "ami-c55673a0"             // AMI for us-east-2 (Ohio),
    userData: userData              // start a simple web server
});
 
exports.group = group;
exports.server = server;
exports.publicIp = server.publicIp;
exports.publicHostName = server.publicDns;

ʻO kēia ka papahana Pulumi kumu: hoʻokaʻawale wale ia i kahi hui palekana EC2 a me kahi hiʻohiʻona. Eia naʻe, pono e hoʻomaopopo ʻia eia mākou e uhaki nei i nā lula ʻekolu i ʻōlelo ʻia ma luna. E kākau kāua i nā hoʻokolohua!

Nā hoʻāʻo kākau

ʻO ke ʻano maʻamau o kā mākou hoʻokolohua e like me nā hoʻokolohua Mocha maʻamau:

ec2tests.js

test.js:
let assert = require("assert");
let mocha = require("mocha");
let pulumi = require("@pulumi/pulumi");
let infra = require("./index");
 
describe("Infrastructure", function() {
    let server = infra.server;
    describe("#server", function() {
        // TODO(check 1): Должен быть тэг Name.
        // TODO(check 2): Не должно быть inline-скрипта userData.
    });
    let group = infra.group;
    describe("#group", function() {
        // TODO(check 3): Не должно быть SSH, открытого в Интернет.
    });
});

I kēia manawa, e kākau kāua i kā mākou hoʻāʻo mua: e hōʻoia i ka loaʻa ʻana o ka hōʻailona Name. No ka nānā ʻana i kēia, loaʻa wale iā mākou ka EC2 instance object a nānā i ka waiwai pili tags:

 // check 1: Должен быть тэг Name.
        it("must have a name tag", function(done) {
            pulumi.all([server.urn, server.tags]).apply(([urn, tags]) => {
                if (!tags || !tags["Name"]) {
                    done(new Error(`Missing a name tag on server ${urn}`));
                } else {
                    done();
                }
            });
        });

Ua like ia me ka ho'āʻo maʻamau, akā me kekahi mau hiʻohiʻona pono e ʻike:

  • No ka mea ke nīnau nei mākou i ke kūlana o kahi kumuwaiwai ma mua o ka hoʻolaha ʻana, e holo mau ʻia kā mākou mau hoʻokolohua ma ke ʻano "plan" (a i ʻole "preview") mode. No laila, nui nā waiwai i ʻole e kiʻi ʻia nā waiwai a ʻaʻole e wehewehe ʻia. Loaʻa kēia i nā waiwai hoʻopuka a pau i helu ʻia e kāu mea hāʻawi kapua. He mea maʻamau kēia no kā mākou hoʻāʻo - nānā wale mākou i ka ʻikepili komo. E hoʻi mākou i kēia pilikia ma hope, i ka wā e pili ana i nā hoʻokolohua hoʻohui.
  • No ka mea, ʻo nā waiwai waiwai a pau o Pulumi he mau hoʻopuka, a ua loiloi ʻia ka nui o ia mau mea, pono mākou e hoʻohana i ke ʻano hoʻohana no ke komo ʻana i nā waiwai. Ua like loa keia me na olelo hoopomaikai a me ka hana then .
  • No ka mea ke hoʻohana nei mākou i kekahi mau waiwai e hōʻike i ke kumu URN i ka memo hewa, pono mākou e hoʻohana i ka hana pulumi.alle hui pu ia lakou.
  • ʻO ka mea hope loa, ʻoiai ua helu ʻia kēia mau waiwai me ka asynchronously, pono mākou e hoʻohana i ka hiʻohiʻona callback async i kūkulu ʻia ʻo Mocha. done a i ʻole ka hoʻihoʻi ʻana i kahi ʻōlelo hoʻohiki.

Ke hoʻonohonoho mākou i nā mea a pau, hiki iā mākou ke komo i nā mea hoʻokomo e like me nā waiwai JavaScript maʻalahi. Waiwai tags he palapala 'āina (hui hui), no laila e hoʻomaopopo mākou he (1) ʻaʻole wahaheʻe, a (2) aia kahi kī no Name. He mea maʻalahi loa a hiki iā mākou ke hoʻāʻo i kekahi mea!

I kēia manawa e kākau kāua i kā mākou helu lua. ʻOi aku ka maʻalahi:

 // check 2: Не должно быть inline-скрипта userData.
        it("must not use userData (use an AMI instead)", function(done) {
            pulumi.all([server.urn, server.userData]).apply(([urn, userData]) => {
                if (userData) {
                    done(new Error(`Illegal use of userData on server ${urn}`));
                } else {
                    done();
                }
            });
        });

A ʻo ka hope, e kākau kākou i ka hoʻāʻo ʻekolu. E ʻoi aku ka paʻakikī o kēia no ka mea ke ʻimi nei mākou i nā lula e pili ana i ka pūʻulu palekana, hiki ke nui, a me nā pae CIDR i kēlā mau lula, a hiki ke nui. Akā ua hoʻokō mākou:

    // check 3: Не должно быть SSH, открытого в Интернет.
        it("must not open port 22 (SSH) to the Internet", function(done) {
            pulumi.all([ group.urn, group.ingress ]).apply(([ urn, ingress ]) => {
                if (ingress.find(rule =>
                        rule.fromPort == 22 && rule.cidrBlocks.find(block =>
                            block === "0.0.0.0/0"))) {
                    done(new Error(`Illegal SSH port 22 open to the Internet (CIDR 0.0.0.0/0) on group ${urn}`));
                } else {
                    done();
                }
            });
        });

ʻo ia wale nō. I kēia manawa, e holo kāua i nā hoʻokolohua!

E holo ana i na hoao

I ka hapanui o nā hihia, hiki iā ʻoe ke holo i nā hoʻokolohua ma ke ʻano maʻamau, me ka hoʻohana ʻana i ke kaʻina hoʻāʻo o kāu koho. Akā, aia kekahi hiʻohiʻona o Pulumi e pono ke nānā aku.
ʻO ka mea maʻamau, no ka holo ʻana i nā polokalamu Pulumi, hoʻohana ʻia ka pulumi CLI (Command Line interface), nāna e hoʻonohonoho i ka manawa holo ʻōlelo, hoʻomalu i ka hoʻomaka ʻana o ka mīkini Pulumi i hiki ke hoʻopaʻa ʻia nā hana me nā kumuwaiwai a hoʻokomo ʻia i loko o ka papahana, etc. Eia naʻe, hoʻokahi pilikia. Ke holo nei ma lalo o ka mana o kāu hoʻāʻo ʻana, ʻaʻohe kamaʻilio ma waena o ka CLI a me ka mīkini Pulumi.

No ka hoʻoponopono ʻana i kēia pilikia, pono mākou e wehewehe i kēia:

  • ʻO ka inoa papahana, aia i loko o ka hoʻololi kaiapuni PULUMI_NODEJS_PROJECT (a i ʻole, ʻoi aku ka laulā, PULUMI__PROJECT для других языков).
    ʻO ka inoa o ka pūʻulu i hōʻike ʻia ma ka hoʻololi kaiapuni PULUMI_NODEJS_STACK (a i ʻole, ʻoi aku ka laulā, PULUMI__ STACK).
    ʻO kāu mau hoʻololi hoʻonohonoho hoʻonohonoho. Hiki ke loaʻa iā lākou me ka hoʻohana ʻana i kahi ʻano hoʻololi kaiapuni PULUMI_CONFIG a ʻo kā lākou ʻano palapala ʻāina ʻo JSON me nā kī / waiwai paʻa.

    E hoʻopuka ka papahana i nā ʻōlelo luhi e hōʻike ana ʻaʻole i loaʻa ka pilina i ka CLI/engine i ka wā o ka hoʻokō. He mea koʻikoʻi kēia no ka mea ʻaʻole e hoʻokau maoli kāu polokalamu i kekahi mea a hiki mai paha ia me ke kahaha inā ʻaʻole ia ka mea āu i manaʻo ai e hana! No ka haʻi aku iā Pulumi ʻo ia ka mea āu e pono ai, hiki iā ʻoe ke hoʻouka PULUMI_TEST_MODE в true.

    E noʻonoʻo pono mākou e kuhikuhi i ka inoa o ka papahana my-ws, inoa waihona dev, a me ka AWS Region us-west-2. ʻO ka laina kauoha no ka holo ʻana i nā hoʻokolohua Mocha e like me kēia:

    $ PULUMI_TEST_MODE=true 
        PULUMI_NODEJS_STACK="my-ws" 
        PULUMI_NODEJS_PROJECT="dev" 
        PULUMI_CONFIG='{ "aws:region": "us-west-2" }' 
        mocha tests.js

    ʻO ka hana ʻana i kēia, e like me ka mea i manaʻo ʻia, e hōʻike mai iā mākou he ʻekolu mau hoʻokolohua hāʻule!

    Infrastructure
        #server
          1) must have a name tag
     	 2) must not use userData (use an AMI instead)
        #group
          3) must not open port 22 (SSH) to the Internet
    
      0 passing (17ms)
      3 failing
     
     1) Infrastructure
           #server
             must have a name tag:
         Error: Missing a name tag on server
            urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www
    
     2) Infrastructure
           #server
             must not use userData (use an AMI instead):
         Error: Illegal use of userData on server
            urn:pulumi:my-ws::my-dev::aws:ec2/instance:Instance::web-server-www
    
     3) Infrastructure
           #group
             must not open port 22 (SSH) to the Internet:
         Error: Illegal SSH port 22 open to the Internet (CIDR 0.0.0.0/0) on group

    E hoʻoponopono i kā mākou papahana:

    "use strict";
     
    let aws = require("@pulumi/aws");
     
    let group = new aws.ec2.SecurityGroup("web-secgrp", {
        ingress: [
            { protocol: "tcp", fromPort: 80, toPort: 80, cidrBlocks: ["0.0.0.0/0"] },
        ],
    });
     
    let server = new aws.ec2.Instance("web-server-www", {
        tags: { "Name": "web-server-www" },
        instanceType: "t2.micro",
        securityGroups: [ group.name ], // reference the group object above
        ami: "ami-c55673a0"             // AMI for us-east-2 (Ohio),
    });
     
    exports.group = group;
    exports.server = server;
    exports.publicIp = server.publicIp;
    exports.publicHostName = server.publicDns;
    

    A laila e holo hou i nā hoʻokolohua:

    Infrastructure
        #server
          ✓ must have a name tag
          ✓ must not use userData (use an AMI instead)
        #group
          ✓ must not open port 22 (SSH) to the Internet
     
     
     3 passing (16ms)

    Ua holo maikaʻi nā mea a pau... Hurray! ✓✓✓

    ʻO ia wale nō no kēia lā, akā e kamaʻilio mākou e pili ana i ka hoʻāʻo ʻana ma ka ʻāpana ʻelua o ka unuhi 😉

Source: www.habr.com

Pākuʻi i ka manaʻo hoʻopuka