çãããããã«ã¡ã¯ã ãã®ã¬ãŒãã§æ°ããªæµããå§ãŸãããšãæåŸ
ããŠ
ã€ã³ãã©ã¹ãã©ã¯ã㣠ã³ãŒãã« Pulumi ãšæ±çšããã°ã©ãã³ã°èšèª (Infra Structure as Code) ã䜿çšãããšãã¹ãã«ãšç¥èã®å©çšå¯èœæ§ãæœè±¡åã«ããã³ãŒãå
ã®ãã€ã©ãŒãã¬ãŒãã®æé€ãIDE ããªã³ã¿ãŒãªã©ã®ããŒã ã«éŠŽæã¿ã®ããããŒã«ãªã©ãå€ãã®å©ç¹ãåŸãããŸãã ããããã¹ãŠã®ãœãããŠã§ã¢ ãšã³ãžãã¢ãªã³ã° ããŒã«ã¯ãçç£æ§ãåäžãããã ãã§ãªããã³ãŒãã®å質ãåäžãããŸãã ãããã£ãŠãæ±çšããã°ã©ãã³ã°èšèªã®äœ¿çšã«ãããå¥ã®éèŠãªãœãããŠã§ã¢éçºææ³ãå°å
¥ã§ããããã«ãªãã®ã¯åœç¶ã®ããšã§ãã ãã¹ã.
ãã®èšäºã§ã¯ãPulumi ãã³ãŒããšããŠã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã®ãã¹ãã«ã©ã®ããã«åœ¹ç«ã€ããèŠãŠãããŸãã
ã€ã³ãã©ã¹ãã©ã¯ãã£ããã¹ãããçç±
詳现ã«å ¥ãåã«ããããããã€ã³ãã©ã¹ãã©ã¯ãã£ããã¹ãããå¿ èŠãããã®ã¯ãªãã§ãã?ããšãã質åããã䟡å€ããããŸãã ããã«ã¯å€ãã®çç±ããããŸããããã®äžéšã以äžã«ç€ºããŸãã
- ããã°ã©ã ããžãã¯ã®åã ã®é¢æ°ãŸãã¯æçã®åäœãã¹ã
- ç¹å®ã®å¶çŽã«å¯ŸããŠã€ã³ãã©ã¹ãã©ã¯ãã£ã®æãŸããç¶æ ãæ€èšŒããŸãã
- ã¹ãã¬ãŒãž ãã±ããã®æå·åã®æ¬ åŠããã€ã³ã¿ãŒãããããä»®æ³ãã·ã³ãžã®ä¿è·ãããŠããªããªãŒãã³ ã¢ã¯ã»ã¹ãªã©ãäžè¬çãªãšã©ãŒã®æ€åºã
- ã€ã³ãã©ã¹ãã©ã¯ã㣠ããããžã§ãã³ã°ã®å®è£ ã確èªããŸãã
- ãããã°ã©ã ããããã€ã³ãã©ã¹ãã©ã¯ãã£å ã§å®è¡ãããã¢ããªã±ãŒã·ã§ã³ ããžãã¯ã®ã©ã³ã¿ã€ã ãã¹ããå®è¡ããããããžã§ãã³ã°åŸã®æ©èœã確èªããŸãã
- ã芧ã®ãšãããã€ã³ãã©ã¹ãã©ã¯ã㣠ãã¹ãã«ã¯å¹ åºããªãã·ã§ã³ããããŸãã Polumi ã«ã¯ããã®ç¯å²ã®ããããç¹ã§ãã¹ãããããã®ã¡ã«ããºã ããããŸãã å§ããŠããããã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã
åäœãã¹ã
Pulumi ããã°ã©ã ã¯ãJavaScriptãPythonãTypeScriptãGo ãªã©ã®æ±çšããã°ã©ãã³ã°èšèªã§äœæãããŸãã ãããã£ãŠããã¹ã ãã¬ãŒã ã¯ãŒã¯ãå«ãããŒã«ãã©ã€ãã©ãªãå«ãããããã®èšèªã®èœåãæ倧éã«æŽ»çšã§ããŸãã Pulumi ã¯ãã«ãã¯ã©ãŠãã§ãããããã©ã®ã¯ã©ãŠã ãããã€ããŒããã®ãã¹ãã«ã䜿çšã§ããŸãã
(ãã®èšäºã§ã¯ãå€èšèªããã«ãã¯ã©ãŠãã«ãããããããJavaScript ãš Mocha ã䜿çšããAWS ãäžå¿ã«èª¬æããŸããPython ã䜿çšããããšãã§ããŸã) unittest
ãGo ãã¹ã ãã¬ãŒã ã¯ãŒã¯ããŸãã¯ãã®ä»ã®ä»»æã®ãã¹ã ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸãã ãããŠãã¡ãããPulumi 㯠AzureãGoogle CloudãKubernetes ãšããŸãé£æºããŸãã)
ãããŸã§èŠãŠããããã«ãã€ã³ãã©ã¹ãã©ã¯ã㣠ã³ãŒãããã¹ãããçç±ã¯ããã€ããããŸãã ãã® XNUMX ã€ã¯åŸæ¥ã®åäœãã¹ãã§ãã ã³ãŒãã«ã¯ãããšãã°ãCIDR ãèšç®ããããååãã¿ã°ãåçã«èšç®ãããããé¢æ°ãå«ãŸããŠããå¯èœæ§ãããããã§ãã - ãããããã¹ãããããªãã§ãããã ããã¯ããæ°ã«å
¥ãã®ããã°ã©ãã³ã°èšèªã§ã¢ããªã±ãŒã·ã§ã³ã®éåžžã®åäœãã¹ããäœæããã®ãšåãã§ãã
ããå°ãè€éã«ããã«ã¯ãããã°ã©ã ããªãœãŒã¹ãã©ã®ããã«å²ãåœãŠããã確èªã§ããŸãã 説æã®ããã«ãåçŽãª EC2 ãµãŒããŒãäœæããå¿
èŠãããã次ã®ããšã確èªããããšæ³åããŠã¿ãŸãããã
- ã€ã³ã¹ã¿ã³ã¹ã«ã¯ã¿ã°ããããŸã
Name
. - ã€ã³ã¹ã¿ã³ã¹ã§ã¯ã€ã³ã©ã€ã³ ã¹ã¯ãªããã䜿çšããªãã§ãã ãã
userData
- AMI (ã€ã¡ãŒãž) ã䜿çšããå¿ èŠããããŸãã - SSH ãã€ã³ã¿ãŒãããã«å ¬éããªãã§ãã ããã
ãã®äŸã¯ä»¥äžã«åºã¥ããŠããŸã
ã€ã³ããã¯ã¹.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;
ããã¯åºæ¬ç㪠Pulumi ããã°ã©ã ã§ããããã¯åã« EC2 ã»ãã¥ãªã㣠ã°ã«ãŒããšã€ã³ã¹ã¿ã³ã¹ãå²ãåœãŠãã ãã§ãã ãã ããããã§ã¯äžèšã® XNUMX ã€ã®ã«ãŒã«ãã¹ãŠã«éåããŠããããšã«æ³šæããŠãã ããã ãã¹ããæžããŠã¿ãŸãããïŒ
ãã¹ãã®äœæ
ãã¹ãã®äžè¬çãªæ§é ã¯ãéåžžã® Mocha ãã¹ããšåãããã«ãªããŸãã
ec2test.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, ПÑкÑÑÑПгП в ÐÐœÑеÑМеÑ.
});
});
ããã§ã¯ãæåã®ãã¹ããæžããŠã¿ãŸããããã€ã³ã¹ã¿ã³ã¹ã«ã¿ã°ãããããšã確èªããŠãã ããã Name
ã ããã確èªããã«ã¯ãEC2 ã€ã³ã¹ã¿ã³ã¹ ãªããžã§ã¯ããååŸãã察å¿ããããããã£ã確èªããã ãã§ãã 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();
}
});
});
ããã¯éåžžã®ãã¹ãã®ããã«èŠããŸããã泚ç®ã«å€ããæ©èœãããã€ããããŸãã
- ãããã€åã«ãªãœãŒã¹ã®ç¶æ ãã¯ãšãªããããããã¹ãã¯åžžã«ãèšç»ã(ãŸãã¯ããã¬ãã¥ãŒã) ã¢ãŒãã§å®è¡ãããŸãã ãããã£ãŠãå€ãåã«ååŸãããªãããŸãã¯å®çŸ©ãããªãããããã£ãå€æ°ãããŸãã ããã«ã¯ãã¯ã©ãŠã ãããã€ããŒã«ãã£ãŠèšç®ããããã¹ãŠã®åºåããããã£ãå«ãŸããŸãã ããã¯ãã¹ãã§ã¯æ£åžžã§ããå ¥åããŒã¿ã®ã¿ããã§ãã¯ããŸãã ãã®åé¡ã«ã€ããŠã¯ãåŸã§çµ±åãã¹ãã®ãšãã«åã³åãäžããŸãã
- ãã¹ãŠã® Pulumi ãªãœãŒã¹ ããããã£ã¯åºåã§ããããã®å€ãã¯éåæã§è©äŸ¡ããããããå€ã«ã¢ã¯ã»ã¹ããã«ã¯ apply ã¡ãœããã䜿çšããå¿
èŠããããŸãã ããã¯promiseãšafunctionã«éåžžã«ãã䌌ãŠããŸã
then
. - ãšã©ãŒ ã¡ãã»ãŒãžã«ãªãœãŒã¹ URN ã衚瀺ããããã«ããã€ãã®ããããã£ã䜿çšããŠãããããé¢æ°ã䜿çšããå¿
èŠããããŸãã
pulumi.all
ããããçµã¿åãããŸãã - æåŸã«ããããã®å€ã¯éåæã§èšç®ããããããMocha ã®çµã¿èŸŒã¿ã®éåæã³ãŒã«ããã¯æ©èœã䜿çšããå¿
èŠããããŸãã
done
ãŸãã¯çŽæãè¿ãã
ãã¹ãŠãèšå®ããããåçŽãª JavaScript å€ãšããŠå
¥åã«ã¢ã¯ã»ã¹ã§ããããã«ãªããŸãã è²¡ç£ tags
ã¯ããã (é£æ³é
å) ãªã®ã§ã(1) false ã§ã¯ãªãããšãããã³ (2) ã®ããŒãããããšã確èªããŸãã Name
ã ãšãŠãã·ã³ãã«ãªã®ã§ãäœã§ããã¹ãã§ããããã«ãªããŸããã
ã§ã¯ãXNUMX çªç®ã®å°åæãæžããŠã¿ãŸãããã ããã«ç°¡åã§ã:
// 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();
}
});
});
æåŸã«ãXNUMX çªç®ã®ãã¹ããäœæããŸãããã ã»ãã¥ãªã㣠ã°ã«ãŒãã«é¢é£ä»ãããããã°ã€ã³ ã«ãŒã« (å€æ°ååšããå¯èœæ§ããã) ãšããããã®ã«ãŒã«å ã® CIDR ç¯å² (åæ§ã«å€æ°ååšããå¯èœæ§ããããŸã) ãæ¢ããŠãããããããã¯å°ãè€éã«ãªããŸãã ããããç§ãã¡ã¯æ¬¡ã®ããšãå®è¡ã§ããŸããã
// 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();
}
});
});
ããã ãã§ãã ã§ã¯ããã¹ããå®è¡ããŠã¿ãŸãããã
ãã¹ãã®å®è¡
ã»ãšãã©ã®å Žåãéžæãããã¹ã ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŠãéåžžã®æ¹æ³ã§ãã¹ããå®è¡ã§ããŸãã ãã ããPulumi ã«ã¯æ³šç®ã«å€ããæ©èœã XNUMX ã€ãããŸãã
éåžžãPulumi ããã°ã©ã ãå®è¡ããã«ã¯ãèšèªã©ã³ã¿ã€ã ãæ§æãããªãœãŒã¹ã䜿çšããæäœãèšé²ããŠèšç»ã«å«ããããšãã§ããããã« Pulumi ãšã³ãžã³ã®èµ·åãå¶åŸ¡ãã pulimi CLI (ã³ãã³ã ã©ã€ã³ ã€ã³ã¿ãŒãã§ã€ã¹) ã䜿çšãããŸãã ãã ããåé¡ã XNUMX ã€ãããŸãã ãã¹ã ãã¬ãŒã ã¯ãŒã¯ã®å¶åŸ¡äžã§å®è¡ããå ŽåãCLI ãš Pulumi ãšã³ãžã³ã®éã«éä¿¡ã¯ãããŸããã
ãã®åé¡ãåé¿ããã«ã¯ã以äžãæå®ããã ãã§ãã
- ç°å¢å€æ°ã«å«ãŸãããããžã§ã¯ãå
PULUMI_NODEJS_PROJECT
(ãŸãã¯ãããäžè¬çã«ã¯ãPULUMI__PROJECT ÐŽÐ»Ñ ÐŽÑÑÐ³ÐžÑ ÑзÑкПв).
ç°å¢å€æ°ã§æå®ãããã¹ã¿ãã¯ã®ååPULUMI_NODEJS_STACK
(ãŸãã¯ãããäžè¬çã«ã¯ãPULUMI__ STACK).
ã¹ã¿ãã¯æ§æå€æ°ã ç°å¢å€æ°ã䜿çšããŠååŸã§ããŸããPULUMI_CONFIG
ãã®åœ¢åŒã¯ããŒãšå€ã®ãã¢ãå«ã JSON ãããã§ããããã°ã©ã ã¯ãå®è¡äžã« CLI/ãšã³ãžã³ãžã®æ¥ç¶ãå©çšã§ããªãããšã瀺ãèŠåãçºè¡ããŸãã ããã°ã©ã ã¯å®éã«ã¯äœããããã€ããªããããããã¯éèŠã§ããããããæå³ãããã®ã§ã¯ãªãå Žåã¯é©ããããããŸããã Pulumi ã«ããããŸãã«å¿ èŠãªãã®ã§ããããšãäŒããã«ã¯ã次ã®ããã«ã€ã³ã¹ããŒã«ããŸãã
PULUMI_TEST_MODE
вtrue
.ãããžã§ã¯ãåãæå®ããå¿ èŠããããšæ³åããŠãã ããã
my-ws
ãã¹ã¿ãã¯ådev
ãããã³ AWS ãªãŒãžã§ã³us-west-2
ã Mocha ãã¹ããå®è¡ããããã®ã³ãã³ã ã©ã€ã³ã¯æ¬¡ã®ããã«ãªããŸãã$ PULUMI_TEST_MODE=true PULUMI_NODEJS_STACK="my-ws" PULUMI_NODEJS_PROJECT="dev" PULUMI_CONFIG='{ "aws:region": "us-west-2" }' mocha tests.js
ãããå®è¡ãããšãäºæ³ã©ããã倱æãããã¹ãã XNUMX ã€ããããšãããããŸãã
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
ããã°ã©ã ãä¿®æ£ããŠã¿ãŸãããã
"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;
ãããŠããã¹ããå床å®è¡ããŸãã
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)
ãã¹ãŠããŸããããŸãã...äžæ³ïŒ âââ
ä»æ¥ã¯ãããŸã§ã§ãããå°å ¥ãã¹ãã«ã€ããŠã¯ç¿»èš³ã®åŸåã§ã話ããŸã ð
åºæïŒ habr.com