【Pulumi】Pulumi ~ 入門編 / Hello World in Local/k8s ~

■ はじめに

クラウドサービスを使わずに、Local環境で、
Pulumi の勉強するための環境を欲しかった。

Pulumi のサポートするサービスに該当するのが、
Kubernetes(k8s) のみだったので、以下の関連記事で構築してみた。

https://dk521123.hatenablog.com/entry/2020/05/01/000000

 今回は、Pulumiの入門として
その環境から公式サイトの「Get Started with Kubernetes」を
Windows/VirtualBox/k8s/TypeScript で 試してみる。
その時にハマったこともメモっておく。

目次

【0】「Get Started with Kubernetes」について
 1)目的
 2)実行環境
 3)手順概要
【1】Minikubeを起動をする
【2】新規プロジェクトを作成する
【3】出力ファイルの確認
 補足:システムが管理している出力ファイル
【4】デプロイ(1回目)
 補足:システムが管理している出力ファイル
【5】プログラムを修正
 1)index.ts を修正する
 2)設定値をセットする
【6】デプロイ(2回目)
 補足:システムが管理している出力ファイル
【7】動作確認
【8】後片付け
 1)Pulumiの後片付け
 2)Minikubeの後片付け

【0】「Get Started with Kubernetes」について

* 以下のサイトを参照。

https://www.pulumi.com/docs/get-started/kubernetes/

1)目的

* Pulumi で Kubernetes上でNGINX をデプロイする

2)実行環境

https://www.pulumi.com/docs/get-started/kubernetes/begin/

* 実行環境は、以下の通り。
 + OS : Windows 11
 + Pulumi : v3.25.1
 + VirtualBox : バージョン 6.1.32 r149290 (Qt5.6.2)
 + Kubernetes : v1.23.4 (Minikube)
 + Node.js : v16.14.0

* 構築されていない場合は、以下の関連記事を参考に構築してみる

Pulumi ~ 環境設定編 ~
https://dk521123.hatenablog.com/entry/2022/01/10/155206
KubernetesWindows / 環境構築編 ~
https://dk521123.hatenablog.com/entry/2020/05/01/000000
Node.js ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2021/11/06/000000

3)手順概要

1)Minikubeを起動をする
2)新規プロジェクトを作成する
3)出力ファイルの確認
4)デプロイ(1回目)
5)プログラムを修正
6)デプロイ(2回目)
7)動作確認
8)後片付け

 => 以降に詳細を記述する。

【1】Minikubeを起動をする

* コマンドプロンプトを起動し、以下を入力し、Minikubeを起動をする

コマンド例

minikube start

# VirtualBox を見てみると、VM「minikube」が存在するはず

【2】新規プロジェクトを作成する

https://www.pulumi.com/docs/get-started/kubernetes/create-project/

を参考に実行していく

コマンド例

# QuickStartでは載っていないが、ログインしておいた方がいい
# Windows環境の特定の場所を指定
#  それ以外方法は、以下の関連記事を参照のこと
#    => https://dk521123.hatenablog.com/entry/2021/10/25/215508
md c:\tmp\pulumi\state\quickstart
pulumi login file://c:/tmp/pulumi/state/quickstart

# 専用ディレクトリ作成および移動
mkdir quickstart && cd quickstart

# kubernetes-typescript でプロジェクト作成
pulumi new kubernetes-typescript

出力例

This command will walk you through creating a new Pulumi project.

Enter a value or leave blank to accept the (default), and press <ENTER>.
Press ^C at any time to quit.

project name: (quickstart)
project description: (A minimal Kubernetes TypeScript Pulumi program)
Created project 'quickstart'

stack name: (dev)
Created stack 'dev'

Installing dependencies...


added 123 packages, and audited 124 packages in 6s

31 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
Finished installing dependencies

Your new project is ready to go!

To perform an initial deployment, run 'pulumi up'

【3】出力ファイルの確認

https://www.pulumi.com/docs/get-started/kubernetes/review-project/

* 以下のようなファイルがあれば、OK
 + Pulumi.yaml
 + Pulumi.dev.yaml
 + index.ts

index.ts

import * as k8s from "@pulumi/kubernetes";

const appLabels = { app: "nginx" };
const deployment = new k8s.apps.v1.Deployment("nginx", {
    spec: {
        selector: { matchLabels: appLabels },
        replicas: 1,
        template: {
            metadata: { labels: appLabels },
            spec: { containers: [{ name: "nginx", image: "nginx" }] }
        }
    }
});
export const name = deployment.metadata.name;

補足:システムが管理している出力ファイル

* pulumi new 後には、pulumiのシステム自体が管理している
 ファイルが出力される

C:\tmp\pulumi\state\quickstart 配下の状態

.pulumi (フォルダ)
 + locks
   + dev (フォルダ)
 + stacks
   + dev.json << Stack (スタック)を管理しているJSONファイル
   + dev.json.attrs

dev.json

{
    "version": 3,
    "checkpoint": {
        "stack": "dev"
    }
}

【4】デプロイ(1回目)

https://www.pulumi.com/docs/get-started/kubernetes/deploy-stack/

* とりあえず、pulumi up でデプロイする

コマンド例

pulumi up
# yes を選択

補足:システムが管理している出力ファイル

* pulumi up 後に、pulumiのシステム自体が管理している
 ファイルが出力される

C:\tmp\pulumi\state\quickstart 配下の状態

.pulumi (フォルダ)
 + backups << ★追加
   + dev (フォルダ)
     + dev.xxxxxxxxxxxxxxxxxxxx.json
     + dev.xxxxxxxxxxxxxxxxxxxx.json.attrs
 + history << ★追加
   + dev (フォルダ)
     + dev.xxxxxxxxxxxxxxxxxxxx.checkpoint.json
     + dev.xxxxxxxxxxxxxxxxxxxx.checkpoint.json.attrs
     + dev.xxxxxxxxxxxxxxxxxxxx.history.json
     + dev.xxxxxxxxxxxxxxxxxxxx.history.json.attrs
 + locks
   + dev (フォルダ)
 + stacks
   + dev.json << pulumi up してStackファイルが更新された
   + dev.json.attrs

dev.json

{
    "version": 3,
    "checkpoint": {
        "stack": "dev",
        "latest": {
            "manifest": {
                "time": "2022-03-20T23:44:35.0992158+09:00",
                "magic": "xxxxx",
                "version": "v3.26.1"
            },
・・・略・・・
            "resources": [
                {
                    "urn": "urn:pulumi:dev::quickstart::pulumi:pulumi:Stack::quickstart-dev",
                    "custom": false,
                    "type": "pulumi:pulumi:Stack",
                    "outputs": {
                        "name": "nginx-sgsj9izc"
                    },
                    "sequenceNumber": 1
                },
・・・略・・・
}

【5】プログラムを修正

https://www.pulumi.com/docs/get-started/kubernetes/modify-program/

1)index.ts を修正する

index.ts

import * as pulumi from "@pulumi/pulumi";
import * as k8s from "@pulumi/kubernetes";

// Minikube does not implement services of type `LoadBalancer`; require the user to specify if we're
// running on minikube, and if so, create only services of type ClusterIP.
const config = new pulumi.Config();
const isMinikube = config.requireBoolean("isMinikube");

const appName = "nginx";
const appLabels = { app: appName };
const deployment = new k8s.apps.v1.Deployment(appName, {
    spec: {
        selector: { matchLabels: appLabels },
        replicas: 1,
        template: {
            metadata: { labels: appLabels },
            spec: { containers: [{ name: appName, image: "nginx" }] }
        }
    }
});

// Allocate an IP to the Deployment.
const frontend = new k8s.core.v1.Service(appName, {
    metadata: { labels: deployment.spec.template.metadata.labels },
    spec: {
        type: isMinikube ? "ClusterIP" : "LoadBalancer",
        ports: [{ port: 80, targetPort: 80, protocol: "TCP" }],
        selector: appLabels
    }
});

// When "done", this will print the public IP.
export const ip = isMinikube
    ? frontend.spec.clusterIP
    : frontend.status.loadBalancer.apply(
          (lb) => lb.ingress[0].ip || lb.ingress[0].hostname
      );

2)設定値をセットする

* 公式では「pulumi config set isMinikube false」としているが
 今回は、Minikubeで動いているから trueを設定した

コマンド例

pulumi config set isMinikube true

Pulumi.dev.yaml (設定ファイルで管理される)

config:
  quickstart:isMinikube: "true"

【6】デプロイ(2回目)

https://www.pulumi.com/docs/get-started/kubernetes/deploy-changes/

コマンド例

$ pulumi up
# yes を選択

$ kubectl get service
NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
kubernetes       ClusterIP   10.96.0.1        <none>        443/TCP   35m
nginx-3zyl82du   ClusterIP   10.111.163.131   <none>        80/TCP    30s

# ローカルポートを、Podに転送
$ kubectl port-forward service/nginx-3zyl82du 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80
Handling connection for 8080
Handling connection for 8080

補足:システムが管理している出力ファイル

* pulumi up 後に、pulumiのシステム自体が管理している
 ファイルが出力される

C:\tmp\pulumi\state\quickstart 配下の状態

.pulumi (フォルダ)
 + backups
   + dev (フォルダ)
     + dev.xxxxxxxxxxxxxxxxxxxx.json
     + dev.xxxxxxxxxxxxxxxxxxxx.json.attrs
 + history
   + dev (フォルダ)
     + dev.yyyyyyyyyyyyyyyyyyy.checkpoint.json << ★追加
     + dev.yyyyyyyyyyyyyyyyyyy.checkpoint.json.attrs << ★追加
     + dev.yyyyyyyyyyyyyyyyyyy.history.json << ★追加
     + dev.yyyyyyyyyyyyyyyyyyy.history.json.attrs << ★追加
     + dev.xxxxxxxxxxxxxxxxxxxx.checkpoint.json
     + dev.xxxxxxxxxxxxxxxxxxxx.checkpoint.json.attrs
     + dev.xxxxxxxxxxxxxxxxxxxx.history.json
     + dev.xxxxxxxxxxxxxxxxxxxx.history.json.attrs 
+ locks
   + dev (フォルダ)
 + stacks
   + dev.json << pulumi up して更新
   + dev.json.attrs

【7】動作確認

* ブラウザで http://localhost/ (http://localhost:8080/)にアクセスする
 => 「Welcome to nginx!」が表示されればOK

【8】後片付け

1)Pulumiの後片付け

https://www.pulumi.com/docs/get-started/kubernetes/destroy-stack/

# リソースの削除
$ pulumi destroy

# スタックの削除
$ pulumi stack rm

2)Minikubeの後片付け

# Minikubeを停止する
minikube stop

# Virtualbox の vm を削除
minikube delete

関連記事

Pulumi ~ 基礎知識編 ~
https://dk521123.hatenablog.com/entry/2021/10/23/025230
Pulumi ~ 環境設定編 ~
https://dk521123.hatenablog.com/entry/2022/01/10/155206
Pulumi ~ 入門編 / Hello World in AWS
https://dk521123.hatenablog.com/entry/2022/03/11/184041
Pulumi ~ 基本編 / CLI
https://dk521123.hatenablog.com/entry/2021/10/25/215508
Pulumi ~ 基本編 / Config ~
https://dk521123.hatenablog.com/entry/2022/03/15/224217
Pulumi ~ 基本編 / Logging ~
https://dk521123.hatenablog.com/entry/2022/03/04/111618
Pulumi ~ 基本編 / Component ~
https://dk521123.hatenablog.com/entry/2022/03/05/100153
Pulumi ~ AWS S3 / KMS のデプロイ ~
https://dk521123.hatenablog.com/entry/2022/03/03/095415
Pulumi ~ AWS Glue のデプロイ ~
https://dk521123.hatenablog.com/entry/2022/03/02/122037
Pulumi に関するトラブル
https://dk521123.hatenablog.com/entry/2022/01/11/105319
pulumi up 時のトラブル
https://dk521123.hatenablog.com/entry/2022/04/05/150240
KubernetesWindows / 環境構築編 ~
https://dk521123.hatenablog.com/entry/2020/05/01/000000
Kubernetes ~ 基本編 / kubectlコマンド ~
https://dk521123.hatenablog.com/entry/2022/01/12/110555
Node.js ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2021/11/06/000000